diff options
author | UbitUmarov | 2017-06-21 18:39:58 +0100 |
---|---|---|
committer | UbitUmarov | 2017-06-21 18:40:53 +0100 |
commit | 637d35631cd88258d5f3da44c2959985a047ae2d (patch) | |
tree | 0ca8e02530b3cc04849288ac295f44cadc203ed6 | |
parent | changes to AutoBackModule. Store folder and number of days expire is now als... (diff) | |
download | opensim-SC-637d35631cd88258d5f3da44c2959985a047ae2d.zip opensim-SC-637d35631cd88258d5f3da44c2959985a047ae2d.tar.gz opensim-SC-637d35631cd88258d5f3da44c2959985a047ae2d.tar.bz2 opensim-SC-637d35631cd88258d5f3da44c2959985a047ae2d.tar.xz |
make oar/iar assets writer be done by caller thread like the rest of the
oar/iar save. This may look more painfull but should reduce errors and
threads fights. Fill lucky i just don't stop the entire simulation during
this
3 files changed, 50 insertions, 176 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index f002ad7..dde93db 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | |||
@@ -423,14 +423,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
423 | m_log.DebugFormat( | 423 | m_log.DebugFormat( |
424 | "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count); | 424 | "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count); |
425 | 425 | ||
426 | AssetsRequest ar | 426 | AssetsRequest ar = new AssetsRequest( |
427 | = new AssetsRequest( | ||
428 | new AssetsArchiver(m_archiveWriter), | 427 | new AssetsArchiver(m_archiveWriter), |
429 | m_assetGatherer.GatheredUuids, m_scene.AssetService, | 428 | m_assetGatherer.GatheredUuids, m_scene.AssetService, |
430 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, | 429 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, |
431 | options, ReceivedAllAssets); | 430 | options, ReceivedAllAssets); |
432 | 431 | ar.Execute(); | |
433 | WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name)); | ||
434 | } | 432 | } |
435 | else | 433 | else |
436 | { | 434 | { |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs index 8dabcee..5037219 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs | |||
@@ -195,14 +195,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
195 | m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); | 195 | m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); |
196 | 196 | ||
197 | // Asynchronously request all the assets required to perform this archive operation | 197 | // Asynchronously request all the assets required to perform this archive operation |
198 | AssetsRequest ar | 198 | AssetsRequest ar = new AssetsRequest( |
199 | = new AssetsRequest( | ||
200 | new AssetsArchiver(m_archiveWriter), assetUuids, | 199 | new AssetsArchiver(m_archiveWriter), assetUuids, |
201 | m_rootScene.AssetService, m_rootScene.UserAccountService, | 200 | m_rootScene.AssetService, m_rootScene.UserAccountService, |
202 | m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); | 201 | m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); |
203 | 202 | ||
204 | WorkManager.RunInThread(o => ar.Execute(), null, "Archive Assets Request"); | 203 | // WorkManager.RunInThread(o => ar.Execute(), null, "Archive Assets Request"); |
205 | 204 | ar.Execute(); | |
206 | // CloseArchive() will be called from ReceivedAllAssets() | 205 | // CloseArchive() will be called from ReceivedAllAssets() |
207 | } | 206 | } |
208 | else | 207 | else |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index d380da8..f303498 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs | |||
@@ -62,24 +62,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
62 | }; | 62 | }; |
63 | 63 | ||
64 | /// <value> | 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 | |||
77 | /// <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; |
@@ -104,6 +86,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
104 | /// </value> | 86 | /// </value> |
105 | private int m_repliesRequired; | 87 | private int m_repliesRequired; |
106 | 88 | ||
89 | private System.Timers.Timer m_timeOutTimer; | ||
90 | private bool m_timeout; | ||
91 | |||
107 | /// <value> | 92 | /// <value> |
108 | /// Asset service used to request the assets | 93 | /// Asset service used to request the assets |
109 | /// </value> | 94 | /// </value> |
@@ -129,186 +114,76 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
129 | m_scopeID = scope; | 114 | m_scopeID = scope; |
130 | m_options = options; | 115 | m_options = options; |
131 | m_repliesRequired = uuids.Count; | 116 | 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 | } | 117 | } |
141 | 118 | ||
142 | protected internal void Execute() | 119 | protected internal void Execute() |
143 | { | 120 | { |
144 | m_requestState = RequestState.Running; | 121 | Culture.SetCurrentCulture(); |
145 | |||
146 | m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired); | 122 | m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired); |
147 | 123 | ||
148 | // We can stop here if there are no assets to fetch | 124 | // We can stop here if there are no assets to fetch |
149 | if (m_repliesRequired == 0) | 125 | if (m_repliesRequired == 0) |
150 | { | 126 | { |
151 | m_requestState = RequestState.Completed; | ||
152 | PerformAssetsRequestCallback(false); | 127 | PerformAssetsRequestCallback(false); |
153 | return; | 128 | return; |
154 | } | 129 | } |
155 | 130 | ||
156 | m_requestCallbackTimer.Enabled = true; | 131 | m_timeOutTimer = new System.Timers.Timer(60000); |
132 | m_timeOutTimer .AutoReset = false; | ||
133 | m_timeOutTimer.Elapsed += OnTimeout; | ||
134 | m_timeout = false; | ||
157 | 135 | ||
158 | foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids) | 136 | foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids) |
159 | { | 137 | { |
160 | // m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); | 138 | string thiskey = kvp.Key.ToString(); |
161 | 139 | try | |
162 | // m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); | ||
163 | AssetBase asset = m_assetService.Get(kvp.Key.ToString()); | ||
164 | PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) | ||
169 | { | ||
170 | bool timedOut = true; | ||
171 | |||
172 | try | ||
173 | { | ||
174 | lock (this) | ||
175 | { | 140 | { |
176 | // Take care of the possibilty that this thread started but was paused just outside the lock before | 141 | m_timeOutTimer.Enabled = true; |
177 | // the final request came in (assuming that such a thing is possible) | 142 | AssetBase asset = m_assetService.Get(thiskey); |
178 | if (m_requestState == RequestState.Completed) | 143 | if(m_timeout) |
144 | break; | ||
145 | |||
146 | m_timeOutTimer.Enabled = false; | ||
147 | |||
148 | if(asset == null) | ||
179 | { | 149 | { |
180 | timedOut = false; | 150 | m_notFoundAssetUuids.Add(new UUID(thiskey)); |
181 | return; | 151 | continue; |
182 | } | 152 | } |
183 | 153 | ||
184 | m_requestState = RequestState.Aborted; | 154 | sbyte assetType = kvp.Value; |
185 | } | 155 | if (asset != null && assetType == (sbyte)AssetType.Unknown) |
186 | 156 | { | |
187 | // Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure | 157 | m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType)); |
188 | // case anyway. | 158 | asset.Type = assetType; |
189 | List<UUID> uuids = new List<UUID>(); | 159 | } |
190 | foreach (UUID uuid in m_uuids.Keys) | ||
191 | { | ||
192 | uuids.Add(uuid); | ||
193 | } | ||
194 | |||
195 | foreach (UUID uuid in m_foundAssetUuids) | ||
196 | { | ||
197 | uuids.Remove(uuid); | ||
198 | } | ||
199 | 160 | ||
200 | foreach (UUID uuid in m_notFoundAssetUuids) | 161 | m_foundAssetUuids.Add(asset.FullID); |
201 | { | 162 | m_assetsArchiver.WriteAsset(PostProcess(asset)); |
202 | uuids.Remove(uuid); | ||
203 | } | 163 | } |
204 | 164 | ||
205 | m_log.ErrorFormat( | 165 | catch (Exception e) |
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 | { | 166 | { |
211 | m_log.ErrorFormat("[ARCHIVER]: No information about asset {0} received", uuid); | 167 | m_log.ErrorFormat("[ARCHIVER]: Execute failed with {0}", e); |
212 | |||
213 | if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT) | ||
214 | break; | ||
215 | } | 168 | } |
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 | } | ||
227 | finally | ||
228 | { | ||
229 | if (timedOut) | ||
230 | WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback"); | ||
231 | } | 169 | } |
232 | } | ||
233 | |||
234 | protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset) | ||
235 | { | ||
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 | |||
243 | AssetRequestCallback(fetchedAssetID, this, fetchedAsset); | ||
244 | } | ||
245 | |||
246 | /// <summary> | ||
247 | /// Called back by the asset cache when it has the asset | ||
248 | /// </summary> | ||
249 | /// <param name="assetID"></param> | ||
250 | /// <param name="asset"></param> | ||
251 | public void AssetRequestCallback(string id, object sender, AssetBase asset) | ||
252 | { | ||
253 | Culture.SetCurrentCulture(); | ||
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 | 170 | ||
272 | if (asset != null) | 171 | m_timeOutTimer.Dispose(); |
273 | { | ||
274 | // m_log.DebugFormat("[ARCHIVER]: Writing asset {0}", id); | ||
275 | m_foundAssetUuids.Add(asset.FullID); | ||
276 | 172 | ||
277 | m_assetsArchiver.WriteAsset(PostProcess(asset)); | 173 | if(m_timeout) |
278 | } | 174 | m_log.DebugFormat("[ARCHIVER]: Aborted because AssetService request timeout. Successfully added {0} assets", m_foundAssetUuids.Count); |
279 | else | 175 | else if(m_notFoundAssetUuids.Count == 0) |
280 | { | 176 | m_log.DebugFormat("[ARCHIVER]: Successfully added all {0} assets", m_foundAssetUuids.Count); |
281 | // m_log.DebugFormat("[ARCHIVER]: Recording asset {0} as not found", id); | 177 | else |
282 | m_notFoundAssetUuids.Add(new UUID(id)); | 178 | m_log.DebugFormat("[ARCHIVER]: Successfully added {0} assets ({1} assets not found)", |
283 | } | ||
284 | |||
285 | if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired) | ||
286 | { | ||
287 | m_requestState = RequestState.Completed; | ||
288 | if(m_notFoundAssetUuids.Count == 0) | ||
289 | m_log.DebugFormat( | ||
290 | "[ARCHIVER]: Successfully added {0} assets", | ||
291 | m_foundAssetUuids.Count); | ||
292 | else | ||
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); | 179 | m_foundAssetUuids.Count, m_notFoundAssetUuids.Count); |
296 | 180 | ||
297 | 181 | PerformAssetsRequestCallback(m_timeout); | |
298 | // We want to stop using the asset cache thread asap | 182 | } |
299 | // as we now need to do the work of producing the rest of the archive | 183 | |
300 | WorkManager.RunInThread(PerformAssetsRequestCallback, false, "Archive Assets Request Callback"); | 184 | void OnTimeout(object source, ElapsedEventArgs args) |
301 | } | 185 | { |
302 | else | 186 | m_timeout = true; |
303 | { | ||
304 | m_requestCallbackTimer.Start(); | ||
305 | } | ||
306 | } | ||
307 | } | ||
308 | catch (Exception e) | ||
309 | { | ||
310 | m_log.ErrorFormat("[ARCHIVER]: AssetRequestCallback failed with {0}", e); | ||
311 | } | ||
312 | } | 187 | } |
313 | 188 | ||
314 | /// <summary> | 189 | /// <summary> |
@@ -316,6 +191,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
316 | /// </summary> | 191 | /// </summary> |
317 | protected void PerformAssetsRequestCallback(object o) | 192 | protected void PerformAssetsRequestCallback(object o) |
318 | { | 193 | { |
194 | if(m_assetsRequestCallback == null) | ||
195 | return; | ||
319 | Culture.SetCurrentCulture(); | 196 | Culture.SetCurrentCulture(); |
320 | 197 | ||
321 | Boolean timedOut = (Boolean)o; | 198 | Boolean timedOut = (Boolean)o; |