Committing the second part of Jim Greensky @ Intel Lab's patch, re-prioritizing updates

prioritization
John Hurliman 2009-10-17 18:01:22 -07:00
parent e28ac42486
commit fdb2a75ad3
11 changed files with 267 additions and 20 deletions

View File

@ -1042,6 +1042,10 @@ namespace OpenSim.Client.MXP.ClientStack
Session.Send(me); Session.Send(me);
} }
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{
}
public void FlushPrimUpdates() public void FlushPrimUpdates()
{ {
} }

View File

@ -596,6 +596,11 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{
throw new System.NotImplementedException();
}
public void FlushPrimUpdates() public void FlushPrimUpdates()
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();

View File

@ -448,6 +448,8 @@ namespace OpenSim.Framework
public delegate void AvatarInterestUpdate(IClientAPI client, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages); public delegate void AvatarInterestUpdate(IClientAPI client, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages);
public delegate void PlacesQuery(UUID QueryID, UUID TransactionID, string QueryText, uint QueryFlags, byte Category, string SimName, IClientAPI client); public delegate void PlacesQuery(UUID QueryID, UUID TransactionID, string QueryText, uint QueryFlags, byte Category, string SimName, IClientAPI client);
public delegate double UpdatePriorityHandler(UpdatePriorityData data);
#endregion #endregion
public struct DirPlacesReplyData public struct DirPlacesReplyData
@ -744,6 +746,29 @@ namespace OpenSim.Framework
public double priority { get { return this.m_priority; } } public double priority { get { return this.m_priority; } }
} }
public struct UpdatePriorityData {
private double m_priority;
private uint m_localID;
public UpdatePriorityData(double priority, uint localID) {
this.m_priority = priority;
this.m_localID = localID;
}
public double priority { get { return this.m_priority; } }
public uint localID { get { return this.m_localID; } }
}
[Flags]
public enum StateUpdateTypes
{
None = 0,
AvatarTerse = 1,
PrimitiveTerse = AvatarTerse << 1,
PrimitiveFull = PrimitiveTerse << 1,
All = AvatarTerse | PrimitiveTerse | PrimitiveFull,
}
public interface IClientAPI public interface IClientAPI
{ {
Vector3 StartPos { get; set; } Vector3 StartPos { get; set; }
@ -1118,6 +1143,8 @@ namespace OpenSim.Framework
void SendPrimTerseUpdate(SendPrimitiveTerseData data); void SendPrimTerseUpdate(SendPrimitiveTerseData data);
void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler);
void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
List<InventoryFolderBase> folders, bool fetchFolders, List<InventoryFolderBase> folders, bool fetchFolders,
bool fetchItems); bool fetchItems);

View File

@ -3582,37 +3582,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP
void HandleQueueEmpty(ThrottleOutPacketType queue) void HandleQueueEmpty(ThrottleOutPacketType queue)
{ {
int count = 0;
switch (queue) switch (queue)
{ {
case ThrottleOutPacketType.Texture: case ThrottleOutPacketType.Texture:
ProcessTextureRequests(); ProcessTextureRequests();
break; break;
case ThrottleOutPacketType.Task: case ThrottleOutPacketType.Task:
lock (m_avatarTerseUpdates.SyncRoot) if (Monitor.TryEnter(m_avatarTerseUpdates.SyncRoot, 1))
count = m_avatarTerseUpdates.Count;
if (count > 0)
{ {
ProcessAvatarTerseUpdates(); try
return; {
if (m_avatarTerseUpdates.Count > 0)
{
ProcessAvatarTerseUpdates();
return;
}
}
finally { Monitor.Exit(m_avatarTerseUpdates.SyncRoot); }
} }
break; break;
case ThrottleOutPacketType.State: case ThrottleOutPacketType.State:
lock (m_primFullUpdates.SyncRoot) if (Monitor.TryEnter(m_primFullUpdates.SyncRoot, 1))
count = m_primFullUpdates.Count;
if (count > 0)
{ {
ProcessPrimFullUpdates(); try
return; {
if (m_primFullUpdates.Count > 0)
{
ProcessPrimFullUpdates();
return;
}
}
finally { Monitor.Exit(m_primFullUpdates.SyncRoot); }
} }
lock (m_primTerseUpdates.SyncRoot) if (Monitor.TryEnter(m_primTerseUpdates.SyncRoot, 1))
count = m_primTerseUpdates.Count;
if (count > 0)
{ {
ProcessPrimTerseUpdates(); try
return; {
if (m_primTerseUpdates.Count > 0)
{
ProcessPrimTerseUpdates();
return;
}
}
finally { Monitor.Exit(m_primTerseUpdates.SyncRoot); }
} }
break; break;
} }
@ -3703,6 +3717,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
} }
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{
PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler terse_update_priority_handler =
delegate(ref double priority, uint local_id)
{
priority = handler(new UpdatePriorityData(priority, local_id));
return priority != double.NaN;
};
PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler =
delegate(ref double priority, uint local_id)
{
priority = handler(new UpdatePriorityData(priority, local_id));
return priority != double.NaN;
};
if ((type & StateUpdateTypes.AvatarTerse) != 0) {
lock (m_avatarTerseUpdates.SyncRoot)
m_avatarTerseUpdates.Reprioritize(terse_update_priority_handler);
}
if ((type & StateUpdateTypes.PrimitiveFull) != 0) {
lock (m_primFullUpdates.SyncRoot)
m_primFullUpdates.Reprioritize(update_priority_handler);
}
if ((type & StateUpdateTypes.PrimitiveTerse) != 0) {
lock (m_primTerseUpdates.SyncRoot)
m_primTerseUpdates.Reprioritize(terse_update_priority_handler);
}
}
public void FlushPrimUpdates() public void FlushPrimUpdates()
{ {
while (m_primFullUpdates.Count > 0) while (m_primFullUpdates.Count > 0)
@ -10465,6 +10510,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region PriorityQueue #region PriorityQueue
private class PriorityQueue<TPriority, TValue> private class PriorityQueue<TPriority, TValue>
{ {
internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id);
private MinHeap<MinHeapItem>[] heaps = new MinHeap<MinHeapItem>[1]; private MinHeap<MinHeapItem>[] heaps = new MinHeap<MinHeapItem>[1];
private Dictionary<uint, LookupItem> lookup_table = new Dictionary<uint, LookupItem>(); private Dictionary<uint, LookupItem> lookup_table = new Dictionary<uint, LookupItem>();
private Comparison<TPriority> comparison; private Comparison<TPriority> comparison;
@ -10539,6 +10586,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
} }
internal void Reprioritize(UpdatePriorityHandler handler)
{
MinHeapItem item;
TPriority priority;
foreach (LookupItem lookup in new List<LookupItem>(this.lookup_table.Values))
{
if (lookup.Heap.TryGetValue(lookup.Handle, out item))
{
priority = item.Priority;
if (handler(ref priority, item.LocalID))
{
if (lookup.Heap.ContainsHandle(lookup.Handle))
lookup.Heap[lookup.Handle] =
new MinHeapItem(priority, item.Value, item.LocalID);
}
else
{
m_log.Warn("[LLClientView] UpdatePriorityHandle returned false, dropping update");
lookup.Heap.Remove(lookup.Handle);
this.lookup_table.Remove(item.LocalID);
}
}
}
}
#region MinHeapItem #region MinHeapItem
private struct MinHeapItem : IComparable<MinHeapItem> private struct MinHeapItem : IComparable<MinHeapItem>
{ {

View File

@ -527,6 +527,10 @@ namespace OpenSim.Region.Examples.SimpleModule
{ {
} }
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{
}
public void FlushPrimUpdates() public void FlushPrimUpdates()
{ {
} }

View File

@ -278,6 +278,10 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_firstHeartbeat = true; private bool m_firstHeartbeat = true;
private UpdatePrioritizationSchemes m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time; private UpdatePrioritizationSchemes m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
private bool m_reprioritization_enabled = true;
private double m_reprioritization_interval = 2000.0;
private double m_root_reprioritization_distance = 5.0;
private double m_child_reprioritization_distance = 10.0;
private object m_deleting_scene_object = new object(); private object m_deleting_scene_object = new object();
@ -291,6 +295,10 @@ namespace OpenSim.Region.Framework.Scenes
#region Properties #region Properties
public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return this.m_update_prioritization_scheme; } } public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return this.m_update_prioritization_scheme; } }
public bool IsReprioritizationEnabled { get { return m_reprioritization_enabled; } }
public double ReprioritizationInterval { get { return m_reprioritization_interval; } }
public double RootReprioritizationDistance { get { return m_root_reprioritization_distance; } }
public double ChildReprioritizationDistance { get { return m_child_reprioritization_distance; } }
public AgentCircuitManager AuthenticateHandler public AgentCircuitManager AuthenticateHandler
{ {
@ -542,6 +550,11 @@ namespace OpenSim.Region.Framework.Scenes
m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time; m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
break; break;
} }
m_reprioritization_enabled = interest_management_config.GetBoolean("ReprioritizationEnabled", true);
m_reprioritization_interval = interest_management_config.GetDouble("ReprioritizationInterval", 5000.0);
m_root_reprioritization_distance = interest_management_config.GetDouble("RootReprioritizationDistance", 10.0);
m_child_reprioritization_distance = interest_management_config.GetDouble("ChildReprioritizationDistance", 20.0);
} }
m_log.Info("[SCENE]: Using the " + m_update_prioritization_scheme + " prioritization scheme"); m_log.Info("[SCENE]: Using the " + m_update_prioritization_scheme + " prioritization scheme");

View File

@ -846,7 +846,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
/// <param name="localID"></param> /// <param name="localID"></param>
/// <returns>null if no scene object group containing that prim is found</returns> /// <returns>null if no scene object group containing that prim is found</returns>
private SceneObjectGroup GetGroupByPrim(uint localID) public SceneObjectGroup GetGroupByPrim(uint localID)
{ {
if (Entities.ContainsKey(localID)) if (Entities.ContainsKey(localID))
return Entities[localID] as SceneObjectGroup; return Entities[localID] as SceneObjectGroup;

View File

@ -28,6 +28,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Timers;
using OpenMetaverse; using OpenMetaverse;
using log4net; using log4net;
using OpenSim.Framework; using OpenSim.Framework;
@ -172,6 +173,11 @@ namespace OpenSim.Region.Framework.Scenes
// Position of agent's camera in world (region cordinates) // Position of agent's camera in world (region cordinates)
protected Vector3 m_CameraCenter = Vector3.Zero; protected Vector3 m_CameraCenter = Vector3.Zero;
protected Vector3 m_lastCameraCenter = Vector3.Zero;
protected Timer m_reprioritization_timer;
protected bool m_reprioritizing = false;
protected bool m_reprioritization_called = false;
// Use these three vectors to figure out what the agent is looking at // Use these three vectors to figure out what the agent is looking at
// Convert it to a Matrix and/or Quaternion // Convert it to a Matrix and/or Quaternion
@ -639,7 +645,14 @@ namespace OpenSim.Region.Framework.Scenes
m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
AbsolutePosition = m_controllingClient.StartPos; AbsolutePosition = posLastSignificantMove = m_CameraCenter =
m_lastCameraCenter = m_controllingClient.StartPos;
m_reprioritization_timer = new Timer(world.ReprioritizationInterval);
m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
m_reprioritization_timer.AutoReset = false;
AdjustKnownSeeds(); AdjustKnownSeeds();
TrySetMovementAnimation("STAND"); // TODO: I think, this won't send anything, as we are still a child here... TrySetMovementAnimation("STAND"); // TODO: I think, this won't send anything, as we are still a child here...
@ -1219,6 +1232,11 @@ namespace OpenSim.Region.Framework.Scenes
// Camera location in world. We'll need to raytrace // Camera location in world. We'll need to raytrace
// from this location from time to time. // from this location from time to time.
m_CameraCenter = agentData.CameraCenter; m_CameraCenter = agentData.CameraCenter;
if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance)
{
ReprioritizeUpdates();
m_lastCameraCenter = m_CameraCenter;
}
// Use these three vectors to figure out what the agent is looking at // Use these three vectors to figure out what the agent is looking at
// Convert it to a Matrix and/or Quaternion // Convert it to a Matrix and/or Quaternion
@ -2823,7 +2841,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
// Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
if (Util.GetDistanceTo(AbsolutePosition,m_LastChildAgentUpdatePosition) > 32) if (Util.GetDistanceTo(AbsolutePosition, m_LastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
{ {
ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
cadu.ActiveGroupID = UUID.Zero.Guid; cadu.ActiveGroupID = UUID.Zero.Guid;
@ -3118,6 +3136,12 @@ namespace OpenSim.Region.Framework.Scenes
if (cAgentData.Position != new Vector3(-1, -1, -1)) // UGH!! if (cAgentData.Position != new Vector3(-1, -1, -1)) // UGH!!
m_pos = new Vector3(cAgentData.Position.X + shiftx, cAgentData.Position.Y + shifty, cAgentData.Position.Z); m_pos = new Vector3(cAgentData.Position.X + shiftx, cAgentData.Position.Y + shifty, cAgentData.Position.Z);
if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance)
{
posLastSignificantMove = AbsolutePosition;
ReprioritizeUpdates();
}
// It's hard to say here.. We can't really tell where the camera position is unless it's in world cordinates from the sending region // It's hard to say here.. We can't really tell where the camera position is unless it's in world cordinates from the sending region
m_CameraCenter = cAgentData.Center; m_CameraCenter = cAgentData.Center;
@ -3498,6 +3522,16 @@ namespace OpenSim.Region.Framework.Scenes
{ {
m_knownChildRegions.Clear(); m_knownChildRegions.Clear();
} }
lock (m_reprioritization_timer)
{
m_reprioritization_timer.Enabled = false;
m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize);
}
// I don't get it but mono crashes when you try to dispose of this timer,
// unsetting the elapsed callback should be enough to allow for cleanup however.
//m_reprioritizationTimer.Dispose();
m_sceneViewer.Close(); m_sceneViewer.Close();
RemoveFromPhysicalScene(); RemoveFromPhysicalScene();
@ -3913,5 +3947,79 @@ namespace OpenSim.Region.Framework.Scenes
{ {
return Vector3.Distance(AbsolutePosition, position); return Vector3.Distance(AbsolutePosition, position);
} }
private double GetSOGUpdatePriority(SceneObjectGroup sog)
{
switch (Scene.UpdatePrioritizationScheme)
{
case Scene.UpdatePrioritizationSchemes.Time:
throw new InvalidOperationException("UpdatePrioritizationScheme for time not supported for reprioritization");
case Scene.UpdatePrioritizationSchemes.Distance:
return sog.GetPriorityByDistance((IsChildAgent) ? AbsolutePosition : CameraPosition);
case Scene.UpdatePrioritizationSchemes.SimpleAngularDistance:
return sog.GetPriorityBySimpleAngularDistance((IsChildAgent) ? AbsolutePosition : CameraPosition);
default:
throw new InvalidOperationException("UpdatePrioritizationScheme not defined");
}
}
private double UpdatePriority(UpdatePriorityData data)
{
EntityBase entity;
SceneObjectGroup group;
if (Scene.Entities.TryGetValue(data.localID, out entity))
{
group = entity as SceneObjectGroup;
if (group != null)
return GetSOGUpdatePriority(group);
ScenePresence presence = entity as ScenePresence;
if (presence == null)
throw new InvalidOperationException("entity found is neither SceneObjectGroup nor ScenePresence");
switch (Scene.UpdatePrioritizationScheme)
{
case Scene.UpdatePrioritizationSchemes.Time:
throw new InvalidOperationException("UpdatePrioritization for time not supported for reprioritization");
case Scene.UpdatePrioritizationSchemes.Distance:
case Scene.UpdatePrioritizationSchemes.SimpleAngularDistance:
return GetPriorityByDistance((IsChildAgent) ? AbsolutePosition : CameraPosition);
default:
throw new InvalidOperationException("UpdatePrioritizationScheme not defined");
}
}
else
{
group = Scene.SceneGraph.GetGroupByPrim(data.localID);
if (group != null)
return GetSOGUpdatePriority(group);
}
return double.NaN;
}
private void ReprioritizeUpdates()
{
if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != Scene.UpdatePrioritizationSchemes.Time)
{
lock (m_reprioritization_timer)
{
if (!m_reprioritizing)
m_reprioritization_timer.Enabled = m_reprioritizing = true;
else
m_reprioritization_called = true;
}
}
}
private void Reprioritize(object sender, ElapsedEventArgs e)
{
m_controllingClient.ReprioritizeUpdates(StateUpdateTypes.All, UpdatePriority);
lock (m_reprioritization_timer)
{
m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called;
m_reprioritization_called = false;
}
}
} }
} }

View File

@ -1048,6 +1048,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
} }
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{
}
public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, bool fetchFolders, bool fetchItems) public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, bool fetchFolders, bool fetchItems)
{ {

View File

@ -616,6 +616,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
} }
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{
}
public void FlushPrimUpdates() public void FlushPrimUpdates()
{ {
} }

View File

@ -620,6 +620,10 @@ namespace OpenSim.Tests.Common.Mock
{ {
} }
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
{
}
public void FlushPrimUpdates() public void FlushPrimUpdates()
{ {
} }