aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorUbitUmarov2017-06-21 18:39:58 +0100
committerUbitUmarov2017-06-21 18:40:53 +0100
commit637d35631cd88258d5f3da44c2959985a047ae2d (patch)
tree0ca8e02530b3cc04849288ac295f44cadc203ed6 /OpenSim/Region
parent changes to AutoBackModule. Store folder and number of days expire is now als... (diff)
downloadopensim-SC_OLD-637d35631cd88258d5f3da44c2959985a047ae2d.zip
opensim-SC_OLD-637d35631cd88258d5f3da44c2959985a047ae2d.tar.gz
opensim-SC_OLD-637d35631cd88258d5f3da44c2959985a047ae2d.tar.bz2
opensim-SC_OLD-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
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs213
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;