29 using System.Collections.Generic;
30 using System.Reflection;
31 using System.Threading;
35 using OpenSim.Framework;
36 using OpenSim.Framework.Monitoring;
37 using OpenSim.Framework.Serialization;
38 using OpenSim.Framework.Serialization.External;
39 using OpenSim.Services.Interfaces;
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 public delegate
void AssetsRequestCallback(
54 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids,
bool timedOut);
68 protected const int TIMEOUT = 60 * 1000;
73 protected const int MAX_UUID_DISPLAY_ON_TIMEOUT = 3;
80 private RequestState m_requestState = RequestState.Initial;
85 protected IDictionary<UUID, sbyte>
m_uuids;
95 protected List<UUID> m_foundAssetUuids =
new List<UUID>();
100 protected List<UUID> m_notFoundAssetUuids =
new List<UUID>();
105 private int m_repliesRequired;
121 UUID scope, Dictionary<string, object>
options,
122 AssetsRequestCallback assetsRequestCallback)
124 m_assetsArchiver = assetsArchiver;
126 m_assetsRequestCallback = assetsRequestCallback;
127 m_assetService = assetService;
128 m_userAccountService = userService;
131 m_repliesRequired = uuids.Count;
137 m_requestCallbackTimer =
new System.Timers.Timer(TIMEOUT);
138 m_requestCallbackTimer.AutoReset =
false;
139 m_requestCallbackTimer.Elapsed +=
new ElapsedEventHandler(OnRequestCallbackTimeout);
142 protected internal void Execute()
144 m_requestState = RequestState.Running;
146 m_log.DebugFormat(
"[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired);
149 if (m_repliesRequired == 0)
151 m_requestState = RequestState.Completed;
152 PerformAssetsRequestCallback(
false);
156 m_requestCallbackTimer.Enabled =
true;
158 foreach (KeyValuePair<UUID, sbyte> kvp
in m_uuids)
163 AssetBase asset = m_assetService.Get(kvp.Key.ToString());
164 PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset);
170 bool timedOut =
true;
178 if (m_requestState == RequestState.Completed)
184 m_requestState = RequestState.Aborted;
189 List<UUID> uuids =
new List<UUID>();
190 foreach (UUID uuid
in m_uuids.Keys)
195 foreach (UUID uuid
in m_foundAssetUuids)
200 foreach (UUID uuid
in m_notFoundAssetUuids)
206 "[ARCHIVER]: Asset service failed to return information about {0} requested assets", uuids.Count);
209 foreach (UUID uuid
in uuids)
211 m_log.ErrorFormat(
"[ARCHIVER]: No information about asset {0} received", uuid);
213 if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT)
217 if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT)
219 "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT);
221 m_log.Error(
"[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE.");
225 m_log.ErrorFormat(
"[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace);
230 WorkManager.RunInThread(PerformAssetsRequestCallback,
true,
"Archive Assets Request Callback");
237 if (fetchedAsset != null && fetchedAsset.
Type == (sbyte)AssetType.Unknown)
239 m_log.InfoFormat(
"[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
240 fetchedAsset.Type = (sbyte)assetType;
243 AssetRequestCallback(fetchedAssetID,
this, fetchedAsset);
253 Culture.SetCurrentCulture();
261 m_requestCallbackTimer.Stop();
263 if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed))
266 "[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.",
275 m_foundAssetUuids.Add(asset.FullID);
277 m_assetsArchiver.WriteAsset(PostProcess(asset));
282 m_notFoundAssetUuids.Add(
new UUID(
id));
285 if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired)
287 m_requestState = RequestState.Completed;
290 "[ARCHIVER]: Successfully added {0} assets ({1} assets not found but these may be expected invalid references)",
291 m_foundAssetUuids.Count, m_notFoundAssetUuids.Count);
295 WorkManager.RunInThread(PerformAssetsRequestCallback,
false,
"Archive Assets Request Callback");
299 m_requestCallbackTimer.Start();
305 m_log.ErrorFormat(
"[ARCHIVER]: AssetRequestCallback failed with {0}", e);
314 Culture.SetCurrentCulture();
316 Boolean timedOut = (Boolean)o;
320 m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids, timedOut);
325 "[ARCHIVER]: Terminating archive creation since asset requster callback failed with {0}", e);
331 if (asset.
Type == (sbyte)AssetType.Object && asset.
Data != null && m_options.ContainsKey(
"home"))
334 string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data),
string.Empty, m_options[
"home"].ToString(), m_userAccountService, m_scopeID);
335 asset.Data = Utils.StringToBytes(xml);
IAssetService m_assetService
IDictionary< UUID, sbyte > m_uuids
void PerformAssetsRequestCallback(object o)
Perform the callback on the original requester of the assets
sbyte Type
(sbyte) AssetType enum
System.Timers.Timer m_requestCallbackTimer
Dictionary< string, object > m_options
AssetsArchiver m_assetsArchiver
Asset class. All Assets are reference by this class or a class derived from this class ...
Encapsulate the asynchronous requests for the assets required for an archive operation ...
void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset)
void OnRequestCallbackTimeout(object source, ElapsedEventArgs args)
IUserAccountService m_userAccountService
AssetsRequestCallback m_assetsRequestCallback
void AssetRequestCallback(string id, object sender, AssetBase asset)
Called back by the asset cache when it has the asset
AssetBase PostProcess(AssetBase asset)