aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
authorBlueWall2011-04-13 09:53:44 -0400
committerBlueWall2011-04-13 09:53:44 -0400
commitd3457eae7a33f01a8fa906c4040792cdc4a67857 (patch)
treef92e60733b8397576b86c486e05aa5219f27d034 /OpenSim/Region/ClientStack
parentMerge branch 'master' of /home/opensim/src/OpenSim/Core (diff)
parentMove example HttpProxy setting to OpenSim.ini.example and tidy (diff)
downloadopensim-SC_OLD-d3457eae7a33f01a8fa906c4040792cdc4a67857.zip
opensim-SC_OLD-d3457eae7a33f01a8fa906c4040792cdc4a67857.tar.gz
opensim-SC_OLD-d3457eae7a33f01a8fa906c4040792cdc4a67857.tar.bz2
opensim-SC_OLD-d3457eae7a33f01a8fa906c4040792cdc4a67857.tar.xz
Merge branch 'master' of /home/git/repo/OpenSim
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs415
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs245
4 files changed, 424 insertions, 244 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 2c6795f..8de31d7 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -49,6 +49,8 @@ using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using Nini.Config; 50using Nini.Config;
51 51
52using System.IO;
53
52namespace OpenSim.Region.ClientStack.LindenUDP 54namespace OpenSim.Region.ClientStack.LindenUDP
53{ 55{
54 public delegate bool PacketMethod(IClientAPI simClient, Packet packet); 56 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
@@ -298,6 +300,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP
298 /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary> 300 /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
299 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; 301 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
300 302
303 // First log file or time has expired, start writing to a new log file
304//<MIC>
305// -----------------------------------------------------------------
306// -----------------------------------------------------------------
307// THIS IS DEBUGGING CODE & SHOULD BE REMOVED
308// -----------------------------------------------------------------
309// -----------------------------------------------------------------
310 public class QueueLogger
311 {
312 public Int32 start = 0;
313 public StreamWriter Log = null;
314 private Dictionary<UUID,int> m_idMap = new Dictionary<UUID,int>();
315
316 public QueueLogger()
317 {
318 DateTime now = DateTime.Now;
319 String fname = String.Format("queue-{0}.log", now.ToString("yyyyMMddHHmmss"));
320 Log = new StreamWriter(fname);
321
322 start = Util.EnvironmentTickCount();
323 }
324
325 public int LookupID(UUID uuid)
326 {
327 int localid;
328 if (! m_idMap.TryGetValue(uuid,out localid))
329 {
330 localid = m_idMap.Count + 1;
331 m_idMap[uuid] = localid;
332 }
333
334 return localid;
335 }
336 }
337
338 public static QueueLogger QueueLog = null;
339
340 // -----------------------------------------------------------------
341 public void LogAvatarUpdateEvent(UUID client, UUID avatar, Int32 timeinqueue)
342 {
343 if (QueueLog == null)
344 QueueLog = new QueueLogger();
345
346 Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
347 lock(QueueLog)
348 {
349 int cid = QueueLog.LookupID(client);
350 int aid = QueueLog.LookupID(avatar);
351 QueueLog.Log.WriteLine("{0},AU,AV{1:D4},AV{2:D4},{3}",ticks,cid,aid,timeinqueue);
352 }
353 }
354
355 // -----------------------------------------------------------------
356 public void LogQueueProcessEvent(UUID client, PriorityQueue queue, uint maxup)
357 {
358 if (QueueLog == null)
359 QueueLog = new QueueLogger();
360
361 Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
362 lock(QueueLog)
363 {
364 int cid = QueueLog.LookupID(client);
365 QueueLog.Log.WriteLine("{0},PQ,AV{1:D4},{2},{3}",ticks,cid,maxup,queue.ToString());
366 }
367 }
368// -----------------------------------------------------------------
369// -----------------------------------------------------------------
370// -----------------------------------------------------------------
371// -----------------------------------------------------------------
372//</MIC>
373
301 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 374 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
302 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients 375 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
303 376
@@ -3547,18 +3620,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3547 3620
3548 #region Primitive Packet/Data Sending Methods 3621 #region Primitive Packet/Data Sending Methods
3549 3622
3623
3550 /// <summary> 3624 /// <summary>
3551 /// Generate one of the object update packets based on PrimUpdateFlags 3625 /// Generate one of the object update packets based on PrimUpdateFlags
3552 /// and broadcast the packet to clients 3626 /// and broadcast the packet to clients
3553 /// </summary> 3627 /// </summary>
3554 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3628 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3555 { 3629 {
3556 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3630 //double priority = m_prioritizer.GetUpdatePriority(this, entity);
3631 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3557 3632
3558 lock (m_entityUpdates.SyncRoot) 3633 lock (m_entityUpdates.SyncRoot)
3559 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation), entity.LocalId); 3634 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3560 } 3635 }
3561 3636
3637 private Int32 m_LastQueueFill = 0;
3638 private uint m_maxUpdates = 0;
3639
3562 private void ProcessEntityUpdates(int maxUpdates) 3640 private void ProcessEntityUpdates(int maxUpdates)
3563 { 3641 {
3564 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3642 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3566,19 +3644,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3566 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3644 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3567 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3645 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3568 3646
3569 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; 3647 if (maxUpdates <= 0)
3648 {
3649 m_maxUpdates = Int32.MaxValue;
3650 }
3651 else
3652 {
3653 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
3654 {
3655 m_maxUpdates = (uint)maxUpdates;
3656 }
3657 else
3658 {
3659 if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
3660 m_maxUpdates += 5;
3661 else
3662 m_maxUpdates = m_maxUpdates >> 1;
3663 }
3664 m_maxUpdates = Util.Clamp<uint>(m_maxUpdates,10,500);
3665 }
3666 m_LastQueueFill = Util.EnvironmentTickCount();
3667
3570 int updatesThisCall = 0; 3668 int updatesThisCall = 0;
3571 3669
3670//<MIC>
3671// DEBUGGING CODE... REMOVE
3672// LogQueueProcessEvent(this.m_agentId,m_entityUpdates,m_maxUpdates);
3673//</MIC>
3572 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3674 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3573 // condition where a kill can be processed before an out-of-date update for the same object. 3675 // condition where a kill can be processed before an out-of-date update for the same object.
3574 lock (m_killRecord) 3676 lock (m_killRecord)
3575 { 3677 {
3576 float avgTimeDilation = 1.0f; 3678 float avgTimeDilation = 1.0f;
3577 EntityUpdate update; 3679 EntityUpdate update;
3578 while (updatesThisCall < maxUpdates) 3680 Int32 timeinqueue; // this is just debugging code & can be dropped later
3681
3682 while (updatesThisCall < m_maxUpdates)
3579 { 3683 {
3580 lock (m_entityUpdates.SyncRoot) 3684 lock (m_entityUpdates.SyncRoot)
3581 if (!m_entityUpdates.TryDequeue(out update)) 3685 if (!m_entityUpdates.TryDequeue(out update, out timeinqueue))
3582 break; 3686 break;
3583 avgTimeDilation += update.TimeDilation; 3687 avgTimeDilation += update.TimeDilation;
3584 avgTimeDilation *= 0.5f; 3688 avgTimeDilation *= 0.5f;
@@ -3679,36 +3783,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3679 } 3783 }
3680 else 3784 else
3681 { 3785 {
3682 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment) 3786 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3683 // {
3684 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3685 // string text = sop.Text;
3686 // if (text.IndexOf("\n") >= 0)
3687 // text = text.Remove(text.IndexOf("\n"));
3688 //
3689 // if (m_attachmentsSent.Contains(sop.ParentID))
3690 // {
3691 //// m_log.DebugFormat(
3692 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3693 //// sop.LocalId, text);
3694 //
3695 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3696 //
3697 // m_attachmentsSent.Add(sop.LocalId);
3698 // }
3699 // else
3700 // {
3701 // m_log.DebugFormat(
3702 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3703 // sop.LocalId, text, sop.ParentID);
3704 //
3705 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3706 // }
3707 // }
3708 // else
3709 // {
3710 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3711 // }
3712 } 3787 }
3713 } 3788 }
3714 else if (!canUseImproved) 3789 else if (!canUseImproved)
@@ -3802,26 +3877,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3802 3877
3803 public void ReprioritizeUpdates() 3878 public void ReprioritizeUpdates()
3804 { 3879 {
3805 //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
3806
3807 lock (m_entityUpdates.SyncRoot) 3880 lock (m_entityUpdates.SyncRoot)
3808 m_entityUpdates.Reprioritize(UpdatePriorityHandler); 3881 m_entityUpdates.Reprioritize(UpdatePriorityHandler);
3809 } 3882 }
3810 3883
3811 private bool UpdatePriorityHandler(ref double priority, uint localID) 3884 private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)
3812 { 3885 {
3813 EntityBase entity; 3886 if (entity != null)
3814 if (m_scene.Entities.TryGetValue(localID, out entity))
3815 { 3887 {
3816 priority = m_prioritizer.GetUpdatePriority(this, entity); 3888 priority = m_prioritizer.GetUpdatePriority(this, entity);
3889 return true;
3817 } 3890 }
3818 3891
3819 return priority != double.NaN; 3892 return false;
3820 } 3893 }
3821 3894
3822 public void FlushPrimUpdates() 3895 public void FlushPrimUpdates()
3823 { 3896 {
3824 m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName); 3897 m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
3825 3898
3826 while (m_entityUpdates.Count > 0) 3899 while (m_entityUpdates.Count > 0)
3827 ProcessEntityUpdates(-1); 3900 ProcessEntityUpdates(-1);
@@ -4272,8 +4345,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4272 OutPacket(packet, ThrottleOutPacketType.Task); 4345 OutPacket(packet, ThrottleOutPacketType.Task);
4273 } 4346 }
4274 4347
4275 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) 4348 public void SendLandProperties(
4349 int sequence_id, bool snap_selection, int request_result, ILandObject lo,
4350 float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags)
4276 { 4351 {
4352// m_log.DebugFormat("[LLCLIENTVIEW]: Sending land properties for {0} to {1}", lo.LandData.GlobalID, Name);
4353
4354 LandData landData = lo.LandData;
4355
4277 ParcelPropertiesMessage updateMessage = new ParcelPropertiesMessage(); 4356 ParcelPropertiesMessage updateMessage = new ParcelPropertiesMessage();
4278 4357
4279 updateMessage.AABBMax = landData.AABBMax; 4358 updateMessage.AABBMax = landData.AABBMax;
@@ -4281,15 +4360,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4281 updateMessage.Area = landData.Area; 4360 updateMessage.Area = landData.Area;
4282 updateMessage.AuctionID = landData.AuctionID; 4361 updateMessage.AuctionID = landData.AuctionID;
4283 updateMessage.AuthBuyerID = landData.AuthBuyerID; 4362 updateMessage.AuthBuyerID = landData.AuthBuyerID;
4284
4285 updateMessage.Bitmap = landData.Bitmap; 4363 updateMessage.Bitmap = landData.Bitmap;
4286
4287 updateMessage.Desc = landData.Description; 4364 updateMessage.Desc = landData.Description;
4288 updateMessage.Category = landData.Category; 4365 updateMessage.Category = landData.Category;
4289 updateMessage.ClaimDate = Util.ToDateTime(landData.ClaimDate); 4366 updateMessage.ClaimDate = Util.ToDateTime(landData.ClaimDate);
4290 updateMessage.ClaimPrice = landData.ClaimPrice; 4367 updateMessage.ClaimPrice = landData.ClaimPrice;
4291 updateMessage.GroupID = landData.GroupID; 4368 updateMessage.GroupID = landData.GroupID;
4292 updateMessage.GroupPrims = landData.GroupPrims;
4293 updateMessage.IsGroupOwned = landData.IsGroupOwned; 4369 updateMessage.IsGroupOwned = landData.IsGroupOwned;
4294 updateMessage.LandingType = (LandingType) landData.LandingType; 4370 updateMessage.LandingType = (LandingType) landData.LandingType;
4295 updateMessage.LocalID = landData.LocalID; 4371 updateMessage.LocalID = landData.LocalID;
@@ -4310,9 +4386,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4310 updateMessage.Name = landData.Name; 4386 updateMessage.Name = landData.Name;
4311 updateMessage.OtherCleanTime = landData.OtherCleanTime; 4387 updateMessage.OtherCleanTime = landData.OtherCleanTime;
4312 updateMessage.OtherCount = 0; //TODO: Unimplemented 4388 updateMessage.OtherCount = 0; //TODO: Unimplemented
4313 updateMessage.OtherPrims = landData.OtherPrims; 4389 updateMessage.OwnerID = landData.OwnerID;
4314 updateMessage.OwnerID = landData.OwnerID;
4315 updateMessage.OwnerPrims = landData.OwnerPrims;
4316 updateMessage.ParcelFlags = (ParcelFlags) landData.Flags; 4390 updateMessage.ParcelFlags = (ParcelFlags) landData.Flags;
4317 updateMessage.ParcelPrimBonus = simObjectBonusFactor; 4391 updateMessage.ParcelPrimBonus = simObjectBonusFactor;
4318 updateMessage.PassHours = landData.PassHours; 4392 updateMessage.PassHours = landData.PassHours;
@@ -4327,10 +4401,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4327 4401
4328 updateMessage.RentPrice = 0; 4402 updateMessage.RentPrice = 0;
4329 updateMessage.RequestResult = (ParcelResult) request_result; 4403 updateMessage.RequestResult = (ParcelResult) request_result;
4330 updateMessage.SalePrice = landData.SalePrice; 4404 updateMessage.SalePrice = landData.SalePrice;
4331 updateMessage.SelectedPrims = landData.SelectedPrims;
4332 updateMessage.SelfCount = 0; //TODO: Unimplemented 4405 updateMessage.SelfCount = 0; //TODO: Unimplemented
4333 updateMessage.SequenceID = sequence_id; 4406 updateMessage.SequenceID = sequence_id;
4407
4334 if (landData.SimwideArea > 0) 4408 if (landData.SimwideArea > 0)
4335 { 4409 {
4336 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4410 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
@@ -4340,22 +4414,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4340 { 4414 {
4341 updateMessage.SimWideMaxPrims = 0; 4415 updateMessage.SimWideMaxPrims = 0;
4342 } 4416 }
4343 updateMessage.SimWideTotalPrims = landData.SimwidePrims; 4417
4344 updateMessage.SnapSelection = snap_selection; 4418 updateMessage.SnapSelection = snap_selection;
4345 updateMessage.SnapshotID = landData.SnapshotID; 4419 updateMessage.SnapshotID = landData.SnapshotID;
4346 updateMessage.Status = (ParcelStatus) landData.Status; 4420 updateMessage.Status = (ParcelStatus) landData.Status;
4347 updateMessage.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims + 4421 updateMessage.UserLocation = landData.UserLocation;
4348 landData.SelectedPrims; 4422 updateMessage.UserLookAt = landData.UserLookAt;
4349 updateMessage.UserLocation = landData.UserLocation; 4423
4350 updateMessage.UserLookAt = landData.UserLookAt; 4424 updateMessage.MediaType = landData.MediaType;
4351 4425 updateMessage.MediaDesc = landData.MediaDescription;
4352 updateMessage.MediaType = landData.MediaType; 4426 updateMessage.MediaWidth = landData.MediaWidth;
4353 updateMessage.MediaDesc = landData.MediaDescription; 4427 updateMessage.MediaHeight = landData.MediaHeight;
4354 updateMessage.MediaWidth = landData.MediaWidth; 4428 updateMessage.MediaLoop = landData.MediaLoop;
4355 updateMessage.MediaHeight = landData.MediaHeight; 4429 updateMessage.ObscureMusic = landData.ObscureMusic;
4356 updateMessage.MediaLoop = landData.MediaLoop; 4430 updateMessage.ObscureMedia = landData.ObscureMedia;
4357 updateMessage.ObscureMusic = landData.ObscureMusic; 4431
4358 updateMessage.ObscureMedia = landData.ObscureMedia; 4432 IPrimCounts pc = lo.PrimCounts;
4433 updateMessage.OwnerPrims = pc.Owner;
4434 updateMessage.GroupPrims = pc.Group;
4435 updateMessage.OtherPrims = pc.Others;
4436 updateMessage.SelectedPrims = pc.Selected;
4437 updateMessage.TotalPrims = pc.Total;
4438 updateMessage.SimWideTotalPrims = pc.Simulator;
4359 4439
4360 try 4440 try
4361 { 4441 {
@@ -4363,13 +4443,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4363 if (eq != null) 4443 if (eq != null)
4364 { 4444 {
4365 eq.ParcelProperties(updateMessage, this.AgentId); 4445 eq.ParcelProperties(updateMessage, this.AgentId);
4366 } else { 4446 }
4367 m_log.Warn("No EQ Interface when sending parcel data."); 4447 else
4448 {
4449 m_log.Warn("[LLCLIENTVIEW]: No EQ Interface when sending parcel data.");
4368 } 4450 }
4369 } 4451 }
4370 catch (Exception ex) 4452 catch (Exception ex)
4371 { 4453 {
4372 m_log.Error("Unable to send parcel data via eventqueue - exception: " + ex.ToString()); 4454 m_log.Error("[LLCLIENTVIEW]: Unable to send parcel data via eventqueue - exception: " + ex.ToString());
4373 } 4455 }
4374 } 4456 }
4375 4457
@@ -4929,7 +5011,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4929 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); 5011 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
4930 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); 5012 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false);
4931 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); 5013 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest);
4932 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest, false); 5014 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest);
4933 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); 5015 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false);
4934 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false); 5016 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false);
4935 AddLocalPacketHandler(PacketType.ParcelPropertiesRequest, HandleParcelPropertiesRequest, false); 5017 AddLocalPacketHandler(PacketType.ParcelPropertiesRequest, HandleParcelPropertiesRequest, false);
@@ -8800,13 +8882,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8800 case "instantmessage": 8882 case "instantmessage":
8801 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 8883 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
8802 { 8884 {
8803 if (messagePacket.ParamList.Length < 5) 8885 if (messagePacket.ParamList.Length < 2)
8804 return true; 8886 return true;
8887
8805 UUID invoice = messagePacket.MethodData.Invoice; 8888 UUID invoice = messagePacket.MethodData.Invoice;
8806 UUID SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
8807 string SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
8808 string Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
8809 UUID sessionID = messagePacket.AgentData.SessionID; 8889 UUID sessionID = messagePacket.AgentData.SessionID;
8890
8891 UUID SenderID;
8892 string SenderName;
8893 string Message;
8894
8895 if (messagePacket.ParamList.Length < 5)
8896 {
8897 SenderID = AgentId;
8898 SenderName = Utils.BytesToString(messagePacket.ParamList[0].Parameter);
8899 Message = Utils.BytesToString(messagePacket.ParamList[1].Parameter);
8900 }
8901 else
8902 {
8903 SenderID = new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
8904 SenderName = Utils.BytesToString(messagePacket.ParamList[3].Parameter);
8905 Message = Utils.BytesToString(messagePacket.ParamList[4].Parameter);
8906 }
8907
8810 OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message); 8908 OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message);
8811 } 8909 }
8812 return true; 8910 return true;
@@ -11701,171 +11799,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11701 OutPacket(pack, ThrottleOutPacketType.Task); 11799 OutPacket(pack, ThrottleOutPacketType.Task);
11702 } 11800 }
11703 11801
11704 #region PriorityQueue
11705 public class PriorityQueue
11706 {
11707 internal delegate bool UpdatePriorityHandler(ref double priority, uint local_id);
11708
11709 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
11710 private Dictionary<uint, LookupItem> m_lookupTable;
11711 private Comparison<double> m_comparison;
11712 private object m_syncRoot = new object();
11713
11714 internal PriorityQueue() :
11715 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<double>.Default) { }
11716 internal PriorityQueue(int capacity) :
11717 this(capacity, Comparer<double>.Default) { }
11718 internal PriorityQueue(IComparer<double> comparer) :
11719 this(new Comparison<double>(comparer.Compare)) { }
11720 internal PriorityQueue(Comparison<double> comparison) :
11721 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
11722 internal PriorityQueue(int capacity, IComparer<double> comparer) :
11723 this(capacity, new Comparison<double>(comparer.Compare)) { }
11724 internal PriorityQueue(int capacity, Comparison<double> comparison)
11725 {
11726 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
11727
11728 for (int i = 0; i < m_heaps.Length; ++i)
11729 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
11730 this.m_comparison = comparison;
11731 }
11732
11733 public object SyncRoot { get { return this.m_syncRoot; } }
11734 internal int Count
11735 {
11736 get
11737 {
11738 int count = 0;
11739 for (int i = 0; i < m_heaps.Length; ++i)
11740 count = m_heaps[i].Count;
11741 return count;
11742 }
11743 }
11744
11745 public bool Enqueue(double priority, EntityUpdate value, uint local_id)
11746 {
11747 LookupItem item;
11748
11749 if (m_lookupTable.TryGetValue(local_id, out item))
11750 {
11751 // Combine flags
11752 value.Flags |= item.Heap[item.Handle].Value.Flags;
11753
11754 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
11755 return false;
11756 }
11757 else
11758 {
11759 item.Heap = m_heaps[0];
11760 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
11761 m_lookupTable.Add(local_id, item);
11762 return true;
11763 }
11764 }
11765
11766 internal EntityUpdate Peek()
11767 {
11768 for (int i = 0; i < m_heaps.Length; ++i)
11769 if (m_heaps[i].Count > 0)
11770 return m_heaps[i].Min().Value;
11771 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
11772 }
11773
11774 internal bool TryDequeue(out EntityUpdate value)
11775 {
11776 for (int i = 0; i < m_heaps.Length; ++i)
11777 {
11778 if (m_heaps[i].Count > 0)
11779 {
11780 MinHeapItem item = m_heaps[i].RemoveMin();
11781 m_lookupTable.Remove(item.LocalID);
11782 value = item.Value;
11783 return true;
11784 }
11785 }
11786
11787 value = default(EntityUpdate);
11788 return false;
11789 }
11790
11791 internal void Reprioritize(UpdatePriorityHandler handler)
11792 {
11793 MinHeapItem item;
11794 double priority;
11795
11796 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
11797 {
11798 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
11799 {
11800 priority = item.Priority;
11801 if (handler(ref priority, item.LocalID))
11802 {
11803 if (lookup.Heap.ContainsHandle(lookup.Handle))
11804 lookup.Heap[lookup.Handle] =
11805 new MinHeapItem(priority, item.Value, item.LocalID, this.m_comparison);
11806 }
11807 else
11808 {
11809 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
11810 lookup.Heap.Remove(lookup.Handle);
11811 this.m_lookupTable.Remove(item.LocalID);
11812 }
11813 }
11814 }
11815 }
11816
11817 #region MinHeapItem
11818 private struct MinHeapItem : IComparable<MinHeapItem>
11819 {
11820 private double priority;
11821 private EntityUpdate value;
11822 private uint local_id;
11823 private Comparison<double> comparison;
11824
11825 internal MinHeapItem(double priority, EntityUpdate value, uint local_id) :
11826 this(priority, value, local_id, Comparer<double>.Default) { }
11827 internal MinHeapItem(double priority, EntityUpdate value, uint local_id, IComparer<double> comparer) :
11828 this(priority, value, local_id, new Comparison<double>(comparer.Compare)) { }
11829 internal MinHeapItem(double priority, EntityUpdate value, uint local_id, Comparison<double> comparison)
11830 {
11831 this.priority = priority;
11832 this.value = value;
11833 this.local_id = local_id;
11834 this.comparison = comparison;
11835 }
11836
11837 internal double Priority { get { return this.priority; } }
11838 internal EntityUpdate Value { get { return this.value; } }
11839 internal uint LocalID { get { return this.local_id; } }
11840
11841 public override string ToString()
11842 {
11843 StringBuilder sb = new StringBuilder();
11844 sb.Append("[");
11845 sb.Append(this.priority.ToString());
11846 sb.Append(",");
11847 if (this.value != null)
11848 sb.Append(this.value.ToString());
11849 sb.Append("]");
11850 return sb.ToString();
11851 }
11852
11853 public int CompareTo(MinHeapItem other)
11854 {
11855 return this.comparison(this.priority, other.priority);
11856 }
11857 }
11858 #endregion
11859
11860 #region LookupItem
11861 private struct LookupItem
11862 {
11863 internal MinHeap<MinHeapItem> Heap;
11864 internal IHandle Handle;
11865 }
11866 #endregion
11867 }
11868
11869 public struct PacketProcessor 11802 public struct PacketProcessor
11870 { 11803 {
11871 public PacketMethod method; 11804 public PacketMethod method;
@@ -11886,8 +11819,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11886 } 11819 }
11887 } 11820 }
11888 11821
11889 #endregion
11890
11891 public static OSD BuildEvent(string eventName, OSD eventBody) 11822 public static OSD BuildEvent(string eventName, OSD eventBody)
11892 { 11823 {
11893 OSDMap osdEvent = new OSDMap(2); 11824 OSDMap osdEvent = new OSDMap(2);
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 65a8fe3..9a8bfd3 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -149,7 +149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
149 /// <summary>Caches packed throttle information</summary> 149 /// <summary>Caches packed throttle information</summary>
150 private byte[] m_packedThrottles; 150 private byte[] m_packedThrottles;
151 151
152 private int m_defaultRTO = 3000; 152 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
153 private int m_maxRTO = 60000; 153 private int m_maxRTO = 60000;
154 154
155 /// <summary> 155 /// <summary>
@@ -557,7 +557,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
557 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR)); 557 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
558 558
559 // Clamp the retransmission timeout to manageable values 559 // Clamp the retransmission timeout to manageable values
560 rto = Utils.Clamp(RTO, m_defaultRTO, m_maxRTO); 560 rto = Utils.Clamp(rto, m_defaultRTO, m_maxRTO);
561 561
562 RTO = rto; 562 RTO = rto;
563 563
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
index d2779ba..6eebd9d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
@@ -100,6 +100,10 @@ namespace OpenMetaverse
100 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
101 101
102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
103
104 m_log.DebugFormat(
105 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
106 ipep.Address, ipep.Port);
103 107
104 m_udpSocket = new Socket( 108 m_udpSocket = new Socket(
105 AddressFamily.InterNetwork, 109 AddressFamily.InterNetwork,
diff --git a/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
new file mode 100644
index 0000000..364ce4b
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs
@@ -0,0 +1,245 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Framework.Client;
35using log4net;
36
37namespace OpenSim.Region.ClientStack.LindenUDP
38{
39 public class PriorityQueue
40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 internal delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
44
45 // Heap[0] for self updates
46 // Heap[1..12] for entity updates
47
48 internal const uint m_numberOfQueues = 12;
49
50 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[m_numberOfQueues];
51 private Dictionary<uint, LookupItem> m_lookupTable;
52 private uint m_nextQueue = 0;
53 private UInt64 m_nextRequest = 0;
54
55 private object m_syncRoot = new object();
56 public object SyncRoot {
57 get { return this.m_syncRoot; }
58 }
59
60 internal PriorityQueue() : this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY) { }
61
62 internal PriorityQueue(int capacity)
63 {
64 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
65
66 for (int i = 0; i < m_heaps.Length; ++i)
67 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
68 }
69
70 internal int Count
71 {
72 get
73 {
74 int count = 0;
75 for (int i = 0; i < m_heaps.Length; ++i)
76 count += m_heaps[i].Count;
77 return count;
78 }
79 }
80
81 public bool Enqueue(uint pqueue, EntityUpdate value)
82 {
83 LookupItem lookup;
84
85 uint localid = value.Entity.LocalId;
86 UInt64 entry = m_nextRequest++;
87 if (m_lookupTable.TryGetValue(localid, out lookup))
88 {
89 entry = lookup.Heap[lookup.Handle].EntryOrder;
90 value.Flags |= lookup.Heap[lookup.Handle].Value.Flags;
91 lookup.Heap.Remove(lookup.Handle);
92 }
93
94 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
95 lookup.Heap = m_heaps[pqueue];
96 lookup.Heap.Add(new MinHeapItem(pqueue, entry, value), ref lookup.Handle);
97 m_lookupTable[localid] = lookup;
98
99 return true;
100 }
101
102 internal bool TryDequeue(out EntityUpdate value, out Int32 timeinqueue)
103 {
104 for (int i = 0; i < m_numberOfQueues; ++i)
105 {
106 // To get the fair queing, we cycle through each of the
107 // queues when finding an element to dequeue, this code
108 // assumes that the distribution of updates in the queues
109 // is polynomial, probably quadractic (eg distance of PI * R^2)
110 uint h = (uint)((m_nextQueue + i) % m_numberOfQueues);
111 if (m_heaps[h].Count > 0)
112 {
113 m_nextQueue = (uint)((h + 1) % m_numberOfQueues);
114
115 MinHeapItem item = m_heaps[h].RemoveMin();
116 m_lookupTable.Remove(item.Value.Entity.LocalId);
117 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
118 value = item.Value;
119
120 return true;
121 }
122 }
123
124 timeinqueue = 0;
125 value = default(EntityUpdate);
126 return false;
127 }
128
129 internal void Reprioritize(UpdatePriorityHandler handler)
130 {
131 MinHeapItem item;
132 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
133 {
134 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
135 {
136 uint pqueue = item.PriorityQueue;
137 uint localid = item.Value.Entity.LocalId;
138
139 if (handler(ref pqueue, item.Value.Entity))
140 {
141 // unless the priority queue has changed, there is no need to modify
142 // the entry
143 pqueue = Util.Clamp<uint>(pqueue, 0, m_numberOfQueues - 1);
144 if (pqueue != item.PriorityQueue)
145 {
146 lookup.Heap.Remove(lookup.Handle);
147
148 LookupItem litem = lookup;
149 litem.Heap = m_heaps[pqueue];
150 litem.Heap.Add(new MinHeapItem(pqueue, item), ref litem.Handle);
151 m_lookupTable[localid] = litem;
152 }
153 }
154 else
155 {
156 // m_log.WarnFormat("[PQUEUE]: UpdatePriorityHandler returned false for {0}",item.Value.Entity.UUID);
157 lookup.Heap.Remove(lookup.Handle);
158 this.m_lookupTable.Remove(localid);
159 }
160 }
161 }
162 }
163
164 public override string ToString()
165 {
166 string s = "";
167 for (int i = 0; i < m_numberOfQueues; i++)
168 {
169 if (s != "") s += ",";
170 s += m_heaps[i].Count.ToString();
171 }
172 return s;
173 }
174
175#region MinHeapItem
176 private struct MinHeapItem : IComparable<MinHeapItem>
177 {
178 private EntityUpdate value;
179 internal EntityUpdate Value {
180 get {
181 return this.value;
182 }
183 }
184
185 private uint pqueue;
186 internal uint PriorityQueue {
187 get {
188 return this.pqueue;
189 }
190 }
191
192 private Int32 entrytime;
193 internal Int32 EntryTime {
194 get {
195 return this.entrytime;
196 }
197 }
198
199 private UInt64 entryorder;
200 internal UInt64 EntryOrder
201 {
202 get {
203 return this.entryorder;
204 }
205 }
206
207 internal MinHeapItem(uint pqueue, MinHeapItem other)
208 {
209 this.entrytime = other.entrytime;
210 this.entryorder = other.entryorder;
211 this.value = other.value;
212 this.pqueue = pqueue;
213 }
214
215 internal MinHeapItem(uint pqueue, UInt64 entryorder, EntityUpdate value)
216 {
217 this.entrytime = Util.EnvironmentTickCount();
218 this.entryorder = entryorder;
219 this.value = value;
220 this.pqueue = pqueue;
221 }
222
223 public override string ToString()
224 {
225 return String.Format("[{0},{1},{2}]",pqueue,entryorder,value.Entity.LocalId);
226 }
227
228 public int CompareTo(MinHeapItem other)
229 {
230 // I'm assuming that the root part of an SOG is added to the update queue
231 // before the component parts
232 return Comparer<UInt64>.Default.Compare(this.EntryOrder, other.EntryOrder);
233 }
234 }
235#endregion
236
237#region LookupItem
238 private struct LookupItem
239 {
240 internal MinHeap<MinHeapItem> Heap;
241 internal IHandle Handle;
242 }
243#endregion
244 }
245}