aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs233
1 files changed, 131 insertions, 102 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index a8f5c99..a72cf83 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -226,7 +226,6 @@ namespace Flotsam.RegionModules.AssetCache
226 if (m_AssetService == null) 226 if (m_AssetService == null)
227 { 227 {
228 m_AssetService = scene.RequestModuleInterface<IAssetService>(); 228 m_AssetService = scene.RequestModuleInterface<IAssetService>();
229
230 } 229 }
231 } 230 }
232 } 231 }
@@ -250,140 +249,170 @@ namespace Flotsam.RegionModules.AssetCache
250 249
251 private void UpdateMemoryCache(string key, AssetBase asset) 250 private void UpdateMemoryCache(string key, AssetBase asset)
252 { 251 {
253 if (m_MemoryCacheEnabled) 252 m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
254 m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
255 } 253 }
256 254
257 public void Cache(AssetBase asset) 255 private void UpdateFileCache(string key, AssetBase asset)
258 { 256 {
259 // TODO: Spawn this off to some seperate thread to do the actual writing 257 string filename = GetFileName(asset.ID);
260 if (asset != null)
261 {
262 m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
263
264 UpdateMemoryCache(asset.ID, asset);
265
266 string filename = GetFileName(asset.ID);
267 258
268 try 259 try
260 {
261 // If the file is already cached, don't cache it, just touch it so access time is updated
262 if (File.Exists(filename))
269 { 263 {
270 // If the file is already cached, don't cache it, just touch it so access time is updated 264 File.SetLastAccessTime(filename, DateTime.Now);
271 if (File.Exists(filename)) 265 }
266 else
267 {
268 // Once we start writing, make sure we flag that we're writing
269 // that object to the cache so that we don't try to write the
270 // same file multiple times.
271 lock (m_CurrentlyWriting)
272 { 272 {
273 File.SetLastAccessTime(filename, DateTime.Now);
274 } else {
275
276 // Once we start writing, make sure we flag that we're writing
277 // that object to the cache so that we don't try to write the
278 // same file multiple times.
279 lock (m_CurrentlyWriting)
280 {
281#if WAIT_ON_INPROGRESS_REQUESTS 273#if WAIT_ON_INPROGRESS_REQUESTS
282 if (m_CurrentlyWriting.ContainsKey(filename)) 274 if (m_CurrentlyWriting.ContainsKey(filename))
283 { 275 {
284 return; 276 return;
285 } 277 }
286 else 278 else
287 { 279 {
288 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); 280 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
289 } 281 }
290 282
291#else 283#else
292 if (m_CurrentlyWriting.Contains(filename)) 284 if (m_CurrentlyWriting.Contains(filename))
293 { 285 {
294 return; 286 return;
295 }
296 else
297 {
298 m_CurrentlyWriting.Add(filename);
299 }
300#endif
301
302 } 287 }
303 288 else
304 Util.FireAndForget( 289 {
305 delegate { WriteFileCache(filename, asset); }); 290 m_CurrentlyWriting.Add(filename);
291 }
292#endif
306 } 293 }
307 } 294
308 catch (Exception e) 295 Util.FireAndForget(
309 { 296 delegate { WriteFileCache(filename, asset); });
310 LogException(e);
311 } 297 }
312 } 298 }
299 catch (Exception e)
300 {
301 LogException(e);
302 }
313 } 303 }
314 304
315 public AssetBase Get(string id) 305 public void Cache(AssetBase asset)
316 { 306 {
317 m_Requests++; 307 // TODO: Spawn this off to some seperate thread to do the actual writing
308 if (asset != null)
309 {
310 //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
318 311
312 if (m_MemoryCacheEnabled)
313 UpdateMemoryCache(asset.ID, asset);
314
315 UpdateFileCache(asset.ID, asset);
316 }
317 }
318
319 /// <summary>
320 /// Try to get an asset from the in-memory cache.
321 /// </summary>
322 /// <param name="id"></param>
323 /// <returns></returns>
324 private AssetBase GetFromMemoryCache(string id)
325 {
319 AssetBase asset = null; 326 AssetBase asset = null;
320 327
321 if (m_MemoryCacheEnabled && m_MemoryCache.TryGetValue(id, out asset)) 328 if (m_MemoryCache.TryGetValue(id, out asset))
322 {
323 m_MemoryHits++; 329 m_MemoryHits++;
324 } 330
325 else 331 return asset;
332 }
333
334 /// <summary>
335 /// Try to get an asset from the file cache.
336 /// </summary>
337 /// <param name="id"></param>
338 /// <returns></returns>
339 private AssetBase GetFromFileCache(string id)
340 {
341 AssetBase asset = null;
342
343 string filename = GetFileName(id);
344 if (File.Exists(filename))
326 { 345 {
327 string filename = GetFileName(id); 346 FileStream stream = null;
328 if (File.Exists(filename)) 347 try
329 { 348 {
330 FileStream stream = null; 349 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
331 try 350 BinaryFormatter bformatter = new BinaryFormatter();
332 {
333 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
334 BinaryFormatter bformatter = new BinaryFormatter();
335 351
336 asset = (AssetBase)bformatter.Deserialize(stream); 352 asset = (AssetBase)bformatter.Deserialize(stream);
337 353
338 UpdateMemoryCache(id, asset); 354 UpdateMemoryCache(id, asset);
339 355
340 m_DiskHits++; 356 m_DiskHits++;
341 } 357 }
342 catch (System.Runtime.Serialization.SerializationException e) 358 catch (System.Runtime.Serialization.SerializationException e)
343 { 359 {
344 LogException(e); 360 LogException(e);
345 361
346 // If there was a problem deserializing the asset, the asset may 362 // If there was a problem deserializing the asset, the asset may
347 // either be corrupted OR was serialized under an old format 363 // either be corrupted OR was serialized under an old format
348 // {different version of AssetBase} -- we should attempt to 364 // {different version of AssetBase} -- we should attempt to
349 // delete it and re-cache 365 // delete it and re-cache
350 File.Delete(filename); 366 File.Delete(filename);
351 } 367 }
352 catch (Exception e) 368 catch (Exception e)
353 { 369 {
354 LogException(e); 370 LogException(e);
355 }
356 finally
357 {
358 if (stream != null)
359 stream.Close();
360 }
361 } 371 }
372 finally
373 {
374 if (stream != null)
375 stream.Close();
376 }
377 }
362 378
363 379
364#if WAIT_ON_INPROGRESS_REQUESTS 380#if WAIT_ON_INPROGRESS_REQUESTS
365 // Check if we're already downloading this asset. If so, try to wait for it to 381 // Check if we're already downloading this asset. If so, try to wait for it to
366 // download. 382 // download.
367 if (m_WaitOnInprogressTimeout > 0) 383 if (m_WaitOnInprogressTimeout > 0)
368 { 384 {
369 m_RequestsForInprogress++; 385 m_RequestsForInprogress++;
370 386
371 ManualResetEvent waitEvent; 387 ManualResetEvent waitEvent;
372 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) 388 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
373 {
374 waitEvent.WaitOne(m_WaitOnInprogressTimeout);
375 return Get(id);
376 }
377 }
378#else
379 // Track how often we have the problem that an asset is requested while
380 // it is still being downloaded by a previous request.
381 if (m_CurrentlyWriting.Contains(filename))
382 { 389 {
383 m_RequestsForInprogress++; 390 waitEvent.WaitOne(m_WaitOnInprogressTimeout);
391 return Get(id);
384 } 392 }
385#endif
386 } 393 }
394#else
395 // Track how often we have the problem that an asset is requested while
396 // it is still being downloaded by a previous request.
397 if (m_CurrentlyWriting.Contains(filename))
398 {
399 m_RequestsForInprogress++;
400 }
401#endif
402
403 return asset;
404 }
405
406 public AssetBase Get(string id)
407 {
408 m_Requests++;
409
410 AssetBase asset = null;
411
412 if (m_MemoryCacheEnabled)
413 asset = GetFromMemoryCache(id);
414 else
415 asset = GetFromFileCache(id);
387 416
388 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 417 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
389 { 418 {
@@ -474,9 +503,9 @@ namespace Flotsam.RegionModules.AssetCache
474 /// removes empty tier directories. 503 /// removes empty tier directories.
475 /// </summary> 504 /// </summary>
476 /// <param name="dir"></param> 505 /// <param name="dir"></param>
506 /// <param name="purgeLine"></param>
477 private void CleanExpiredFiles(string dir, DateTime purgeLine) 507 private void CleanExpiredFiles(string dir, DateTime purgeLine)
478 { 508 {
479
480 foreach (string file in Directory.GetFiles(dir)) 509 foreach (string file in Directory.GetFiles(dir))
481 { 510 {
482 if (File.GetLastAccessTime(file) < purgeLine) 511 if (File.GetLastAccessTime(file) < purgeLine)