change caps get mesh and texture throttle

0.9.1.0-post-fixes
UbitUmarov 2018-10-08 17:29:42 +01:00
parent 7eeaee631d
commit 57ec0d3884
4 changed files with 96 additions and 172 deletions

View File

@ -100,7 +100,6 @@ namespace OpenSim.Capabilities.Handlers
Hashtable responsedata = new Hashtable(); Hashtable responsedata = new Hashtable();
responsedata["int_response_code"] = 400; //501; //410; //404; responsedata["int_response_code"] = 400; //501; //410; //404;
responsedata["content_type"] = "text/plain"; responsedata["content_type"] = "text/plain";
responsedata["str_response_string"] = "Request wasn't what was expected";
responsedata["int_bytes"] = 0; responsedata["int_bytes"] = 0;
string meshStr = string.Empty; string meshStr = string.Empty;
@ -125,7 +124,6 @@ namespace OpenSim.Capabilities.Handlers
{ {
if (mesh.Type == (SByte)AssetType.Mesh) if (mesh.Type == (SByte)AssetType.Mesh)
{ {
Hashtable headers = new Hashtable(); Hashtable headers = new Hashtable();
responsedata["headers"] = headers; responsedata["headers"] = headers;

View File

@ -87,7 +87,6 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>(); private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
#region Region Module interfaceBase Members #region Region Module interfaceBase Members
public Type ReplaceableInterface public Type ReplaceableInterface
@ -134,7 +133,6 @@ namespace OpenSim.Region.ClientStack.Linden
s.EventManager.OnRegisterCaps -= RegisterCaps; s.EventManager.OnRegisterCaps -= RegisterCaps;
s.EventManager.OnDeregisterCaps -= DeregisterCaps; s.EventManager.OnDeregisterCaps -= DeregisterCaps;
s.EventManager.OnThrottleUpdate -= ThrottleUpdate;
m_NumberScenes--; m_NumberScenes--;
m_scene = null; m_scene = null;
} }
@ -153,7 +151,6 @@ namespace OpenSim.Region.ClientStack.Linden
s.EventManager.OnRegisterCaps += RegisterCaps; s.EventManager.OnRegisterCaps += RegisterCaps;
s.EventManager.OnDeregisterCaps += DeregisterCaps; s.EventManager.OnDeregisterCaps += DeregisterCaps;
s.EventManager.OnThrottleUpdate += ThrottleUpdate;
m_NumberScenes++; m_NumberScenes++;
@ -212,18 +209,6 @@ namespace OpenSim.Region.ClientStack.Linden
} }
} }
// Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
public void ThrottleUpdate(ScenePresence p)
{
UUID user = p.UUID;
int imagethrottle = p.ControllingClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset);
PollServiceMeshEventArgs args;
if (m_pollservices.TryGetValue(user, out args))
{
args.UpdateThrottle(imagethrottle);
}
}
private class PollServiceMeshEventArgs : PollServiceEventArgs private class PollServiceMeshEventArgs : PollServiceEventArgs
{ {
private List<Hashtable> requests = private List<Hashtable> requests =
@ -233,18 +218,28 @@ namespace OpenSim.Region.ClientStack.Linden
private HashSet<UUID> dropedResponses = new HashSet<UUID>(); private HashSet<UUID> dropedResponses = new HashSet<UUID>();
private Scene m_scene; private Scene m_scene;
private MeshCapsDataThrottler m_throttler; private ScenePresence m_presence;
public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) : public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
base(null, uri, null, null, null, null, pId, int.MaxValue) base(null, uri, null, null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
m_throttler = new MeshCapsDataThrottler(100000);
// x is request id, y is userid // x is request id, y is userid
HasEvents = (x, y) => HasEvents = (x, y) =>
{ {
lock (responses) lock (responses)
{ {
return m_throttler.hasEvents(x, responses); APollResponse response;
if (responses.TryGetValue(x, out response))
{
if (m_presence == null)
m_presence = m_scene.GetScenePresence(pId);
if (m_presence == null || m_presence.IsDeleted)
return true;
return m_presence.CapCanSendAsset(1, response.bytes);
}
return false;
} }
}; };
@ -269,7 +264,6 @@ namespace OpenSim.Region.ClientStack.Linden
finally finally
{ {
responses.Remove(x); responses.Remove(x);
m_throttler.PassTime();
} }
} }
}; };
@ -282,7 +276,6 @@ namespace OpenSim.Region.ClientStack.Linden
reqinfo.request = y; reqinfo.request = y;
m_queue.Add(reqinfo); m_queue.Add(reqinfo);
m_throttler.PassTime();
}; };
// this should never happen except possible on shutdown // this should never happen except possible on shutdown
@ -307,7 +300,7 @@ namespace OpenSim.Region.ClientStack.Linden
public void Process(APollRequest requestinfo) public void Process(APollRequest requestinfo)
{ {
Hashtable response; Hashtable curresponse;
UUID requestID = requestinfo.reqID; UUID requestID = requestinfo.reqID;
@ -328,19 +321,17 @@ namespace OpenSim.Region.ClientStack.Linden
// If the avatar is gone, don't bother to get the texture // If the avatar is gone, don't bother to get the texture
if(m_scene.GetScenePresence(Id) == null) if(m_scene.GetScenePresence(Id) == null)
{ {
response = new Hashtable(); curresponse = new Hashtable();
curresponse["int_response_code"] = 500;
response["int_response_code"] = 500; curresponse["str_response_string"] = "Script timeout";
response["str_response_string"] = "Script timeout"; curresponse["content_type"] = "text/plain";
response["content_type"] = "text/plain"; curresponse["keepalive"] = false;
response["keepalive"] = false; responses[requestID] = new APollResponse() { bytes = 0, response = curresponse };
responses[requestID] = new APollResponse() { bytes = 0, response = response};
return; return;
} }
} }
response = m_getMeshHandler.Handle(requestinfo.request); curresponse = m_getMeshHandler.Handle(requestinfo.request);
lock(responses) lock(responses)
{ {
@ -355,20 +346,10 @@ namespace OpenSim.Region.ClientStack.Linden
responses[requestID] = new APollResponse() responses[requestID] = new APollResponse()
{ {
bytes = (int)response["int_bytes"], bytes = (int)curresponse["int_bytes"],
response = response response = curresponse
}; };
} }
m_throttler.PassTime();
}
internal void UpdateThrottle(int pthrottle)
{
int tmp = 2 * pthrottle;
if(tmp < 10000)
tmp = 10000;
m_throttler.ThrottleBytes = tmp;
} }
} }
@ -419,52 +400,5 @@ namespace OpenSim.Region.ClientStack.Linden
m_pollservices.Remove(agentID); m_pollservices.Remove(agentID);
} }
} }
internal sealed class MeshCapsDataThrottler
{
private double lastTimeElapsed = 0;
private double BytesSent = 0;
public MeshCapsDataThrottler(int pBytes)
{
if(pBytes < 10000)
pBytes = 10000;
ThrottleBytes = pBytes;
lastTimeElapsed = Util.GetTimeStamp();
}
public bool hasEvents(UUID key, Dictionary<UUID, APollResponse> responses)
{
PassTime();
APollResponse response;
if (responses.TryGetValue(key, out response))
{
// Normal
if (response.bytes == 0 || BytesSent <= ThrottleBytes)
{
BytesSent += response.bytes;
return true;
}
}
return false;
}
public void PassTime()
{
double currenttime = Util.GetTimeStamp();
double timeElapsed = currenttime - lastTimeElapsed;
if(timeElapsed < .05)
return;
int add = (int)(ThrottleBytes * timeElapsed);
if (add >= 1000)
{
lastTimeElapsed = currenttime;
BytesSent -= add;
if (BytesSent < 0) BytesSent = 0;
}
}
public int ThrottleBytes;
}
} }
} }

View File

@ -113,7 +113,6 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
s.EventManager.OnRegisterCaps -= RegisterCaps; s.EventManager.OnRegisterCaps -= RegisterCaps;
s.EventManager.OnDeregisterCaps -= DeregisterCaps; s.EventManager.OnDeregisterCaps -= DeregisterCaps;
s.EventManager.OnThrottleUpdate -= ThrottleUpdate;
m_NumberScenes--; m_NumberScenes--;
m_scene = null; m_scene = null;
} }
@ -129,7 +128,6 @@ namespace OpenSim.Region.ClientStack.Linden
s.EventManager.OnRegisterCaps += RegisterCaps; s.EventManager.OnRegisterCaps += RegisterCaps;
s.EventManager.OnDeregisterCaps += DeregisterCaps; s.EventManager.OnDeregisterCaps += DeregisterCaps;
s.EventManager.OnThrottleUpdate += ThrottleUpdate;
m_NumberScenes++; m_NumberScenes++;
@ -150,19 +148,6 @@ namespace OpenSim.Region.ClientStack.Linden
} }
} }
// Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
public void ThrottleUpdate(ScenePresence p)
{
byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
UUID user = p.UUID;
int imagethrottle = p.ControllingClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Texture);
PollServiceTextureEventArgs args;
if (m_pollservices.TryGetValue(user,out args))
{
args.UpdateThrottle(imagethrottle);
}
}
public void PostInitialise() public void PostInitialise()
{ {
} }
@ -198,20 +183,27 @@ namespace OpenSim.Region.ClientStack.Linden
private HashSet<UUID> dropedResponses = new HashSet<UUID>(); private HashSet<UUID> dropedResponses = new HashSet<UUID>();
private Scene m_scene; private Scene m_scene;
private CapsDataThrottler m_throttler; private ScenePresence m_presence;
public PollServiceTextureEventArgs(UUID pId, Scene scene) : public PollServiceTextureEventArgs(UUID pId, Scene scene) :
base(null, "", null, null, null, null, pId, int.MaxValue) base(null, "", null, null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
m_throttler = new CapsDataThrottler(100000);
// x is request id, y is userid // x is request id, y is userid
HasEvents = (x, y) => HasEvents = (x, y) =>
{ {
lock (responses) lock (responses)
{ {
bool ret = m_throttler.hasEvents(x, responses); APollResponse response;
return ret; if (responses.TryGetValue(x, out response))
{
if (m_presence == null)
m_presence = m_scene.GetScenePresence(pId);
if (m_presence == null || m_presence.IsDeleted)
return true;
return m_presence.CapCanSendAsset(0, response.bytes);
}
return false;
} }
}; };
@ -235,7 +227,6 @@ namespace OpenSim.Region.ClientStack.Linden
finally finally
{ {
responses.Remove(x); responses.Remove(x);
m_throttler.PassTime();
} }
} }
}; };
@ -260,7 +251,6 @@ namespace OpenSim.Region.ClientStack.Linden
} }
} }
m_queue.Add(reqinfo); m_queue.Add(reqinfo);
m_throttler.PassTime();
}; };
// this should never happen except possible on shutdown // this should never happen except possible on shutdown
@ -346,7 +336,6 @@ namespace OpenSim.Region.ClientStack.Linden
if(dropedResponses.Contains(requestID)) if(dropedResponses.Contains(requestID))
{ {
dropedResponses.Remove(requestID); dropedResponses.Remove(requestID);
m_throttler.PassTime();
return; return;
} }
} }
@ -356,15 +345,6 @@ namespace OpenSim.Region.ClientStack.Linden
response = response response = response
}; };
} }
m_throttler.PassTime();
}
internal void UpdateThrottle(int pimagethrottle)
{
int tmp = 2 * pimagethrottle;
if(tmp < 10000)
tmp = 10000;
m_throttler.ThrottleBytes = tmp;
} }
} }
@ -437,49 +417,5 @@ namespace OpenSim.Region.ClientStack.Linden
poolreq.thepoll.Process(poolreq); poolreq.thepoll.Process(poolreq);
} }
} }
internal sealed class CapsDataThrottler
{
private double lastTimeElapsed = 0;
private volatile int BytesSent = 0;
public CapsDataThrottler(int pBytes)
{
if(pBytes < 10000)
pBytes = 10000;
ThrottleBytes = pBytes;
lastTimeElapsed = Util.GetTimeStamp();
}
public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.APollResponse> responses)
{
PassTime();
// Note, this is called IN LOCK
GetTextureModule.APollResponse response;
if (responses.TryGetValue(key, out response))
{
if (response.bytes == 0 || BytesSent <= ThrottleBytes)
{
BytesSent += response.bytes;
return true;
}
}
return false;
}
public void PassTime()
{
double currenttime = Util.GetTimeStamp();
double timeElapsed = currenttime - lastTimeElapsed;
if(timeElapsed < .05)
return;
int add = (int)(ThrottleBytes * timeElapsed);
if (add >= 1000)
{
lastTimeElapsed = currenttime;
BytesSent -= add;
if (BytesSent < 0) BytesSent = 0;
}
}
public int ThrottleBytes;
}
} }
} }

View File

@ -1118,6 +1118,20 @@ namespace OpenSim.Region.Framework.Scenes
m_LandingPointBehavior = LandingPointBehavior.SL; m_LandingPointBehavior = LandingPointBehavior.SL;
} }
m_bandwidth = 100000;
m_lastBandwithTime = Util.GetTimeStamp() + 0.1;
IConfig cconfig = m_scene.Config.Configs["ClientStack.LindenCaps"];
if (cconfig != null)
{
m_capbandwidth = cconfig.GetInt("Cap_AssetThrottle", m_capbandwidth);
if(m_capbandwidth > 0)
{
m_bandwidth = m_capbandwidth;
if(m_bandwidth < 50000)
m_bandwidth = 50000;
}
}
m_bandwidthBurst = m_bandwidth / 5;
ControllingClient.RefreshGroupMembership(); ControllingClient.RefreshGroupMembership();
} }
@ -4626,7 +4640,12 @@ namespace OpenSim.Region.Framework.Scenes
private void RaiseUpdateThrottles() private void RaiseUpdateThrottles()
{ {
m_scene.EventManager.TriggerThrottleUpdate(this); if(m_capbandwidth > 0)
return;
m_bandwidth = 4 * ControllingClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Texture);
if(m_bandwidth < 50000)
m_bandwidth = 50000;
m_bandwidthBurst = m_bandwidth / 5;
} }
/// <summary> /// <summary>
@ -6830,5 +6849,42 @@ namespace OpenSim.Region.Framework.Scenes
{ {
return Overrides.GetOverriddenAnimation(animState); return Overrides.GetOverriddenAnimation(animState);
} }
// http caps assets bandwidth control
private int m_capbandwidth = -1;
private int m_bandwidth = 100000;
private int m_bandwidthBurst = 20000;
private int m_bytesControl;
private double m_lastBandwithTime;
public bool CapCanSendAsset(int type, int size)
{
if(size == 0)
return true;
if(type > 1)
{
// not texture or mesh
m_bytesControl -= size;
return true;
}
double currenttime = Util.GetTimeStamp();
double timeElapsed = currenttime - m_lastBandwithTime;
if (timeElapsed > .05)
{
m_lastBandwithTime = currenttime;
int add = (int)(m_bandwidth * timeElapsed);
m_bytesControl += add;
if (m_bytesControl > m_bandwidthBurst)
m_bytesControl = m_bandwidthBurst;
}
if (m_bytesControl > 0 )
{
m_bytesControl -= size;
return true;
}
return false;
}
} }
} }