From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../CoreModules/World/Archiver/AssetsRequest.cs | 232 +++++---------------- 1 file changed, 56 insertions(+), 176 deletions(-) (limited to 'OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs') diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index db66c83..91f4dc3 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -60,29 +60,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver Completed, Aborted }; - - /// - /// Timeout threshold if we still need assets or missing asset notifications but have stopped receiving them - /// from the asset service - /// - protected const int TIMEOUT = 60 * 1000; - - /// - /// If a timeout does occur, limit the amount of UUID information put to the console. - /// - protected const int MAX_UUID_DISPLAY_ON_TIMEOUT = 3; - - protected System.Timers.Timer m_requestCallbackTimer; /// - /// State of this request - /// - private RequestState m_requestState = RequestState.Initial; - - /// /// uuids to request /// protected IDictionary m_uuids; + private int m_previousErrorsCount; /// /// Callback used when all the assets requested have been received. @@ -93,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// List of assets that were found. This will be passed back to the requester. /// protected List m_foundAssetUuids = new List(); - + /// /// Maintain a list of assets that could not be found. This will be passed back to the requester. /// @@ -104,217 +87,114 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// private int m_repliesRequired; + private System.Timers.Timer m_timeOutTimer; + private bool m_timeout; + /// /// Asset service used to request the assets /// protected IAssetService m_assetService; protected IUserAccountService m_userAccountService; - protected UUID m_scopeID; // the grid ID + protected UUID m_scopeID; // the grid ID protected AssetsArchiver m_assetsArchiver; protected Dictionary m_options; protected internal AssetsRequest( - AssetsArchiver assetsArchiver, IDictionary uuids, - IAssetService assetService, IUserAccountService userService, - UUID scope, Dictionary options, + AssetsArchiver assetsArchiver, IDictionary uuids, + int previousErrorsCount, + IAssetService assetService, IUserAccountService userService, + UUID scope, Dictionary options, AssetsRequestCallback assetsRequestCallback) { m_assetsArchiver = assetsArchiver; m_uuids = uuids; + m_previousErrorsCount = previousErrorsCount; m_assetsRequestCallback = assetsRequestCallback; m_assetService = assetService; m_userAccountService = userService; m_scopeID = scope; m_options = options; m_repliesRequired = uuids.Count; - - // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread - // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received - // so we can properly abort that thread. Or request all assets synchronously, though that would be a more - // radical change - m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); - m_requestCallbackTimer.AutoReset = false; - m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); } protected internal void Execute() { - m_requestState = RequestState.Running; - - m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired); - + Culture.SetCurrentCulture(); // We can stop here if there are no assets to fetch if (m_repliesRequired == 0) { - m_requestState = RequestState.Completed; PerformAssetsRequestCallback(false); return; } - m_requestCallbackTimer.Enabled = true; + m_timeOutTimer = new System.Timers.Timer(60000); + m_timeOutTimer .AutoReset = false; + m_timeOutTimer.Elapsed += OnTimeout; + m_timeout = false; foreach (KeyValuePair kvp in m_uuids) { -// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); - -// m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); - AssetBase asset = m_assetService.Get(kvp.Key.ToString()); - PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); - } - } + string thiskey = kvp.Key.ToString(); + try + { + m_timeOutTimer.Enabled = true; + AssetBase asset = m_assetService.Get(thiskey); + if(m_timeout) + break; + + m_timeOutTimer.Enabled = false; - protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) - { - bool timedOut = true; + if(asset == null) + { + m_notFoundAssetUuids.Add(new UUID(thiskey)); + continue; + } - try - { - lock (this) - { - // Take care of the possibilty that this thread started but was paused just outside the lock before - // the final request came in (assuming that such a thing is possible) - if (m_requestState == RequestState.Completed) + sbyte assetType = kvp.Value; + if (asset != null && assetType == (sbyte)AssetType.Unknown) { - timedOut = false; - return; + m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType)); + asset.Type = assetType; } - - m_requestState = RequestState.Aborted; - } - // Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure - // case anyway. - List uuids = new List(); - foreach (UUID uuid in m_uuids.Keys) - { - uuids.Add(uuid); + m_foundAssetUuids.Add(asset.FullID); + m_assetsArchiver.WriteAsset(PostProcess(asset)); } - foreach (UUID uuid in m_foundAssetUuids) - { - uuids.Remove(uuid); - } - - foreach (UUID uuid in m_notFoundAssetUuids) + catch (Exception e) { - uuids.Remove(uuid); - } - - m_log.ErrorFormat( - "[ARCHIVER]: Asset service failed to return information about {0} requested assets", uuids.Count); - - int i = 0; - foreach (UUID uuid in uuids) - { - m_log.ErrorFormat("[ARCHIVER]: No information about asset {0} received", uuid); - - if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT) - break; + m_log.ErrorFormat("[ARCHIVER]: Execute failed with {0}", e); } - - if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT) - m_log.ErrorFormat( - "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT); - - m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE."); - } - catch (Exception e) - { - m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace); } - finally - { - if (timedOut) - WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback"); - } - } - protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset) - { - // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer - if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown) - { - m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType)); - fetchedAsset.Type = (sbyte)assetType; - } + m_timeOutTimer.Dispose(); + int totalerrors = m_notFoundAssetUuids.Count + m_previousErrorsCount; - AssetRequestCallback(fetchedAssetID, this, fetchedAsset); - } + if(m_timeout) + m_log.DebugFormat("[ARCHIVER]: Aborted because AssetService request timeout. Successfully added {0} assets", m_foundAssetUuids.Count); + else if(totalerrors == 0) + m_log.DebugFormat("[ARCHIVER]: Successfully added all {0} assets", m_foundAssetUuids.Count); + else + m_log.DebugFormat("[ARCHIVER]: Successfully added {0} assets ({1} of total possible assets requested were not found, were damaged or were not assets)", + m_foundAssetUuids.Count, totalerrors); - /// - /// Called back by the asset cache when it has the asset - /// - /// - /// - public void AssetRequestCallback(string id, object sender, AssetBase asset) + PerformAssetsRequestCallback(m_timeout); + } + + private void OnTimeout(object source, ElapsedEventArgs args) { - Culture.SetCurrentCulture(); - - try - { - lock (this) - { - //m_log.DebugFormat("[ARCHIVER]: Received callback for asset {0}", id); - - m_requestCallbackTimer.Stop(); - - if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed)) - { - m_log.WarnFormat( - "[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.", - id, m_requestState); - - return; - } - - if (asset != null) - { - if (m_options.ContainsKey("verbose")) - m_log.InfoFormat("[ARCHIVER]: Writing asset {0}", id); - - m_foundAssetUuids.Add(asset.FullID); - - m_assetsArchiver.WriteAsset(PostProcess(asset)); - } - else - { - if (m_options.ContainsKey("verbose")) - m_log.InfoFormat("[ARCHIVER]: Recording asset {0} as not found", id); - - m_notFoundAssetUuids.Add(new UUID(id)); - } - - if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired) - { - m_requestState = RequestState.Completed; - - m_log.DebugFormat( - "[ARCHIVER]: Successfully added {0} assets ({1} assets not found but these may be expected invalid references)", - m_foundAssetUuids.Count, m_notFoundAssetUuids.Count); - - // We want to stop using the asset cache thread asap - // as we now need to do the work of producing the rest of the archive - WorkManager.RunInThread(PerformAssetsRequestCallback, false, "Archive Assets Request Callback"); - } - else - { - m_requestCallbackTimer.Start(); - } - } - } - catch (Exception e) - { - m_log.ErrorFormat("[ARCHIVER]: AssetRequestCallback failed with {0}", e); - } + m_timeout = true; } /// /// Perform the callback on the original requester of the assets /// - protected void PerformAssetsRequestCallback(object o) + private void PerformAssetsRequestCallback(object o) { + if(m_assetsRequestCallback == null) + return; Culture.SetCurrentCulture(); Boolean timedOut = (Boolean)o; @@ -330,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - protected AssetBase PostProcess(AssetBase asset) + private AssetBase PostProcess(AssetBase asset) { if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) { -- cgit v1.1