From ca754b0156a63411730be1d6472a3c4c51c7efc3 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 2 Dec 2018 16:17:23 +0000 Subject: [PATCH] avoid a data copy --- .../Handlers/GetAssets/GetAssetsHandler.cs | 25 ++-- .../HttpServer/PollServiceHttpRequest.cs | 112 ++++++++++-------- 2 files changed, 69 insertions(+), 68 deletions(-) diff --git a/OpenSim/Capabilities/Handlers/GetAssets/GetAssetsHandler.cs b/OpenSim/Capabilities/Handlers/GetAssets/GetAssetsHandler.cs index 92608a64a4..ef6499994c 100644 --- a/OpenSim/Capabilities/Handlers/GetAssets/GetAssetsHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetAssets/GetAssetsHandler.cs @@ -139,22 +139,21 @@ namespace OpenSim.Capabilities.Handlers // if(type != AssetType.Mesh && type != AssetType.Texture) // m_log.Warn("[GETASSETS]: type: " + query); + responsedata["content_type"] = asset.Metadata.ContentType; + responsedata["bin_response_data"] = asset.Data; + responsedata["int_bytes"] = asset.Data.Length; + responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK; + string range = String.Empty; if (((Hashtable)request["headers"])["range"] != null) range = (string)((Hashtable)request["headers"])["range"]; else if (((Hashtable)request["headers"])["Range"] != null) range = (string)((Hashtable)request["headers"])["Range"]; - - responsedata["content_type"] = asset.Metadata.ContentType; + else + return responsedata; // full asset if (String.IsNullOrEmpty(range)) - { - // full asset - responsedata["bin_response_data"] = asset.Data; - responsedata["int_bytes"] = asset.Data.Length; - responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK; - return responsedata; - } + return responsedata; // full asset // range request int start, end; @@ -181,18 +180,12 @@ namespace OpenSim.Capabilities.Handlers headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, asset.Data.Length); responsedata["headers"] = headers; responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent; - - byte[] d = new byte[len]; - Array.Copy(asset.Data, start, d, 0, len); - responsedata["bin_response_data"] = d; + responsedata["bin_start"] = start; responsedata["int_bytes"] = len; return responsedata; } m_log.Warn("[GETASSETS]: Failed to parse a range, sending full asset: " + assetStr); - responsedata["bin_response_data"] = asset.Data; - responsedata["int_bytes"] = asset.Data.Length; - responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK; return responsedata; } } diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs index cf4f835002..66fd2c6fca 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs @@ -81,44 +81,18 @@ namespace OpenSim.Framework.Servers.HttpServer internal void DoHTTPGruntWork(Hashtable responsedata) { + if (Request.Body.CanRead) + Request.Body.Dispose(); + OSHttpResponse response = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext); - byte[] buffer = srvDoHTTPGruntWork(responsedata, response); - - if(Request.Body.CanRead) - Request.Body.Dispose(); - - response.SendChunked = false; - response.ContentLength64 = buffer.Length; - - try - { - response.OutputStream.Write(buffer, 0, buffer.Length); - response.Send(); - buffer = null; - } - catch (Exception ex) - { - if(ex is System.Net.Sockets.SocketException) - { - // only mute connection reset by peer so we are not totally blind for now - if(((System.Net.Sockets.SocketException)ex).SocketErrorCode != System.Net.Sockets.SocketError.ConnectionReset) - m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex); - } - else - m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex); - } - - PollServiceArgs.RequestsHandled++; - } - - internal byte[] srvDoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) - { - int responsecode; + int responsecode = 200; string responseString = String.Empty; - byte[] responseBytes = null; string contentType; + byte[] buffer = null; + int rangeStart = 0; + int rangeLen = -1; if (responsedata == null) { @@ -132,12 +106,23 @@ namespace OpenSim.Framework.Servers.HttpServer try { //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); - responsecode = (int)responsedata["int_response_code"]; + if(responsedata["int_response_code"] != null) + responsecode = (int)responsedata["int_response_code"]; if (responsedata["bin_response_data"] != null) - responseBytes = (byte[])responsedata["bin_response_data"]; + { + buffer = (byte[])responsedata["bin_response_data"]; + responsedata["bin_response_data"] = null; + + if (responsedata["bin_start"] != null) + rangeStart = (int)responsedata["bin_start"]; + + if (responsedata["int_bytes"] != null) + rangeLen = (int)responsedata["int_bytes"]; + } else responseString = (string)responsedata["str_response_string"]; + contentType = (string)responsedata["content_type"]; if (responseString == null) responseString = String.Empty; @@ -159,7 +144,6 @@ namespace OpenSim.Framework.Servers.HttpServer { response.ProtocolVersion = (string)responsedata["http_protocol_version"]; } - if (responsedata.ContainsKey("keepalive")) { bool keepalive = (bool)responsedata["keepalive"]; @@ -170,13 +154,6 @@ namespace OpenSim.Framework.Servers.HttpServer if (responsedata.ContainsKey("access_control_allow_origin")) response.AddHeader("Access-Control-Allow-Origin", (string)responsedata["access_control_allow_origin"]); - if (string.IsNullOrEmpty(contentType)) - { - contentType = "text/html"; - } - - // The client ignores anything but 200 here for web login, so ensure that this is 200 for that - response.StatusCode = responsecode; if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) @@ -184,7 +161,11 @@ namespace OpenSim.Framework.Servers.HttpServer response.RedirectLocation = (string)responsedata["str_redirect_location"]; } - response.AddHeader("Content-Type", contentType); + if (string.IsNullOrEmpty(contentType)) + response.AddHeader("Content-Type", "text/html"); + else + response.AddHeader("Content-Type", contentType); + if (responsedata.ContainsKey("headers")) { Hashtable headerdata = (Hashtable)responsedata["headers"]; @@ -193,13 +174,7 @@ namespace OpenSim.Framework.Servers.HttpServer response.AddHeader(header, headerdata[header].ToString()); } - byte[] buffer; - - if (responseBytes != null) - { - buffer = responseBytes; - } - else + if(buffer == null) { if (!(contentType.Contains("image") || contentType.Contains("x-shockwave-flash") @@ -217,8 +192,41 @@ namespace OpenSim.Framework.Servers.HttpServer response.ContentEncoding = Encoding.UTF8; } - return buffer; + if (rangeStart < 0 || rangeStart > buffer.Length) + rangeStart = 0; + + if (rangeLen < 0) + rangeLen = buffer.Length; + else if (rangeLen + rangeStart > buffer.Length) + rangeLen = buffer.Length - rangeStart; + + response.SendChunked = false; + response.ContentLength64 = rangeLen; + + try + { + if(rangeLen > 0) + response.OutputStream.Write(buffer, rangeStart, rangeLen); + + buffer = null; + + response.Send(); + } + catch (Exception ex) + { + if(ex is System.Net.Sockets.SocketException) + { + // only mute connection reset by peer so we are not totally blind for now + if(((System.Net.Sockets.SocketException)ex).SocketErrorCode != System.Net.Sockets.SocketError.ConnectionReset) + m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex); + } + else + m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex); + } + + PollServiceArgs.RequestsHandled++; } + internal void DoHTTPstop() { OSHttpResponse response