aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to 'OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs')
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs232
1 files changed, 56 insertions, 176 deletions
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
60 Completed, 60 Completed,
61 Aborted 61 Aborted
62 }; 62 };
63
64 /// <value>
65 /// Timeout threshold if we still need assets or missing asset notifications but have stopped receiving them
66 /// from the asset service
67 /// </value>
68 protected const int TIMEOUT = 60 * 1000;
69
70 /// <value>
71 /// If a timeout does occur, limit the amount of UUID information put to the console.
72 /// </value>
73 protected const int MAX_UUID_DISPLAY_ON_TIMEOUT = 3;
74
75 protected System.Timers.Timer m_requestCallbackTimer;
76 63
77 /// <value> 64 /// <value>
78 /// State of this request
79 /// </value>
80 private RequestState m_requestState = RequestState.Initial;
81
82 /// <value>
83 /// uuids to request 65 /// uuids to request
84 /// </value> 66 /// </value>
85 protected IDictionary<UUID, sbyte> m_uuids; 67 protected IDictionary<UUID, sbyte> m_uuids;
68 private int m_previousErrorsCount;
86 69
87 /// <value> 70 /// <value>
88 /// Callback used when all the assets requested have been received. 71 /// Callback used when all the assets requested have been received.
@@ -93,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
93 /// List of assets that were found. This will be passed back to the requester. 76 /// List of assets that were found. This will be passed back to the requester.
94 /// </value> 77 /// </value>
95 protected List<UUID> m_foundAssetUuids = new List<UUID>(); 78 protected List<UUID> m_foundAssetUuids = new List<UUID>();
96 79
97 /// <value> 80 /// <value>
98 /// Maintain a list of assets that could not be found. This will be passed back to the requester. 81 /// Maintain a list of assets that could not be found. This will be passed back to the requester.
99 /// </value> 82 /// </value>
@@ -104,217 +87,114 @@ namespace OpenSim.Region.CoreModules.World.Archiver
104 /// </value> 87 /// </value>
105 private int m_repliesRequired; 88 private int m_repliesRequired;
106 89
90 private System.Timers.Timer m_timeOutTimer;
91 private bool m_timeout;
92
107 /// <value> 93 /// <value>
108 /// Asset service used to request the assets 94 /// Asset service used to request the assets
109 /// </value> 95 /// </value>
110 protected IAssetService m_assetService; 96 protected IAssetService m_assetService;
111 protected IUserAccountService m_userAccountService; 97 protected IUserAccountService m_userAccountService;
112 protected UUID m_scopeID; // the grid ID 98 protected UUID m_scopeID; // the grid ID
113 99
114 protected AssetsArchiver m_assetsArchiver; 100 protected AssetsArchiver m_assetsArchiver;
115 101
116 protected Dictionary<string, object> m_options; 102 protected Dictionary<string, object> m_options;
117 103
118 protected internal AssetsRequest( 104 protected internal AssetsRequest(
119 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids, 105 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
120 IAssetService assetService, IUserAccountService userService, 106 int previousErrorsCount,
121 UUID scope, Dictionary<string, object> options, 107 IAssetService assetService, IUserAccountService userService,
108 UUID scope, Dictionary<string, object> options,
122 AssetsRequestCallback assetsRequestCallback) 109 AssetsRequestCallback assetsRequestCallback)
123 { 110 {
124 m_assetsArchiver = assetsArchiver; 111 m_assetsArchiver = assetsArchiver;
125 m_uuids = uuids; 112 m_uuids = uuids;
113 m_previousErrorsCount = previousErrorsCount;
126 m_assetsRequestCallback = assetsRequestCallback; 114 m_assetsRequestCallback = assetsRequestCallback;
127 m_assetService = assetService; 115 m_assetService = assetService;
128 m_userAccountService = userService; 116 m_userAccountService = userService;
129 m_scopeID = scope; 117 m_scopeID = scope;
130 m_options = options; 118 m_options = options;
131 m_repliesRequired = uuids.Count; 119 m_repliesRequired = uuids.Count;
132
133 // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread
134 // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received
135 // so we can properly abort that thread. Or request all assets synchronously, though that would be a more
136 // radical change
137 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
138 m_requestCallbackTimer.AutoReset = false;
139 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
140 } 120 }
141 121
142 protected internal void Execute() 122 protected internal void Execute()
143 { 123 {
144 m_requestState = RequestState.Running; 124 Culture.SetCurrentCulture();
145
146 m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired);
147
148 // We can stop here if there are no assets to fetch 125 // We can stop here if there are no assets to fetch
149 if (m_repliesRequired == 0) 126 if (m_repliesRequired == 0)
150 { 127 {
151 m_requestState = RequestState.Completed;
152 PerformAssetsRequestCallback(false); 128 PerformAssetsRequestCallback(false);
153 return; 129 return;
154 } 130 }
155 131
156 m_requestCallbackTimer.Enabled = true; 132 m_timeOutTimer = new System.Timers.Timer(60000);
133 m_timeOutTimer .AutoReset = false;
134 m_timeOutTimer.Elapsed += OnTimeout;
135 m_timeout = false;
157 136
158 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids) 137 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
159 { 138 {
160// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); 139 string thiskey = kvp.Key.ToString();
161 140 try
162// m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); 141 {
163 AssetBase asset = m_assetService.Get(kvp.Key.ToString()); 142 m_timeOutTimer.Enabled = true;
164 PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); 143 AssetBase asset = m_assetService.Get(thiskey);
165 } 144 if(m_timeout)
166 } 145 break;
146
147 m_timeOutTimer.Enabled = false;
167 148
168 protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) 149 if(asset == null)
169 { 150 {
170 bool timedOut = true; 151 m_notFoundAssetUuids.Add(new UUID(thiskey));
152 continue;
153 }
171 154
172 try 155 sbyte assetType = kvp.Value;
173 { 156 if (asset != null && assetType == (sbyte)AssetType.Unknown)
174 lock (this)
175 {
176 // Take care of the possibilty that this thread started but was paused just outside the lock before
177 // the final request came in (assuming that such a thing is possible)
178 if (m_requestState == RequestState.Completed)
179 { 157 {
180 timedOut = false; 158 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType));
181 return; 159 asset.Type = assetType;
182 } 160 }
183
184 m_requestState = RequestState.Aborted;
185 }
186 161
187 // Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure 162 m_foundAssetUuids.Add(asset.FullID);
188 // case anyway. 163 m_assetsArchiver.WriteAsset(PostProcess(asset));
189 List<UUID> uuids = new List<UUID>();
190 foreach (UUID uuid in m_uuids.Keys)
191 {
192 uuids.Add(uuid);
193 } 164 }
194 165
195 foreach (UUID uuid in m_foundAssetUuids) 166 catch (Exception e)
196 {
197 uuids.Remove(uuid);
198 }
199
200 foreach (UUID uuid in m_notFoundAssetUuids)
201 { 167 {
202 uuids.Remove(uuid); 168 m_log.ErrorFormat("[ARCHIVER]: Execute failed with {0}", e);
203 }
204
205 m_log.ErrorFormat(
206 "[ARCHIVER]: Asset service failed to return information about {0} requested assets", uuids.Count);
207
208 int i = 0;
209 foreach (UUID uuid in uuids)
210 {
211 m_log.ErrorFormat("[ARCHIVER]: No information about asset {0} received", uuid);
212
213 if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT)
214 break;
215 } 169 }
216
217 if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT)
218 m_log.ErrorFormat(
219 "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT);
220
221 m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE.");
222 }
223 catch (Exception e)
224 {
225 m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace);
226 } 170 }
227 finally
228 {
229 if (timedOut)
230 WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback");
231 }
232 }
233 171
234 protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset) 172 m_timeOutTimer.Dispose();
235 { 173 int totalerrors = m_notFoundAssetUuids.Count + m_previousErrorsCount;
236 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
237 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
238 {
239 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
240 fetchedAsset.Type = (sbyte)assetType;
241 }
242 174
243 AssetRequestCallback(fetchedAssetID, this, fetchedAsset); 175 if(m_timeout)
244 } 176 m_log.DebugFormat("[ARCHIVER]: Aborted because AssetService request timeout. Successfully added {0} assets", m_foundAssetUuids.Count);
177 else if(totalerrors == 0)
178 m_log.DebugFormat("[ARCHIVER]: Successfully added all {0} assets", m_foundAssetUuids.Count);
179 else
180 m_log.DebugFormat("[ARCHIVER]: Successfully added {0} assets ({1} of total possible assets requested were not found, were damaged or were not assets)",
181 m_foundAssetUuids.Count, totalerrors);
245 182
246 /// <summary> 183 PerformAssetsRequestCallback(m_timeout);
247 /// Called back by the asset cache when it has the asset 184 }
248 /// </summary> 185
249 /// <param name="assetID"></param> 186 private void OnTimeout(object source, ElapsedEventArgs args)
250 /// <param name="asset"></param>
251 public void AssetRequestCallback(string id, object sender, AssetBase asset)
252 { 187 {
253 Culture.SetCurrentCulture(); 188 m_timeout = true;
254
255 try
256 {
257 lock (this)
258 {
259 //m_log.DebugFormat("[ARCHIVER]: Received callback for asset {0}", id);
260
261 m_requestCallbackTimer.Stop();
262
263 if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed))
264 {
265 m_log.WarnFormat(
266 "[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.",
267 id, m_requestState);
268
269 return;
270 }
271
272 if (asset != null)
273 {
274 if (m_options.ContainsKey("verbose"))
275 m_log.InfoFormat("[ARCHIVER]: Writing asset {0}", id);
276
277 m_foundAssetUuids.Add(asset.FullID);
278
279 m_assetsArchiver.WriteAsset(PostProcess(asset));
280 }
281 else
282 {
283 if (m_options.ContainsKey("verbose"))
284 m_log.InfoFormat("[ARCHIVER]: Recording asset {0} as not found", id);
285
286 m_notFoundAssetUuids.Add(new UUID(id));
287 }
288
289 if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired)
290 {
291 m_requestState = RequestState.Completed;
292
293 m_log.DebugFormat(
294 "[ARCHIVER]: Successfully added {0} assets ({1} assets not found but these may be expected invalid references)",
295 m_foundAssetUuids.Count, m_notFoundAssetUuids.Count);
296
297 // We want to stop using the asset cache thread asap
298 // as we now need to do the work of producing the rest of the archive
299 WorkManager.RunInThread(PerformAssetsRequestCallback, false, "Archive Assets Request Callback");
300 }
301 else
302 {
303 m_requestCallbackTimer.Start();
304 }
305 }
306 }
307 catch (Exception e)
308 {
309 m_log.ErrorFormat("[ARCHIVER]: AssetRequestCallback failed with {0}", e);
310 }
311 } 189 }
312 190
313 /// <summary> 191 /// <summary>
314 /// Perform the callback on the original requester of the assets 192 /// Perform the callback on the original requester of the assets
315 /// </summary> 193 /// </summary>
316 protected void PerformAssetsRequestCallback(object o) 194 private void PerformAssetsRequestCallback(object o)
317 { 195 {
196 if(m_assetsRequestCallback == null)
197 return;
318 Culture.SetCurrentCulture(); 198 Culture.SetCurrentCulture();
319 199
320 Boolean timedOut = (Boolean)o; 200 Boolean timedOut = (Boolean)o;
@@ -330,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
330 } 210 }
331 } 211 }
332 212
333 protected AssetBase PostProcess(AssetBase asset) 213 private AssetBase PostProcess(AssetBase asset)
334 { 214 {
335 if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) 215 if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home"))
336 { 216 {