diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index d7abe4721f..32d4239b6d 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -197,6 +197,8 @@ namespace OpenSim.Framework public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool; public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod; + public static readonly string UUIDZeroString = UUID.Zero.ToString(); + public static bool IsPlatformMono { get { return Type.GetType("Mono.Runtime") != null; } diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 6472b090a7..23490bb8db 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -835,7 +835,7 @@ namespace OpenSim.Framework { using (Stream respStream = response.GetResponseStream()) { - deserial = XMLResponseHelper.LogAndDeserialize( + deserial = XMLResponseHelper.LogAndDeserialize( reqnum, respStream, response.ContentLength); } } @@ -863,7 +863,7 @@ namespace OpenSim.Framework { using (Stream respStream = response.GetResponseStream()) { - deserial = XMLResponseHelper.LogAndDeserialize( + deserial = XMLResponseHelper.LogAndDeserialize( reqnum, respStream, response.ContentLength); } } @@ -1165,7 +1165,7 @@ namespace OpenSim.Framework /// public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj) { - return MakeRequest(verb, requestUrl, obj, 0); + return MakeRequest(verb, requestUrl, obj, 0, null); } public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj, IServiceAuth auth) @@ -1187,34 +1187,11 @@ namespace OpenSim.Framework /// public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj, int pTimeout) { - return MakeRequest(verb, requestUrl, obj, pTimeout, 0); - } - - public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj, int pTimeout, IServiceAuth auth) - { - return MakeRequest(verb, requestUrl, obj, pTimeout, 0, auth); - } - - /// Perform a synchronous REST request. - /// - /// - /// - /// - /// - /// Request timeout in milliseconds. Timeout.Infinite indicates no timeout. If 0 is passed then the default HttpWebRequest timeout is used (100 seconds) - /// - /// - /// - /// The response. If there was an internal exception or the request timed out, - /// then the default(TResponse) is returned. - /// - public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections) - { - return MakeRequest(verb, requestUrl, obj, pTimeout, maxConnections, null); + return MakeRequest(verb, requestUrl, obj, pTimeout, null); } /// - /// Perform a synchronous REST request. + /// Perform a synchronous something request. /// /// /// @@ -1222,17 +1199,16 @@ namespace OpenSim.Framework /// /// Request timeout in milliseconds. Timeout.Infinite indicates no timeout. If 0 is passed then the default HttpWebRequest timeout is used (100 seconds) /// - /// /// /// The response. If there was an internal exception or the request timed out, /// then the default(TResponse) is returned. /// - public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections, IServiceAuth auth) + public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj, int pTimeout, IServiceAuth auth) { int reqnum = WebUtil.RequestNumber++; if (WebUtil.DebugLevel >= 3) - m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} SRestObjectRequest {1} {2}", + m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} SRestObjReq {1} {2}", reqnum, verb, requestUrl); int tickstart = Util.EnvironmentTickCount(); @@ -1247,17 +1223,14 @@ namespace OpenSim.Framework if (auth != null) auth.AddAuthorization(request.Headers); - request.AllowWriteStreamBuffering = false; - if (pTimeout != 0) request.Timeout = pTimeout; - request.Method = verb; } catch (Exception e) { - m_log.DebugFormat("[SRestObjectRequest]: Exception in creating request {0} {1}: {2}{3}", + m_log.DebugFormat("[SRestObjReq]: Exception in creating request {0} {1}: {2}{3}", verb, requestUrl, e.Message, e.StackTrace); return deserial; } @@ -1269,7 +1242,7 @@ namespace OpenSim.Framework request.ContentType = "text/xml"; byte[] data; - XmlWriterSettings settings = new XmlWriterSettings(){Encoding = Util.UTF8}; + XmlWriterSettings settings = new XmlWriterSettings() { Encoding = Util.UTF8 }; using (MemoryStream ms = new MemoryStream()) using (XmlWriter writer = XmlWriter.Create(ms, settings)) { @@ -1293,13 +1266,12 @@ namespace OpenSim.Framework catch (Exception e) { m_log.DebugFormat( - "[SRestObjectRequest]: Exception in making request {0} {1}: {2}{3}", + "[SRestObjReq]: Exception in making request {0} {1}: {2}{3}", verb, requestUrl, e.Message, e.StackTrace); return deserial; } - int rcvlen = 0; try { @@ -1310,13 +1282,13 @@ namespace OpenSim.Framework rcvlen = (int)resp.ContentLength; using (Stream respStream = resp.GetResponseStream()) { - deserial = XMLResponseHelper.LogAndDeserialize( + deserial = XMLResponseHelper.LogAndDeserialize( reqnum, respStream, resp.ContentLength); } } else { - m_log.DebugFormat("[SRestObjectRequest]: Oops! no content found in response stream from {0} {1}", + m_log.DebugFormat("[SRestObjReq]: Oops! no content found in response stream from {0} {1}", verb, requestUrl); } } @@ -1329,37 +1301,37 @@ namespace OpenSim.Framework { if (hwr.StatusCode == HttpStatusCode.Unauthorized) { - m_log.ErrorFormat("[SRestObjectRequest]: {0} requires authentication", + m_log.ErrorFormat("[SRestObjReq]: {0} requires authentication", requestUrl); } - else if(hwr.StatusCode != HttpStatusCode.NotFound) + else if (hwr.StatusCode != HttpStatusCode.NotFound) { - m_log.WarnFormat("[SRestObjectRequest]: {0} returned error: {1}", + m_log.WarnFormat("[SRestObjReq]: {0} returned error: {1}", requestUrl, hwr.StatusCode); } } else m_log.ErrorFormat( - "[SRestObjectRequest]: WebException for {0} {1} {2} {3}", + "[SRestObjReq]: WebException for {0} {1} {2} {3}", verb, requestUrl, typeof(TResponse).ToString(), e.Message); } } catch (System.InvalidOperationException) { // This is what happens when there is invalid XML - m_log.DebugFormat("[SRestObjectRequest]: Invalid XML from {0} {1} {2}", + m_log.DebugFormat("[SRestObjReq]: Invalid XML from {0} {1} {2}", verb, requestUrl, typeof(TResponse).ToString()); } catch (Exception e) { - m_log.DebugFormat("[SRestObjectRequest]: Exception on response from {0} {1}: {2}", + m_log.DebugFormat("[SRestObjReq]: Exception on response from {0} {1}: {2}", verb, requestUrl, e.Message); } int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); if (tickdiff > WebUtil.LongCallTime) { - m_log.InfoFormat("[LOGHTTP]: Slow SRestObjectRequest {0} {1} {2} took {3}ms, {4}bytes", + m_log.InfoFormat("[LOGHTTP]: Slow SRestObjReq {0} {1} {2} took {3}ms, {4}bytes", reqnum, verb, requestUrl, tickdiff, rcvlen); } else if (WebUtil.DebugLevel >= 4) @@ -1369,11 +1341,112 @@ namespace OpenSim.Framework } return deserial; } + + public static TResponse MakeGetRequest(string requestUrl, int pTimeout, IServiceAuth auth) + { + int reqnum = WebUtil.RequestNumber++; + + if (WebUtil.DebugLevel >= 3) + m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} SRestObjReq GET {2}", reqnum, requestUrl); + int tickstart = Util.EnvironmentTickCount(); + + TResponse deserial = default(TResponse); + HttpWebRequest request = null; + try + { + request = (HttpWebRequest)WebRequest.Create(requestUrl); + + if (auth != null) + auth.AddAuthorization(request.Headers); + + request.AllowWriteStreamBuffering = false; + + if (pTimeout != 0) + request.Timeout = pTimeout; + + request.Method = "GET"; + } + catch (Exception e) + { + m_log.DebugFormat("[SRestObjReq]: Exception in creating GET request {0}: {1}{2}", + requestUrl, e.Message, e.StackTrace); + return deserial; + } + + int rcvlen = 0; + try + { + using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse()) + { + if (resp.ContentLength != 0) + { + rcvlen = (int)resp.ContentLength; + using (Stream respStream = resp.GetResponseStream()) + { + deserial = XMLResponseHelper.LogAndDeserialize( + reqnum, respStream, resp.ContentLength); + } + } + else + { + m_log.DebugFormat("[SRestObjReq]: Oops! no content found in response stream from GET {0}", + requestUrl); + } + } + } + catch (WebException e) + { + using (HttpWebResponse hwr = (HttpWebResponse)e.Response) + { + if (hwr != null) + { + if (hwr.StatusCode == HttpStatusCode.Unauthorized) + { + m_log.ErrorFormat("[SRestObjReq]: GET {0} requires authentication", + requestUrl); + } + else if (hwr.StatusCode != HttpStatusCode.NotFound) + { + m_log.WarnFormat("[SRestObjReq]: GET {0} returned error: {1}", + requestUrl, hwr.StatusCode); + } + } + else + m_log.ErrorFormat( + "[SRestObjReq]: WebException for GET {0} {1} {2}", + requestUrl, typeof(TResponse).ToString(), e.Message); + } + } + catch (System.InvalidOperationException) + { + // This is what happens when there is invalid XML + m_log.DebugFormat("[SRestObjReq]: Invalid XML from GET {0} {1}", + requestUrl, typeof(TResponse).ToString()); + } + catch (Exception e) + { + m_log.DebugFormat("[SRestObjReq]: Exception on response from GET {0}: {1}", + requestUrl, e.Message); + } + + int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); + if (tickdiff > WebUtil.LongCallTime) + { + m_log.InfoFormat("[LOGHTTP]: Slow SRestObjReq GET {0} {1} took {2}ms, {3}bytes", + reqnum, requestUrl, tickdiff, rcvlen); + } + else if (WebUtil.DebugLevel >= 4) + { + m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms", + reqnum, tickdiff); + } + return deserial; + } } public static class XMLResponseHelper { - public static TResponse LogAndDeserialize(int reqnum, Stream respStream, long contentLength) + public static TResponse LogAndDeserialize(int reqnum, Stream respStream, long contentLength) { XmlSerializer deserializer = new XmlSerializer(typeof(TResponse)); if (WebUtil.DebugLevel >= 5) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 1408d4ea2b..6a0d2c6a04 100755 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -403,7 +403,6 @@ namespace OpenSim.Region.CoreModules.Asset public void Cache(AssetBase asset, bool replace = false) { - // TODO: Spawn this off to some seperate thread to do the actual writing if (asset != null) { //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID); @@ -423,9 +422,7 @@ namespace OpenSim.Region.CoreModules.Asset public void CacheNegative(string id) { if (m_negativeCacheEnabled) - { m_negativeCache.Add(id, m_negativeExpiration); - } } /// @@ -578,6 +575,9 @@ namespace OpenSim.Region.CoreModules.Asset m_Requests++; + if (id.Equals(Util.UUIDZeroString)) + return false; + if (m_negativeCache.ContainsKey(id)) return false; @@ -696,6 +696,9 @@ namespace OpenSim.Region.CoreModules.Asset if (m_MemoryCacheEnabled) m_MemoryCache.Remove(id); + if (m_negativeCacheEnabled) + m_negativeCache.Remove(id); + if (m_FileCacheEnabled) { string filename = GetFileName(id); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 4884766ccd..eaba3e2ab3 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -248,11 +248,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset } } + if (id.Equals(Util.UUIDZeroString)) + return false; + return m_AssetService.Get(id, sender, delegate (string assetID, object s, AssetBase a) { - if ((a != null) && (m_Cache != null)) - m_Cache.Cache(a); - + if(m_Cache != null) + { + if (a == null) + m_Cache.CacheNegative(assetID); + else + m_Cache.Cache(a); + } // if (null == a) // m_log.WarnFormat("[LOCAL ASSET SERVICES CONNECTOR]: Could not asynchronously find asset with id {0}", id); @@ -272,18 +279,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (asset.Local) { -// m_log.DebugFormat( -// "[LOCAL ASSET SERVICE CONNECTOR]: Returning asset {0} {1} without querying database since status Temporary = {2}, Local = {3}", -// asset.Name, asset.ID, asset.Temporary, asset.Local); - return asset.ID; } else { -// m_log.DebugFormat( -// "[LOCAL ASSET SERVICE CONNECTOR]: Passing {0} {1} on to asset service for storage, status Temporary = {2}, Local = {3}", -// asset.Name, asset.ID, asset.Temporary, asset.Local); - return m_AssetService.Store(asset); } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RegionAssetConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RegionAssetConnectorModule.cs index e50431ee72..e58ae31bbd 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RegionAssetConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RegionAssetConnectorModule.cs @@ -305,8 +305,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return null; } if(StoreOnLocalGrid) - Store(asset); - else if (m_Cache != null) + StoreLocal(asset); + if (m_Cache != null) m_Cache.Cache(asset); } else if (m_Cache != null) @@ -345,6 +345,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (asset == null) { + if (id.Equals(Util.UUIDZeroString)) + return false; + lock (m_AssetHandlers) { AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate (AssetBase _asset) { callBack(id, sender, _asset); }); diff --git a/OpenSim/Services/AssetService/XAssetService.cs b/OpenSim/Services/AssetService/XAssetService.cs index 674849dfbe..1a5bac5d07 100644 --- a/OpenSim/Services/AssetService/XAssetService.cs +++ b/OpenSim/Services/AssetService/XAssetService.cs @@ -167,9 +167,7 @@ namespace OpenSim.Services.AssetService { //m_log.DebugFormat("[XASSET SERVICE]: Get asset async {0}", id); - UUID assetID; - - if (!UUID.TryParse(id, out assetID)) + if (!UUID.TryParse(id, out UUID assetID) || assetID == UUID.Zero) return false; AssetBase asset = Get(id); diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs index c996053613..82898d07f1 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs @@ -144,7 +144,7 @@ namespace OpenSim.Services.Connectors { string uri = m_ServerURI + "/assets/" + id; - asset = SynchronousRestObjectRequester.MakeRequest("GET", uri, 0, m_Auth); + asset = SynchronousRestObjectRequester.MakeGetRequest(uri, 0, m_Auth); if (m_Cache != null) { if (asset != null) @@ -177,7 +177,7 @@ namespace OpenSim.Services.Connectors return null; string uri = m_ServerURI + "/assets/" + id + "/metadata"; - return SynchronousRestObjectRequester.MakeRequest("GET", uri, 0, m_Auth); + return SynchronousRestObjectRequester.MakeGetRequest(uri, 0, m_Auth); } @@ -269,7 +269,7 @@ namespace OpenSim.Services.Connectors string id = r.id; try { - AssetBase a = SynchronousRestObjectRequester.MakeRequest("GET", r.uri, 0, 30000, m_Auth); + AssetBase a = SynchronousRestObjectRequester.MakeGetRequest(r.uri, 30000, m_Auth); if (a != null && m_Cache != null) m_Cache.Cache(a); @@ -338,12 +338,9 @@ namespace OpenSim.Services.Connectors if (asset.FullID == UUID.Zero) { - UUID uuid = UUID.Zero; - if (UUID.TryParse(asset.ID, out uuid)) - { + if (UUID.TryParse(asset.ID, out UUID uuid)) asset.FullID = uuid; - } - if(asset.FullID == UUID.Zero) + else { m_log.WarnFormat("[Assets] Zero IDs: {0}",asset.Name); asset.FullID = UUID.Random(); @@ -351,11 +348,9 @@ namespace OpenSim.Services.Connectors } } - if (m_Cache != null) - m_Cache.Cache(asset); - if (asset.Temporary || asset.Local) { + m_Cache?.Cache(asset); return asset.ID; } @@ -385,8 +380,7 @@ namespace OpenSim.Services.Connectors // Placing this here, so that this work with old asset servers that don't send any reply back // SynchronousRestObjectRequester returns somethins that is not an empty string asset.ID = newID; - if (m_Cache != null) - m_Cache.Cache(asset); + m_Cache?.Cache(asset); } } @@ -402,7 +396,6 @@ namespace OpenSim.Services.Connectors m_Cache?.Get(id, out asset); - if (asset == null) { AssetMetadata metadata = GetMetadata(id); @@ -426,19 +419,13 @@ namespace OpenSim.Services.Connectors public virtual bool Delete(string id) { + m_Cache?.Expire(id); + if (m_ServerURI == null) return false; string uri = m_ServerURI + "/assets/" + id; - - if (SynchronousRestObjectRequester.MakeRequest("DELETE", uri, 0, m_Auth)) - { - if (m_Cache != null) - m_Cache.Expire(id); - - return true; - } - return false; + return SynchronousRestObjectRequester.MakeRequest("DELETE", uri, 0, m_Auth); } } } diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs index 6739e584b2..d4ff23d633 100644 --- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs @@ -128,6 +128,9 @@ namespace OpenSim.Services.Connectors string url = string.Empty; string assetID = string.Empty; + if (id.Equals(Util.UUIDZeroString)) + return false; + if (Util.ParseForeignAssetID(id, out url, out assetID) > 0) { IAssetService connector = GetConnector(url);