aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorMelanie2011-04-12 00:27:39 +0100
committerMelanie2011-04-12 00:27:39 +0100
commit42b96a8be0e6cc754776058071fb60782ec05023 (patch)
treef5e3f8e4b4e5c27ee5f83c5c3e9f2aae5bcf7e11 /OpenSim/Region
parentMerge branch 'master' into careminster-presence-refactor (diff)
parentminor: add a bit more method doc to IInventoryService.GetItem() (diff)
downloadopensim-SC_OLD-42b96a8be0e6cc754776058071fb60782ec05023.zip
opensim-SC_OLD-42b96a8be0e6cc754776058071fb60782ec05023.tar.gz
opensim-SC_OLD-42b96a8be0e6cc754776058071fb60782ec05023.tar.bz2
opensim-SC_OLD-42b96a8be0e6cc754776058071fb60782ec05023.tar.xz
Merge branch 'master' into careminster-presence-refactor
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs18
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs597
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/PriorityQueue.cs245
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs42
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs264
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs14
8 files changed, 677 insertions, 510 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 3f4ee59..14f670d 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -341,10 +341,15 @@ namespace OpenSim
341 341
342 m_console.Commands.AddCommand("region", false, "config get", 342 m_console.Commands.AddCommand("region", false, "config get",
343 "config get [<section>] [<key>]", 343 "config get [<section>] [<key>]",
344 "Show a config option", 344 "Synonym for config show",
345 HandleConfig);
346
347 m_console.Commands.AddCommand("region", false, "config show",
348 "config show [<section>] [<key>]",
349 "Show config information",
345 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine 350 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
346 + "If a section is given but not a field, then all fields in that section are printed.", 351 + "If a section is given but not a field, then all fields in that section are printed.",
347 HandleConfig); 352 HandleConfig);
348 353
349 m_console.Commands.AddCommand("region", false, "config save", 354 m_console.Commands.AddCommand("region", false, "config save",
350 "config save <path>", 355 "config save <path>",
@@ -593,7 +598,9 @@ namespace OpenSim
593 598
594 if (cmdparams.Length > 0) 599 if (cmdparams.Length > 0)
595 { 600 {
596 switch (cmdparams[0].ToLower()) 601 string firstParam = cmdparams[0].ToLower();
602
603 switch (firstParam)
597 { 604 {
598 case "set": 605 case "set":
599 if (cmdparams.Length < 4) 606 if (cmdparams.Length < 4)
@@ -618,6 +625,7 @@ namespace OpenSim
618 break; 625 break;
619 626
620 case "get": 627 case "get":
628 case "show":
621 if (cmdparams.Length == 1) 629 if (cmdparams.Length == 1)
622 { 630 {
623 foreach (IConfig config in m_config.Source.Configs) 631 foreach (IConfig config in m_config.Source.Configs)
@@ -654,8 +662,8 @@ namespace OpenSim
654 } 662 }
655 else 663 else
656 { 664 {
657 Notice("Syntax: config get [<section>] [<key>]"); 665 Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
658 Notice("Example: config get ScriptEngine.DotNetEngine NumberOfScriptThreads"); 666 Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
659 } 667 }
660 668
661 break; 669 break;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 789e86c..5b2484d 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);
@@ -299,6 +301,77 @@ namespace OpenSim.Region.ClientStack.LindenUDP
299 /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary> 301 /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
300 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; 302 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
301 303
304 // First log file or time has expired, start writing to a new log file
305//<MIC>
306// -----------------------------------------------------------------
307// -----------------------------------------------------------------
308// THIS IS DEBUGGING CODE & SHOULD BE REMOVED
309// -----------------------------------------------------------------
310// -----------------------------------------------------------------
311 public class QueueLogger
312 {
313 public Int32 start = 0;
314 public StreamWriter Log = null;
315 private Dictionary<UUID,int> m_idMap = new Dictionary<UUID,int>();
316
317 public QueueLogger()
318 {
319 DateTime now = DateTime.Now;
320 String fname = String.Format("queue-{0}.log", now.ToString("yyyyMMddHHmmss"));
321 Log = new StreamWriter(fname);
322
323 start = Util.EnvironmentTickCount();
324 }
325
326 public int LookupID(UUID uuid)
327 {
328 int localid;
329 if (! m_idMap.TryGetValue(uuid,out localid))
330 {
331 localid = m_idMap.Count + 1;
332 m_idMap[uuid] = localid;
333 }
334
335 return localid;
336 }
337 }
338
339 public static QueueLogger QueueLog = null;
340
341 // -----------------------------------------------------------------
342 public void LogAvatarUpdateEvent(UUID client, UUID avatar, Int32 timeinqueue)
343 {
344 if (QueueLog == null)
345 QueueLog = new QueueLogger();
346
347 Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
348 lock(QueueLog)
349 {
350 int cid = QueueLog.LookupID(client);
351 int aid = QueueLog.LookupID(avatar);
352 QueueLog.Log.WriteLine("{0},AU,AV{1:D4},AV{2:D4},{3}",ticks,cid,aid,timeinqueue);
353 }
354 }
355
356 // -----------------------------------------------------------------
357 public void LogQueueProcessEvent(UUID client, PriorityQueue queue, uint maxup)
358 {
359 if (QueueLog == null)
360 QueueLog = new QueueLogger();
361
362 Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start);
363 lock(QueueLog)
364 {
365 int cid = QueueLog.LookupID(client);
366 QueueLog.Log.WriteLine("{0},PQ,AV{1:D4},{2},{3}",ticks,cid,maxup,queue.ToString());
367 }
368 }
369// -----------------------------------------------------------------
370// -----------------------------------------------------------------
371// -----------------------------------------------------------------
372// -----------------------------------------------------------------
373//</MIC>
374
302 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 375 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
303 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients 376 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
304 377
@@ -3575,6 +3648,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3575 3648
3576 #region Primitive Packet/Data Sending Methods 3649 #region Primitive Packet/Data Sending Methods
3577 3650
3651
3578 /// <summary> 3652 /// <summary>
3579 /// Generate one of the object update packets based on PrimUpdateFlags 3653 /// Generate one of the object update packets based on PrimUpdateFlags
3580 /// and broadcast the packet to clients 3654 /// and broadcast the packet to clients
@@ -3590,12 +3664,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3590 return; // Don't send updates for other people's HUDs 3664 return; // Don't send updates for other people's HUDs
3591 } 3665 }
3592 3666
3593 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3667 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3594 3668
3595 lock (m_entityUpdates.SyncRoot) 3669 lock (m_entityUpdates.SyncRoot)
3596 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation), entity.LocalId); 3670 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3597 } 3671 }
3598 3672
3673 private Int32 m_LastQueueFill = 0;
3674 private uint m_maxUpdates = 0;
3675
3599 private void ProcessEntityUpdates(int maxUpdates) 3676 private void ProcessEntityUpdates(int maxUpdates)
3600 { 3677 {
3601 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3678 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3603,195 +3680,232 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3603 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3680 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3604 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3681 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3605 3682
3606 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; 3683 if (maxUpdates <= 0)
3684 {
3685 m_maxUpdates = Int32.MaxValue;
3686 }
3687 else
3688 {
3689 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
3690 {
3691 m_maxUpdates = (uint)maxUpdates;
3692 }
3693 else
3694 {
3695 if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
3696 m_maxUpdates += 5;
3697 else
3698 m_maxUpdates = m_maxUpdates >> 1;
3699 }
3700 m_maxUpdates = Util.Clamp<uint>(m_maxUpdates,10,500);
3701 }
3702 m_LastQueueFill = Util.EnvironmentTickCount();
3703
3607 int updatesThisCall = 0; 3704 int updatesThisCall = 0;
3608 3705
3609 float avgTimeDilation = 0; 3706//<MIC>
3707// DEBUGGING CODE... REMOVE
3708// LogQueueProcessEvent(this.m_agentId,m_entityUpdates,m_maxUpdates);
3709//</MIC>
3710 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3711 // condition where a kill can be processed before an out-of-date update for the same object.
3712 float avgTimeDilation = 1.0f;
3610 3713
3611 EntityUpdate update; 3714 lock (m_killRecord)
3612 while (updatesThisCall < maxUpdates)
3613 { 3715 {
3614 lock (m_entityUpdates.SyncRoot) 3716 EntityUpdate update;
3615 if (!m_entityUpdates.TryDequeue(out update)) 3717 Int32 timeinqueue; // this is just debugging code & can be dropped later
3616 break; 3718
3617 3719 while (updatesThisCall < m_maxUpdates)
3618 avgTimeDilation += update.TimeDilation;
3619 avgTimeDilation *= 0.5f;
3620
3621 if (update.Entity is SceneObjectPart)
3622 { 3720 {
3623 SceneObjectPart part = (SceneObjectPart)update.Entity; 3721 lock (m_entityUpdates.SyncRoot)
3722 if (!m_entityUpdates.TryDequeue(out update, out timeinqueue))
3723 break;
3724 avgTimeDilation += update.TimeDilation;
3725 avgTimeDilation *= 0.5f;
3624 3726
3625 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3727 if (update.Entity is SceneObjectPart)
3626 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3627 // safety measure.
3628 //
3629 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3630 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3631 // updates and kills on different threads with different scheduling strategies, hence this protection.
3632 //
3633 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3634 // after the root prim has been deleted.
3635 lock (m_killRecord)
3636 { 3728 {
3637 if (m_killRecord.Contains(part.LocalId)) 3729 SceneObjectPart part = (SceneObjectPart)update.Entity;
3638 continue; 3730
3639 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId)) 3731 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3640 continue; 3732 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3641 } 3733 // safety measure.
3642 3734 //
3643 if (part.ParentGroup.IsDeleted) 3735 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3644 continue; 3736 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3737 // updates and kills on different threads with different scheduling strategies, hence this protection.
3738 //
3739 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3740 // after the root prim has been deleted.
3741 lock (m_killRecord)
3742 {
3743 if (m_killRecord.Contains(part.LocalId))
3744 continue;
3745 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3746 continue;
3747 }
3645 3748
3646 if (part.ParentGroup.IsAttachment) 3749 if (part.ParentGroup.IsDeleted)
3647 { // Someone else's HUD, why are we getting these?
3648 if (part.ParentGroup.OwnerID != AgentId &&
3649 part.ParentGroup.RootPart.Shape.State >= 30)
3650 continue;
3651 ScenePresence sp;
3652 // Owner is not in the sim, don't update it to
3653 // anyone
3654 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3655 continue; 3750 continue;
3656 3751
3657 List<SceneObjectGroup> atts = sp.Attachments; 3752 if (part.ParentGroup.IsAttachment)
3658 bool found = false; 3753 { // Someone else's HUD, why are we getting these?
3659 foreach (SceneObjectGroup att in atts) 3754 if (part.ParentGroup.OwnerID != AgentId &&
3660 { 3755 part.ParentGroup.RootPart.Shape.State >= 30)
3661 if (att == part.ParentGroup) 3756 continue;
3757 ScenePresence sp;
3758 // Owner is not in the sim, don't update it to
3759 // anyone
3760 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3761 continue;
3762
3763 List<SceneObjectGroup> atts = sp.Attachments;
3764 bool found = false;
3765 foreach (SceneObjectGroup att in atts)
3662 { 3766 {
3663 found = true; 3767 if (att == part.ParentGroup)
3664 break; 3768 {
3769 found = true;
3770 break;
3771 }
3665 } 3772 }
3666 }
3667 3773
3668 // It's an attachment of a valid avatar, but 3774 // It's an attachment of a valid avatar, but
3669 // doesn't seem to be attached, skip 3775 // doesn't seem to be attached, skip
3670 if (!found) 3776 if (!found)
3671 continue; 3777 continue;
3672 } 3778 }
3673 3779
3674 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3780 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3675 {
3676 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3677 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3678 { 3781 {
3679 part.Shape.LightEntry = false; 3782 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3783 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3784 {
3785 part.Shape.LightEntry = false;
3786 }
3680 } 3787 }
3681 } 3788 }
3682 }
3683
3684 ++updatesThisCall;
3685 3789
3686 #region UpdateFlags to packet type conversion 3790 ++updatesThisCall;
3687 3791
3688 PrimUpdateFlags updateFlags = update.Flags; 3792 #region UpdateFlags to packet type conversion
3689 3793
3690 bool canUseCompressed = true; 3794 PrimUpdateFlags updateFlags = update.Flags;
3691 bool canUseImproved = true;
3692 3795
3693 // Compressed object updates only make sense for LL primitives 3796 bool canUseCompressed = true;
3694 if (!(update.Entity is SceneObjectPart)) 3797 bool canUseImproved = true;
3695 {
3696 canUseCompressed = false;
3697 }
3698 3798
3699 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3799 // Compressed object updates only make sense for LL primitives
3700 { 3800 if (!(update.Entity is SceneObjectPart))
3701 canUseCompressed = false;
3702 canUseImproved = false;
3703 }
3704 else
3705 {
3706 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3707 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3708 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3709 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3710 { 3801 {
3711 canUseCompressed = false; 3802 canUseCompressed = false;
3712 } 3803 }
3713 3804
3714 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || 3805 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3715 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3716 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3717 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3718 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3719 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3720 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3721 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3722 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3723 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3724 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3725 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3726 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3727 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3728 { 3806 {
3807 canUseCompressed = false;
3729 canUseImproved = false; 3808 canUseImproved = false;
3730 } 3809 }
3731 } 3810 else
3811 {
3812 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3813 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3814 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3815 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3816 {
3817 if (update.Entity is ScenePresence)
3818 {
3819 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3820 }
3821 else
3822 {
3823 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3824 }
3825 }
3732 3826
3733 #endregion UpdateFlags to packet type conversion 3827 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3828 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3829 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3830 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3831 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3832 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3833 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3834 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3835 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3836 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3837 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3838 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3839 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3840 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3841 {
3842 canUseImproved = false;
3843 }
3844 }
3734 3845
3735 #region Block Construction 3846 #endregion UpdateFlags to packet type conversion
3736 3847
3737 // TODO: Remove this once we can build compressed updates 3848 #region Block Construction
3738 canUseCompressed = false;
3739 3849
3740 if (!canUseImproved && !canUseCompressed) 3850 // TODO: Remove this once we can build compressed updates
3741 { 3851 canUseCompressed = false;
3742 if (update.Entity is ScenePresence) 3852
3853 if (!canUseImproved && !canUseCompressed)
3854 {
3855 if (update.Entity is ScenePresence)
3856 {
3857 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3858 }
3859 else
3860 {
3861 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3862 // {
3863 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3864 // string text = sop.Text;
3865 // if (text.IndexOf("\n") >= 0)
3866 // text = text.Remove(text.IndexOf("\n"));
3867 //
3868 // if (m_attachmentsSent.Contains(sop.ParentID))
3869 // {
3870 //// m_log.DebugFormat(
3871 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3872 //// sop.LocalId, text);
3873 //
3874 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3875 //
3876 // m_attachmentsSent.Add(sop.LocalId);
3877 // }
3878 // else
3879 // {
3880 // m_log.DebugFormat(
3881 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3882 // sop.LocalId, text, sop.ParentID);
3883 //
3884 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3885 // }
3886 // }
3887 // else
3888 // {
3889 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3890 // }
3891 }
3892 }
3893 else if (!canUseImproved)
3743 { 3894 {
3744 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); 3895 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3745 } 3896 }
3746 else 3897 else
3747 { 3898 {
3748// if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment) 3899 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3749// { 3900 // Self updates go into a special list
3750// SceneObjectPart sop = (SceneObjectPart)update.Entity; 3901 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3751// string text = sop.Text; 3902 else
3752// if (text.IndexOf("\n") >= 0) 3903 // Everything else goes here
3753// text = text.Remove(text.IndexOf("\n")); 3904 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3754//
3755// if (m_attachmentsSent.Contains(sop.ParentID))
3756// {
3757//// m_log.DebugFormat(
3758//// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3759//// sop.LocalId, text);
3760//
3761// objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3762//
3763// m_attachmentsSent.Add(sop.LocalId);
3764// }
3765// else
3766// {
3767// m_log.DebugFormat(
3768// "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3769// sop.LocalId, text, sop.ParentID);
3770//
3771// m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3772// }
3773// }
3774// else
3775// {
3776 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3777// }
3778 } 3905 }
3779 }
3780 else if (!canUseImproved)
3781 {
3782 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3783 }
3784 else
3785 {
3786 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3787 // Self updates go into a special list
3788 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3789 else
3790 // Everything else goes here
3791 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3792 }
3793 3906
3794 #endregion Block Construction 3907 #endregion Block Construction
3908 }
3795 } 3909 }
3796 3910
3797 #region Packet Sending 3911 #region Packet Sending
@@ -3864,26 +3978,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3864 3978
3865 public void ReprioritizeUpdates() 3979 public void ReprioritizeUpdates()
3866 { 3980 {
3867 //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
3868
3869 lock (m_entityUpdates.SyncRoot) 3981 lock (m_entityUpdates.SyncRoot)
3870 m_entityUpdates.Reprioritize(UpdatePriorityHandler); 3982 m_entityUpdates.Reprioritize(UpdatePriorityHandler);
3871 } 3983 }
3872 3984
3873 private bool UpdatePriorityHandler(ref double priority, uint localID) 3985 private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)
3874 { 3986 {
3875 EntityBase entity; 3987 if (entity != null)
3876 if (m_scene.Entities.TryGetValue(localID, out entity))
3877 { 3988 {
3878 priority = m_prioritizer.GetUpdatePriority(this, entity); 3989 priority = m_prioritizer.GetUpdatePriority(this, entity);
3990 return true;
3879 } 3991 }
3880 3992
3881 return priority != double.NaN; 3993 return false;
3882 } 3994 }
3883 3995
3884 public void FlushPrimUpdates() 3996 public void FlushPrimUpdates()
3885 { 3997 {
3886 m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName); 3998 m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
3887 3999
3888 while (m_entityUpdates.Count > 0) 4000 while (m_entityUpdates.Count > 0)
3889 ProcessEntityUpdates(-1); 4001 ProcessEntityUpdates(-1);
@@ -11831,171 +11943,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11831 OutPacket(pack, ThrottleOutPacketType.Task); 11943 OutPacket(pack, ThrottleOutPacketType.Task);
11832 } 11944 }
11833 11945
11834 #region PriorityQueue
11835 public class PriorityQueue
11836 {
11837 internal delegate bool UpdatePriorityHandler(ref double priority, uint local_id);
11838
11839 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
11840 private Dictionary<uint, LookupItem> m_lookupTable;
11841 private Comparison<double> m_comparison;
11842 private object m_syncRoot = new object();
11843
11844 internal PriorityQueue() :
11845 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<double>.Default) { }
11846 internal PriorityQueue(int capacity) :
11847 this(capacity, Comparer<double>.Default) { }
11848 internal PriorityQueue(IComparer<double> comparer) :
11849 this(new Comparison<double>(comparer.Compare)) { }
11850 internal PriorityQueue(Comparison<double> comparison) :
11851 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
11852 internal PriorityQueue(int capacity, IComparer<double> comparer) :
11853 this(capacity, new Comparison<double>(comparer.Compare)) { }
11854 internal PriorityQueue(int capacity, Comparison<double> comparison)
11855 {
11856 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
11857
11858 for (int i = 0; i < m_heaps.Length; ++i)
11859 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
11860 this.m_comparison = comparison;
11861 }
11862
11863 public object SyncRoot { get { return this.m_syncRoot; } }
11864 internal int Count
11865 {
11866 get
11867 {
11868 int count = 0;
11869 for (int i = 0; i < m_heaps.Length; ++i)
11870 count = m_heaps[i].Count;
11871 return count;
11872 }
11873 }
11874
11875 public bool Enqueue(double priority, EntityUpdate value, uint local_id)
11876 {
11877 LookupItem item;
11878
11879 if (m_lookupTable.TryGetValue(local_id, out item))
11880 {
11881 // Combine flags
11882 value.Flags |= item.Heap[item.Handle].Value.Flags;
11883
11884 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
11885 return false;
11886 }
11887 else
11888 {
11889 item.Heap = m_heaps[0];
11890 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
11891 m_lookupTable.Add(local_id, item);
11892 return true;
11893 }
11894 }
11895
11896 internal EntityUpdate Peek()
11897 {
11898 for (int i = 0; i < m_heaps.Length; ++i)
11899 if (m_heaps[i].Count > 0)
11900 return m_heaps[i].Min().Value;
11901 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
11902 }
11903
11904 internal bool TryDequeue(out EntityUpdate value)
11905 {
11906 for (int i = 0; i < m_heaps.Length; ++i)
11907 {
11908 if (m_heaps[i].Count > 0)
11909 {
11910 MinHeapItem item = m_heaps[i].RemoveMin();
11911 m_lookupTable.Remove(item.LocalID);
11912 value = item.Value;
11913 return true;
11914 }
11915 }
11916
11917 value = default(EntityUpdate);
11918 return false;
11919 }
11920
11921 internal void Reprioritize(UpdatePriorityHandler handler)
11922 {
11923 MinHeapItem item;
11924 double priority;
11925
11926 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
11927 {
11928 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
11929 {
11930 priority = item.Priority;
11931 if (handler(ref priority, item.LocalID))
11932 {
11933 if (lookup.Heap.ContainsHandle(lookup.Handle))
11934 lookup.Heap[lookup.Handle] =
11935 new MinHeapItem(priority, item.Value, item.LocalID, this.m_comparison);
11936 }
11937 else
11938 {
11939 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
11940 lookup.Heap.Remove(lookup.Handle);
11941 this.m_lookupTable.Remove(item.LocalID);
11942 }
11943 }
11944 }
11945 }
11946
11947 #region MinHeapItem
11948 private struct MinHeapItem : IComparable<MinHeapItem>
11949 {
11950 private double priority;
11951 private EntityUpdate value;
11952 private uint local_id;
11953 private Comparison<double> comparison;
11954
11955 internal MinHeapItem(double priority, EntityUpdate value, uint local_id) :
11956 this(priority, value, local_id, Comparer<double>.Default) { }
11957 internal MinHeapItem(double priority, EntityUpdate value, uint local_id, IComparer<double> comparer) :
11958 this(priority, value, local_id, new Comparison<double>(comparer.Compare)) { }
11959 internal MinHeapItem(double priority, EntityUpdate value, uint local_id, Comparison<double> comparison)
11960 {
11961 this.priority = priority;
11962 this.value = value;
11963 this.local_id = local_id;
11964 this.comparison = comparison;
11965 }
11966
11967 internal double Priority { get { return this.priority; } }
11968 internal EntityUpdate Value { get { return this.value; } }
11969 internal uint LocalID { get { return this.local_id; } }
11970
11971 public override string ToString()
11972 {
11973 StringBuilder sb = new StringBuilder();
11974 sb.Append("[");
11975 sb.Append(this.priority.ToString());
11976 sb.Append(",");
11977 if (this.value != null)
11978 sb.Append(this.value.ToString());
11979 sb.Append("]");
11980 return sb.ToString();
11981 }
11982
11983 public int CompareTo(MinHeapItem other)
11984 {
11985 return this.comparison(this.priority, other.priority);
11986 }
11987 }
11988 #endregion
11989
11990 #region LookupItem
11991 private struct LookupItem
11992 {
11993 internal MinHeap<MinHeapItem> Heap;
11994 internal IHandle Handle;
11995 }
11996 #endregion
11997 }
11998
11999 public struct PacketProcessor 11946 public struct PacketProcessor
12000 { 11947 {
12001 public PacketMethod method; 11948 public PacketMethod method;
@@ -12016,8 +11963,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12016 } 11963 }
12017 } 11964 }
12018 11965
12019 #endregion
12020
12021 public static OSD BuildEvent(string eventName, OSD eventBody) 11966 public static OSD BuildEvent(string eventName, OSD eventBody)
12022 { 11967 {
12023 OSDMap osdEvent = new OSDMap(2); 11968 OSDMap osdEvent = new OSDMap(2);
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index d6159cd..0fa074d 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 public bool m_deliverPackets = true; 154 public bool m_deliverPackets = true;
155 155
@@ -567,7 +567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
567 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR)); 567 int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
568 568
569 // Clamp the retransmission timeout to manageable values 569 // Clamp the retransmission timeout to manageable values
570 rto = Utils.Clamp(RTO, m_defaultRTO, m_maxRTO); 570 rto = Utils.Clamp(rto, m_defaultRTO, m_maxRTO);
571 571
572 RTO = rto; 572 RTO = rto;
573 573
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}
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 51742ff..4e64979 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -29,8 +29,10 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net; 31using System.Net;
32using System.Net.Security;
32using System.Text; 33using System.Text;
33using System.Threading; 34using System.Threading;
35using System.Security.Cryptography.X509Certificates;
34using Nini.Config; 36using Nini.Config;
35using OpenMetaverse; 37using OpenMetaverse;
36using OpenSim.Framework; 38using OpenSim.Framework;
@@ -100,8 +102,24 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
100 102
101 public HttpRequestModule() 103 public HttpRequestModule()
102 { 104 {
105 ServicePointManager.ServerCertificateValidationCallback +=ValidateServerCertificate;
103 } 106 }
104 107
108 public static bool ValidateServerCertificate(
109 object sender,
110 X509Certificate certificate,
111 X509Chain chain,
112 SslPolicyErrors sslPolicyErrors)
113 {
114 HttpWebRequest Request = (HttpWebRequest)sender;
115
116 if (Request.Headers.Get("NoVerifyCert") != null)
117 {
118 return true;
119 }
120
121 return chain.Build(new X509Certificate2(certificate));
122 }
105 #region IHttpRequestModule Members 123 #region IHttpRequestModule Members
106 124
107 public UUID MakeHttpRequest(string url, string parameters, string body) 125 public UUID MakeHttpRequest(string url, string parameters, string body)
@@ -141,8 +159,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
141 break; 159 break;
142 160
143 case (int)HttpRequestConstants.HTTP_VERIFY_CERT: 161 case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
144 162 htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0);
145 // TODO implement me
146 break; 163 break;
147 } 164 }
148 } 165 }
@@ -189,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
189 * Not sure how important ordering is is here - the next first 206 * Not sure how important ordering is is here - the next first
190 * one completed in the list is returned, based soley on its list 207 * one completed in the list is returned, based soley on its list
191 * position, not the order in which the request was started or 208 * position, not the order in which the request was started or
192 * finsihed. I thought about setting up a queue for this, but 209 * finished. I thought about setting up a queue for this, but
193 * it will need some refactoring and this works 'enough' right now 210 * it will need some refactoring and this works 'enough' right now
194 */ 211 */
195 212
@@ -237,8 +254,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
237 254
238 m_scene.RegisterModuleInterface<IHttpRequestModule>(this); 255 m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
239 256
240 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 257 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
241 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 258 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
242 259
243 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 260 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
244 } 261 }
@@ -282,7 +299,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
282 public string HttpMethod = "GET"; 299 public string HttpMethod = "GET";
283 public string HttpMIMEType = "text/plain;charset=utf-8"; 300 public string HttpMIMEType = "text/plain;charset=utf-8";
284 public int HttpTimeout; 301 public int HttpTimeout;
285 // public bool HttpVerifyCert = true; // not implemented 302 public bool HttpVerifyCert = true;
286 private Thread httpThread; 303 private Thread httpThread;
287 304
288 // Request info 305 // Request info
@@ -348,6 +365,17 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
348 Request.Method = HttpMethod; 365 Request.Method = HttpMethod;
349 Request.ContentType = HttpMIMEType; 366 Request.ContentType = HttpMIMEType;
350 367
368 if(!HttpVerifyCert)
369 {
370 // We could hijack Connection Group Name to identify
371 // a desired security exception. But at the moment we'll use a dummy header instead.
372// Request.ConnectionGroupName = "NoVerify";
373 Request.Headers.Add("NoVerifyCert", "true");
374 }
375// else
376// {
377// Request.ConnectionGroupName="Verify";
378// }
351 if (proxyurl != null && proxyurl.Length > 0) 379 if (proxyurl != null && proxyurl.Length > 0)
352 { 380 {
353 if (proxyexcepts != null && proxyexcepts.Length > 0) 381 if (proxyexcepts != null && proxyexcepts.Length > 0)
@@ -450,4 +478,4 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
450 } 478 }
451 } 479 }
452 } 480 }
453} 481} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 69ba2042..32ee674 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -223,7 +223,8 @@ namespace OpenSim.Region.Framework
223 catch (Exception e) 223 catch (Exception e)
224 { 224 {
225 m_log.ErrorFormat( 225 m_log.ErrorFormat(
226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e); 226 "[MODULES]: Could not load types for plugin DLL {0}. Exception {1} {2}",
227 pluginAssembly.FullName, e.Message, e.StackTrace);
227 228
228 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
229 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to? 230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index cde8d3f..cd6dc95 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -58,17 +58,8 @@ namespace OpenSim.Region.Framework.Scenes
58 58
59 public class Prioritizer 59 public class Prioritizer
60 { 60 {
61// private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
62 62
63 /// <summary>
64 /// This is added to the priority of all child prims, to make sure that the root prim update is sent to the
65 /// viewer before child prim updates.
66 /// The adjustment is added to child prims and subtracted from root prims, so the gap ends up
67 /// being double. We do it both ways so that there is a still a priority delta even if the priority is already
68 /// double.MinValue or double.MaxValue.
69 /// </summary>
70 private double m_childPrimAdjustmentFactor = 0.05;
71
72 private Scene m_scene; 63 private Scene m_scene;
73 64
74 public Prioritizer(Scene scene) 65 public Prioritizer(Scene scene)
@@ -76,17 +67,35 @@ namespace OpenSim.Region.Framework.Scenes
76 m_scene = scene; 67 m_scene = scene;
77 } 68 }
78 69
79 public double GetUpdatePriority(IClientAPI client, ISceneEntity entity) 70 /// <summary>
71 /// Returns the priority queue into which the update should be placed. Updates within a
72 /// queue will be processed in arrival order. There are currently 12 priority queues
73 /// implemented in PriorityQueue class in LLClientView. Queue 0 is generally retained
74 /// for avatar updates. The fair queuing discipline for processing the priority queues
75 /// assumes that the number of entities in each priority queues increases exponentially.
76 /// So for example... if queue 1 contains all updates within 10m of the avatar or camera
77 /// then queue 2 at 20m is about 3X bigger in space & about 3X bigger in total number
78 /// of updates.
79 /// </summary>
80 public uint GetUpdatePriority(IClientAPI client, ISceneEntity entity)
80 { 81 {
81 double priority = 0; 82 // If entity is null we have a serious problem
82
83 if (entity == null) 83 if (entity == null)
84 return 100000; 84 {
85 m_log.WarnFormat("[PRIORITIZER] attempt to prioritize null entity");
86 throw new InvalidOperationException("Prioritization entity not defined");
87 }
88
89 // If this is an update for our own avatar give it the highest priority
90 if (client.AgentId == entity.UUID)
91 return 0;
92
93 uint priority;
85 94
86 switch (m_scene.UpdatePrioritizationScheme) 95 switch (m_scene.UpdatePrioritizationScheme)
87 { 96 {
88 case UpdatePrioritizationSchemes.Time: 97 case UpdatePrioritizationSchemes.Time:
89 priority = GetPriorityByTime(); 98 priority = GetPriorityByTime(client, entity);
90 break; 99 break;
91 case UpdatePrioritizationSchemes.Distance: 100 case UpdatePrioritizationSchemes.Distance:
92 priority = GetPriorityByDistance(client, entity); 101 priority = GetPriorityByDistance(client, entity);
@@ -104,182 +113,119 @@ namespace OpenSim.Region.Framework.Scenes
104 throw new InvalidOperationException("UpdatePrioritizationScheme not defined."); 113 throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
105 } 114 }
106 115
107 // Adjust priority so that root prims are sent to the viewer first. This is especially important for
108 // attachments acting as huds, since current viewers fail to display hud child prims if their updates
109 // arrive before the root one.
110 if (entity is SceneObjectPart)
111 {
112 SceneObjectPart sop = ((SceneObjectPart)entity);
113
114 if (sop.IsRoot)
115 {
116 if (priority >= double.MinValue + m_childPrimAdjustmentFactor)
117 priority -= m_childPrimAdjustmentFactor;
118 }
119 else
120 {
121 if (priority <= double.MaxValue - m_childPrimAdjustmentFactor)
122 priority += m_childPrimAdjustmentFactor;
123 }
124 }
125
126 return priority; 116 return priority;
127 } 117 }
128 118
129 private double GetPriorityByTime() 119
120 private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
130 { 121 {
131 return DateTime.UtcNow.ToOADate(); 122 return 1;
132 } 123 }
133 124
134 private double GetPriorityByDistance(IClientAPI client, ISceneEntity entity) 125 private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
135 { 126 {
136 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 127 return ComputeDistancePriority(client,entity,false);
137 if (presence != null) 128 }
138 { 129
139 // If this is an update for our own avatar give it the highest priority 130 private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
140 if (presence == entity) 131 {
141 return 0.0; 132 return ComputeDistancePriority(client,entity,true);
142
143 // Use the camera position for local agents and avatar position for remote agents
144 Vector3 presencePos = (presence.IsChildAgent) ?
145 presence.AbsolutePosition :
146 presence.CameraPosition;
147
148 // Use group position for child prims
149 Vector3 entityPos;
150 if (entity is SceneObjectPart)
151 {
152 // Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
153 // before its scheduled update was triggered
154 //entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
155 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
156 }
157 else
158 {
159 entityPos = entity.AbsolutePosition;
160 }
161
162 return Vector3.DistanceSquared(presencePos, entityPos);
163 }
164
165 return double.NaN;
166 } 133 }
167 134
168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) 135 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
169 { 136 {
170 if (entity == null) return double.NaN; 137 if (entity == null) return 0;
138
139 uint pqueue = ComputeDistancePriority(client,entity,true);
140
171 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 141 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
172 if (presence != null) 142 if (presence != null)
173 { 143 {
174 // If this is an update for our own avatar give it the highest priority
175 if (presence == entity)
176 return 0.0;
177
178 // Use group position for child prims
179 Vector3 entityPos = entity.AbsolutePosition;
180 if (entity is SceneObjectPart)
181 {
182 // Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
183 // before its scheduled update was triggered
184 //entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
185 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
186 }
187 else
188 {
189 entityPos = entity.AbsolutePosition;
190 }
191
192 if (!presence.IsChildAgent) 144 if (!presence.IsChildAgent)
193 { 145 {
194 // Root agent. Use distance from camera and a priority decrease for objects behind us 146 if (entity is SceneObjectPart)
195 Vector3 camPosition = presence.CameraPosition; 147 {
196 Vector3 camAtAxis = presence.CameraAtAxis; 148 // Non physical prims are lower priority than physical prims
197 149 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
198 // Distance 150 if (physActor == null || !physActor.IsPhysical)
199 double priority = Vector3.DistanceSquared(camPosition, entityPos); 151 pqueue++;
200 152
201 // Plane equation 153 // Attachments are high priority,
202 float d = -Vector3.Dot(camPosition, camAtAxis); 154 // MIC: shouldn't these already be in the highest priority queue already
203 float p = Vector3.Dot(camAtAxis, entityPos) + d; 155 // since their root position is same as the avatars?
204 if (p < 0.0f) priority *= 2.0; 156 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
205 157 pqueue = 1;
206 return priority; 158 }
207 }
208 else
209 {
210 // Child agent. Use the normal distance method
211 Vector3 presencePos = presence.AbsolutePosition;
212
213 return Vector3.DistanceSquared(presencePos, entityPos);
214 } 159 }
215 } 160 }
216 161
217 return double.NaN; 162 return pqueue;
218 } 163 }
219 164
220 private double GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 165 private uint ComputeDistancePriority(IClientAPI client, ISceneEntity entity, bool useFrontBack)
221 { 166 {
222 // If this is an update for our own avatar give it the highest priority 167 // If this is an update for our own avatar give it the highest priority
223 if (client.AgentId == entity.UUID) 168 if (client.AgentId == entity.UUID)
224 return 0.0; 169 return 0;
225 if (entity == null) 170 if (entity == null)
226 return double.NaN; 171 return 0;
227 172
173 // Get this agent's position
228 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 174 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
229 if (presence != null) 175 if (presence == null)
230 { 176 {
231 // Use group position for child prims 177 m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId);
232 Vector3 entityPos; 178 // throw new InvalidOperationException("Prioritization agent not defined");
233 if (entity is SceneObjectPart) 179 return Int32.MaxValue;
234 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition; 180 }
235 else 181
236 entityPos = entity.AbsolutePosition; 182 // Use group position for child prims, since we are putting child prims in
237 183 // the same queue with the root of the group, the root prim (which goes into
238 if (!presence.IsChildAgent) 184 // the queue first) should always be sent first, no need to adjust child prim
239 { 185 // priorities
240 if (entity is ScenePresence) 186 Vector3 entityPos = entity.AbsolutePosition;
241 return 1.0; 187 if (entity is SceneObjectPart)
242 188 {
243 // Root agent. Use distance from camera and a priority decrease for objects behind us 189 SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup;
244 Vector3 camPosition = presence.CameraPosition; 190 if (group != null)
245 Vector3 camAtAxis = presence.CameraAtAxis; 191 entityPos = group.AbsolutePosition;
246 192 }
247 // Distance
248 double priority = Vector3.DistanceSquared(camPosition, entityPos);
249
250 // Plane equation
251 float d = -Vector3.Dot(camPosition, camAtAxis);
252 float p = Vector3.Dot(camAtAxis, entityPos) + d;
253 if (p < 0.0f) priority *= 2.0;
254 193
255 if (entity is SceneObjectPart) 194 // Use the camera position for local agents and avatar position for remote agents
256 { 195 Vector3 presencePos = (presence.IsChildAgent) ?
257 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) 196 presence.AbsolutePosition :
258 { 197 presence.CameraPosition;
259 priority = 1.0;
260 }
261 else
262 {
263 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
264 if (physActor == null || !physActor.IsPhysical)
265 priority += 100;
266 }
267 198
268 if (((SceneObjectPart)entity).ParentGroup.RootPart != (SceneObjectPart)entity) 199 // Compute the distance...
269 priority +=1; 200 double distance = Vector3.Distance(presencePos, entityPos);
270 }
271 return priority;
272 }
273 else
274 {
275 // Child agent. Use the normal distance method
276 Vector3 presencePos = presence.AbsolutePosition;
277 201
278 return Vector3.DistanceSquared(presencePos, entityPos); 202 // And convert the distance to a priority queue, this computation gives queues
279 } 203 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
204 uint pqueue = 1;
205 for (int i = 0; i < 8; i++)
206 {
207 if (distance < 10 * Math.Pow(2.0,i))
208 break;
209 pqueue++;
210 }
211
212 // If this is a root agent, then determine front & back
213 // Bump up the priority queue (drop the priority) for any objects behind the avatar
214 if (useFrontBack && ! presence.IsChildAgent)
215 {
216 // Root agent, decrease priority for objects behind us
217 Vector3 camPosition = presence.CameraPosition;
218 Vector3 camAtAxis = presence.CameraAtAxis;
219
220 // Plane equation
221 float d = -Vector3.Dot(camPosition, camAtAxis);
222 float p = Vector3.Dot(camAtAxis, entityPos) + d;
223 if (p < 0.0f)
224 pqueue++;
280 } 225 }
281 226
282 return double.NaN; 227 return pqueue;
283 } 228 }
229
284 } 230 }
285} 231}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 8ceb814..cda8adb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -10930,12 +10930,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10930 { 10930 {
10931 UUID rq = UUID.Random(); 10931 UUID rq = UUID.Random();
10932 10932
10933 UUID tid = AsyncCommands. 10933 AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
10934 DataserverPlugin.RegisterRequest(m_localID,
10935 m_itemID, rq.ToString());
10936 10934
10937 AsyncCommands. 10935 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
10938 DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
10939 10936
10940 return rq.ToString(); 10937 return rq.ToString();
10941 } 10938 }
@@ -10949,12 +10946,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10949 { 10946 {
10950 UUID rq = UUID.Random(); 10947 UUID rq = UUID.Random();
10951 10948
10952 UUID tid = AsyncCommands. 10949 AsyncCommands.DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString());
10953 DataserverPlugin.RegisterRequest(m_localID,
10954 m_itemID, rq.ToString());
10955 10950
10956 AsyncCommands. 10951 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
10957 DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
10958 10952
10959 return rq.ToString(); 10953 return rq.ToString();
10960 } 10954 }