diff --git a/OpenSim/Framework/RestClient.cs b/OpenSim/Framework/RestClient.cs index 4939cf7bfd..21b99cb30d 100644 --- a/OpenSim/Framework/RestClient.cs +++ b/OpenSim/Framework/RestClient.cs @@ -32,6 +32,7 @@ using System.Net; using System.Reflection; using System.Text; using System.Threading; +using System.Threading.Tasks; using System.Web; using log4net; @@ -117,8 +118,7 @@ namespace OpenSim.Framework /// /// Default Buffer size of a block requested from the web-server /// - private const int BufferSize = 4096; // Read blocks of 4 KB. - + private const int BufferSize = 4 * 4096; // Read blocks of 4 * 4 KB. /// /// if an exception occours during async processing, we need to save it, so it can be @@ -181,10 +181,7 @@ namespace OpenSim.Framework /// path entry public void AddResourcePath(string element) { - if (isSlashed(element)) - _pathElements.Add(element.Substring(0, element.Length - 1)); - else - _pathElements.Add(element); + _pathElements.Add(Util.TrimEndSlash(element)); } /// @@ -237,16 +234,6 @@ namespace OpenSim.Framework set { _method = value; } } - /// - /// True if string contains a trailing slash '/' - /// - /// string to be examined - /// true if slash is present - private static bool isSlashed(string s) - { - return s.Substring(s.Length - 1, 1) == "/"; - } - /// /// Build a Uri based on the initial Url, path elements and parameters /// @@ -339,9 +326,8 @@ namespace OpenSim.Framework lock (_lock) { _request = (HttpWebRequest) WebRequest.Create(buildUri()); - _request.KeepAlive = false; _request.ContentType = "application/xml"; - _request.Timeout = 200000; + _request.Timeout = 90000; _request.Method = RequestMethod; _asyncException = null; if (auth != null) @@ -351,8 +337,6 @@ namespace OpenSim.Framework if (WebUtil.DebugLevel >= 3) m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} REST {1} to {2}", reqnum, _request.Method, _request.RequestUri); -// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); - try { using (_response = (HttpWebResponse) _request.GetResponse()) @@ -365,12 +349,6 @@ namespace OpenSim.Framework _resource.Write(_readbuf, 0, length); length = src.Read(_readbuf, 0, BufferSize); } - - // TODO! Implement timeout, without killing the server - // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted - //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); - - // _allDone.WaitOne(); } } } @@ -391,7 +369,6 @@ namespace OpenSim.Framework return null; } - if (_asyncException != null) throw _asyncException; @@ -408,57 +385,39 @@ namespace OpenSim.Framework } } - public Stream Request(Stream src, IServiceAuth auth) + // just post data, ignoring result + public async Task AsyncPOSTRequest(byte[] src, IServiceAuth auth) { - _request = (HttpWebRequest) WebRequest.Create(buildUri()); - _request.KeepAlive = false; + _request = (HttpWebRequest)WebRequest.Create(buildUri()); _request.ContentType = "application/xml"; _request.Timeout = 90000; - _request.Method = RequestMethod; + _request.Method = "POST"; _asyncException = null; _request.ContentLength = src.Length; if (auth != null) auth.AddAuthorization(_request.Headers); - src.Seek(0, SeekOrigin.Begin); - int reqnum = WebUtil.RequestNumber++; - if (WebUtil.DebugLevel >= 3) - m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} REST {1} to {2}", reqnum, _request.Method, _request.RequestUri); - if (WebUtil.DebugLevel >= 5) - WebUtil.LogOutgoingDetail(string.Format("SEND {0}: ", reqnum), src); - - try { using (Stream dst = _request.GetRequestStream()) { -// m_log.Debug("[REST]: GetRequestStream is ok"); - - byte[] buf = new byte[1024]; - int length = src.Read(buf, 0, 1024); -// m_log.Debug("[REST]: First Read is ok"); - while (length > 0) - { - dst.Write(buf, 0, length); - length = src.Read(buf, 0, 1024); - } + await dst.WriteAsync(src, 0, src.Length).ConfigureAwait(false); } - - _response = (HttpWebResponse)_request.GetResponse(); + _response = (HttpWebResponse)await _request.GetResponseAsync().ConfigureAwait(false); } catch (WebException e) { m_log.WarnFormat("[REST]: Request {0} {1} failed with status {2} and message {3}", RequestMethod, _request.RequestUri, e.Status, e.Message); - return null; + return; } catch (Exception e) { m_log.WarnFormat( "[REST]: Request {0} {1} failed with exception {2} {3}", RequestMethod, _request.RequestUri, e.Message, e.StackTrace); - return null; + return; } if (WebUtil.DebugLevel >= 5) @@ -467,7 +426,7 @@ namespace OpenSim.Framework { using (StreamReader reader = new StreamReader(responseStream)) { - string responseStr = reader.ReadToEnd(); + string responseStr = await reader.ReadToEndAsync().ConfigureAwait(false); WebUtil.LogResponseDetail(reqnum, responseStr); } } @@ -475,14 +434,6 @@ namespace OpenSim.Framework if (_response != null) _response.Close(); - -// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); - - // TODO! Implement timeout, without killing the server - // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted - //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); - - return null; } #region Async Invocation diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs index b9f9298014..a8b79fec90 100644 --- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs @@ -35,6 +35,7 @@ using System.Xml.Serialization; using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Threading.Tasks; using log4net; using OpenSim.Framework; using OpenSim.Framework.ServiceAuth; @@ -187,13 +188,13 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures { } - public void Store(UUID agentId, WearableCacheItem[] data) + public async Task Store(UUID agentId, WearableCacheItem[] data) { if (m_URL == String.Empty) return; int numberWears = 0; - MemoryStream reqStream; + byte[] uploadData; using (MemoryStream bakeStream = new MemoryStream()) using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null)) @@ -236,25 +237,20 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures bakeWriter.WriteEndElement(); bakeWriter.Flush(); - reqStream = new MemoryStream(bakeStream.ToArray()); + uploadData = bakeStream.ToArray(); } - - Util.FireAndForget( - delegate - { + //Util.FireAndForget( + // delegate + // { using(RestClient rc = new RestClient(m_URL)) { - rc.AddResourcePath("bakes"); - rc.AddResourcePath(agentId.ToString()); - rc.RequestMethod = "POST"; - - rc.Request(reqStream, m_Auth); + rc.AddResourcePath("bakes/" + agentId.ToString()); + await rc.AsyncPOSTRequest(uploadData, m_Auth).ConfigureAwait(false); m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", numberWears, agentId); } - if(reqStream != null) - reqStream.Dispose(); - }, null, "XBakesModule.Store" - ); + uploadData = null; + // }, null, "XBakesModule.Store" + //); } } } diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs index 4d8409beeb..990ded2bc7 100644 --- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs @@ -26,6 +26,7 @@ */ using System; +using System.Threading.Tasks; using Nini.Config; using OpenSim.Framework; using OpenMetaverse; @@ -37,7 +38,7 @@ namespace OpenSim.Services.Interfaces WearableCacheItem[] Get(UUID id); void Store(UUID id); - void Store(UUID id, WearableCacheItem[] WearableCache); + Task Store(UUID id, WearableCacheItem[] WearableCache); void UpdateMeshAvatar(UUID id); } }