diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 3b0430bed0..d73802e0b5 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1116,6 +1116,8 @@ namespace OpenSim.Framework /// void SendKillObject(List localID); + void SendPartFullUpdate(ISceneEntity ent, uint? parentID); + void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs index e4f1111e02..d6c39a78b1 100644 --- a/OpenSim/Framework/PriorityQueue.cs +++ b/OpenSim/Framework/PriorityQueue.cs @@ -62,7 +62,9 @@ namespace OpenSim.Framework private uint m_nextQueue = 0; private uint m_countFromQueue = 0; // first queues are imediate, so no counts - private uint[] m_queueCounts = {0, 0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1}; +// private uint[] m_queueCounts = { 0, 0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1 }; + private uint[] m_queueCounts = {0, 0, 8, 8, 5, 4, 3, 2, 1, 1, 1, 1}; + // this is ava, ava, attach, <10m, 20,40,80,160m,320,640,1280, + // next request is a counter of the number of updates queued, it provides // a total ordering on the updates coming through the queue and is more diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index b0cb4ea7a8..06f13015e3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3838,47 +3838,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); } - /// - /// Requeue an EntityUpdate when it was not acknowledged by the client. - /// We will update the priority and put it in the correct queue, merging update flags - /// with any other updates that may be queued for the same entity. - /// The original update time is used for the merged update. - /// - private void ResendPrimUpdate(EntityUpdate update) - { - // If the update exists in priority queue, it will be updated. - // If it does not exist then it will be added with the current (rather than its original) priority - uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); + /* dont use this + udp packet resent must be done at udp level only + re map from a packet to original updates just doesnt work - lock (m_entityUpdates.SyncRoot) - m_entityUpdates.Enqueue(priority, update); - } + /// + /// Requeue an EntityUpdate when it was not acknowledged by the client. + /// We will update the priority and put it in the correct queue, merging update flags + /// with any other updates that may be queued for the same entity. + /// The original update time is used for the merged update. + /// + private void ResendPrimUpdate(EntityUpdate update) + { + // If the update exists in priority queue, it will be updated. + // If it does not exist then it will be added with the current (rather than its original) priority + uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); - /// - /// Requeue a list of EntityUpdates when they were not acknowledged by the client. - /// We will update the priority and put it in the correct queue, merging update flags - /// with any other updates that may be queued for the same entity. - /// The original update time is used for the merged update. - /// - private void ResendPrimUpdates(List updates, OutgoingPacket oPacket) - { - // m_log.WarnFormat("[CLIENT] resending prim updates {0}, packet sequence number {1}", updates[0].UpdateTime, oPacket.SequenceNumber); + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Enqueue(priority, update); + } - // Remove the update packet from the list of packets waiting for acknowledgement - // because we are requeuing the list of updates. They will be resent in new packets - // with the most recent state and priority. - m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); - // Count this as a resent packet since we are going to requeue all of the updates contained in it - Interlocked.Increment(ref m_udpClient.PacketsResent); + /// + /// Requeue a list of EntityUpdates when they were not acknowledged by the client. + /// We will update the priority and put it in the correct queue, merging update flags + /// with any other updates that may be queued for the same entity. + /// The original update time is used for the merged update. + /// + private void ResendPrimUpdates(List updates, OutgoingPacket oPacket) + { + // m_log.WarnFormat("[CLIENT] resending prim updates {0}, packet sequence number {1}", updates[0].UpdateTime, oPacket.SequenceNumber); - // We're not going to worry about interlock yet since its not currently critical that this total count - // is 100% correct - m_udpServer.PacketsResentCount++; + // Remove the update packet from the list of packets waiting for acknowledgement + // because we are requeuing the list of updates. They will be resent in new packets + // with the most recent state and priority. + m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); - foreach (EntityUpdate update in updates) - ResendPrimUpdate(update); - } + // Count this as a resent packet since we are going to requeue all of the updates contained in it + Interlocked.Increment(ref m_udpClient.PacketsResent); + + // We're not going to worry about interlock yet since its not currently critical that this total count + // is 100% correct + m_udpServer.PacketsResentCount++; + + foreach (EntityUpdate update in updates) + ResendPrimUpdate(update); + } + */ // OpenSim.Framework.Lazy> objectUpdateBlocks = new OpenSim.Framework.Lazy>(); // OpenSim.Framework.Lazy> compressedUpdateBlocks = new OpenSim.Framework.Lazy>(); @@ -4197,12 +4203,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; - OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); +// OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); + // use default udp retry + OutPacket(packet, ThrottleOutPacketType.Task, true); } + + #endregion Packet Sending + } + // hack.. dont use + public void SendPartFullUpdate(ISceneEntity ent, uint? parentID) + { + if (ent is SceneObjectPart) + { + SceneObjectPart part = (SceneObjectPart)ent; + ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = 1; + packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + + ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, this.m_agentId); + if (parentID.HasValue) + { + blk.ParentID = parentID.Value; + } + + packet.ObjectData[0] = blk; + + OutPacket(packet, ThrottleOutPacketType.Task, true); + } + } + public void ReprioritizeUpdates() { lock (m_entityUpdates.SyncRoot) diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index 19d268943a..c0405adde4 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -175,7 +175,7 @@ namespace OpenSim.Region.Framework.Scenes { // Attachments are high priority, if (((SceneObjectPart)entity).ParentGroup.IsAttachment) - return 1; + return 2; pqueue = ComputeDistancePriority(client, entity, false); @@ -233,16 +233,28 @@ namespace OpenSim.Region.Framework.Scenes // And convert the distance to a priority queue, this computation gives queues // at 10, 20, 40, 80, 160, 320, 640, and 1280m - uint pqueue = PriorityQueue.NumberOfImmediateQueues; + uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; - +/* for (int i = 0; i < queues - 1; i++) { if (distance < 30 * Math.Pow(2.0,i)) break; pqueue++; } - +*/ + if (distance > 10f) + { + float tmp = (float)Math.Log((double)distance) * 1.4426950408889634073599246810019f - 3.3219280948873623478703194294894f; + // for a map identical to original: + // now + // 1st constant is 1/(log(2)) (natural log) so we get log2(distance) + // 2st constant makes it be log2(distance/10) + pqueue += (uint)tmp; + if (pqueue > queues - 1) + pqueue = queues - 1; + } + // If this is a root agent, then determine front & back // Bump up the priority queue (drop the priority) for any objects behind the avatar if (useFrontBack && ! presence.IsChildAgent) diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index dd0c828067..f5be7a7c64 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -295,6 +295,18 @@ namespace OpenSim.Region.Framework.Scenes return myID; } + + public uint AllocatePresenceLocalId() + { + uint myID; + + _primAllocateMutex.WaitOne(); + myID = ++m_lastAllocatedLocalId; + ++m_lastAllocatedLocalId; + _primAllocateMutex.ReleaseMutex(); + + return myID; + } #region Module Methods diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index a0c3ba985c..73283ed270 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -969,7 +969,7 @@ namespace OpenSim.Region.Framework.Scenes m_name = String.Format("{0} {1}", Firstname, Lastname); m_scene = world; m_uuid = client.AgentId; - LocalId = m_scene.AllocateLocalId(); + LocalId = m_scene.AllocatePresenceLocalId(); UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); if (account != null) @@ -1878,7 +1878,6 @@ namespace OpenSim.Region.Framework.Scenes if (!IsChildAgent) { - ValidateAndSendAppearanceAndAgentData(); m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts)); @@ -1900,35 +1899,31 @@ namespace OpenSim.Region.Framework.Scenes m_log.DebugFormat( "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); - List kk = new List(); - // Resume scripts this possible should also be moved down after sending the avatar to viewer ? foreach (SceneObjectGroup sog in m_attachments) { - foreach (SceneObjectPart part in sog.Parts) - kk.Add(part.LocalId); - sog.SendFullUpdateToClient(ControllingClient); SendFullUpdateToClient(ControllingClient); - // sog.ScheduleGroupForFullUpdate(); - m_scene.ForEachScenePresence(delegate(ScenePresence p) + if (!sog.HasPrivateAttachmentPoint) { - if (p == this) - return; - if (sog.HasPrivateAttachmentPoint) - return; - if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) - return; - - p.ControllingClient.SendKillObject(kk); - sog.SendFullUpdateToClient(p.ControllingClient); - SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path - }); - + // sog.ScheduleGroupForFullUpdate(); + m_scene.ForEachScenePresence(delegate(ScenePresence p) + { + if (p == this) + return; + + if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) + return; + + p.ControllingClient.SendPartFullUpdate(sog.RootPart,LocalId + 1); + sog.SendFullUpdateToClient(p.ControllingClient); + SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path + }); + } + sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); sog.ResumeScripts(); - kk.Clear(); } } } @@ -4752,12 +4747,18 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectGroup sog in m_attachments) { if (p == this || !sog.HasPrivateAttachmentPoint) + { + p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1); sog.SendFullUpdateToClient(p.ControllingClient); + } } SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path } } + // send attachments to a client without filters except for huds + // for now they are checked in several places down the line... + // kills all parts before sending public void SendAttachmentsToAgentNFPK(ScenePresence p) { lock (m_attachments) @@ -5680,7 +5681,7 @@ namespace OpenSim.Region.Framework.Scenes p.SendAppearanceToAgent(this); if (p.Animator != null) p.Animator.SendAnimPackToClient(ControllingClient); - p.SendAttachmentsToAgentNFPK(this); + p.SendAttachmentsToAgentNF(this); } } } @@ -5995,7 +5996,7 @@ namespace OpenSim.Region.Framework.Scenes SendAppearanceToAgent(p); if (Animator != null) Animator.SendAnimPackToClient(p.ControllingClient); - SendAttachmentsToAgentNFPK(p); + SendAttachmentsToAgentNF(p); } } @@ -6011,7 +6012,7 @@ namespace OpenSim.Region.Framework.Scenes p.SendAppearanceToAgent(this); if (p.Animator != null) p.Animator.SendAnimPackToClient(ControllingClient); - p.SendAttachmentsToAgentNFPK(this); + p.SendAttachmentsToAgentNF(this); } } } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index f35ea92caf..2112b718aa 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1702,5 +1702,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server { } + public void SendPartFullUpdate(ISceneEntity ent, uint? parentID) + { + } } } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 7002d75869..fa1d38a31f 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -1272,5 +1272,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } + public void SendPartFullUpdate(ISceneEntity ent, uint? parentID) + { + } + } } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index f3eaed3a2a..27580300d8 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -536,6 +536,10 @@ namespace OpenSim.Tests.Common.Mock ReceivedKills.AddRange(localID); } + public void SendPartFullUpdate(ISceneEntity ent, uint? parentID) + { + } + public virtual void SetChildAgentThrottle(byte[] throttle) { }