Merge branch 'master' into bullet-2.82
commit
7ba3b88fb6
|
@ -4201,6 +4201,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}",
|
||||||
|
// updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name);
|
||||||
|
//
|
||||||
#endregion Packet Sending
|
#endregion Packet Sending
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12337,6 +12341,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// provide your own method.</param>
|
/// provide your own method.</param>
|
||||||
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
|
protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method)
|
||||||
{
|
{
|
||||||
|
if (m_outPacketsToDrop != null)
|
||||||
|
if (m_outPacketsToDrop.Contains(packet.Type.ToString()))
|
||||||
|
return;
|
||||||
|
|
||||||
if (DebugPacketLevel > 0)
|
if (DebugPacketLevel > 0)
|
||||||
{
|
{
|
||||||
bool logPacket = true;
|
bool logPacket = true;
|
||||||
|
@ -12395,6 +12403,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <param name="Pack">OpenMetaverse.packet</param>
|
/// <param name="Pack">OpenMetaverse.packet</param>
|
||||||
public void ProcessInPacket(Packet packet)
|
public void ProcessInPacket(Packet packet)
|
||||||
{
|
{
|
||||||
|
if (m_inPacketsToDrop != null)
|
||||||
|
if (m_inPacketsToDrop.Contains(packet.Type.ToString()))
|
||||||
|
return;
|
||||||
|
|
||||||
if (DebugPacketLevel > 0)
|
if (DebugPacketLevel > 0)
|
||||||
{
|
{
|
||||||
bool logPacket = true;
|
bool logPacket = true;
|
||||||
|
@ -13119,5 +13131,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
eq.Enqueue(BuildEvent("BulkUpdateInventory",
|
eq.Enqueue(BuildEvent("BulkUpdateInventory",
|
||||||
llsd), AgentId);
|
llsd), AgentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HashSet<string> m_outPacketsToDrop;
|
||||||
|
|
||||||
|
public bool AddOutPacketToDropSet(string packetName)
|
||||||
|
{
|
||||||
|
if (m_outPacketsToDrop == null)
|
||||||
|
m_outPacketsToDrop = new HashSet<string>();
|
||||||
|
|
||||||
|
return m_outPacketsToDrop.Add(packetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveOutPacketFromDropSet(string packetName)
|
||||||
|
{
|
||||||
|
if (m_outPacketsToDrop == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_outPacketsToDrop.Remove(packetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<string> GetOutPacketDropSet()
|
||||||
|
{
|
||||||
|
return new HashSet<string>(m_outPacketsToDrop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashSet<string> m_inPacketsToDrop;
|
||||||
|
|
||||||
|
public bool AddInPacketToDropSet(string packetName)
|
||||||
|
{
|
||||||
|
if (m_inPacketsToDrop == null)
|
||||||
|
m_inPacketsToDrop = new HashSet<string>();
|
||||||
|
|
||||||
|
return m_inPacketsToDrop.Add(packetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveInPacketFromDropSet(string packetName)
|
||||||
|
{
|
||||||
|
if (m_inPacketsToDrop == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_inPacketsToDrop.Remove(packetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<string> GetInPacketDropSet()
|
||||||
|
{
|
||||||
|
return new HashSet<string>(m_inPacketsToDrop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -650,8 +650,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if (HasUpdates(m_categories))
|
if (HasUpdates(m_categories))
|
||||||
{
|
{
|
||||||
// Asynchronously run the callback
|
if (!m_udpServer.OqrEngine.IsRunning)
|
||||||
Util.FireAndForget(FireQueueEmpty, categories);
|
{
|
||||||
|
// Asynchronously run the callback
|
||||||
|
Util.FireAndForget(FireQueueEmpty, categories);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_udpServer.OqrEngine.QueueRequest(this, categories);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -670,8 +677,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <param name="o">Throttle categories to fire the callback for,
|
/// <param name="o">Throttle categories to fire the callback for,
|
||||||
/// stored as an object to match the WaitCallback delegate
|
/// stored as an object to match the WaitCallback delegate
|
||||||
/// signature</param>
|
/// signature</param>
|
||||||
private void FireQueueEmpty(object o)
|
public void FireQueueEmpty(object o)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[LLUDPCLIENT]: FireQueueEmpty for {0} in {1}", AgentID, m_udpServer.Scene.Name);
|
||||||
|
|
||||||
// int start = Environment.TickCount & Int32.MaxValue;
|
// int start = Environment.TickCount & Int32.MaxValue;
|
||||||
// const int MIN_CALLBACK_MS = 30;
|
// const int MIN_CALLBACK_MS = 30;
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private AgentCircuitManager m_circuitManager;
|
private AgentCircuitManager m_circuitManager;
|
||||||
|
|
||||||
/// <summary>Reference to the scene this UDP server is attached to</summary>
|
/// <summary>Reference to the scene this UDP server is attached to</summary>
|
||||||
protected Scene m_scene;
|
public Scene Scene { get; private set; }
|
||||||
|
|
||||||
/// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
|
/// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
|
||||||
private Location m_location;
|
private Location m_location;
|
||||||
|
@ -355,6 +355,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IClientAPI m_currentIncomingClient;
|
private IClientAPI m_currentIncomingClient;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Experimental facility to run queue empty processing within a controlled number of threads rather than
|
||||||
|
/// requiring massive numbers of short-lived threads from the threadpool when there are a high number of
|
||||||
|
/// connections.
|
||||||
|
/// </summary>
|
||||||
|
public OutgoingQueueRefillEngine OqrEngine { get; private set; }
|
||||||
|
|
||||||
public LLUDPServer(
|
public LLUDPServer(
|
||||||
IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
|
IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
|
||||||
IConfigSource configSource, AgentCircuitManager circuitManager)
|
IConfigSource configSource, AgentCircuitManager circuitManager)
|
||||||
|
@ -432,6 +439,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if (usePools)
|
if (usePools)
|
||||||
EnablePools();
|
EnablePools();
|
||||||
|
|
||||||
|
OqrEngine = new OutgoingQueueRefillEngine(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
|
@ -453,7 +462,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// This thread will process the packets received that are placed on the packetInbox
|
// This thread will process the packets received that are placed on the packetInbox
|
||||||
Watchdog.StartThread(
|
Watchdog.StartThread(
|
||||||
IncomingPacketHandler,
|
IncomingPacketHandler,
|
||||||
string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
|
string.Format("Incoming Packets ({0})", Scene.Name),
|
||||||
ThreadPriority.Normal,
|
ThreadPriority.Normal,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
|
@ -469,7 +478,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
Watchdog.StartThread(
|
Watchdog.StartThread(
|
||||||
OutgoingPacketHandler,
|
OutgoingPacketHandler,
|
||||||
string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName),
|
string.Format("Outgoing Packets ({0})", Scene.Name),
|
||||||
ThreadPriority.Normal,
|
ThreadPriority.Normal,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
|
@ -479,7 +488,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
|
m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name);
|
||||||
base.StopOutbound();
|
base.StopOutbound();
|
||||||
base.StopInbound();
|
base.StopInbound();
|
||||||
}
|
}
|
||||||
|
@ -527,7 +536,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
"The number of objects currently stored within the UDPPacketBuffer pool",
|
"The number of objects currently stored within the UDPPacketBuffer pool",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
m_scene.Name,
|
Scene.Name,
|
||||||
StatType.Pull,
|
StatType.Pull,
|
||||||
stat => stat.Value = Pool.Count,
|
stat => stat.Value = Pool.Count,
|
||||||
StatVerbosity.Debug);
|
StatVerbosity.Debug);
|
||||||
|
@ -541,7 +550,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
"The number of objects currently stored within the incoming packet pool",
|
"The number of objects currently stored within the incoming packet pool",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
m_scene.Name,
|
Scene.Name,
|
||||||
StatType.Pull,
|
StatType.Pull,
|
||||||
stat => stat.Value = m_incomingPacketPool.Count,
|
stat => stat.Value = m_incomingPacketPool.Count,
|
||||||
StatVerbosity.Debug);
|
StatVerbosity.Debug);
|
||||||
|
@ -585,7 +594,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
public void AddScene(IScene scene)
|
public void AddScene(IScene scene)
|
||||||
{
|
{
|
||||||
if (m_scene != null)
|
if (Scene != null)
|
||||||
{
|
{
|
||||||
m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
|
m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
|
||||||
return;
|
return;
|
||||||
|
@ -597,8 +606,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_scene = (Scene)scene;
|
Scene = (Scene)scene;
|
||||||
m_location = new Location(m_scene.RegionInfo.RegionHandle);
|
m_location = new Location(Scene.RegionInfo.RegionHandle);
|
||||||
|
|
||||||
StatsManager.RegisterStat(
|
StatsManager.RegisterStat(
|
||||||
new Stat(
|
new Stat(
|
||||||
|
@ -621,7 +630,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
"Packets reused",
|
"Packets reused",
|
||||||
"Number of packets reused out of all requests to the packet pool",
|
"Number of packets reused out of all requests to the packet pool",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
m_scene.Name,
|
Scene.Name,
|
||||||
StatType.Pull,
|
StatType.Pull,
|
||||||
stat =>
|
stat =>
|
||||||
{ PercentageStat pstat = (PercentageStat)stat;
|
{ PercentageStat pstat = (PercentageStat)stat;
|
||||||
|
@ -635,7 +644,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
"Packet data blocks reused",
|
"Packet data blocks reused",
|
||||||
"Number of data blocks reused out of all requests to the packet pool",
|
"Number of data blocks reused out of all requests to the packet pool",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
m_scene.Name,
|
Scene.Name,
|
||||||
StatType.Pull,
|
StatType.Pull,
|
||||||
stat =>
|
stat =>
|
||||||
{ PercentageStat pstat = (PercentageStat)stat;
|
{ PercentageStat pstat = (PercentageStat)stat;
|
||||||
|
@ -650,7 +659,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
"The number of objects currently stored within the packet pool",
|
"The number of objects currently stored within the packet pool",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
m_scene.Name,
|
Scene.Name,
|
||||||
StatType.Pull,
|
StatType.Pull,
|
||||||
stat => stat.Value = PacketPool.Instance.PacketsPooled,
|
stat => stat.Value = PacketPool.Instance.PacketsPooled,
|
||||||
StatVerbosity.Debug));
|
StatVerbosity.Debug));
|
||||||
|
@ -662,7 +671,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
"The number of objects currently stored within the packet data block pool",
|
"The number of objects currently stored within the packet data block pool",
|
||||||
"",
|
"",
|
||||||
"clientstack",
|
"clientstack",
|
||||||
m_scene.Name,
|
Scene.Name,
|
||||||
StatType.Pull,
|
StatType.Pull,
|
||||||
stat => stat.Value = PacketPool.Instance.BlocksPooled,
|
stat => stat.Value = PacketPool.Instance.BlocksPooled,
|
||||||
StatVerbosity.Debug));
|
StatVerbosity.Debug));
|
||||||
|
@ -688,6 +697,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
+ "If an avatar name is given then only packets from that avatar are logged.",
|
+ "If an avatar name is given then only packets from that avatar are logged.",
|
||||||
HandlePacketCommand);
|
HandlePacketCommand);
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
|
"Debug", false, "debug lludp drop",
|
||||||
|
"debug lludp drop <in|out> <add|remove> <packet-name>",
|
||||||
|
"Drop all in or outbound packets that match the given name",
|
||||||
|
"For test purposes.",
|
||||||
|
HandleDropCommand);
|
||||||
|
|
||||||
MainConsole.Instance.Commands.AddCommand(
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
"Debug",
|
"Debug",
|
||||||
false,
|
false,
|
||||||
|
@ -739,7 +755,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private void HandlePacketCommand(string module, string[] args)
|
private void HandlePacketCommand(string module, string[] args)
|
||||||
{
|
{
|
||||||
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool setAsDefaultLevel = false;
|
bool setAsDefaultLevel = false;
|
||||||
|
@ -775,15 +791,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
MainConsole.Instance.OutputFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"Packet debug for {0} clients set to {1} in {2}",
|
"Packet debug for {0} clients set to {1} in {2}",
|
||||||
(setAll ? "all" : "future"), DefaultClientPacketDebugLevel, m_scene.Name);
|
(setAll ? "all" : "future"), DefaultClientPacketDebugLevel, Scene.Name);
|
||||||
|
|
||||||
if (setAll)
|
if (setAll)
|
||||||
{
|
{
|
||||||
m_scene.ForEachScenePresence(sp =>
|
Scene.ForEachScenePresence(sp =>
|
||||||
{
|
{
|
||||||
MainConsole.Instance.OutputFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"Packet debug for {0} ({1}) set to {2} in {3}",
|
"Packet debug for {0} ({1}) set to {2} in {3}",
|
||||||
sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name);
|
sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, Scene.Name);
|
||||||
|
|
||||||
sp.ControllingClient.DebugPacketLevel = newDebug;
|
sp.ControllingClient.DebugPacketLevel = newDebug;
|
||||||
});
|
});
|
||||||
|
@ -791,13 +807,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_scene.ForEachScenePresence(sp =>
|
Scene.ForEachScenePresence(sp =>
|
||||||
{
|
{
|
||||||
if (name == null || sp.Name == name)
|
if (name == null || sp.Name == name)
|
||||||
{
|
{
|
||||||
MainConsole.Instance.OutputFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"Packet debug for {0} ({1}) set to {2} in {3}",
|
"Packet debug for {0} ({1}) set to {2} in {3}",
|
||||||
sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name);
|
sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, Scene.Name);
|
||||||
|
|
||||||
sp.ControllingClient.DebugPacketLevel = newDebug;
|
sp.ControllingClient.DebugPacketLevel = newDebug;
|
||||||
}
|
}
|
||||||
|
@ -811,9 +827,60 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleDropCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Length != 6)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Usage: debug lludp drop <in|out> <add|remove> <packet-name>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string direction = args[3];
|
||||||
|
string subCommand = args[4];
|
||||||
|
string packetName = args[5];
|
||||||
|
|
||||||
|
if (subCommand == "add")
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat(
|
||||||
|
"Adding packet {0} to {1} drop list for all connections in {2}", direction, packetName, Scene.Name);
|
||||||
|
|
||||||
|
Scene.ForEachScenePresence(
|
||||||
|
sp =>
|
||||||
|
{
|
||||||
|
LLClientView llcv = (LLClientView)sp.ControllingClient;
|
||||||
|
|
||||||
|
if (direction == "in")
|
||||||
|
llcv.AddInPacketToDropSet(packetName);
|
||||||
|
else if (direction == "out")
|
||||||
|
llcv.AddOutPacketToDropSet(packetName);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (subCommand == "remove")
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat(
|
||||||
|
"Removing packet {0} from {1} drop list for all connections in {2}", direction, packetName, Scene.Name);
|
||||||
|
|
||||||
|
Scene.ForEachScenePresence(
|
||||||
|
sp =>
|
||||||
|
{
|
||||||
|
LLClientView llcv = (LLClientView)sp.ControllingClient;
|
||||||
|
|
||||||
|
if (direction == "in")
|
||||||
|
llcv.RemoveInPacketFromDropSet(packetName);
|
||||||
|
else if (direction == "out")
|
||||||
|
llcv.RemoveOutPacketFromDropSet(packetName);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleStartCommand(string module, string[] args)
|
private void HandleStartCommand(string module, string[] args)
|
||||||
{
|
{
|
||||||
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (args.Length != 4)
|
if (args.Length != 4)
|
||||||
|
@ -833,7 +900,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private void HandleStopCommand(string module, string[] args)
|
private void HandleStopCommand(string module, string[] args)
|
||||||
{
|
{
|
||||||
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (args.Length != 4)
|
if (args.Length != 4)
|
||||||
|
@ -853,7 +920,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private void HandlePoolCommand(string module, string[] args)
|
private void HandlePoolCommand(string module, string[] args)
|
||||||
{
|
{
|
||||||
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (args.Length != 4)
|
if (args.Length != 4)
|
||||||
|
@ -869,7 +936,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (EnablePools())
|
if (EnablePools())
|
||||||
{
|
{
|
||||||
EnablePoolStats();
|
EnablePoolStats();
|
||||||
MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name);
|
MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", Scene.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (enabled == "off")
|
else if (enabled == "off")
|
||||||
|
@ -877,7 +944,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (DisablePools())
|
if (DisablePools())
|
||||||
{
|
{
|
||||||
DisablePoolStats();
|
DisablePoolStats();
|
||||||
MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name);
|
MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", Scene.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -890,27 +957,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private void HandleAgentUpdateCommand(string module, string[] args)
|
private void HandleAgentUpdateCommand(string module, string[] args)
|
||||||
{
|
{
|
||||||
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_discardAgentUpdates = !m_discardAgentUpdates;
|
m_discardAgentUpdates = !m_discardAgentUpdates;
|
||||||
|
|
||||||
MainConsole.Instance.OutputFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name);
|
"Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, Scene.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleStatusCommand(string module, string[] args)
|
private void HandleStatusCommand(string module, string[] args)
|
||||||
{
|
{
|
||||||
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MainConsole.Instance.OutputFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
|
"IN LLUDP packet processing for {0} is {1}", Scene.Name, IsRunningInbound ? "enabled" : "disabled");
|
||||||
|
|
||||||
MainConsole.Instance.OutputFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
|
"OUT LLUDP packet processing for {0} is {1}", Scene.Name, IsRunningOutbound ? "enabled" : "disabled");
|
||||||
|
|
||||||
MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
|
MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", Scene.Name, UsePools ? "on" : "off");
|
||||||
|
|
||||||
MainConsole.Instance.OutputFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel);
|
"Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel);
|
||||||
|
@ -1420,7 +1487,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
// Determine which agent this packet came from
|
// Determine which agent this packet came from
|
||||||
IClientAPI client;
|
IClientAPI client;
|
||||||
if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
|
if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
|
||||||
{
|
{
|
||||||
//m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
|
//m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
|
@ -1715,7 +1782,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
|
"[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
|
||||||
uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint);
|
uccp.CircuitCode.Code, Scene.RegionInfo.RegionName, endPoint);
|
||||||
|
|
||||||
AuthenticateResponse sessionInfo;
|
AuthenticateResponse sessionInfo;
|
||||||
if (IsClientAuthorized(uccp, out sessionInfo))
|
if (IsClientAuthorized(uccp, out sessionInfo))
|
||||||
|
@ -1737,7 +1804,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// We only want to send initial data to new clients, not ones which are being converted from child to root.
|
// We only want to send initial data to new clients, not ones which are being converted from child to root.
|
||||||
if (client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
|
AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
|
||||||
bool tp = (aCircuit.teleportFlags > 0);
|
bool tp = (aCircuit.teleportFlags > 0);
|
||||||
// Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
|
// Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
|
||||||
if (!tp && !client.SceneAgent.SentInitialDataToClient)
|
if (!tp && !client.SceneAgent.SentInitialDataToClient)
|
||||||
|
@ -1749,7 +1816,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// Don't create clients for unauthorized requesters.
|
// Don't create clients for unauthorized requesters.
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
|
"[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
|
||||||
uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
|
uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
|
@ -1781,7 +1848,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
|
CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, m_scene.Name);
|
"[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, Scene.Name);
|
||||||
|
|
||||||
// Determine which agent this packet came from
|
// Determine which agent this packet came from
|
||||||
// We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination
|
// We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination
|
||||||
|
@ -1792,7 +1859,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
int count = 40;
|
int count = 40;
|
||||||
while (count-- > 0)
|
while (count-- > 0)
|
||||||
{
|
{
|
||||||
if (m_scene.TryGetClient(endPoint, out client))
|
if (Scene.TryGetClient(endPoint, out client))
|
||||||
{
|
{
|
||||||
if (!client.IsActive)
|
if (!client.IsActive)
|
||||||
{
|
{
|
||||||
|
@ -1801,7 +1868,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// not yet been established).
|
// not yet been established).
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.",
|
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.",
|
||||||
endPoint, client.Name, m_scene.Name);
|
endPoint, client.Name, Scene.Name);
|
||||||
}
|
}
|
||||||
else if (client.SceneAgent == null)
|
else if (client.SceneAgent == null)
|
||||||
{
|
{
|
||||||
|
@ -1813,7 +1880,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// the client manager
|
// the client manager
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.",
|
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.",
|
||||||
endPoint, client.Name, m_scene.Name);
|
endPoint, client.Name, Scene.Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1824,7 +1891,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.",
|
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.",
|
||||||
endPoint, m_scene.Name);
|
endPoint, Scene.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread.Sleep(200);
|
Thread.Sleep(200);
|
||||||
|
@ -1834,7 +1901,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.",
|
"[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.",
|
||||||
endPoint, m_scene.Name);
|
endPoint, Scene.Name);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1846,7 +1913,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// purposes.
|
// purposes.
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.",
|
"[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.",
|
||||||
endPoint, client.Name, m_scene.Name);
|
endPoint, client.Name, Scene.Name);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1941,11 +2008,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// consistently, this lock could probably be removed.
|
// consistently, this lock could probably be removed.
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (!m_scene.TryGetClient(agentID, out client))
|
if (!Scene.TryGetClient(agentID, out client))
|
||||||
{
|
{
|
||||||
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
|
LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
|
||||||
|
|
||||||
client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
|
client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
|
||||||
client.OnLogout += LogoutHandler;
|
client.OnLogout += LogoutHandler;
|
||||||
client.DebugPacketLevel = DefaultClientPacketDebugLevel;
|
client.DebugPacketLevel = DefaultClientPacketDebugLevel;
|
||||||
|
|
||||||
|
@ -1975,13 +2042,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
|
"[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
|
||||||
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name);
|
client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name);
|
||||||
|
|
||||||
if (!client.SceneAgent.IsChildAgent)
|
if (!client.SceneAgent.IsChildAgent)
|
||||||
client.Kick("Simulator logged you out due to connection timeout.");
|
client.Kick("Simulator logged you out due to connection timeout.");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_scene.CloseAgent(client.AgentId, true);
|
Scene.CloseAgent(client.AgentId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void IncomingPacketHandler()
|
private void IncomingPacketHandler()
|
||||||
|
@ -2093,7 +2160,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
// Handle outgoing packets, resends, acknowledgements, and pings for each
|
// Handle outgoing packets, resends, acknowledgements, and pings for each
|
||||||
// client. m_packetSent will be set to true if a packet is sent
|
// client. m_packetSent will be set to true if a packet is sent
|
||||||
m_scene.ForEachClient(clientPacketHandler);
|
Scene.ForEachClient(clientPacketHandler);
|
||||||
|
|
||||||
m_currentOutgoingClient = null;
|
m_currentOutgoingClient = null;
|
||||||
|
|
||||||
|
@ -2260,7 +2327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
watch1.Reset();
|
watch1.Reset();
|
||||||
|
|
||||||
// reuse this -- it's every ~100ms
|
// reuse this -- it's every ~100ms
|
||||||
if (m_scene.EmergencyMonitoring && nticks % 100 == 0)
|
if (Scene.EmergencyMonitoring && nticks % 100 == 0)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})",
|
m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})",
|
||||||
avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent);
|
avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent);
|
||||||
|
@ -2309,7 +2376,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
|
"[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
|
||||||
packet.Type, client.Name, m_scene.RegionInfo.RegionName);
|
packet.Type, client.Name, Scene.RegionInfo.RegionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
IncomingPacketsProcessed++;
|
IncomingPacketsProcessed++;
|
||||||
|
@ -2322,7 +2389,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (!client.IsLoggingOut)
|
if (!client.IsLoggingOut)
|
||||||
{
|
{
|
||||||
client.IsLoggingOut = true;
|
client.IsLoggingOut = true;
|
||||||
m_scene.CloseAgent(client.AgentId, false);
|
Scene.CloseAgent(client.AgentId, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,286 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using log4net;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Monitoring;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
{
|
||||||
|
public struct RefillRequest
|
||||||
|
{
|
||||||
|
public LLUDPClient Client;
|
||||||
|
public ThrottleOutPacketTypeFlags Categories;
|
||||||
|
|
||||||
|
public RefillRequest(LLUDPClient client, ThrottleOutPacketTypeFlags categories)
|
||||||
|
{
|
||||||
|
Client = client;
|
||||||
|
Categories = categories;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OutgoingQueueRefillEngine
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public bool IsRunning { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The timeout in milliseconds to wait for at least one event to be written when the recorder is stopping.
|
||||||
|
/// </summary>
|
||||||
|
public int RequestProcessTimeoutOnStop { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls whether we need to warn in the log about exceeding the max queue size.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is flipped to false once queue max has been exceeded and back to true when it falls below max, in
|
||||||
|
/// order to avoid spamming the log with lots of warnings.
|
||||||
|
/// </remarks>
|
||||||
|
private bool m_warnOverMaxQueue = true;
|
||||||
|
|
||||||
|
private BlockingCollection<RefillRequest> m_requestQueue;
|
||||||
|
|
||||||
|
private CancellationTokenSource m_cancelSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
private LLUDPServer m_udpServer;
|
||||||
|
|
||||||
|
private Stat m_oqreRequestsWaitingStat;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to signal that we are ready to complete stop.
|
||||||
|
/// </summary>
|
||||||
|
private ManualResetEvent m_finishedProcessingAfterStop = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
public OutgoingQueueRefillEngine(LLUDPServer server)
|
||||||
|
{
|
||||||
|
RequestProcessTimeoutOnStop = 5000;
|
||||||
|
m_udpServer = server;
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
|
"Debug",
|
||||||
|
false,
|
||||||
|
"debug lludp oqre",
|
||||||
|
"debug lludp oqre <start|stop|status>",
|
||||||
|
"Start, stop or get status of OutgoingQueueRefillEngine.",
|
||||||
|
"Experimental.",
|
||||||
|
HandleOqreCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
if (IsRunning)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IsRunning = true;
|
||||||
|
|
||||||
|
m_finishedProcessingAfterStop.Reset();
|
||||||
|
|
||||||
|
m_requestQueue = new BlockingCollection<RefillRequest>(new ConcurrentQueue<RefillRequest>(), 5000);
|
||||||
|
|
||||||
|
m_oqreRequestsWaitingStat =
|
||||||
|
new Stat(
|
||||||
|
"OQRERequestsWaiting",
|
||||||
|
"Number of outgong queue refill requests waiting for processing.",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"clientstack",
|
||||||
|
m_udpServer.Scene.Name,
|
||||||
|
StatType.Pull,
|
||||||
|
MeasuresOfInterest.None,
|
||||||
|
stat => stat.Value = m_requestQueue.Count,
|
||||||
|
StatVerbosity.Debug);
|
||||||
|
|
||||||
|
StatsManager.RegisterStat(m_oqreRequestsWaitingStat);
|
||||||
|
|
||||||
|
Watchdog.StartThread(
|
||||||
|
ProcessRequests,
|
||||||
|
String.Format("OutgoingQueueRefillEngineThread ({0})", m_udpServer.Scene.Name),
|
||||||
|
ThreadPriority.Normal,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
int.MaxValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!IsRunning)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IsRunning = false;
|
||||||
|
|
||||||
|
int requestsLeft = m_requestQueue.Count;
|
||||||
|
|
||||||
|
if (requestsLeft <= 0)
|
||||||
|
{
|
||||||
|
m_cancelSource.Cancel();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[OUTGOING QUEUE REFILL ENGINE]: Waiting to write {0} events after stop.", requestsLeft);
|
||||||
|
|
||||||
|
while (requestsLeft > 0)
|
||||||
|
{
|
||||||
|
if (!m_finishedProcessingAfterStop.WaitOne(RequestProcessTimeoutOnStop))
|
||||||
|
{
|
||||||
|
// After timeout no events have been written
|
||||||
|
if (requestsLeft == m_requestQueue.Count)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[OUTGOING QUEUE REFILL ENGINE]: No requests processed after {0} ms wait. Discarding remaining {1} requests",
|
||||||
|
RequestProcessTimeoutOnStop, requestsLeft);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestsLeft = m_requestQueue.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_cancelSource.Dispose();
|
||||||
|
StatsManager.DeregisterStat(m_oqreRequestsWaitingStat);
|
||||||
|
m_oqreRequestsWaitingStat = null;
|
||||||
|
m_requestQueue = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool QueueRequest(LLUDPClient client, ThrottleOutPacketTypeFlags categories)
|
||||||
|
{
|
||||||
|
if (m_requestQueue.Count < m_requestQueue.BoundedCapacity)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[OUTGOING QUEUE REFILL ENGINE]: Adding request for categories {0} for {1} in {2}",
|
||||||
|
// categories, client.AgentID, m_udpServer.Scene.Name);
|
||||||
|
|
||||||
|
m_requestQueue.Add(new RefillRequest(client, categories));
|
||||||
|
|
||||||
|
if (!m_warnOverMaxQueue)
|
||||||
|
m_warnOverMaxQueue = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_warnOverMaxQueue)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[OUTGOING QUEUE REFILL ENGINE]: Request queue at maximum capacity, not recording request from {0} in {1}",
|
||||||
|
client.AgentID, m_udpServer.Scene.Name);
|
||||||
|
|
||||||
|
m_warnOverMaxQueue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessRequests()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (IsRunning || m_requestQueue.Count > 0)
|
||||||
|
{
|
||||||
|
RefillRequest req = m_requestQueue.Take(m_cancelSource.Token);
|
||||||
|
|
||||||
|
// QueueEmpty callback = req.Client.OnQueueEmpty;
|
||||||
|
//
|
||||||
|
// if (callback != null)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// callback(req.Categories);
|
||||||
|
// }
|
||||||
|
// catch (Exception e)
|
||||||
|
// {
|
||||||
|
// m_log.Error("[OUTGOING QUEUE REFILL ENGINE]: ProcessRequests(" + req.Categories + ") threw an exception: " + e.Message, e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
req.Client.FireQueueEmpty(req.Categories);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
m_finishedProcessingAfterStop.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleOqreCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Length != 4)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output("Usage: debug lludp oqre <stop|start|status>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string subCommand = args[3];
|
||||||
|
|
||||||
|
if (subCommand == "stop")
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
MainConsole.Instance.OutputFormat("Stopped OQRE for {0}", m_udpServer.Scene.Name);
|
||||||
|
}
|
||||||
|
else if (subCommand == "start")
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
MainConsole.Instance.OutputFormat("Started OQRE for {0}", m_udpServer.Scene.Name);
|
||||||
|
}
|
||||||
|
else if (subCommand == "status")
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("OQRE in {0}", m_udpServer.Scene.Name);
|
||||||
|
MainConsole.Instance.OutputFormat("Running: {0}", IsRunning);
|
||||||
|
MainConsole.Instance.OutputFormat(
|
||||||
|
"Requests waiting: {0}", IsRunning ? m_requestQueue.Count.ToString() : "n/a");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("Unrecognized OQRE subcommand {0}", subCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -690,7 +690,14 @@ namespace pCampBot
|
||||||
{
|
{
|
||||||
lock (m_bots)
|
lock (m_bots)
|
||||||
{
|
{
|
||||||
m_bots.ForEach(b => b.SitOnGround());
|
foreach (Bot bot in m_bots)
|
||||||
|
{
|
||||||
|
if (bot.ConnectionState == ConnectionState.Connected)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("Sitting bot {0} on ground.", bot.Name);
|
||||||
|
bot.SitOnGround();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,7 +705,14 @@ namespace pCampBot
|
||||||
{
|
{
|
||||||
lock (m_bots)
|
lock (m_bots)
|
||||||
{
|
{
|
||||||
m_bots.ForEach(b => b.Stand());
|
foreach (Bot bot in m_bots)
|
||||||
|
{
|
||||||
|
if (bot.ConnectionState == ConnectionState.Connected)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("Standing bot {0} from ground.", bot.Name);
|
||||||
|
bot.Stand();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue