Committing the second part of Jim Greensky @ Intel Lab's patch, re-prioritizing updates
parent
e28ac42486
commit
fdb2a75ad3
|
@ -1042,6 +1042,10 @@ namespace OpenSim.Client.MXP.ClientStack
|
|||
Session.Send(me);
|
||||
}
|
||||
|
||||
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
|
||||
{
|
||||
}
|
||||
|
||||
public void FlushPrimUpdates()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -596,6 +596,11 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
|
|||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void FlushPrimUpdates()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
|
|
|
@ -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 PlacesQuery(UUID QueryID, UUID TransactionID, string QueryText, uint QueryFlags, byte Category, string SimName, IClientAPI client);
|
||||
|
||||
public delegate double UpdatePriorityHandler(UpdatePriorityData data);
|
||||
|
||||
#endregion
|
||||
|
||||
public struct DirPlacesReplyData
|
||||
|
@ -744,6 +746,29 @@ namespace OpenSim.Framework
|
|||
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
|
||||
{
|
||||
Vector3 StartPos { get; set; }
|
||||
|
@ -1118,6 +1143,8 @@ namespace OpenSim.Framework
|
|||
|
||||
void SendPrimTerseUpdate(SendPrimitiveTerseData data);
|
||||
|
||||
void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler);
|
||||
|
||||
void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
|
||||
List<InventoryFolderBase> folders, bool fetchFolders,
|
||||
bool fetchItems);
|
||||
|
|
|
@ -3582,37 +3582,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
void HandleQueueEmpty(ThrottleOutPacketType queue)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
switch (queue)
|
||||
{
|
||||
case ThrottleOutPacketType.Texture:
|
||||
ProcessTextureRequests();
|
||||
break;
|
||||
case ThrottleOutPacketType.Task:
|
||||
lock (m_avatarTerseUpdates.SyncRoot)
|
||||
count = m_avatarTerseUpdates.Count;
|
||||
if (count > 0)
|
||||
if (Monitor.TryEnter(m_avatarTerseUpdates.SyncRoot, 1))
|
||||
{
|
||||
ProcessAvatarTerseUpdates();
|
||||
return;
|
||||
try
|
||||
{
|
||||
if (m_avatarTerseUpdates.Count > 0)
|
||||
{
|
||||
|
||||
ProcessAvatarTerseUpdates();
|
||||
return;
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(m_avatarTerseUpdates.SyncRoot); }
|
||||
}
|
||||
break;
|
||||
case ThrottleOutPacketType.State:
|
||||
lock (m_primFullUpdates.SyncRoot)
|
||||
count = m_primFullUpdates.Count;
|
||||
if (count > 0)
|
||||
if (Monitor.TryEnter(m_primFullUpdates.SyncRoot, 1))
|
||||
{
|
||||
ProcessPrimFullUpdates();
|
||||
return;
|
||||
try
|
||||
{
|
||||
if (m_primFullUpdates.Count > 0)
|
||||
{
|
||||
ProcessPrimFullUpdates();
|
||||
return;
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(m_primFullUpdates.SyncRoot); }
|
||||
}
|
||||
|
||||
lock (m_primTerseUpdates.SyncRoot)
|
||||
count = m_primTerseUpdates.Count;
|
||||
if (count > 0)
|
||||
if (Monitor.TryEnter(m_primTerseUpdates.SyncRoot, 1))
|
||||
{
|
||||
ProcessPrimTerseUpdates();
|
||||
return;
|
||||
try
|
||||
{
|
||||
if (m_primTerseUpdates.Count > 0)
|
||||
{
|
||||
ProcessPrimTerseUpdates();
|
||||
return;
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(m_primTerseUpdates.SyncRoot); }
|
||||
}
|
||||
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()
|
||||
{
|
||||
while (m_primFullUpdates.Count > 0)
|
||||
|
@ -10465,6 +10510,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
#region PriorityQueue
|
||||
private class PriorityQueue<TPriority, TValue>
|
||||
{
|
||||
internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id);
|
||||
|
||||
private MinHeap<MinHeapItem>[] heaps = new MinHeap<MinHeapItem>[1];
|
||||
private Dictionary<uint, LookupItem> lookup_table = new Dictionary<uint, LookupItem>();
|
||||
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()));
|
||||
}
|
||||
|
||||
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
|
||||
private struct MinHeapItem : IComparable<MinHeapItem>
|
||||
{
|
||||
|
|
|
@ -527,6 +527,10 @@ namespace OpenSim.Region.Examples.SimpleModule
|
|||
{
|
||||
}
|
||||
|
||||
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
|
||||
{
|
||||
}
|
||||
|
||||
public void FlushPrimUpdates()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -278,6 +278,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
private bool m_firstHeartbeat = true;
|
||||
|
||||
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();
|
||||
|
||||
|
@ -291,6 +295,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
#region Properties
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -542,6 +550,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
|
||||
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");
|
||||
|
|
|
@ -846,7 +846,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
/// <param name="localID"></param>
|
||||
/// <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))
|
||||
return Entities[localID] as SceneObjectGroup;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Timers;
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
using OpenSim.Framework;
|
||||
|
@ -172,6 +173,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
// Position of agent's camera in world (region cordinates)
|
||||
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
|
||||
// Convert it to a Matrix and/or Quaternion
|
||||
|
@ -639,7 +645,14 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
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();
|
||||
|
||||
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
|
||||
// from this location from time to time.
|
||||
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
|
||||
// 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
|
||||
if (Util.GetDistanceTo(AbsolutePosition,m_LastChildAgentUpdatePosition) > 32)
|
||||
if (Util.GetDistanceTo(AbsolutePosition, m_LastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
|
||||
{
|
||||
ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
|
||||
cadu.ActiveGroupID = UUID.Zero.Guid;
|
||||
|
@ -3118,6 +3136,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (cAgentData.Position != new Vector3(-1, -1, -1)) // UGH!!
|
||||
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
|
||||
m_CameraCenter = cAgentData.Center;
|
||||
|
||||
|
@ -3498,6 +3522,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
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();
|
||||
|
||||
RemoveFromPhysicalScene();
|
||||
|
@ -3913,5 +3947,79 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
||||
|
|
|
@ -616,6 +616,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
|||
{
|
||||
}
|
||||
|
||||
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
|
||||
{
|
||||
}
|
||||
|
||||
public void FlushPrimUpdates()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -620,6 +620,10 @@ namespace OpenSim.Tests.Common.Mock
|
|||
{
|
||||
}
|
||||
|
||||
public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
|
||||
{
|
||||
}
|
||||
|
||||
public void FlushPrimUpdates()
|
||||
{
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue