Merge branch 'master' into careminster

Conflicts:
	OpenSim/Framework/WebUtil.cs
	OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
	OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
	OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
	OpenSim/Region/Framework/Scenes/ScenePresence.cs
This commit is contained in:
Melanie
2012-05-05 10:32:04 +01:00
60 changed files with 831 additions and 363 deletions

View File

@@ -33,9 +33,9 @@ namespace OpenSim.Framework.Servers.HttpServer
{
public abstract Hashtable Handle(string path, Hashtable Request);
protected BaseHTTPHandler(string httpMethod, string path)
: base(httpMethod, path)
{
}
protected BaseHTTPHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
protected BaseHTTPHandler(string httpMethod, string path, string name, string description)
: base(httpMethod, path, name, description) {}
}
}
}

View File

@@ -156,7 +156,7 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
public List<string> GetStreamHandlerKeys()
public List<string> GetStreamHandlerKeys()
{
lock (m_streamHandlers)
return new List<string>(m_streamHandlers.Keys);
@@ -410,6 +410,8 @@ namespace OpenSim.Framework.Servers.HttpServer
// string reqnum = "unknown";
int tickstart = Environment.TickCount;
IRequestHandler requestHandler = null;
try
{
// OpenSim.Framework.WebUtil.OSHeaderRequestID
@@ -438,8 +440,6 @@ namespace OpenSim.Framework.Servers.HttpServer
//response.KeepAlive = true;
response.SendChunked = false;
IRequestHandler requestHandler;
string path = request.RawUrl;
string handlerKey = GetHandlerKey(request.HttpMethod, path);
@@ -675,8 +675,16 @@ namespace OpenSim.Framework.Servers.HttpServer
// since its just for reporting, tickdiff limit can be adjusted
int tickdiff = Environment.TickCount - tickstart;
if (tickdiff > 3000)
{
m_log.InfoFormat(
"[BASE HTTP SERVER]: slow {0} request for {1} from {2} took {3} ms", requestMethod, uriString, request.RemoteIPEndPoint.ToString(), tickdiff);
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms",
requestMethod,
uriString,
requestHandler != null ? requestHandler.Name : "",
requestHandler != null ? requestHandler.Description : "",
request.RemoteIPEndPoint.ToString(),
tickdiff);
}
}
}

View File

@@ -45,8 +45,16 @@ namespace OpenSim.Framework.Servers.HttpServer
private readonly string m_path;
protected BaseRequestHandler(string httpMethod, string path)
public string Name { get; private set; }
public string Description { get; private set; }
protected BaseRequestHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
protected BaseRequestHandler(string httpMethod, string path, string name, string description)
{
Name = name;
Description = description;
m_httpMethod = httpMethod;
m_path = path;
}

View File

@@ -34,8 +34,9 @@ namespace OpenSim.Framework.Servers.HttpServer
public abstract byte[] Handle(string path, Stream request,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse);
protected BaseStreamHandler(string httpMethod, string path) : base(httpMethod, path)
{
}
protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
protected BaseStreamHandler(string httpMethod, string path, string name, string description)
: base(httpMethod, path, name, description) {}
}
}
}

View File

@@ -36,6 +36,15 @@ namespace OpenSim.Framework.Servers.HttpServer
{
private BinaryMethod m_method;
public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod)
: this(httpMethod, path, binaryMethod, null, null) {}
public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod, string name, string description)
: base(httpMethod, path, name, description)
{
m_method = binaryMethod;
}
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
byte[] data = ReadFully(request);
@@ -45,12 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
return Encoding.UTF8.GetBytes(responseString);
}
public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod)
: base(httpMethod, path)
{
m_method = binaryMethod;
}
private static byte[] ReadFully(Stream stream)
{
byte[] buffer = new byte[1024];
@@ -70,4 +73,4 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
}
}
}

View File

@@ -32,6 +32,25 @@ namespace OpenSim.Framework.Servers.HttpServer
{
public interface IRequestHandler
{
/// <summary>
/// Name for this handler.
/// </summary>
/// <remarks>
/// Used for diagnostics. The path doesn't always describe what the handler does. Can be null if none
/// specified.
/// </remarks>
string Name { get; }
/// <summary>
/// Description for this handler.
/// </summary>
/// <remarks>
/// Used for diagnostics. The path doesn't always describe what the handler does. Can be null if none
/// specified.
/// </remarks>
string Description { get; }
// Return response content type
string ContentType { get; }
@@ -58,4 +77,4 @@ namespace OpenSim.Framework.Servers.HttpServer
{
Hashtable Handle(string path, Hashtable request);
}
}
}

View File

@@ -39,7 +39,11 @@ namespace OpenSim.Framework.Servers.HttpServer
private RestDeserialiseMethod<TRequest, TResponse> m_method;
public RestDeserialiseHandler(string httpMethod, string path, RestDeserialiseMethod<TRequest, TResponse> method)
: base(httpMethod, path)
: this(httpMethod, path, method, null, null) {}
public RestDeserialiseHandler(
string httpMethod, string path, RestDeserialiseMethod<TRequest, TResponse> method, string name, string description)
: base(httpMethod, path, name, description)
{
m_method = method;
}

View File

@@ -38,19 +38,25 @@ namespace OpenSim.Framework.Servers.HttpServer
get { return m_dhttpMethod; }
}
public override Hashtable Handle(string path, Hashtable request)
{
string param = GetParam(path);
request.Add("param", param);
request.Add("path", path);
return m_dhttpMethod(request);
}
public RestHTTPHandler(string httpMethod, string path, GenericHTTPMethod dhttpMethod)
: base(httpMethod, path)
{
m_dhttpMethod = dhttpMethod;
}
public RestHTTPHandler(
string httpMethod, string path, GenericHTTPMethod dhttpMethod, string name, string description)
: base(httpMethod, path, name, description)
{
m_dhttpMethod = dhttpMethod;
}
public override Hashtable Handle(string path, Hashtable request)
{
string param = GetParam(path);
request.Add("param", param);
request.Add("path", path);
return m_dhttpMethod(request);
}
}
}

View File

@@ -39,6 +39,15 @@ namespace OpenSim.Framework.Servers.HttpServer
get { return m_restMethod; }
}
public RestStreamHandler(string httpMethod, string path, RestMethod restMethod)
: this(httpMethod, path, restMethod, null, null) {}
public RestStreamHandler(string httpMethod, string path, RestMethod restMethod, string name, string description)
: base(httpMethod, path, name, description)
{
m_restMethod = restMethod;
}
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
Encoding encoding = Encoding.UTF8;
@@ -52,10 +61,5 @@ namespace OpenSim.Framework.Servers.HttpServer
return Encoding.UTF8.GetBytes(responseString);
}
public RestStreamHandler(string httpMethod, string path, RestMethod restMethod) : base(httpMethod, path)
{
m_restMethod = restMethod;
}
}
}

View File

@@ -26,6 +26,8 @@
*/
using System;
using System.Reflection;
using log4net;
using OpenMetaverse;
namespace OpenSim.Framework
@@ -35,6 +37,8 @@ namespace OpenSim.Framework
/// </summary>
public class TaskInventoryItem : ICloneable
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// XXX This should really be factored out into some constants class.
/// </summary>
@@ -334,12 +338,18 @@ namespace OpenSim.Framework
}
}
public bool OwnerChanged {
get {
public bool OwnerChanged
{
get
{
return _ownerChanged;
}
set {
set
{
_ownerChanged = value;
// m_log.DebugFormat(
// "[TASK INVENTORY ITEM]: Owner changed set {0} for {1} {2} owned by {3}",
// _ownerChanged, Name, ItemID, OwnerID);
}
}

View File

@@ -53,19 +53,36 @@ namespace OpenSim.Framework
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private static int m_requestNumber = 0;
/// <summary>
/// Request number for diagnostic purposes.
/// </summary>
public static int RequestNumber = 0;
// this is the header field used to communicate the local request id
// used for performance and debugging
/// <summary>
/// this is the header field used to communicate the local request id
/// used for performance and debugging
/// </summary>
public const string OSHeaderRequestID = "opensim-request-id";
// number of milliseconds a call can take before it is considered
// a "long" call for warning & debugging purposes
public const int LongCallTime = 500;
/// <summary>
/// Number of milliseconds a call can take before it is considered
/// a "long" call for warning & debugging purposes
/// </summary>
public const int LongCallTime = 3000;
// dictionary of end points
/// <summary>
/// The maximum length of any data logged because of a long request time.
/// </summary>
/// <remarks>
/// This is to truncate any really large post data, such as an asset. In theory, the first section should
/// give us useful information about the call (which agent it relates to if applicable, etc.).
/// </remarks>
public const int MaxRequestDiagLength = 100;
/// <summary>
/// Dictionary of end points
/// </summary>
private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>();
private static object EndPointLock(string url)
{
@@ -128,12 +145,13 @@ namespace OpenSim.Framework
private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
{
int reqnum = m_requestNumber++;
int reqnum = RequestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
string errorMessage = "unknown error";
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
string strBuffer = null;
try
{
@@ -148,7 +166,7 @@ namespace OpenSim.Framework
// If there is some input, write it into the request
if (data != null)
{
string strBuffer = OSDParser.SerializeJsonString(data);
strBuffer = OSDParser.SerializeJsonString(data);
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
if (compressed)
@@ -209,11 +227,18 @@ namespace OpenSim.Framework
}
finally
{
// This just dumps a warning for any operation that takes more than 100 ms
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > LongCallTime)
m_log.DebugFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing",
reqnum,url,method,tickdiff,tickdata);
m_log.InfoFormat(
"[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
method,
url,
tickdiff,
tickdata,
strBuffer != null
? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
: "");
}
m_log.DebugFormat(
@@ -291,17 +316,17 @@ namespace OpenSim.Framework
private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout)
{
int reqnum = m_requestNumber++;
int reqnum = RequestNumber++;
string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
// m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
string errorMessage = "unknown error";
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
string queryString = null;
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "POST";
request.Timeout = timeout;
@@ -312,7 +337,7 @@ namespace OpenSim.Framework
if (data != null)
{
string queryString = BuildQueryString(data);
queryString = BuildQueryString(data);
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
request.ContentLength = buffer.Length;
@@ -355,11 +380,19 @@ namespace OpenSim.Framework
{
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > LongCallTime)
m_log.InfoFormat("[WEB UTIL]: form request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing",
reqnum,url,method,tickdiff,tickdata);
m_log.InfoFormat(
"[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
method,
url,
tickdiff,
tickdata,
queryString != null
? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
: "");
}
m_log.WarnFormat("[WEB UTIL]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
return ErrorResponseMap(errorMessage);
}
@@ -640,8 +673,6 @@ namespace OpenSim.Framework
return new string[0];
}
}
public static class AsynchronousRestObjectRequester
@@ -664,6 +695,12 @@ namespace OpenSim.Framework
public static void MakeRequest<TRequest, TResponse>(string verb,
string requestUrl, TRequest obj, Action<TResponse> action)
{
int reqnum = WebUtil.RequestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
Type type = typeof(TRequest);
@@ -674,12 +711,13 @@ namespace OpenSim.Framework
XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
request.Method = verb;
MemoryStream buffer = null;
if (verb == "POST")
{
request.ContentType = "text/xml";
MemoryStream buffer = new MemoryStream();
buffer = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
@@ -701,6 +739,9 @@ namespace OpenSim.Framework
requestStream.Write(buffer.ToArray(), 0, length);
requestStream.Close();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
request.BeginGetResponse(delegate(IAsyncResult ar)
{
response = request.EndGetResponse(ar);
@@ -726,88 +767,108 @@ namespace OpenSim.Framework
}, null);
}, null);
return;
}
request.BeginGetResponse(delegate(IAsyncResult res2)
else
{
try
request.BeginGetResponse(delegate(IAsyncResult res2)
{
// If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
// documented in MSDN
response = request.EndGetResponse(res2);
Stream respStream = null;
try
{
respStream = response.GetResponseStream();
deserial = (TResponse)deserializer.Deserialize(respStream);
}
catch (System.InvalidOperationException)
{
}
finally
{
respStream.Close();
response.Close();
}
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.ProtocolError)
{
if (e.Response is HttpWebResponse)
// If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
// documented in MSDN
response = request.EndGetResponse(res2);
Stream respStream = null;
try
{
HttpWebResponse httpResponse = (HttpWebResponse)e.Response;
if (httpResponse.StatusCode != HttpStatusCode.NotFound)
{
// We don't appear to be handling any other status codes, so log these feailures to that
// people don't spend unnecessary hours hunting phantom bugs.
m_log.DebugFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}",
verb, requestUrl, httpResponse.StatusCode);
}
respStream = response.GetResponseStream();
deserial = (TResponse)deserializer.Deserialize(respStream);
}
catch (System.InvalidOperationException)
{
}
finally
{
respStream.Close();
response.Close();
}
}
else
catch (WebException e)
{
if (e.Status == WebExceptionStatus.ProtocolError)
{
if (e.Response is HttpWebResponse)
{
HttpWebResponse httpResponse = (HttpWebResponse)e.Response;
if (httpResponse.StatusCode != HttpStatusCode.NotFound)
{
// We don't appear to be handling any other status codes, so log these feailures to that
// people don't spend unnecessary hours hunting phantom bugs.
m_log.DebugFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}",
verb, requestUrl, httpResponse.StatusCode);
}
}
}
else
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}",
verb, requestUrl, e.Status, e.Message);
}
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}",
verb, requestUrl, e.Status, e.Message);
"[ASYNC REQUEST]: Request {0} {1} failed with exception {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
}
}
catch (Exception e)
// m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
try
{
action(deserial);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
}
}, null);
}
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > WebUtil.LongCallTime)
{
string originalRequest = null;
if (buffer != null)
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} failed with exception {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
}
// m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
try
{
action(deserial);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}{3}",
verb, requestUrl, e.Message, e.StackTrace);
}
}, null);
m_log.InfoFormat(
"[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
verb,
requestUrl,
tickdiff,
tickdata,
originalRequest);
}
}
}
public static class SynchronousRestFormsRequester
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Perform a synchronous REST request.
@@ -821,6 +882,12 @@ namespace OpenSim.Framework
/// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
public static string MakeRequest(string verb, string requestUrl, string obj)
{
int reqnum = WebUtil.RequestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
WebRequest request = WebRequest.Create(requestUrl);
request.Method = verb;
string respstring = String.Empty;
@@ -856,6 +923,9 @@ namespace OpenSim.Framework
{
if (requestStream != null)
requestStream.Close();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
}
}
@@ -894,6 +964,18 @@ namespace OpenSim.Framework
m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving {0} {1}", verb, requestUrl);
}
}
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > WebUtil.LongCallTime)
m_log.InfoFormat(
"[FORMS]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
verb,
requestUrl,
tickdiff,
tickdata,
obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
return respstring;
}
}
@@ -921,6 +1003,12 @@ namespace OpenSim.Framework
public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout)
{
int reqnum = WebUtil.RequestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
int tickstart = Util.EnvironmentTickCount();
int tickdata = 0;
Type type = typeof(TRequest);
TResponse deserial = default(TResponse);
@@ -928,12 +1016,13 @@ namespace OpenSim.Framework
request.Method = verb;
if (pTimeout != 0)
request.Timeout = pTimeout * 1000;
MemoryStream buffer = null;
if ((verb == "POST") || (verb == "PUT"))
{
request.ContentType = "text/xml";
MemoryStream buffer = new MemoryStream();
buffer = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
@@ -966,6 +1055,9 @@ namespace OpenSim.Framework
{
if (requestStream != null)
requestStream.Close();
// capture how much time was spent writing
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
}
}
@@ -1013,7 +1105,30 @@ namespace OpenSim.Framework
verb, requestUrl, e.Message, e.StackTrace);
}
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > WebUtil.LongCallTime)
{
string originalRequest = null;
if (buffer != null)
{
originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
}
m_log.InfoFormat(
"[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
reqnum,
verb,
requestUrl,
tickdiff,
tickdata,
originalRequest);
}
return deserial;
}
}
}
}