Merge branch 'master' into careminster

Conflicts:
	OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
	OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
	OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
avinationmerge
Melanie 2013-07-24 03:50:09 +01:00
commit a7eb1b5b85
31 changed files with 656 additions and 277 deletions

View File

@ -64,7 +64,11 @@ namespace OpenSim.Framework.Capabilities
public string CapsObjectPath { get { return m_capsObjectPath; } } public string CapsObjectPath { get { return m_capsObjectPath; } }
private CapsHandlers m_capsHandlers; private CapsHandlers m_capsHandlers;
private Dictionary<string, string> m_externalCapsHandlers;
private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers
= new Dictionary<string, PollServiceEventArgs>();
private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
private IHttpServer m_httpListener; private IHttpServer m_httpListener;
private UUID m_agentID; private UUID m_agentID;
@ -134,7 +138,6 @@ namespace OpenSim.Framework.Capabilities
m_agentID = agent; m_agentID = agent;
m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL); m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL);
m_externalCapsHandlers = new Dictionary<string, string>();
m_regionName = regionName; m_regionName = regionName;
} }
@ -149,6 +152,27 @@ namespace OpenSim.Framework.Capabilities
m_capsHandlers[capName] = handler; m_capsHandlers[capName] = handler;
} }
public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
{
m_pollServiceHandlers.Add(capName, pollServiceHandler);
m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
// string protocol = "http";
// string hostName = m_httpListenerHostName;
//
// if (MainServer.Instance.UseSSL)
// {
// hostName = MainServer.Instance.SSLCommonName;
// port = MainServer.Instance.SSLPort;
// protocol = "https";
// }
// RegisterHandler(
// capName, String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, pollServiceHandler.Url));
}
/// <summary> /// <summary>
/// Register an external handler. The service for this capability is somewhere else /// Register an external handler. The service for this capability is somewhere else
/// given by the URL. /// given by the URL.
@ -165,13 +189,70 @@ namespace OpenSim.Framework.Capabilities
/// </summary> /// </summary>
public void DeregisterHandlers() public void DeregisterHandlers()
{ {
if (m_capsHandlers != null) foreach (string capsName in m_capsHandlers.Caps)
{ {
foreach (string capsName in m_capsHandlers.Caps) m_capsHandlers.Remove(capsName);
}
foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values)
{
m_httpListener.RemovePollServiceHTTPHandler("", handler.Url);
}
}
public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler)
{
return m_pollServiceHandlers.TryGetValue(name, out pollHandler);
}
public Dictionary<string, PollServiceEventArgs> GetPollHandlers()
{
return new Dictionary<string, PollServiceEventArgs>(m_pollServiceHandlers);
}
/// <summary>
/// Return an LLSD-serializable Hashtable describing the
/// capabilities and their handler details.
/// </summary>
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
{
Hashtable caps = CapsHandlers.GetCapsDetails(excludeSeed, requestedCaps);
lock (m_pollServiceHandlers)
{
foreach (KeyValuePair <string, PollServiceEventArgs> kvp in m_pollServiceHandlers)
{ {
m_capsHandlers.Remove(capsName); if (!requestedCaps.Contains(kvp.Key))
continue;
string hostName = m_httpListenerHostName;
uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
string protocol = "http";
if (MainServer.Instance.UseSSL)
{
hostName = MainServer.Instance.SSLCommonName;
port = MainServer.Instance.SSLPort;
protocol = "https";
}
//
// caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
} }
} }
// Add the external too
foreach (KeyValuePair<string, string> kvp in ExternalCapsHandlers)
{
if (!requestedCaps.Contains(kvp.Key))
continue;
caps[kvp.Key] = kvp.Value;
}
return caps;
} }
public void Activate() public void Activate()

View File

@ -77,20 +77,34 @@ namespace OpenSim.Data.Null
} }
#region Environment Settings #region Environment Settings
private Dictionary<UUID, string> EnvironmentSettings = new Dictionary<UUID, string>();
public string LoadRegionEnvironmentSettings(UUID regionUUID) public string LoadRegionEnvironmentSettings(UUID regionUUID)
{ {
//This connector doesn't support the Environment module yet lock (EnvironmentSettings)
{
if (EnvironmentSettings.ContainsKey(regionUUID))
return EnvironmentSettings[regionUUID];
}
return string.Empty; return string.Empty;
} }
public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
{ {
//This connector doesn't support the Environment module yet lock (EnvironmentSettings)
{
EnvironmentSettings[regionUUID] = settings;
}
} }
public void RemoveRegionEnvironmentSettings(UUID regionUUID) public void RemoveRegionEnvironmentSettings(UUID regionUUID)
{ {
//This connector doesn't support the Environment module yet lock (EnvironmentSettings)
{
if (EnvironmentSettings.ContainsKey(regionUUID))
EnvironmentSettings.Remove(regionUUID);
}
} }
#endregion #endregion

View File

@ -1,18 +1,18 @@
:VERSION 1 # -------------------------- :VERSION 2 # --------------------------
BEGIN; BEGIN;
CREATE TABLE hg_traveling_data ( CREATE TABLE hg_traveling_data(
SessionID VARCHAR(36) NOT NULL, SessionID VARCHAR(36) NOT NULL,
UserID VARCHAR(36) NOT NULL, UserID VARCHAR(36) NOT NULL,
GridExternalName VARCHAR(255) NOT NULL DEFAULT '', GridExternalName VARCHAR(255) NOT NULL DEFAULT "",
ServiceToken VARCHAR(255) NOT NULL DEFAULT '', ServiceToken VARCHAR(255) NOT NULL DEFAULT "",
ClientIPAddress VARCHAR(16) NOT NULL DEFAULT '', ClientIPAddress VARCHAR(16) NOT NULL DEFAULT "",
MyIPAddress VARCHAR(16) NOT NULL DEFAULT '', MyIPAddress VARCHAR(16) NOT NULL DEFAULT "",
TMStamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, TMStamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`SessionID`), PRIMARY KEY(SessionID),
KEY (`UserID`) UNIQUE(UserID)
) ENGINE=InnoDB; );
COMMIT; COMMIT;

View File

@ -58,7 +58,7 @@ namespace OpenSim.Framework
{ {
lock (m_queueSync) lock (m_queueSync)
{ {
if (m_queue.Count < 1 && m_pqueue.Count < 1) while (m_queue.Count < 1 && m_pqueue.Count < 1)
{ {
Monitor.Wait(m_queueSync); Monitor.Wait(m_queueSync);
} }
@ -76,9 +76,10 @@ namespace OpenSim.Framework
{ {
lock (m_queueSync) lock (m_queueSync)
{ {
if (m_queue.Count < 1 && m_pqueue.Count < 1) bool success = true;
while (m_queue.Count < 1 && m_pqueue.Count < 1 && success)
{ {
Monitor.Wait(m_queueSync, msTimeout); success = Monitor.Wait(m_queueSync, msTimeout);
} }
if (m_pqueue.Count > 0) if (m_pqueue.Count > 0)
@ -89,8 +90,17 @@ namespace OpenSim.Framework
} }
} }
/// <summary>
/// Indicate whether this queue contains the given item.
/// </summary>
/// <remarks>
/// This method is not thread-safe. Do not rely on the result without consistent external locking.
/// </remarks>
public bool Contains(T item) public bool Contains(T item)
{ {
if (m_queue.Count < 1 && m_pqueue.Count < 1)
return false;
lock (m_queueSync) lock (m_queueSync)
{ {
if (m_pqueue.Contains(item)) if (m_pqueue.Contains(item))
@ -99,16 +109,28 @@ namespace OpenSim.Framework
} }
} }
/// <summary>
/// Return a count of the number of requests on this queue.
/// </summary>
/// <remarks>
/// This method is not thread-safe. Do not rely on the result without consistent external locking.
/// </remarks>
public int Count() public int Count()
{ {
lock (m_queueSync) return m_queue.Count + m_pqueue.Count;
{
return m_queue.Count+m_pqueue.Count;
}
} }
/// <summary>
/// Return the array of items on this queue.
/// </summary>
/// <remarks>
/// This method is not thread-safe. Do not rely on the result without consistent external locking.
/// </remarks>
public T[] GetQueueArray() public T[] GetQueueArray()
{ {
if (m_queue.Count < 1 && m_pqueue.Count < 1)
return new T[0];
lock (m_queueSync) lock (m_queueSync)
{ {
return m_queue.ToArray(); return m_queue.ToArray();

View File

@ -234,7 +234,7 @@ namespace OpenSim.Framework.Console
string uri = "/ReadResponses/" + sessionID.ToString() + "/"; string uri = "/ReadResponses/" + sessionID.ToString() + "/";
m_Server.AddPollServiceHTTPHandler( m_Server.AddPollServiceHTTPHandler(
uri, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout
XmlDocument xmldoc = new XmlDocument(); XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,

View File

@ -387,6 +387,8 @@ namespace OpenSim.Framework.Servers.HttpServer
if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs))
{ {
psEvArgs.RequestsReceived++;
PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request);
if (psEvArgs.Request != null) if (psEvArgs.Request != null)

View File

@ -50,25 +50,39 @@ namespace OpenSim.Framework.Servers.HttpServer
public enum EventType : int public enum EventType : int
{ {
Normal = 0, LongPoll = 0,
LslHttp = 1, LslHttp = 1,
Inventory = 2, Inventory = 2,
Texture = 3, Texture = 3,
Mesh = 4 Mesh = 4
} }
public string Url { get; set; }
/// <summary>
/// Number of requests received for this poll service.
/// </summary>
public int RequestsReceived { get; set; }
/// <summary>
/// Number of requests handled by this poll service.
/// </summary>
public int RequestsHandled { get; set; }
public PollServiceEventArgs( public PollServiceEventArgs(
RequestMethod pRequest, RequestMethod pRequest,
string pUrl,
HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
UUID pId, int pTimeOutms) UUID pId, int pTimeOutms)
{ {
Request = pRequest; Request = pRequest;
Url = pUrl;
HasEvents = pHasEvents; HasEvents = pHasEvents;
GetEvents = pGetEvents; GetEvents = pGetEvents;
NoEvents = pNoEvents; NoEvents = pNoEvents;
Id = pId; Id = pId;
TimeOutms = pTimeOutms; TimeOutms = pTimeOutms;
Type = EventType.Normal; Type = EventType.LongPoll;
} }
} }
} }

View File

@ -26,13 +26,19 @@
*/ */
using System; using System;
using System.Collections;
using System.Reflection;
using System.Text;
using HttpServer; using HttpServer;
using log4net;
using OpenMetaverse; using OpenMetaverse;
namespace OpenSim.Framework.Servers.HttpServer namespace OpenSim.Framework.Servers.HttpServer
{ {
public class PollServiceHttpRequest public class PollServiceHttpRequest
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public readonly PollServiceEventArgs PollServiceArgs; public readonly PollServiceEventArgs PollServiceArgs;
public readonly IHttpClientContext HttpContext; public readonly IHttpClientContext HttpContext;
public readonly IHttpRequest Request; public readonly IHttpRequest Request;
@ -48,5 +54,44 @@ namespace OpenSim.Framework.Servers.HttpServer
RequestTime = System.Environment.TickCount; RequestTime = System.Environment.TickCount;
RequestID = UUID.Random(); RequestID = UUID.Random();
} }
internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
{
OSHttpResponse response
= new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
response.SendChunked = false;
response.ContentLength64 = buffer.Length;
response.ContentEncoding = Encoding.UTF8;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
}
finally
{
//response.OutputStream.Close();
try
{
response.OutputStream.Flush();
response.Send();
//if (!response.KeepAlive && response.ReuseContext)
// response.FreeContext();
}
catch (Exception e)
{
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
}
PollServiceArgs.RequestsHandled++;
}
}
} }
} }

View File

@ -105,7 +105,7 @@ namespace OpenSim.Framework.Servers.HttpServer
{ {
if (m_running) if (m_running)
{ {
if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.Normal) if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll)
{ {
m_requests.Enqueue(req); m_requests.Enqueue(req);
} }
@ -207,7 +207,7 @@ namespace OpenSim.Framework.Servers.HttpServer
if (responsedata == null) if (responsedata == null)
continue; continue;
if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Normal) // This is the event queue if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue
{ {
try try
{ {

View File

@ -1791,10 +1791,12 @@ namespace OpenSim.Framework
FireAndForget(callback, null); FireAndForget(callback, null);
} }
public static void InitThreadPool(int maxThreads) public static void InitThreadPool(int minThreads, int maxThreads)
{ {
if (maxThreads < 2) if (maxThreads < 2)
throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2");
if (minThreads > maxThreads || minThreads < 2)
throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads");
if (m_ThreadPool != null) if (m_ThreadPool != null)
throw new InvalidOperationException("SmartThreadPool is already initialized"); throw new InvalidOperationException("SmartThreadPool is already initialized");
@ -1802,7 +1804,7 @@ namespace OpenSim.Framework
startInfo.ThreadPoolName = "Util"; startInfo.ThreadPoolName = "Util";
startInfo.IdleTimeout = 2000; startInfo.IdleTimeout = 2000;
startInfo.MaxWorkerThreads = maxThreads; startInfo.MaxWorkerThreads = maxThreads;
startInfo.MinWorkerThreads = 2; startInfo.MinWorkerThreads = minThreads;
m_ThreadPool = new SmartThreadPool(startInfo); m_ThreadPool = new SmartThreadPool(startInfo);
} }
@ -1877,7 +1879,7 @@ namespace OpenSim.Framework
break; break;
case FireAndForgetMethod.SmartThreadPool: case FireAndForgetMethod.SmartThreadPool:
if (m_ThreadPool == null) if (m_ThreadPool == null)
InitThreadPool(15); InitThreadPool(2, 15);
m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj); m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
break; break;
case FireAndForgetMethod.Thread: case FireAndForgetMethod.Thread:
@ -2265,7 +2267,7 @@ namespace OpenSim.Framework
{ {
lock (m_syncRoot) lock (m_syncRoot)
{ {
m_lowQueue.Enqueue(data); q.Enqueue(data);
m_s.WaitOne(0); m_s.WaitOne(0);
m_s.Release(); m_s.Release();
} }
@ -2305,7 +2307,7 @@ namespace OpenSim.Framework
{ {
if (m_highQueue.Count > 0) if (m_highQueue.Count > 0)
res = m_highQueue.Dequeue(); res = m_highQueue.Dequeue();
else else if (m_lowQueue.Count > 0)
res = m_lowQueue.Dequeue(); res = m_lowQueue.Dequeue();
if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)

View File

@ -86,6 +86,7 @@ namespace OpenSim
IConfig startupConfig = Config.Configs["Startup"]; IConfig startupConfig = Config.Configs["Startup"];
IConfig networkConfig = Config.Configs["Network"]; IConfig networkConfig = Config.Configs["Network"];
int stpMinThreads = 2;
int stpMaxThreads = 15; int stpMaxThreads = 15;
if (startupConfig != null) if (startupConfig != null)
@ -112,12 +113,13 @@ namespace OpenSim
if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
Util.FireAndForgetMethod = asyncCallMethod; Util.FireAndForgetMethod = asyncCallMethod;
stpMinThreads = startupConfig.GetInt("MinPoolThreads", 15);
stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15); stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15);
m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) "); m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) ");
} }
if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
Util.InitThreadPool(stpMaxThreads); Util.InitThreadPool(stpMinThreads, stpMaxThreads);
m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod); m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
} }
@ -423,8 +425,8 @@ namespace OpenSim
{ {
RegionInfo regionInfo = presence.Scene.RegionInfo; RegionInfo regionInfo = presence.Scene.RegionInfo;
if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && if (presence.Firstname.ToLower().Equals(mainParams[2].ToLower()) &&
presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) presence.Lastname.ToLower().Equals(mainParams[3].ToLower()))
{ {
MainConsole.Instance.Output( MainConsole.Instance.Output(
String.Format( String.Format(
@ -438,6 +440,7 @@ namespace OpenSim
presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
presence.Scene.IncomingCloseAgent(presence.UUID, force); presence.Scene.IncomingCloseAgent(presence.UUID, force);
break;
} }
} }

View File

@ -367,18 +367,7 @@ namespace OpenSim.Region.ClientStack.Linden
foreach (OSD c in capsRequested) foreach (OSD c in capsRequested)
validCaps.Add(c.AsString()); validCaps.Add(c.AsString());
Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true, validCaps); string result = LLSDHelpers.SerialiseLLSDReply(m_HostCapsObj.GetCapsDetails(true, validCaps));
// Add the external too
foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
{
if (!validCaps.Contains(kvp.Key))
continue;
caps[kvp.Key] = kvp.Value;
}
string result = LLSDHelpers.SerialiseLLSDReply(caps);
//m_log.DebugFormat("[CAPS] CapsRequest {0}", result); //m_log.DebugFormat("[CAPS] CapsRequest {0}", result);

View File

@ -65,6 +65,13 @@ namespace OpenSim.Region.ClientStack.Linden
/// </value> /// </value>
public int DebugLevel { get; set; } public int DebugLevel { get; set; }
// Viewer post requests timeout in 60 secs
// https://bitbucket.org/lindenlab/viewer-release/src/421c20423df93d650cc305dc115922bb30040999/indra/llmessage/llhttpclient.cpp?at=default#cl-44
//
private const int VIEWER_TIMEOUT = 60 * 1000;
// Just to be safe, we work on a 10 sec shorter cycle
private const int SERVER_EQ_TIME_NO_EVENTS = VIEWER_TIMEOUT - (10 * 1000);
protected Scene m_scene; protected Scene m_scene;
private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
@ -252,29 +259,32 @@ namespace OpenSim.Region.ClientStack.Linden
List<UUID> removeitems = new List<UUID>(); List<UUID> removeitems = new List<UUID>();
lock (m_AvatarQueueUUIDMapping) lock (m_AvatarQueueUUIDMapping)
{ m_AvatarQueueUUIDMapping.Remove(agentID);
foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
{
// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
if (ky == agentID)
{
removeitems.Add(ky);
}
}
foreach (UUID ky in removeitems) // lock (m_AvatarQueueUUIDMapping)
{ // {
UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky]; // foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
m_AvatarQueueUUIDMapping.Remove(ky); // {
//// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
string eqgPath = GenerateEqgCapPath(eventQueueGetUuid); // if (ky == agentID)
MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath); // {
// removeitems.Add(ky);
// m_log.DebugFormat( // }
// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}", // }
// eqgPath, agentID, m_scene.RegionInfo.RegionName); //
} // foreach (UUID ky in removeitems)
} // {
// UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
// m_AvatarQueueUUIDMapping.Remove(ky);
//
// string eqgPath = GenerateEqgCapPath(eventQueueGetUuid);
// MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath);
//
//// m_log.DebugFormat(
//// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
//// eqgPath, agentID, m_scene.RegionInfo.RegionName);
// }
// }
UUID searchval = UUID.Zero; UUID searchval = UUID.Zero;
@ -359,29 +369,9 @@ namespace OpenSim.Region.ClientStack.Linden
m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
} }
string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID); caps.RegisterPollHandler(
"EventQueueGet",
// Register this as a caps handler new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
// FIXME: Confusingly, we need to register separate as a capability so that the client is told about
// EventQueueGet when it receive capability information, but then we replace the rest handler immediately
// afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
// really it should be possible to directly register the poll handler as a capability.
caps.RegisterHandler(
"EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null, "EventQueueGet", null));
// delegate(Hashtable m_dhttpMethod)
// {
// return ProcessQueue(m_dhttpMethod, agentID, caps);
// }));
// This will persist this beyond the expiry of the caps handlers
// TODO: Add EventQueueGet name/description for diagnostics
MainServer.Instance.AddPollServiceHTTPHandler(
eventQueueGetPath,
new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID, 40000));
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
Random rnd = new Random(Environment.TickCount); Random rnd = new Random(Environment.TickCount);
lock (m_ids) lock (m_ids)
@ -399,7 +389,10 @@ namespace OpenSim.Region.ClientStack.Linden
Queue<OSD> queue = GetQueue(agentID); Queue<OSD> queue = GetQueue(agentID);
if (queue != null) if (queue != null)
lock (queue) lock (queue)
{
//m_log.WarnFormat("POLLED FOR EVENTS BY {0} in {1} -- {2}", agentID, m_scene.RegionInfo.RegionName, queue.Count);
return queue.Count > 0; return queue.Count > 0;
}
return false; return false;
} }
@ -422,7 +415,7 @@ namespace OpenSim.Region.ClientStack.Linden
public Hashtable GetEvents(UUID requestID, UUID pAgentId) public Hashtable GetEvents(UUID requestID, UUID pAgentId)
{ {
if (DebugLevel >= 2) if (DebugLevel >= 2)
m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
Queue<OSD> queue = TryGetQueue(pAgentId); Queue<OSD> queue = TryGetQueue(pAgentId);
OSD element; OSD element;

View File

@ -246,8 +246,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_scene; private Scene m_scene;
private MeshCapsDataThrottler m_throttler; private MeshCapsDataThrottler m_throttler;
public PollServiceMeshEventArgs(UUID pId, Scene scene) : public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
base(null, null, null, null, pId, int.MaxValue) base(null, uri, null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId); m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
@ -361,7 +361,7 @@ namespace OpenSim.Region.ClientStack.Linden
string capUrl = "/CAPS/" + UUID.Random() + "/"; string capUrl = "/CAPS/" + UUID.Random() + "/";
// Register this as a poll service // Register this as a poll service
PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene); PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
args.Type = PollServiceEventArgs.EventType.Mesh; args.Type = PollServiceEventArgs.EventType.Mesh;
MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);

View File

@ -210,7 +210,7 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_scene; private Scene m_scene;
private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
public PollServiceTextureEventArgs(UUID pId, Scene scene) : public PollServiceTextureEventArgs(UUID pId, Scene scene) :
base(null, null, null, null, pId, int.MaxValue) base(null, "", null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
// x is request id, y is userid // x is request id, y is userid

View File

@ -78,7 +78,6 @@ namespace OpenSim.Region.ClientStack.Linden
private static WebFetchInvDescHandler m_webFetchHandler; private static WebFetchInvDescHandler m_webFetchHandler;
private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
private static Thread[] m_workerThreads = null; private static Thread[] m_workerThreads = null;
private static DoubleQueue<aPollRequest> m_queue = private static DoubleQueue<aPollRequest> m_queue =
@ -115,7 +114,6 @@ namespace OpenSim.Region.ClientStack.Linden
return; return;
m_scene.EventManager.OnRegisterCaps -= RegisterCaps; m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
foreach (Thread t in m_workerThreads) foreach (Thread t in m_workerThreads)
Watchdog.AbortThread(t.ManagedThreadId); Watchdog.AbortThread(t.ManagedThreadId);
@ -135,7 +133,6 @@ namespace OpenSim.Region.ClientStack.Linden
m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
m_scene.EventManager.OnRegisterCaps += RegisterCaps; m_scene.EventManager.OnRegisterCaps += RegisterCaps;
m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
if (m_workerThreads == null) if (m_workerThreads == null)
{ {
@ -178,8 +175,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_scene; private Scene m_scene;
public PollServiceInventoryEventArgs(Scene scene, UUID pId) : public PollServiceInventoryEventArgs(Scene scene, string url, UUID pId) :
base(null, null, null, null, pId, int.MaxValue) base(null, url, null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
@ -310,40 +307,39 @@ namespace OpenSim.Region.ClientStack.Linden
if (m_fetchInventoryDescendents2Url == "") if (m_fetchInventoryDescendents2Url == "")
return; return;
string capUrl = "/CAPS/" + UUID.Random() + "/";
// Register this as a poll service // Register this as a poll service
PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, agentID); PollServiceInventoryEventArgs args
= new PollServiceInventoryEventArgs(m_scene, "/CAPS/" + UUID.Random() + "/", agentID);
args.Type = PollServiceEventArgs.EventType.Inventory; args.Type = PollServiceEventArgs.EventType.Inventory;
MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
string hostName = m_scene.RegionInfo.ExternalHostName; caps.RegisterPollHandler("FetchInventoryDescendents2", args);
uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
string protocol = "http";
if (MainServer.Instance.UseSSL) // MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
{ //
hostName = MainServer.Instance.SSLCommonName; // string hostName = m_scene.RegionInfo.ExternalHostName;
port = MainServer.Instance.SSLPort; // uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
protocol = "https"; // string protocol = "http";
} //
// if (MainServer.Instance.UseSSL)
caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); // {
// hostName = MainServer.Instance.SSLCommonName;
m_capsDict[agentID] = capUrl; // port = MainServer.Instance.SSLPort;
// protocol = "https";
// }
//
// caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
} }
private void DeregisterCaps(UUID agentID, Caps caps) // private void DeregisterCaps(UUID agentID, Caps caps)
{ // {
string capUrl; // string capUrl;
//
if (m_capsDict.TryGetValue(agentID, out capUrl)) // if (m_capsDict.TryGetValue(agentID, out capUrl))
{ // {
MainServer.Instance.RemoveHTTPHandler("", capUrl); // MainServer.Instance.RemoveHTTPHandler("", capUrl);
m_capsDict.Remove(agentID); // m_capsDict.Remove(agentID);
} // }
} // }
private void DoInventoryRequests() private void DoInventoryRequests()
{ {
@ -353,7 +349,8 @@ namespace OpenSim.Region.ClientStack.Linden
aPollRequest poolreq = m_queue.Dequeue(); aPollRequest poolreq = m_queue.Dequeue();
poolreq.thepoll.Process(poolreq); if (poolreq != null && poolreq.thepoll != null)
poolreq.thepoll.Process(poolreq);
} }
} }
} }

View File

@ -3816,6 +3816,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ResendPrimUpdate(update); ResendPrimUpdate(update);
} }
// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
//
// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
private void ProcessEntityUpdates(int maxUpdates) private void ProcessEntityUpdates(int maxUpdates)
{ {
OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@ -3828,6 +3839,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
// objectUpdateBlocks.Value.Clear();
// compressedUpdateBlocks.Value.Clear();
// terseUpdateBlocks.Value.Clear();
// terseAgentUpdateBlocks.Value.Clear();
// objectUpdates.Value.Clear();
// compressedUpdates.Value.Clear();
// terseUpdates.Value.Clear();
// terseAgentUpdates.Value.Clear();
// Check to see if this is a flush // Check to see if this is a flush
if (maxUpdates <= 0) if (maxUpdates <= 0)
{ {

View File

@ -809,8 +809,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
PacketPool.Instance.ReturnPacket(packet); PacketPool.Instance.ReturnPacket(packet);
m_dataPresentEvent.Set();
} }
private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
/// <summary> /// <summary>
/// Start the process of sending a packet to the client. /// Start the process of sending a packet to the client.
/// </summary> /// </summary>
@ -1730,6 +1734,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Action generic every round // Action generic every round
Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
// while (true)
while (base.IsRunningOutbound) while (base.IsRunningOutbound)
{ {
m_scene.ThreadAlive(2); m_scene.ThreadAlive(2);
@ -1791,8 +1796,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// If nothing was sent, sleep for the minimum amount of time before a // If nothing was sent, sleep for the minimum amount of time before a
// token bucket could get more tokens // token bucket could get more tokens
if (!m_packetSent) //if (!m_packetSent)
Thread.Sleep((int)TickCountResolution); // Thread.Sleep((int)TickCountResolution);
m_dataPresentEvent.WaitOne(100);
Watchdog.UpdateThread(); Watchdog.UpdateThread();
} }

View File

@ -75,10 +75,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
{ {
m_scene = scene; m_scene = scene;
m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
if (Enabled) if (Enabled)
{ {
// Only register module with scene if it is enabled. All callers check for a null attachments module.
// Ideally, there should be a null attachments module for when this core attachments module has been
// disabled. Registering only when enabled allows for other attachments module implementations.
m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
m_scene.EventManager.OnNewClient += SubscribeToClientEvents; m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);

View File

@ -80,7 +80,7 @@ namespace OpenSim.Region.CoreModules.Framework
MainConsole.Instance.Commands.AddCommand( MainConsole.Instance.Commands.AddCommand(
"Comms", false, "show caps stats by user", "Comms", false, "show caps stats by user",
"show caps stats [<first-name> <last-name>]", "show caps stats by user [<first-name> <last-name>]",
"Shows statistics on capabilities use by user.", "Shows statistics on capabilities use by user.",
"If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.", "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.",
HandleShowCapsStatsByUserCommand); HandleShowCapsStatsByUserCommand);
@ -296,27 +296,31 @@ namespace OpenSim.Region.CoreModules.Framework
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
return; return;
StringBuilder caps = new StringBuilder(); StringBuilder capsReport = new StringBuilder();
caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); capsReport.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
lock (m_capsObjects) lock (m_capsObjects)
{ {
foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects) foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
{ {
caps.AppendFormat("** Circuit {0}:\n", kvp.Key); capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
Caps caps = kvp.Value;
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
{ {
Uri uri = new Uri(kvp2.Value.ToString()); Uri uri = new Uri(kvp2.Value.ToString());
caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
} }
foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers) foreach (KeyValuePair<string, PollServiceEventArgs> kvp2 in caps.GetPollHandlers())
caps.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value); capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, kvp2.Value.Url);
foreach (KeyValuePair<string, string> kvp3 in caps.ExternalCapsHandlers)
capsReport.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
} }
} }
MainConsole.Instance.Output(caps.ToString()); MainConsole.Instance.Output(capsReport.ToString());
} }
private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams) private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams)
@ -375,6 +379,15 @@ namespace OpenSim.Region.CoreModules.Framework
receivedStats[sp.Name] = reqHandler.RequestsReceived; receivedStats[sp.Name] = reqHandler.RequestsReceived;
handledStats[sp.Name] = reqHandler.RequestsHandled; handledStats[sp.Name] = reqHandler.RequestsHandled;
} }
else
{
PollServiceEventArgs pollHandler = null;
if (caps.TryGetPollHandler(capName, out pollHandler))
{
receivedStats[sp.Name] = pollHandler.RequestsReceived;
handledStats[sp.Name] = pollHandler.RequestsHandled;
}
}
} }
); );
@ -407,9 +420,7 @@ namespace OpenSim.Region.CoreModules.Framework
if (caps == null) if (caps == null)
return; return;
Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers(); foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
foreach (IRequestHandler reqHandler in capsHandlers.Values)
{ {
string reqName = reqHandler.Name ?? ""; string reqName = reqHandler.Name ?? "";
@ -424,6 +435,23 @@ namespace OpenSim.Region.CoreModules.Framework
handledStats[reqName] += reqHandler.RequestsHandled; handledStats[reqName] += reqHandler.RequestsHandled;
} }
} }
foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
{
string name = kvp.Key;
PollServiceEventArgs pollHandler = kvp.Value;
if (!receivedStats.ContainsKey(name))
{
receivedStats[name] = pollHandler.RequestsReceived;
handledStats[name] = pollHandler.RequestsHandled;
}
else
{
receivedStats[name] += pollHandler.RequestsReceived;
handledStats[name] += pollHandler.RequestsHandled;
}
}
} }
); );
@ -486,12 +514,16 @@ namespace OpenSim.Region.CoreModules.Framework
if (caps == null) if (caps == null)
return; return;
Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers(); List<CapTableRow> capRows = new List<CapTableRow>();
foreach (IRequestHandler reqHandler in capsHandlers.Values.OrderByDescending(rh => rh.RequestsReceived)) foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
{ capRows.Add(new CapTableRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled));
cdt.AddRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled);
} foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled));
foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived))
cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
sb.Append(cdt.ToString()); sb.Append(cdt.ToString());
*/ */
@ -526,6 +558,14 @@ namespace OpenSim.Region.CoreModules.Framework
totalRequestsHandled += reqHandler.RequestsHandled; totalRequestsHandled += reqHandler.RequestsHandled;
} }
Dictionary<string, PollServiceEventArgs> capsPollHandlers = caps.GetPollHandlers();
foreach (PollServiceEventArgs handler in capsPollHandlers.Values)
{
totalRequestsReceived += handler.RequestsReceived;
totalRequestsHandled += handler.RequestsHandled;
}
cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled); cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled);
} }
); );
@ -533,5 +573,19 @@ namespace OpenSim.Region.CoreModules.Framework
sb.Append(cdt.ToString()); sb.Append(cdt.ToString());
*/ */
} }
private class CapTableRow
{
public string Name { get; set; }
public int RequestsReceived { get; set; }
public int RequestsHandled { get; set; }
public CapTableRow(string name, int requestsReceived, int requestsHandled)
{
Name = name;
RequestsReceived = requestsReceived;
RequestsHandled = requestsHandled;
}
}
} }
} }

View File

@ -42,23 +42,37 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
namespace OpenSim.Region.CoreModules.Framework namespace OpenSim.Region.CoreModules.Framework
{ {
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")]
public class GridServiceThrottleModule : ISharedRegionModule public class ServiceThrottleModule : ISharedRegionModule, IServiceThrottleModule
{ {
private static readonly ILog m_log = LogManager.GetLogger( private static readonly ILog m_log = LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType); MethodBase.GetCurrentMethod().DeclaringType);
private readonly List<Scene> m_scenes = new List<Scene>(); private readonly List<Scene> m_scenes = new List<Scene>();
private System.Timers.Timer m_timer = new System.Timers.Timer();
private OpenSim.Framework.BlockingQueue<GridRegionRequest> m_RequestQueue = new OpenSim.Framework.BlockingQueue<GridRegionRequest>(); private Queue<Action> m_RequestQueue = new Queue<Action>();
private Dictionary<string, List<string>> m_Pending = new Dictionary<string, List<string>>();
private int m_Interval;
#region ISharedRegionModule
public void Initialise(IConfigSource config) public void Initialise(IConfigSource config)
{ {
Watchdog.StartThread( m_Interval = Util.GetConfigVarFromSections<int>(config, "Interval", new string[] { "ServiceThrottle" }, 5000);
ProcessQueue,
"GridServiceRequestThread", m_timer = new System.Timers.Timer();
ThreadPriority.BelowNormal, m_timer.AutoReset = false;
true, m_timer.Enabled = true;
false); m_timer.Interval = 15000; // 15 secs at first
m_timer.Elapsed += ProcessQueue;
m_timer.Start();
//Watchdog.StartThread(
// ProcessQueue,
// "GridServiceRequestThread",
// ThreadPriority.BelowNormal,
// true,
// false);
} }
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
@ -66,7 +80,9 @@ namespace OpenSim.Region.CoreModules.Framework
lock (m_scenes) lock (m_scenes)
{ {
m_scenes.Add(scene); m_scenes.Add(scene);
scene.RegisterModuleInterface<IServiceThrottleModule>(this);
scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnNewClient += OnNewClient;
scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
} }
} }
@ -83,11 +99,6 @@ namespace OpenSim.Region.CoreModules.Framework
} }
} }
void OnNewClient(IClientAPI client)
{
client.OnRegionHandleRequest += OnRegionHandleRequest;
}
public void PostInitialise() public void PostInitialise()
{ {
} }
@ -98,7 +109,7 @@ namespace OpenSim.Region.CoreModules.Framework
public string Name public string Name
{ {
get { return "GridServiceThrottleModule"; } get { return "ServiceThrottleModule"; }
} }
public Type ReplaceableInterface public Type ReplaceableInterface
@ -106,9 +117,31 @@ namespace OpenSim.Region.CoreModules.Framework
get { return null; } get { return null; }
} }
#endregion ISharedRegionMOdule
#region Events
void OnNewClient(IClientAPI client)
{
client.OnRegionHandleRequest += OnRegionHandleRequest;
}
void OnMakeRootAgent(ScenePresence obj)
{
lock (m_timer)
{
if (!m_timer.Enabled)
{
m_timer.Interval = m_Interval;
m_timer.Enabled = true;
m_timer.Start();
}
}
}
public void OnRegionHandleRequest(IClientAPI client, UUID regionID) public void OnRegionHandleRequest(IClientAPI client, UUID regionID)
{ {
//m_log.DebugFormat("[GRIDSERVICE THROTTLE]: RegionHandleRequest {0}", regionID); //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID);
ulong handle = 0; ulong handle = 0;
if (IsLocalRegionHandle(regionID, out handle)) if (IsLocalRegionHandle(regionID, out handle))
{ {
@ -116,11 +149,83 @@ namespace OpenSim.Region.CoreModules.Framework
return; return;
} }
GridRegionRequest request = new GridRegionRequest(client, regionID); Action action = delegate
m_RequestQueue.Enqueue(request); {
GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID);
if (r != null && r.RegionHandle != 0)
client.SendRegionHandle(regionID, r.RegionHandle);
};
Enqueue("region", regionID.ToString(), action);
}
#endregion Events
#region IServiceThrottleModule
public void Enqueue(string category, string itemid, Action continuation)
{
lock (m_RequestQueue)
{
if (m_Pending.ContainsKey(category))
{
if (m_Pending[category].Contains(itemid))
// Don't enqueue, it's already pending
return;
}
else
m_Pending.Add(category, new List<string>());
m_Pending[category].Add(itemid);
m_RequestQueue.Enqueue(delegate
{
lock (m_RequestQueue)
m_Pending[category].Remove(itemid);
continuation();
});
}
}
#endregion IServiceThrottleModule
#region Process Continuation Queue
private void ProcessQueue(object sender, System.Timers.ElapsedEventArgs e)
{
//m_log.DebugFormat("[YYY]: Process queue with {0} continuations", m_RequestQueue.Count);
while (m_RequestQueue.Count > 0)
{
Action continuation = null;
lock (m_RequestQueue)
continuation = m_RequestQueue.Dequeue();
if (continuation != null)
continuation();
}
if (AreThereRootAgents())
{
lock (m_timer)
{
m_timer.Interval = 1000; // 1 sec
m_timer.Enabled = true;
m_timer.Start();
}
}
else
lock (m_timer)
m_timer.Enabled = false;
} }
#endregion Process Continuation Queue
#region Misc
private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle) private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle)
{ {
regionHandle = 0; regionHandle = 0;
@ -133,31 +238,19 @@ namespace OpenSim.Region.CoreModules.Framework
return false; return false;
} }
private void ProcessQueue() private bool AreThereRootAgents()
{ {
while (true) foreach (Scene s in m_scenes)
{ {
Watchdog.UpdateThread(); foreach (ScenePresence sp in s.GetScenePresences())
if (!sp.IsChildAgent)
GridRegionRequest request = m_RequestQueue.Dequeue(); return true;
GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, request.regionID);
if (r != null && r.RegionHandle != 0)
request.client.SendRegionHandle(request.regionID, r.RegionHandle);
} }
return false;
} }
#endregion Misc
} }
class GridRegionRequest
{
public IClientAPI client;
public UUID regionID;
public GridRegionRequest(IClientAPI c, UUID r)
{
client = c;
regionID = r;
}
}
} }

View File

@ -56,13 +56,10 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
protected bool m_Enabled; protected bool m_Enabled;
protected List<Scene> m_Scenes = new List<Scene>(); protected List<Scene> m_Scenes = new List<Scene>();
protected IServiceThrottleModule m_ServiceThrottle;
// The cache // The cache
protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>(); protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>();
// Throttle the name requests
private OpenSim.Framework.BlockingQueue<NameRequest> m_RequestQueue = new OpenSim.Framework.BlockingQueue<NameRequest>();
#region ISharedRegionModule #region ISharedRegionModule
public void Initialise(IConfigSource config) public void Initialise(IConfigSource config)
@ -115,6 +112,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public void RegionLoaded(Scene s) public void RegionLoaded(Scene s)
{ {
if (m_Enabled && m_ServiceThrottle == null)
m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
} }
public void PostInitialise() public void PostInitialise()
@ -154,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
} }
void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", // "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
@ -162,12 +161,31 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
{ {
remote_client.SendNameReply(uuid, "Mr", "OpenSim"); client.SendNameReply(uuid, "Mr", "OpenSim");
} }
else else
{ {
NameRequest request = new NameRequest(remote_client, uuid); string[] names = new string[2];
m_RequestQueue.Enqueue(request); if (TryGetUserNamesFromCache(uuid, names))
{
client.SendNameReply(uuid, names[0], names[1]);
return;
}
// Not found in cache, queue continuation
m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
{
//m_log.DebugFormat("[YYY]: Name request {0}", uuid);
bool foundRealName = TryGetUserNames(uuid, names);
if (names.Length == 2)
{
if (!foundRealName)
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], uuid, client.Name);
client.SendNameReply(uuid, names[0], names[1]);
}
});
} }
} }
@ -283,15 +301,27 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
} }
/// <summary> /// <summary>
/// Try to get the names bound to the given uuid. ///
/// </summary> /// </summary>
/// <returns>True if the name was found, false if not.</returns> /// <param name="uuid"></param>
/// <param name='uuid'></param> /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
/// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param> /// <returns></returns>
private bool TryGetUserNames(UUID uuid, out string[] names) private bool TryGetUserNames(UUID uuid, string[] names)
{ {
names = new string[2]; if (names == null)
names = new string[2];
if (TryGetUserNamesFromCache(uuid, names))
return true;
if (TryGetUserNamesFromServices(uuid, names))
return true;
return false;
}
private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
{
lock (m_UserCache) lock (m_UserCache)
{ {
if (m_UserCache.ContainsKey(uuid)) if (m_UserCache.ContainsKey(uuid))
@ -303,6 +333,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
} }
} }
return false;
}
/// <summary>
/// Try to get the names bound to the given uuid, from the services.
/// </summary>
/// <returns>True if the name was found, false if not.</returns>
/// <param name='uuid'></param>
/// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
{
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
if (account != null) if (account != null)
@ -387,18 +428,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public string GetUserName(UUID uuid) public string GetUserName(UUID uuid)
{ {
string[] names; string[] names = new string[2];
TryGetUserNames(uuid, out names); TryGetUserNames(uuid, names);
if (names.Length == 2) return names[0] + " " + names[1];
{
string firstname = names[0];
string lastname = names[1];
return firstname + " " + lastname;
}
return "(hippos)";
} }
public string GetUserHomeURL(UUID userID) public string GetUserHomeURL(UUID userID)
@ -598,13 +632,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
protected void Init() protected void Init()
{ {
RegisterConsoleCmds(); RegisterConsoleCmds();
Watchdog.StartThread(
ProcessQueue,
"NameRequestThread",
ThreadPriority.BelowNormal,
true,
false);
} }
protected void RegisterConsoleCmds() protected void RegisterConsoleCmds()
@ -674,39 +701,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
MainConsole.Instance.Output(cdt.ToString()); MainConsole.Instance.Output(cdt.ToString());
} }
private void ProcessQueue()
{
while (true)
{
Watchdog.UpdateThread();
NameRequest request = m_RequestQueue.Dequeue();
string[] names;
bool foundRealName = TryGetUserNames(request.uuid, out names);
if (names.Length == 2)
{
if (!foundRealName)
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], request.uuid, request.client.Name);
request.client.SendNameReply(request.uuid, names[0], names[1]);
}
}
}
}
class NameRequest
{
public IClientAPI client;
public UUID uuid;
public NameRequest(IClientAPI c, UUID n)
{
client = c;
uuid = n;
}
} }
} }

View File

@ -219,7 +219,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
string uri = "/lslhttp/" + urlcode.ToString(); string uri = "/lslhttp/" + urlcode.ToString();
PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); PollServiceEventArgs args
= new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
args.Type = PollServiceEventArgs.EventType.LslHttp; args.Type = PollServiceEventArgs.EventType.LslHttp;
m_HttpServer.AddPollServiceHTTPHandler(uri, args); m_HttpServer.AddPollServiceHTTPHandler(uri, args);
@ -266,7 +267,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
string uri = "/lslhttps/" + urlcode.ToString(); string uri = "/lslhttps/" + urlcode.ToString();
PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); PollServiceEventArgs args
= new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
args.Type = PollServiceEventArgs.EventType.LslHttp; args.Type = PollServiceEventArgs.EventType.LslHttp;
m_HttpsServer.AddPollServiceHTTPHandler(uri, args); m_HttpsServer.AddPollServiceHTTPHandler(uri, args);

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IServiceThrottleModule
{
/// <summary>
/// Enqueue a continuation meant to get a resource from elsewhere.
/// As usual with CPS, caller beware: if that continuation is a never-ending computation,
/// the whole thread will be blocked, and no requests are processed
/// </summary>
/// <param name="category">Category of the resource (e.g. name, region)</param>
/// <param name="itemid">The resource identifier</param>
/// <param name="continuation">The continuation to be executed</param>
void Enqueue(string category, string itemid, Action continuation);
}
}

View File

@ -116,7 +116,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
return false; return false;
// Delete existing npc attachments // Delete existing npc attachments
scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false); if(scene.AttachmentsModule != null)
scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false);
// XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet
// since it doesn't transfer attachments // since it doesn't transfer attachments
@ -125,7 +126,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
npc.Appearance = npcAppearance; npc.Appearance = npcAppearance;
// Rez needed npc attachments // Rez needed npc attachments
scene.AttachmentsModule.RezAttachments(npc); if (scene.AttachmentsModule != null)
scene.AttachmentsModule.RezAttachments(npc);
IAvatarFactoryModule module = IAvatarFactoryModule module =
scene.RequestModuleInterface<IAvatarFactoryModule>(); scene.RequestModuleInterface<IAvatarFactoryModule>();

View File

@ -130,6 +130,7 @@ public class BSActorAvatarMove : BSActor
SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
m_physicsScene.BeforeStep += Mover; m_physicsScene.BeforeStep += Mover;
m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty;
m_walkingUpStairs = 0; m_walkingUpStairs = 0;
} }
@ -139,6 +140,7 @@ public class BSActorAvatarMove : BSActor
{ {
if (m_velocityMotor != null) if (m_velocityMotor != null)
{ {
m_controllingPrim.OnPreUpdateProperty -= Process_OnPreUpdateProperty;
m_physicsScene.BeforeStep -= Mover; m_physicsScene.BeforeStep -= Mover;
m_velocityMotor = null; m_velocityMotor = null;
} }
@ -197,7 +199,7 @@ public class BSActorAvatarMove : BSActor
{ {
if (m_controllingPrim.Flying) if (m_controllingPrim.Flying)
{ {
// Flying and not collising and velocity nearly zero. // Flying and not colliding and velocity nearly zero.
m_controllingPrim.ZeroMotion(true /* inTaintTime */); m_controllingPrim.ZeroMotion(true /* inTaintTime */);
} }
} }
@ -266,6 +268,19 @@ public class BSActorAvatarMove : BSActor
} }
} }
// Called just as the property update is received from the physics engine.
// Do any mode necessary for avatar movement.
private void Process_OnPreUpdateProperty(ref EntityProperties entprop)
{
// Don't change position if standing on a stationary object.
if (m_controllingPrim.IsStationary)
{
entprop.Position = m_controllingPrim.RawPosition;
m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
}
}
// Decide if the character is colliding with a low object and compute a force to pop the // Decide if the character is colliding with a low object and compute a force to pop the
// avatar up so it can walk up and over the low objects. // avatar up so it can walk up and over the low objects.
private OMV.Vector3 WalkUpStairs() private OMV.Vector3 WalkUpStairs()

View File

@ -709,10 +709,10 @@ public sealed class BSCharacter : BSPhysObject
// the world that things have changed. // the world that things have changed.
public override void UpdateProperties(EntityProperties entprop) public override void UpdateProperties(EntityProperties entprop)
{ {
// Don't change position if standing on a stationary object. // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
if (!IsStationary) TriggerPreUpdatePropertyAction(ref entprop);
RawPosition = entprop.Position;
RawPosition = entprop.Position;
RawOrientation = entprop.Rotation; RawOrientation = entprop.Rotation;
// Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar
@ -740,7 +740,7 @@ public sealed class BSCharacter : BSPhysObject
// Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
// base.RequestPhysicsterseUpdate(); // PhysScene.PostUpdate(this);
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity); LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity);

View File

@ -103,9 +103,10 @@ public abstract class BSPhysObject : PhysicsActor
CollisionsLastTickStep = -1; CollisionsLastTickStep = -1;
SubscribedEventsMs = 0; SubscribedEventsMs = 0;
CollidingStep = 0; // Crazy values that will never be true
CollidingGroundStep = 0; CollidingStep = BSScene.NotASimulationStep;
CollisionAccumulation = 0; CollidingGroundStep = BSScene.NotASimulationStep;
CollisionAccumulation = BSScene.NotASimulationStep;
ColliderIsMoving = false; ColliderIsMoving = false;
CollisionScore = 0; CollisionScore = 0;
@ -349,7 +350,7 @@ public abstract class BSPhysObject : PhysicsActor
if (value) if (value)
CollidingStep = PhysScene.SimulationStep; CollidingStep = PhysScene.SimulationStep;
else else
CollidingStep = 0; CollidingStep = BSScene.NotASimulationStep;
} }
} }
public override bool CollidingGround { public override bool CollidingGround {
@ -359,7 +360,7 @@ public abstract class BSPhysObject : PhysicsActor
if (value) if (value)
CollidingGroundStep = PhysScene.SimulationStep; CollidingGroundStep = PhysScene.SimulationStep;
else else
CollidingGroundStep = 0; CollidingGroundStep = BSScene.NotASimulationStep;
} }
} }
public override bool CollidingObj { public override bool CollidingObj {
@ -368,7 +369,7 @@ public abstract class BSPhysObject : PhysicsActor
if (value) if (value)
CollidingObjectStep = PhysScene.SimulationStep; CollidingObjectStep = PhysScene.SimulationStep;
else else
CollidingObjectStep = 0; CollidingObjectStep = BSScene.NotASimulationStep;
} }
} }

View File

@ -97,6 +97,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
internal long m_simulationStep = 0; // The current simulation step. internal long m_simulationStep = 0; // The current simulation step.
public long SimulationStep { get { return m_simulationStep; } } public long SimulationStep { get { return m_simulationStep; } }
// A number to use for SimulationStep that is probably not any step value
// Used by the collision code (which remembers the step when a collision happens) to remember not any simulation step.
public static long NotASimulationStep = -1234;
internal float LastTimeStep { get; private set; } // The simulation time from the last invocation of Simulate() internal float LastTimeStep { get; private set; } // The simulation time from the last invocation of Simulate()

View File

@ -51,7 +51,8 @@ namespace OpenSim.Region.RegionCombinerModule
m_virtScene.UnSubscribeToClientPrimEvents(client); m_virtScene.UnSubscribeToClientPrimEvents(client);
m_virtScene.UnSubscribeToClientPrimRezEvents(client); m_virtScene.UnSubscribeToClientPrimRezEvents(client);
m_virtScene.UnSubscribeToClientInventoryEvents(client); m_virtScene.UnSubscribeToClientInventoryEvents(client);
((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client); if(m_virtScene.AttachmentsModule != null)
((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client);
//m_virtScene.UnSubscribeToClientTeleportEvents(client); //m_virtScene.UnSubscribeToClientTeleportEvents(client);
m_virtScene.UnSubscribeToClientScriptEvents(client); m_virtScene.UnSubscribeToClientScriptEvents(client);
@ -66,7 +67,8 @@ namespace OpenSim.Region.RegionCombinerModule
client.OnRezObject += LocalRezObject; client.OnRezObject += LocalRezObject;
m_rootScene.SubscribeToClientInventoryEvents(client); m_rootScene.SubscribeToClientInventoryEvents(client);
((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client); if (m_rootScene.AttachmentsModule != null)
((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client);
//m_rootScene.SubscribeToClientTeleportEvents(client); //m_rootScene.SubscribeToClientTeleportEvents(client);
m_rootScene.SubscribeToClientScriptEvents(client); m_rootScene.SubscribeToClientScriptEvents(client);

View File

@ -1723,5 +1723,9 @@ MaxStringSpace = 0
;; {MaxDistance} {} {Cut-off distance at which sounds will not be sent to users} {100.0} ;; {MaxDistance} {} {Cut-off distance at which sounds will not be sent to users} {100.0}
MaxDistance = 100.0 MaxDistance = 100.0
[ServiceThrottle]
;; Default time interval (in ms) for the throttle service thread to wake up
Interval = 5000
[Modules] [Modules]
Include-modules = "addon-modules/*/config/*.ini" Include-modules = "addon-modules/*/config/*.ini"