diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 1a35d22c3b..ae759caae2 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -109,10 +109,11 @@ namespace OpenSim.Region.ClientStack.Linden "Comms", false, "debug eq", - "debug eq [0|1]", - "Turn on event queue debugging", - "debug eq 1 will turn on event queue debugging. This will log all outgoing event queue messages to clients.\n" - + "debug eq 0 will turn off event queue debugging.", + "debug eq [0|1|2]", + "Turn on event queue debugging" + + "<= 0 - turns off all event queue logging" + + ">= 1 - turns on outgoing event logging" + + ">= 2 - turns on poll notification", HandleDebugEq); } else @@ -235,19 +236,19 @@ namespace OpenSim.Region.ClientStack.Linden // ClientClosed(client.AgentId); // } - private void ClientClosed(UUID AgentID, Scene scene) + private void ClientClosed(UUID agentID, Scene scene) { -// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName); +// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); int count = 0; - while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5) + while (queues.ContainsKey(agentID) && queues[agentID].Count > 0 && count++ < 5) { Thread.Sleep(1000); } lock (queues) { - queues.Remove(AgentID); + queues.Remove(agentID); } List removeitems = new List(); @@ -256,7 +257,7 @@ namespace OpenSim.Region.ClientStack.Linden foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys) { // m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID); - if (ky == AgentID) + if (ky == agentID) { removeitems.Add(ky); } @@ -267,7 +268,12 @@ namespace OpenSim.Region.ClientStack.Linden UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky]; m_AvatarQueueUUIDMapping.Remove(ky); - MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + eventQueueGetUuid.ToString() + "/"); + string eqgPath = GenerateEqgCapPath(eventQueueGetUuid); + MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath); + +// m_log.DebugFormat( +// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}", +// eqgPath, agentID, m_scene.RegionInfo.RegionName); } } @@ -281,7 +287,7 @@ namespace OpenSim.Region.ClientStack.Linden { searchval = m_QueueUUIDAvatarMapping[ky]; - if (searchval == AgentID) + if (searchval == agentID) { removeitems.Add(ky); } @@ -305,6 +311,15 @@ namespace OpenSim.Region.ClientStack.Linden //} } + /// + /// Generate an Event Queue Get handler path for the given eqg uuid. + /// + /// + private string GenerateEqgCapPath(UUID eqgUuid) + { + return string.Format("/CAPS/EQG/{0}/", eqgUuid); + } + public void OnRegisterCaps(UUID agentID, Caps caps) { // Register an event queue for the client @@ -316,8 +331,7 @@ namespace OpenSim.Region.ClientStack.Linden // Let's instantiate a Queue for this agent right now TryGetQueue(agentID); - string capsBase = "/CAPS/EQG/"; - UUID EventQueueGetUUID = UUID.Zero; + UUID eventQueueGetUUID; lock (m_AvatarQueueUUIDMapping) { @@ -325,37 +339,35 @@ namespace OpenSim.Region.ClientStack.Linden if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) { //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); - EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; + eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; } else { - EventQueueGetUUID = UUID.Random(); + eventQueueGetUUID = UUID.Random(); //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); } } lock (m_QueueUUIDAvatarMapping) { - if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID)) - m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID); + if (!m_QueueUUIDAvatarMapping.ContainsKey(eventQueueGetUUID)) + m_QueueUUIDAvatarMapping.Add(eventQueueGetUUID, agentID); } lock (m_AvatarQueueUUIDMapping) { if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID)) - m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID); + m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); } + string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID); + // Register this as a caps handler // FIXME: Confusingly, we need to register separate as a capability so that the client is told about // EventQueueGet when it receive capability information, but then we replace the rest handler immediately // afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but // really it should be possible to directly register the poll handler as a capability. - caps.RegisterHandler( - "EventQueueGet", - new RestHTTPHandler( - "POST", capsBase + EventQueueGetUUID.ToString() + "/", null)); - + caps.RegisterHandler("EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null)); // delegate(Hashtable m_dhttpMethod) // { // return ProcessQueue(m_dhttpMethod, agentID, caps); @@ -364,9 +376,13 @@ namespace OpenSim.Region.ClientStack.Linden // This will persist this beyond the expiry of the caps handlers // TODO: Add EventQueueGet name/description for diagnostics MainServer.Instance.AddPollServiceHTTPHandler( - capsBase + EventQueueGetUUID.ToString() + "/", + eventQueueGetPath, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID)); +// m_log.DebugFormat( +// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}", +// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName); + Random rnd = new Random(Environment.TickCount); lock (m_ids) { @@ -388,9 +404,25 @@ namespace OpenSim.Region.ClientStack.Linden return false; } + /// + /// Logs a debug line for an outbound event queue message if appropriate. + /// + /// Element containing message + private void LogOutboundDebugMessage(OSD element, UUID agentId) + { + if (element is OSDMap) + { + OSDMap ev = (OSDMap)element; + m_log.DebugFormat( + "Eq OUT {0,-30} to {1,-20} {2,-20}", + ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.RegionInfo.RegionName); + } + } + public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request) { -// m_log.DebugFormat("[EVENT QUEUE GET MODULE]: Invoked GetEvents() for {0}", pAgentId); + if (DebugLevel >= 2) + m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); Queue queue = TryGetQueue(pAgentId); OSD element; @@ -414,13 +446,8 @@ namespace OpenSim.Region.ClientStack.Linden } else { - if (DebugLevel > 0 && element is OSDMap) - { - OSDMap ev = (OSDMap)element; - m_log.DebugFormat( - "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}", - ev["message"], m_scene.GetScenePresence(pAgentId).Name); - } + if (DebugLevel > 0) + LogOutboundDebugMessage(element, pAgentId); array.Add(element); @@ -430,13 +457,8 @@ namespace OpenSim.Region.ClientStack.Linden { element = queue.Dequeue(); - if (DebugLevel > 0 && element is OSDMap) - { - OSDMap ev = (OSDMap)element; - m_log.DebugFormat( - "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}", - ev["message"], m_scene.GetScenePresence(pAgentId).Name); - } + if (DebugLevel > 0) + LogOutboundDebugMessage(element, pAgentId); array.Add(element); thisID++; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2bf3638f6c..3cce370262 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2646,7 +2646,8 @@ namespace OpenSim.Region.Framework.Scenes if (sp == null) { m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} to scene {1} at pos {2}", client.Name, RegionInfo.RegionName, client.StartPos); + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); m_clientManager.Add(client); SubscribeToClientEvents(client); @@ -3905,8 +3906,7 @@ namespace OpenSim.Region.Framework.Scenes // XPTO: if this agent is not allowed here as root, always return false - // We have to wait until the viewer contacts this region after receiving EAC. - // That calls AddNewClient, which finally creates the ScenePresence + // TODO: This check should probably be in QueryAccess(). ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); if (nearestParcel == null) { @@ -3917,14 +3917,8 @@ namespace OpenSim.Region.Framework.Scenes return false; } - int num = m_sceneGraph.GetNumberOfScenePresences(); - - if (num >= RegionInfo.RegionSettings.AgentLimit) - { - if (!Permissions.IsAdministrator(cAgentData.AgentID)) - return false; - } - + // We have to wait until the viewer contacts this region after receiving EAC. + // That calls AddNewClient, which finally creates the ScenePresence ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) @@ -3968,14 +3962,28 @@ namespace OpenSim.Region.Framework.Scenes return false; } + /// + /// Poll until the requested ScenePresence appears or we timeout. + /// + /// The scene presence is found, else null. + /// protected virtual ScenePresence WaitGetScenePresence(UUID agentID) { int ntimes = 10; - ScenePresence childAgentUpdate = null; - while ((childAgentUpdate = GetScenePresence(agentID)) == null && (ntimes-- > 0)) + ScenePresence sp = null; + while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) Thread.Sleep(1000); - return childAgentUpdate; + if (sp == null) + m_log.WarnFormat( + "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", + agentID, RegionInfo.RegionName); +// else +// m_log.DebugFormat( +// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits", +// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes); + + return sp; } public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) @@ -5177,13 +5185,22 @@ namespace OpenSim.Region.Framework.Scenes // child agent creation, thereby emulating the SL behavior. public bool QueryAccess(UUID agentID, Vector3 position, out string reason) { - int num = m_sceneGraph.GetNumberOfScenePresences(); + // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. + // However, the long term fix is to make sure root agent count is always accurate. + m_sceneGraph.RecalculateStats(); + + int num = m_sceneGraph.GetRootAgentCount(); if (num >= RegionInfo.RegionSettings.AgentLimit) { if (!Permissions.IsAdministrator(agentID)) { reason = "The region is full"; + + m_log.DebugFormat( + "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}", + agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit); + return false; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 481592277d..ddf1550c0a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -779,11 +779,6 @@ namespace OpenSim.Region.Framework.Scenes return m_scenePresenceArray; } - public int GetNumberOfScenePresences() - { - return m_scenePresenceArray.Count; - } - /// /// Request a scene presence by UUID. Fast, indexed lookup. /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 0d5c218d34..0c66e49ff8 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1169,6 +1169,12 @@ namespace OpenSim.Region.Framework.Scenes Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); m_callbackURI = null; } +// else +// { +// m_log.DebugFormat( +// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", +// client.Name, client.AgentId, m_scene.RegionInfo.RegionName); +// } ValidateAndSendAppearanceAndAgentData(); @@ -2508,7 +2514,7 @@ namespace OpenSim.Region.Framework.Scenes // If we are using the the cached appearance then send it out to everyone if (cachedappearance) { - m_log.DebugFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); + m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); // If the avatars baked textures are all in the cache, then we have a // complete appearance... send it out, if not, then we'll send it when @@ -2970,7 +2976,7 @@ namespace OpenSim.Region.Framework.Scenes public void ChildAgentDataUpdate(AgentData cAgentData) { - //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); +// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); if (!IsChildAgent) return; @@ -3110,6 +3116,9 @@ namespace OpenSim.Region.Framework.Scenes m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; +// m_log.DebugFormat( +// "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", +// Name, m_scene.RegionInfo.RegionName, m_callbackURI); m_pos = cAgent.Position; m_velocity = cAgent.Velocity; diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index 8397eb4331..54b69a2c73 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -1261,14 +1261,20 @@ namespace OpenSim.Region.Physics.OdePlugin { m_requestedUpdateFrequency = ms; m_eventsubscription = ms; - CollisionEventsThisFrame.Clear(); + + // Don't clear collision event reporting here. This is called directly from scene code and so can lead + // to a race condition with the simulate loop + _parent_scene.AddCollisionEventReporting(this); } public override void UnSubscribeEvents() { CollisionEventsThisFrame.Clear(); - _parent_scene.RemoveCollisionEventReporting(this); + + // Don't clear collision event reporting here. This is called directly from scene code and so can lead + // to a race condition with the simulate loop + m_requestedUpdateFrequency = 0; m_eventsubscription = 0; } diff --git a/OpenSim/Tools/pCampBot/pCampBot.cs b/OpenSim/Tools/pCampBot/pCampBot.cs index 52e750185a..9e82577be5 100644 --- a/OpenSim/Tools/pCampBot/pCampBot.cs +++ b/OpenSim/Tools/pCampBot/pCampBot.cs @@ -29,6 +29,7 @@ using System; using System.Reflection; using System.Threading; using log4net; +using log4net.Config; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; @@ -52,6 +53,8 @@ namespace pCampBot [STAThread] public static void Main(string[] args) { + XmlConfigurator.Configure(); + IConfig config = ParseConfig(args); if (config.Get("help") != null || config.Get("loginuri") == null) { diff --git a/bin/pCampBot.exe.config b/bin/pCampBot.exe.config index 3f19ee855d..9cfb7e91e4 100644 --- a/bin/pCampBot.exe.config +++ b/bin/pCampBot.exe.config @@ -8,7 +8,7 @@ - +