aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
authorMic Bowman2011-04-12 12:36:36 -0700
committerMic Bowman2011-04-12 12:36:36 -0700
commit095e602c4ac6da315f3f6711e24f034b6c490a02 (patch)
tree3d9d7dba1eda4184efed5293e6e7e0c7ada81e21 /OpenSim/Region/ClientStack
parentNew tokenbucket algorithm. This one provides fair sharing of the queues (diff)
downloadopensim-SC-095e602c4ac6da315f3f6711e24f034b6c490a02.zip
opensim-SC-095e602c4ac6da315f3f6711e24f034b6c490a02.tar.gz
opensim-SC-095e602c4ac6da315f3f6711e24f034b6c490a02.tar.bz2
opensim-SC-095e602c4ac6da315f3f6711e24f034b6c490a02.tar.xz
First pass at moving object property requests into a queue similar
to the entity update queue. The number of property packets can become significant when selecting/deselecting large numbers of objects. This is experimental code.
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs351
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs12
2 files changed, 220 insertions, 143 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 934a2d5..b96343e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -386,6 +386,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
386 386
387 private int m_cachedTextureSerial; 387 private int m_cachedTextureSerial;
388 private PriorityQueue m_entityUpdates; 388 private PriorityQueue m_entityUpdates;
389 private PriorityQueue m_entityProps;
389 private Prioritizer m_prioritizer; 390 private Prioritizer m_prioritizer;
390 private bool m_disableFacelights = false; 391 private bool m_disableFacelights = false;
391 392
@@ -433,9 +434,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
433 protected IAssetService m_assetService; 434 protected IAssetService m_assetService;
434 private const bool m_checkPackets = true; 435 private const bool m_checkPackets = true;
435 436
436 private Timer m_propertiesPacketTimer;
437 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
438
439 #endregion Class Members 437 #endregion Class Members
440 438
441 #region Properties 439 #region Properties
@@ -511,6 +509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
511 m_scene = scene; 509 m_scene = scene;
512 510
513 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 511 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
512 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
514 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 513 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
515 m_killRecord = new HashSet<uint>(); 514 m_killRecord = new HashSet<uint>();
516// m_attachmentsSent = new HashSet<uint>(); 515// m_attachmentsSent = new HashSet<uint>();
@@ -534,9 +533,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
534 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 533 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
535 m_udpClient.OnPacketStats += PopulateStats; 534 m_udpClient.OnPacketStats += PopulateStats;
536 535
537 m_propertiesPacketTimer = new Timer(100);
538 m_propertiesPacketTimer.Elapsed += ProcessObjectPropertiesPacket;
539
540 m_prioritizer = new Prioritizer(m_scene); 536 m_prioritizer = new Prioritizer(m_scene);
541 537
542 RegisterLocalPacketHandlers(); 538 RegisterLocalPacketHandlers();
@@ -3636,9 +3632,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3636 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); 3632 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3637 } 3633 }
3638 3634
3639 private Int32 m_LastQueueFill = 0;
3640 private uint m_maxUpdates = 0;
3641
3642 private void ProcessEntityUpdates(int maxUpdates) 3635 private void ProcessEntityUpdates(int maxUpdates)
3643 { 3636 {
3644 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3637 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3646,46 +3639,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3646 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3639 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3647 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3640 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3648 3641
3642 // Check to see if this is a flush
3649 if (maxUpdates <= 0) 3643 if (maxUpdates <= 0)
3650 { 3644 {
3651 m_maxUpdates = Int32.MaxValue; 3645 maxUpdates = Int32.MaxValue;
3652 } 3646 }
3653 else 3647
3654 {
3655 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
3656 {
3657 m_maxUpdates = (uint)maxUpdates;
3658 }
3659 else
3660 {
3661 if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
3662 m_maxUpdates += 5;
3663 else
3664 m_maxUpdates = m_maxUpdates >> 1;
3665 }
3666 m_maxUpdates = Util.Clamp<uint>(m_maxUpdates,10,500);
3667 }
3668 m_LastQueueFill = Util.EnvironmentTickCount();
3669
3670 int updatesThisCall = 0; 3648 int updatesThisCall = 0;
3671 3649
3672//<MIC>
3673// DEBUGGING CODE... REMOVE
3674// LogQueueProcessEvent(this.m_agentId,m_entityUpdates,m_maxUpdates);
3675//</MIC>
3676 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3650 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3677 // condition where a kill can be processed before an out-of-date update for the same object. 3651 // condition where a kill can be processed before an out-of-date update for the same object.
3678 lock (m_killRecord) 3652 lock (m_killRecord)
3679 { 3653 {
3680 float avgTimeDilation = 1.0f; 3654 float avgTimeDilation = 1.0f;
3681 EntityUpdate update; 3655 IEntityUpdate iupdate;
3682 Int32 timeinqueue; // this is just debugging code & can be dropped later 3656 Int32 timeinqueue; // this is just debugging code & can be dropped later
3683 3657
3684 while (updatesThisCall < m_maxUpdates) 3658 while (updatesThisCall < maxUpdates)
3685 { 3659 {
3686 lock (m_entityUpdates.SyncRoot) 3660 lock (m_entityUpdates.SyncRoot)
3687 if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) 3661 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3688 break; 3662 break;
3663
3664 EntityUpdate update = (EntityUpdate)iupdate;
3665
3689 avgTimeDilation += update.TimeDilation; 3666 avgTimeDilation += update.TimeDilation;
3690 avgTimeDilation *= 0.5f; 3667 avgTimeDilation *= 0.5f;
3691 3668
@@ -3725,7 +3702,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3725 3702
3726 #region UpdateFlags to packet type conversion 3703 #region UpdateFlags to packet type conversion
3727 3704
3728 PrimUpdateFlags updateFlags = update.Flags; 3705 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3729 3706
3730 bool canUseCompressed = true; 3707 bool canUseCompressed = true;
3731 bool canUseImproved = true; 3708 bool canUseImproved = true;
@@ -3804,6 +3781,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3804 3781
3805 #endregion Block Construction 3782 #endregion Block Construction
3806 } 3783 }
3784
3807 3785
3808 #region Packet Sending 3786 #region Packet Sending
3809 3787
@@ -3904,12 +3882,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3904 3882
3905 #endregion Primitive Packet/Data Sending Methods 3883 #endregion Primitive Packet/Data Sending Methods
3906 3884
3885 // These are used to implement an adaptive backoff in the number
3886 // of updates converted to packets. Since we don't want packets
3887 // to sit in the queue with old data, only convert enough updates
3888 // to packets that can be sent in 200ms.
3889 private Int32 m_LastQueueFill = 0;
3890 private Int32 m_maxUpdates = 0;
3891
3907 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 3892 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
3908 { 3893 {
3909 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) 3894 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
3910 { 3895 {
3896 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
3897 {
3898 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
3899 }
3900 else
3901 {
3902 if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
3903 m_maxUpdates += 5;
3904 else
3905 m_maxUpdates = m_maxUpdates >> 1;
3906 }
3907 m_maxUpdates = Util.Clamp<Int32>(m_maxUpdates,10,500);
3908 m_LastQueueFill = Util.EnvironmentTickCount();
3909
3911 if (m_entityUpdates.Count > 0) 3910 if (m_entityUpdates.Count > 0)
3912 ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback); 3911 ProcessEntityUpdates(m_maxUpdates);
3912
3913 if (m_entityProps.Count > 0)
3914 ProcessEntityPropertyRequests(m_maxUpdates);
3913 } 3915 }
3914 3916
3915 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) 3917 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
@@ -4023,134 +4025,192 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4023 OutPacket(pack, ThrottleOutPacketType.Task); 4025 OutPacket(pack, ThrottleOutPacketType.Task);
4024 } 4026 }
4025 4027
4026 public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, 4028/// -----------------------------------------------------------------
4027 uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, 4029/// <mic>
4028 uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, 4030/// -----------------------------------------------------------------
4029 UUID LastOwnerID, string ObjectName, string Description)
4030 {
4031 ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4032 // TODO: don't create new blocks if recycling an old packet
4033
4034 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
4035 objPropDB.RequestFlags = RequestFlags;
4036 objPropDB.ObjectID = ObjectUUID;
4037 if (OwnerID == GroupID)
4038 objPropDB.OwnerID = UUID.Zero;
4039 else
4040 objPropDB.OwnerID = OwnerID;
4041 objPropDB.GroupID = GroupID;
4042 objPropDB.BaseMask = BaseMask;
4043 objPropDB.OwnerMask = OwnerMask;
4044 objPropDB.GroupMask = GroupMask;
4045 objPropDB.EveryoneMask = EveryoneMask;
4046 objPropDB.NextOwnerMask = NextOwnerMask;
4047 4031
4048 // TODO: More properties are needed in SceneObjectPart! 4032 private class ObjectPropertyUpdate : IEntityUpdate
4049 objPropDB.OwnershipCost = OwnershipCost;
4050 objPropDB.SaleType = SaleType;
4051 objPropDB.SalePrice = SalePrice;
4052 objPropDB.Category = Category;
4053 objPropDB.LastOwnerID = LastOwnerID;
4054 objPropDB.Name = Util.StringToBytes256(ObjectName);
4055 objPropDB.Description = Util.StringToBytes256(Description);
4056 objPropFamilyPack.ObjectData = objPropDB;
4057 objPropFamilyPack.Header.Zerocoded = true;
4058 OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task);
4059 }
4060
4061 public void SendObjectPropertiesReply(
4062 UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID,
4063 UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID,
4064 UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName,
4065 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask,
4066 uint BaseMask, byte saleType, int salePrice)
4067 { 4033 {
4068 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 4034 internal bool SendFamilyProps;
4069 // TODO: don't create new blocks if recycling an old packet 4035
4036 public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam)
4037 : base(entity,flags)
4038 {
4039 SendFamilyProps = sendfam;
4040 }
4041 }
4042
4043 public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags)
4044 {
4045 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
4046 lock (m_entityProps.SyncRoot)
4047 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true));
4048 }
4070 4049
4071 ObjectPropertiesPacket.ObjectDataBlock block = 4050 public void SendObjectPropertiesReply(ISceneEntity entity)
4072 new ObjectPropertiesPacket.ObjectDataBlock(); 4051 {
4052 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
4053 lock (m_entityProps.SyncRoot)
4054 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false));
4055 }
4073 4056
4074 block.ItemID = ItemID; 4057 private void ProcessEntityPropertyRequests(int maxUpdates)
4075 block.CreationDate = CreationDate; 4058 {
4076 block.CreatorID = CreatorUUID; 4059 OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>> objectFamilyBlocks =
4077 block.FolderID = FolderUUID; 4060 new OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>>();
4078 block.FromTaskID = FromTaskUUID;
4079 block.GroupID = GroupUUID;
4080 block.InventorySerial = InventorySerial;
4081 4061
4082 block.LastOwnerID = LastOwnerUUID; 4062 OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
4083 // proper.ObjectData[0].LastOwnerID = UUID.Zero; 4063 new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
4084 4064
4085 block.ObjectID = ObjectUUID; 4065 IEntityUpdate iupdate;
4086 if (OwnerUUID == GroupUUID) 4066 Int32 timeinqueue; // this is just debugging code & can be dropped later
4087 block.OwnerID = UUID.Zero;
4088 else
4089 block.OwnerID = OwnerUUID;
4090 block.TouchName = Util.StringToBytes256(TouchTitle);
4091 block.TextureID = TextureID;
4092 block.SitName = Util.StringToBytes256(SitTitle);
4093 block.Name = Util.StringToBytes256(ItemName);
4094 block.Description = Util.StringToBytes256(ItemDescription);
4095 block.OwnerMask = OwnerMask;
4096 block.NextOwnerMask = NextOwnerMask;
4097 block.GroupMask = GroupMask;
4098 block.EveryoneMask = EveryoneMask;
4099 block.BaseMask = BaseMask;
4100 // proper.ObjectData[0].AggregatePerms = 53;
4101 // proper.ObjectData[0].AggregatePermTextures = 0;
4102 // proper.ObjectData[0].AggregatePermTexturesOwner = 0;
4103 block.SaleType = saleType;
4104 block.SalePrice = salePrice;
4105 4067
4106 lock (m_propertiesPacketTimer) 4068 int updatesThisCall = 0;
4069 while (updatesThisCall < m_maxUpdates)
4107 { 4070 {
4108 m_propertiesBlocks.Add(block); 4071 lock (m_entityProps.SyncRoot)
4072 if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue))
4073 break;
4109 4074
4110 int length = 0; 4075 ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate;
4111 foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) 4076 if (update.SendFamilyProps)
4112 { 4077 {
4113 length += b.Length; 4078 if (update.Entity is SceneObjectPart)
4079 {
4080 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4081 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
4082 objectFamilyBlocks.Value.Add(objPropDB);
4083 }
4114 } 4084 }
4115 if (length > 1100) // FIXME: use real MTU 4085 else
4116 { 4086 {
4117 ProcessObjectPropertiesPacket(null, null); 4087 if (update.Entity is SceneObjectPart)
4118 m_propertiesPacketTimer.Stop(); 4088 {
4119 return; 4089 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4090 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
4091 objectPropertiesBlocks.Value.Add(objPropDB);
4092 }
4120 } 4093 }
4094 }
4095
4096
4097 if (objectPropertiesBlocks.IsValueCreated)
4098 {
4099 List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
4121 4100
4122 m_propertiesPacketTimer.Stop(); 4101 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4123 m_propertiesPacketTimer.Start(); 4102 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
4103 for (int i = 0; i < blocks.Count; i++)
4104 packet.ObjectData[i] = blocks[i];
4105
4106 packet.Header.Zerocoded = true;
4107 OutPacket(packet, ThrottleOutPacketType.Task, true);
4124 } 4108 }
4109
4110
4111 if (objectFamilyBlocks.IsValueCreated)
4112 {
4113 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
4114
4115 // ObjectPropertiesFamilyPacket objPropFamilyPack =
4116 // (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4117 //
4118 // objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count];
4119 // for (int i = 0; i < blocks.Count; i++)
4120 // objPropFamilyPack.ObjectData[i] = blocks[i];
4121 //
4122 // OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true);
4123
4124 // one packet per object block... uggh...
4125 for (int i = 0; i < blocks.Count; i++)
4126 {
4127 ObjectPropertiesFamilyPacket packet =
4128 (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4125 4129
4126 //proper.Header.Zerocoded = true; 4130 packet.ObjectData = blocks[i];
4127 //OutPacket(proper, ThrottleOutPacketType.Task); 4131 packet.Header.Zerocoded = true;
4132 OutPacket(packet, ThrottleOutPacketType.Task);
4133 }
4134
4135 }
4136
4128 } 4137 }
4129 4138
4130 private void ProcessObjectPropertiesPacket(Object sender, ElapsedEventArgs e) 4139 private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, uint requestFlags)
4131 { 4140 {
4132 ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 4141 ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
4133 4142
4134 lock (m_propertiesPacketTimer) 4143 block.RequestFlags = requestFlags;
4135 { 4144 block.ObjectID = sop.UUID;
4136 m_propertiesPacketTimer.Stop(); 4145 if (sop.OwnerID == sop.GroupID)
4146 block.OwnerID = UUID.Zero;
4147 else
4148 block.OwnerID = sop.OwnerID;
4149 block.GroupID = sop.GroupID;
4150 block.BaseMask = sop.BaseMask;
4151 block.OwnerMask = sop.OwnerMask;
4152 block.GroupMask = sop.GroupMask;
4153 block.EveryoneMask = sop.EveryoneMask;
4154 block.NextOwnerMask = sop.NextOwnerMask;
4137 4155
4138 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4156 // TODO: More properties are needed in SceneObjectPart!
4157 block.OwnershipCost = sop.OwnershipCost;
4158 block.SaleType = sop.ObjectSaleType;
4159 block.SalePrice = sop.SalePrice;
4160 block.Category = sop.Category;
4161 block.LastOwnerID = sop.CreatorID; // copied from old SOG call... is this right?
4162 block.Name = Util.StringToBytes256(sop.Name);
4163 block.Description = Util.StringToBytes256(sop.Description);
4139 4164
4140 int index = 0; 4165 return block;
4166 }
4141 4167
4142 foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) 4168 private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
4143 { 4169 {
4144 proper.ObjectData[index++] = b; 4170 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4145 } 4171 // TODO: don't create new blocks if recycling an old packet
4146 4172
4147 m_propertiesBlocks.Clear(); 4173 ObjectPropertiesPacket.ObjectDataBlock block =
4148 } 4174 new ObjectPropertiesPacket.ObjectDataBlock();
4175
4176 block.ObjectID = sop.UUID;
4177 block.Name = Util.StringToBytes256(sop.Name);
4178 block.Description = Util.StringToBytes256(sop.Description);
4149 4179
4150 proper.Header.Zerocoded = true; 4180 block.CreationDate = (ulong)sop.CreationDate * 1000000; // viewer wants date in microseconds
4151 OutPacket(proper, ThrottleOutPacketType.Task); 4181 block.CreatorID = sop.CreatorID;
4182 block.GroupID = sop.GroupID;
4183 block.LastOwnerID = sop.LastOwnerID;
4184 if (sop.OwnerID == sop.GroupID)
4185 block.OwnerID = UUID.Zero;
4186 else
4187 block.OwnerID = sop.OwnerID;
4188
4189 block.ItemID = sop.FromUserInventoryItemID;
4190 block.FolderID = UUID.Zero; // sop.FromFolderID ??
4191 block.FromTaskID = UUID.Zero; // ???
4192 block.InventorySerial = (short)sop.InventorySerial;
4193
4194 SceneObjectPart root = sop.ParentGroup.RootPart;
4195
4196 block.TouchName = Util.StringToBytes256(root.TouchName);
4197 block.TextureID = new byte[0]; // TextureID ???
4198 block.SitName = Util.StringToBytes256(root.SitName);
4199 block.OwnerMask = root.OwnerMask;
4200 block.NextOwnerMask = root.NextOwnerMask;
4201 block.GroupMask = root.GroupMask;
4202 block.EveryoneMask = root.EveryoneMask;
4203 block.BaseMask = root.BaseMask;
4204 block.SaleType = root.ObjectSaleType;
4205 block.SalePrice = root.SalePrice;
4206
4207 return block;
4152 } 4208 }
4153 4209
4210/// -----------------------------------------------------------------
4211/// </mic>
4212/// -----------------------------------------------------------------
4213
4154 #region Estate Data Sending Methods 4214 #region Estate Data Sending Methods
4155 4215
4156 private static bool convertParamStringToBool(byte[] field) 4216 private static bool convertParamStringToBool(byte[] field)
@@ -4482,6 +4542,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4482 4542
4483 public void SendForceClientSelectObjects(List<uint> ObjectIDs) 4543 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4484 { 4544 {
4545 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4546
4485 bool firstCall = true; 4547 bool firstCall = true;
4486 const int MAX_OBJECTS_PER_PACKET = 251; 4548 const int MAX_OBJECTS_PER_PACKET = 251;
4487 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); 4549 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
@@ -11374,6 +11436,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11374 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); 11436 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
11375 } 11437 }
11376 11438
11439 if (throttlePacketType == ThrottleOutPacketType.Task)
11440 {
11441 System.Diagnostics.StackTrace stackTrace = new System.Diagnostics.StackTrace(); // get call stack
11442 System.Diagnostics.StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
11443
11444 string stack = "";
11445 for (int count = 1; count < stackFrames.Length; count++)
11446 {
11447 stack += (stack == "" ? "" : ",") + stackFrames[count].GetMethod().Name;
11448 if (count > 5) break;
11449 }
11450
11451 // m_log.WarnFormat("[BADGUY] {0}", stack);
11452 }
11453
11377 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); 11454 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting);
11378 } 11455 }
11379 11456
diff --git a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
index 364ce4b..6521a00 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
78 } 78 }
79 } 79 }
80 80
81 public bool Enqueue(uint pqueue, EntityUpdate value) 81 public bool Enqueue(uint pqueue, IEntityUpdate value)
82 { 82 {
83 LookupItem lookup; 83 LookupItem lookup;
84 84
@@ -99,7 +99,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
99 return true; 99 return true;
100 } 100 }
101 101
102 internal bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue) 102 internal bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
103 { 103 {
104 for (int i = 0; i < m_numberOfQueues; ++i) 104 for (int i = 0; i < m_numberOfQueues; ++i)
105 { 105 {
@@ -122,7 +122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
122 } 122 }
123 123
124 timeinqueue = 0; 124 timeinqueue = 0;
125 value = default(EntityUpdate); 125 value = default(IEntityUpdate);
126 return false; 126 return false;
127 } 127 }
128 128
@@ -175,8 +175,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
175#region MinHeapItem 175#region MinHeapItem
176 private struct MinHeapItem : IComparable<MinHeapItem> 176 private struct MinHeapItem : IComparable<MinHeapItem>
177 { 177 {
178 private EntityUpdate value; 178 private IEntityUpdate value;
179 internal EntityUpdate Value { 179 internal IEntityUpdate Value {
180 get { 180 get {
181 return this.value; 181 return this.value;
182 } 182 }
@@ -212,7 +212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
212 this.pqueue = pqueue; 212 this.pqueue = pqueue;
213 } 213 }
214 214
215 internal MinHeapItem(uint pqueue, UInt64 entryorder, EntityUpdate value) 215 internal MinHeapItem(uint pqueue, UInt64 entryorder, IEntityUpdate value)
216 { 216 {
217 this.entrytime = Util.EnvironmentTickCount(); 217 this.entrytime = Util.EnvironmentTickCount();
218 this.entryorder = entryorder; 218 this.entryorder = entryorder;