use concurrentdic on pollhandlers, simplify a bit

master
UbitUmarov 2020-04-23 16:04:54 +01:00
parent 92518129ee
commit fefcda52f5
6 changed files with 80 additions and 88 deletions

View File

@ -28,6 +28,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
@ -51,7 +52,7 @@ namespace OpenSim.Framework.Capabilities
public class Caps public class Caps
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private string m_httpListenerHostName; private string m_httpListenerHostName;
private uint m_httpListenPort; private uint m_httpListenPort;
@ -64,8 +65,8 @@ namespace OpenSim.Framework.Capabilities
private CapsHandlers m_capsHandlers; private CapsHandlers m_capsHandlers;
private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers private ConcurrentDictionary<string, PollServiceEventArgs> m_pollServiceHandlers
= new Dictionary<string, PollServiceEventArgs>(); = new ConcurrentDictionary<string, PollServiceEventArgs>();
private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>(); private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
@ -181,9 +182,15 @@ namespace OpenSim.Framework.Capabilities
// "[CAPS]: Registering handler with name {0}, url {1} for {2}", // "[CAPS]: Registering handler with name {0}, url {1} for {2}",
// capName, pollServiceHandler.Url, m_agentID, m_regionName); // capName, pollServiceHandler.Url, m_agentID, m_regionName);
m_pollServiceHandlers.Add(capName, pollServiceHandler); if(!m_pollServiceHandlers.TryAdd(capName, pollServiceHandler))
{
m_log.ErrorFormat(
"[CAPS]: Handler with name {0} already registered (ulr {1}, agent {2}, region {3}",
capName, pollServiceHandler.Url, m_agentID, m_regionName);
return;
}
m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler); m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler);
// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; // uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
// string protocol = "http"; // string protocol = "http";
@ -223,7 +230,7 @@ namespace OpenSim.Framework.Capabilities
foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values) foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values)
{ {
m_httpListener.RemovePollServiceHTTPHandler("", handler.Url); m_httpListener.RemovePollServiceHTTPHandler(handler.Url);
} }
m_pollServiceHandlers.Clear(); m_pollServiceHandlers.Clear();
} }

View File

@ -426,8 +426,7 @@ namespace OpenSim.Framework.Console
// This call is a CAP. The URL is the authentication. // This call is a CAP. The URL is the authentication.
string uri = "/ReadResponses/" + sessionID.ToString() + "/"; string uri = "/ReadResponses/" + sessionID.ToString() + "/";
m_Server.AddPollServiceHTTPHandler( m_Server.AddPollServiceHTTPHandler(new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, null, sessionID,25000)); // 25 secs timeout
uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, null, sessionID,25000)); // 25 secs timeout
// Our reply is an XML document. // Our reply is an XML document.
// TODO: Change this to Linq.Xml // TODO: Change this to Linq.Xml

View File

@ -28,6 +28,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
@ -97,11 +98,11 @@ namespace OpenSim.Framework.Servers.HttpServer
protected Dictionary<string, bool> m_rpcHandlersKeepAlive = new Dictionary<string, bool>(); protected Dictionary<string, bool> m_rpcHandlersKeepAlive = new Dictionary<string, bool>();
protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/ protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/
protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>(); protected ConcurrentDictionary<string, IRequestHandler> m_streamHandlers = new ConcurrentDictionary<string, IRequestHandler>();
protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>(); protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>();
// protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>(); // protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>();
protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = protected ConcurrentDictionary<string, PollServiceEventArgs> m_pollHandlers =
new Dictionary<string, PollServiceEventArgs>(); new ConcurrentDictionary<string, PollServiceEventArgs>();
protected Dictionary<string, WebSocketRequestDelegate> m_WebSocketHandlers = protected Dictionary<string, WebSocketRequestDelegate> m_WebSocketHandlers =
new Dictionary<string, WebSocketRequestDelegate>(); new Dictionary<string, WebSocketRequestDelegate>();
@ -328,14 +329,17 @@ namespace OpenSim.Framework.Servers.HttpServer
string path = handler.Path; string path = handler.Path;
string handlerKey = GetHandlerKey(httpMethod, path); string handlerKey = GetHandlerKey(httpMethod, path);
lock (m_streamHandlers)
{
if (!m_streamHandlers.ContainsKey(handlerKey))
{
// m_log.DebugFormat("[BASE HTTP SERVER]: Adding handler key {0}", handlerKey); // m_log.DebugFormat("[BASE HTTP SERVER]: Adding handler key {0}", handlerKey);
m_streamHandlers.Add(handlerKey, handler); m_streamHandlers.TryAdd(handlerKey, handler);
} }
}
public void AddGenericStreamHandler(IRequestHandler handler)
{
if(String.IsNullOrWhiteSpace(handler.Path))
return;
// m_log.DebugFormat("[BASE HTTP SERVER]: Adding handler key {0}", handlerKey);
m_streamHandlers.TryAdd(handler.Path, handler);
} }
public void AddWebSocketHandler(string servicepath, WebSocketRequestDelegate handler) public void AddWebSocketHandler(string servicepath, WebSocketRequestDelegate handler)
@ -356,8 +360,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public List<string> GetStreamHandlerKeys() public List<string> GetStreamHandlerKeys()
{ {
lock (m_streamHandlers) return new List<string>(m_streamHandlers.Keys);
return new List<string>(m_streamHandlers.Keys);
} }
private static string GetHandlerKey(string httpMethod, string path) private static string GetHandlerKey(string httpMethod, string path)
@ -456,24 +459,19 @@ namespace OpenSim.Framework.Servers.HttpServer
return new List<string>(m_HTTPHandlers.Keys); return new List<string>(m_HTTPHandlers.Keys);
} }
public bool AddPollServiceHTTPHandler(string methodName, PollServiceEventArgs args) public bool AddPollServiceHTTPHandler(string url, PollServiceEventArgs args)
{ {
lock (m_pollHandlers) return m_pollHandlers.TryAdd(url, args);
{ }
if (!m_pollHandlers.ContainsKey(methodName))
{
m_pollHandlers.Add(methodName, args);
return true;
}
}
return false; public bool AddPollServiceHTTPHandler(PollServiceEventArgs args)
{
return m_pollHandlers.TryAdd(args.Url, args);
} }
public List<string> GetPollServiceHandlerKeys() public List<string> GetPollServiceHandlerKeys()
{ {
lock (m_pollHandlers) return new List<string>(m_pollHandlers.Keys);
return new List<string>(m_pollHandlers.Keys);
} }
// // Note that the agent string is provided simply to differentiate // // Note that the agent string is provided simply to differentiate
@ -533,7 +531,7 @@ namespace OpenSim.Framework.Servers.HttpServer
IHttpClientContext context = (IHttpClientContext)source; IHttpClientContext context = (IHttpClientContext)source;
IHttpRequest request = args.Request; IHttpRequest request = args.Request;
if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out PollServiceEventArgs psEvArgs)) if (TryGetPollServiceHTTPHandler(request.UriPath, out PollServiceEventArgs psEvArgs))
{ {
psEvArgs.RequestsReceived++; psEvArgs.RequestsReceived++;
PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request);
@ -567,15 +565,7 @@ namespace OpenSim.Framework.Servers.HttpServer
} }
OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request)); OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request));
HandleRequest(req, resp); HandleRequest(req, resp);
// !!!HACK ALERT!!!
// There seems to be a bug in the underlying http code that makes subsequent requests
// come up with trash in Accept headers. Until that gets fixed, we're cleaning them up here.
if (request.AcceptTypes != null)
for (int i = 0; i < request.AcceptTypes.Length; i++)
request.AcceptTypes[i] = string.Empty;
} }
/// <summary> /// <summary>
@ -999,6 +989,9 @@ namespace OpenSim.Framework.Servers.HttpServer
private bool TryGetPollServiceHTTPHandler(string handlerKey, out PollServiceEventArgs oServiceEventArgs) private bool TryGetPollServiceHTTPHandler(string handlerKey, out PollServiceEventArgs oServiceEventArgs)
{ {
if(m_pollHandlers.TryGetValue(handlerKey, out oServiceEventArgs))
return true;
string bestMatch = null; string bestMatch = null;
lock (m_pollHandlers) lock (m_pollHandlers)
@ -2109,12 +2102,19 @@ namespace OpenSim.Framework.Servers.HttpServer
public void RemoveStreamHandler(string httpMethod, string path) public void RemoveStreamHandler(string httpMethod, string path)
{ {
if (m_streamHandlers.TryRemove(path, out IRequestHandler dummy))
return;
string handlerKey = GetHandlerKey(httpMethod, path); string handlerKey = GetHandlerKey(httpMethod, path);
//m_log.DebugFormat("[BASE HTTP SERVER]: Removing handler key {0}", handlerKey); //m_log.DebugFormat("[BASE HTTP SERVER]: Removing handler key {0}", handlerKey);
lock (m_streamHandlers) m_streamHandlers.TryRemove(handlerKey, out dummy);
m_streamHandlers.Remove(handlerKey); }
public void RemoveStreamHandler(string path)
{
m_streamHandlers.TryRemove(path, out IRequestHandler dummy);
} }
public void RemoveHTTPHandler(string httpMethod, string path) public void RemoveHTTPHandler(string httpMethod, string path)
@ -2134,25 +2134,29 @@ namespace OpenSim.Framework.Servers.HttpServer
public void RemovePollServiceHTTPHandler(string httpMethod, string path) public void RemovePollServiceHTTPHandler(string httpMethod, string path)
{ {
lock (m_pollHandlers) m_pollHandlers.TryRemove(path, out PollServiceEventArgs dummy);
m_pollHandlers.Remove(path);
} }
// public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) public void RemovePollServiceHTTPHandler(string path)
// { {
// lock (m_agentHandlers) m_pollHandlers.TryRemove(path, out PollServiceEventArgs dummy);
// { }
// IHttpAgentHandler foundHandler;
// // public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler)
// if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) // {
// { // lock (m_agentHandlers)
// m_agentHandlers.Remove(agent); // {
// return true; // IHttpAgentHandler foundHandler;
// } //
// } // if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler)
// // {
// return false; // m_agentHandlers.Remove(agent);
// } // return true;
// }
// }
//
// return false;
// }
public void RemoveXmlRPCHandler(string method) public void RemoveXmlRPCHandler(string method)
{ {

View File

@ -62,24 +62,6 @@ namespace OpenSim.Framework.Servers.HttpServer
Description = description; Description = description;
m_httpMethod = httpMethod; m_httpMethod = httpMethod;
m_path = path; m_path = path;
// FIXME: A very temporary measure to stop the simulator stats being overwhelmed with user CAPS info.
// Needs to be fixed properly in stats display
if (!path.StartsWith("/CAPS/"))
{
StatsManager.RegisterStat(
new Stat(
"requests",
"requests",
"Number of requests received by this service endpoint",
"requests",
"service",
string.Format("{0}:{1}", httpMethod, path),
StatType.Pull,
MeasuresOfInterest.AverageChangeOverTime,
s => s.Value = RequestsReceived,
StatVerbosity.Debug));
}
} }
public virtual string Path public virtual string Path

View File

@ -399,7 +399,7 @@ namespace OpenSim.Region.ClientStack.Linden
PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene); PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene);
//args.Type = PollServiceEventArgs.EventType.Texture; //args.Type = PollServiceEventArgs.EventType.Texture;
MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); MainServer.Instance.AddPollServiceHTTPHandler(args);
if (handler != null) if (handler != null)
handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", capUrl); handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", capUrl);
@ -419,7 +419,7 @@ namespace OpenSim.Region.ClientStack.Linden
PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene); PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene);
//args.Type = PollServiceEventArgs.EventType.Mesh; //args.Type = PollServiceEventArgs.EventType.Mesh;
MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); MainServer.Instance.AddPollServiceHTTPHandler(args);
if (handler != null) if (handler != null)
handler.RegisterExternalUserCapsHandler(agentID, caps, "GetMesh", capUrl); handler.RegisterExternalUserCapsHandler(agentID, caps, "GetMesh", capUrl);
@ -437,7 +437,7 @@ namespace OpenSim.Region.ClientStack.Linden
PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene); PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene);
//args.Type = PollServiceEventArgs.EventType.Mesh2; //args.Type = PollServiceEventArgs.EventType.Mesh2;
MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); MainServer.Instance.AddPollServiceHTTPHandler(args);
if (handler != null) if (handler != null)
handler.RegisterExternalUserCapsHandler(agentID, caps, "GetMesh2", capUrl); handler.RegisterExternalUserCapsHandler(agentID, caps, "GetMesh2", capUrl);
@ -456,7 +456,7 @@ namespace OpenSim.Region.ClientStack.Linden
PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene); PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene);
//args.Type = PollServiceEventArgs.EventType.Asset; //args.Type = PollServiceEventArgs.EventType.Asset;
MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); MainServer.Instance.AddPollServiceHTTPHandler(args);
if (handler != null) if (handler != null)
handler.RegisterExternalUserCapsHandler(agentID, caps, "ViewerAsset", capUrl); handler.RegisterExternalUserCapsHandler(agentID, caps, "ViewerAsset", capUrl);
@ -473,23 +473,23 @@ namespace OpenSim.Region.ClientStack.Linden
string capUrl; string capUrl;
if (m_capsDictTexture.TryGetValue(agentID, out capUrl)) if (m_capsDictTexture.TryGetValue(agentID, out capUrl))
{ {
MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); MainServer.Instance.RemovePollServiceHTTPHandler(capUrl);
m_capsDictTexture.Remove(agentID); m_capsDictTexture.Remove(agentID);
} }
if (m_capsDictGetMesh.TryGetValue(agentID, out capUrl)) if (m_capsDictGetMesh.TryGetValue(agentID, out capUrl))
{ {
MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); MainServer.Instance.RemovePollServiceHTTPHandler(capUrl);
m_capsDictGetMesh.Remove(agentID); m_capsDictGetMesh.Remove(agentID);
} }
if (m_capsDictGetMesh2.TryGetValue(agentID, out capUrl)) if (m_capsDictGetMesh2.TryGetValue(agentID, out capUrl))
{ {
MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); MainServer.Instance.RemovePollServiceHTTPHandler(capUrl);
m_capsDictGetMesh2.Remove(agentID); m_capsDictGetMesh2.Remove(agentID);
} }
if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl)) if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl))
{ {
MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); MainServer.Instance.RemovePollServiceHTTPHandler(capUrl);
m_capsDictGetAsset.Remove(agentID); m_capsDictGetAsset.Remove(agentID);
} }
} }

View File

@ -262,7 +262,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
PollServiceEventArgs args PollServiceEventArgs args
= new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, Drop, urlcode, 25000); = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, Drop, urlcode, 25000);
//args.Type = PollServiceEventArgs.EventType.LslHttp; //args.Type = PollServiceEventArgs.EventType.LslHttp;
m_HttpServer.AddPollServiceHTTPHandler(uri, args); m_HttpServer.AddPollServiceHTTPHandler(args);
// m_log.DebugFormat( // m_log.DebugFormat(
// "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", // "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}",
@ -320,7 +320,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
PollServiceEventArgs args PollServiceEventArgs args
= new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, Drop, urlcode, 25000); = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, Drop, urlcode, 25000);
//args.Type = PollServiceEventArgs.EventType.LslHttp; //args.Type = PollServiceEventArgs.EventType.LslHttp;
m_HttpsServer.AddPollServiceHTTPHandler(uri, args); m_HttpsServer.AddPollServiceHTTPHandler(args);
// m_log.DebugFormat( // m_log.DebugFormat(
// "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", // "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}",