aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs')
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs267
1 files changed, 168 insertions, 99 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 9ef5bc9..d85d727 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -86,6 +86,8 @@ namespace Flotsam.RegionModules.AssetCache
86 private List<string> m_CurrentlyWriting = new List<string>(); 86 private List<string> m_CurrentlyWriting = new List<string>();
87#endif 87#endif
88 88
89 private bool m_FileCacheEnabled = true;
90
89 private ExpiringCache<string, AssetBase> m_MemoryCache; 91 private ExpiringCache<string, AssetBase> m_MemoryCache;
90 private bool m_MemoryCacheEnabled = false; 92 private bool m_MemoryCacheEnabled = false;
91 93
@@ -146,6 +148,7 @@ namespace Flotsam.RegionModules.AssetCache
146 } 148 }
147 else 149 else
148 { 150 {
151 m_FileCacheEnabled = assetConfig.GetBoolean("FileCacheEnabled", m_FileCacheEnabled);
149 m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); 152 m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory);
150 153
151 m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); 154 m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
@@ -173,7 +176,7 @@ namespace Flotsam.RegionModules.AssetCache
173 176
174 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); 177 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
175 178
176 if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) 179 if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
177 { 180 {
178 m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds); 181 m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds);
179 m_CacheCleanTimer.AutoReset = true; 182 m_CacheCleanTimer.AutoReset = true;
@@ -226,7 +229,6 @@ namespace Flotsam.RegionModules.AssetCache
226 if (m_AssetService == null) 229 if (m_AssetService == null)
227 { 230 {
228 m_AssetService = scene.RequestModuleInterface<IAssetService>(); 231 m_AssetService = scene.RequestModuleInterface<IAssetService>();
229
230 } 232 }
231 } 233 }
232 } 234 }
@@ -250,18 +252,15 @@ namespace Flotsam.RegionModules.AssetCache
250 252
251 private void UpdateMemoryCache(string key, AssetBase asset) 253 private void UpdateMemoryCache(string key, AssetBase asset)
252 { 254 {
253 if (m_MemoryCacheEnabled) 255 m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
254 m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
255 } 256 }
256 257
257 public void Cache(AssetBase asset) 258 private void UpdateFileCache(string key, AssetBase asset)
258 { 259 {
259 // TODO: Spawn this off to some seperate thread to do the actual writing 260 // TODO: Spawn this off to some seperate thread to do the actual writing
260 if (asset != null) 261 if (asset != null)
261 { 262 {
262 UpdateMemoryCache(asset.ID, asset); 263 string filename = GetFileName(key);
263
264 string filename = GetFileName(asset.ID);
265 264
266 try 265 try
267 { 266 {
@@ -278,8 +277,8 @@ namespace Flotsam.RegionModules.AssetCache
278 catch 277 catch
279 { 278 {
280 } 279 }
281 } else { 280 } else {
282 281
283 // Once we start writing, make sure we flag that we're writing 282 // Once we start writing, make sure we flag that we're writing
284 // that object to the cache so that we don't try to write the 283 // that object to the cache so that we don't try to write the
285 // same file multiple times. 284 // same file multiple times.
@@ -319,78 +318,118 @@ namespace Flotsam.RegionModules.AssetCache
319 } 318 }
320 } 319 }
321 320
322 public AssetBase Get(string id) 321 public void Cache(AssetBase asset)
323 { 322 {
324 m_Requests++; 323 // TODO: Spawn this off to some seperate thread to do the actual writing
324 if (asset != null)
325 {
326 //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
327
328 if (m_MemoryCacheEnabled)
329 UpdateMemoryCache(asset.ID, asset);
330
331 if (m_FileCacheEnabled)
332 UpdateFileCache(asset.ID, asset);
333 }
334 }
325 335
336 /// <summary>
337 /// Try to get an asset from the in-memory cache.
338 /// </summary>
339 /// <param name="id"></param>
340 /// <returns></returns>
341 private AssetBase GetFromMemoryCache(string id)
342 {
326 AssetBase asset = null; 343 AssetBase asset = null;
327 344
328 if (m_MemoryCacheEnabled && m_MemoryCache.TryGetValue(id, out asset)) 345 if (m_MemoryCache.TryGetValue(id, out asset))
329 {
330 m_MemoryHits++; 346 m_MemoryHits++;
331 } 347
332 else 348 return asset;
349 }
350
351 /// <summary>
352 /// Try to get an asset from the file cache.
353 /// </summary>
354 /// <param name="id"></param>
355 /// <returns></returns>
356 private AssetBase GetFromFileCache(string id)
357 {
358 AssetBase asset = null;
359
360 string filename = GetFileName(id);
361 if (File.Exists(filename))
333 { 362 {
334 string filename = GetFileName(id); 363 FileStream stream = null;
335 if (File.Exists(filename)) 364 try
336 { 365 {
337 FileStream stream = null; 366 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
338 try 367 BinaryFormatter bformatter = new BinaryFormatter();
339 {
340 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
341 BinaryFormatter bformatter = new BinaryFormatter();
342 368
343 asset = (AssetBase)bformatter.Deserialize(stream); 369 asset = (AssetBase)bformatter.Deserialize(stream);
344 370
345 UpdateMemoryCache(id, asset); 371 UpdateMemoryCache(id, asset);
346 372
347 m_DiskHits++; 373 m_DiskHits++;
348 } 374 }
349 catch (System.Runtime.Serialization.SerializationException e) 375 catch (System.Runtime.Serialization.SerializationException e)
350 { 376 {
351 LogException(e); 377 LogException(e);
352 378
353 // If there was a problem deserializing the asset, the asset may 379 // If there was a problem deserializing the asset, the asset may
354 // either be corrupted OR was serialized under an old format 380 // either be corrupted OR was serialized under an old format
355 // {different version of AssetBase} -- we should attempt to 381 // {different version of AssetBase} -- we should attempt to
356 // delete it and re-cache 382 // delete it and re-cache
357 File.Delete(filename); 383 File.Delete(filename);
358 } 384 }
359 catch (Exception e) 385 catch (Exception e)
360 { 386 {
361 LogException(e); 387 LogException(e);
362 }
363 finally
364 {
365 if (stream != null)
366 stream.Close();
367 }
368 } 388 }
389 finally
390 {
391 if (stream != null)
392 stream.Close();
393 }
394 }
369 395
370 396
371#if WAIT_ON_INPROGRESS_REQUESTS 397#if WAIT_ON_INPROGRESS_REQUESTS
372 // Check if we're already downloading this asset. If so, try to wait for it to 398 // Check if we're already downloading this asset. If so, try to wait for it to
373 // download. 399 // download.
374 if (m_WaitOnInprogressTimeout > 0) 400 if (m_WaitOnInprogressTimeout > 0)
375 { 401 {
376 m_RequestsForInprogress++; 402 m_RequestsForInprogress++;
377 403
378 ManualResetEvent waitEvent; 404 ManualResetEvent waitEvent;
379 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) 405 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
380 {
381 waitEvent.WaitOne(m_WaitOnInprogressTimeout);
382 return Get(id);
383 }
384 }
385#else
386 // Track how often we have the problem that an asset is requested while
387 // it is still being downloaded by a previous request.
388 if (m_CurrentlyWriting.Contains(filename))
389 { 406 {
390 m_RequestsForInprogress++; 407 waitEvent.WaitOne(m_WaitOnInprogressTimeout);
408 return Get(id);
391 } 409 }
392#endif
393 } 410 }
411#else
412 // Track how often we have the problem that an asset is requested while
413 // it is still being downloaded by a previous request.
414 if (m_CurrentlyWriting.Contains(filename))
415 {
416 m_RequestsForInprogress++;
417 }
418#endif
419
420 return asset;
421 }
422
423 public AssetBase Get(string id)
424 {
425 m_Requests++;
426
427 AssetBase asset = null;
428
429 if (m_MemoryCacheEnabled)
430 asset = GetFromMemoryCache(id);
431 else if (m_FileCacheEnabled)
432 asset = GetFromFileCache(id);
394 433
395 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 434 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
396 { 435 {
@@ -424,10 +463,13 @@ namespace Flotsam.RegionModules.AssetCache
424 463
425 try 464 try
426 { 465 {
427 string filename = GetFileName(id); 466 if (m_FileCacheEnabled)
428 if (File.Exists(filename))
429 { 467 {
430 File.Delete(filename); 468 string filename = GetFileName(id);
469 if (File.Exists(filename))
470 {
471 File.Delete(filename);
472 }
431 } 473 }
432 474
433 if (m_MemoryCacheEnabled) 475 if (m_MemoryCacheEnabled)
@@ -442,11 +484,14 @@ namespace Flotsam.RegionModules.AssetCache
442 public void Clear() 484 public void Clear()
443 { 485 {
444 if (m_LogLevel >= 2) 486 if (m_LogLevel >= 2)
445 m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing Cache."); 487 m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing caches.");
446 488
447 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 489 if (m_FileCacheEnabled)
448 { 490 {
449 Directory.Delete(dir); 491 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
492 {
493 Directory.Delete(dir);
494 }
450 } 495 }
451 496
452 if (m_MemoryCacheEnabled) 497 if (m_MemoryCacheEnabled)
@@ -481,9 +526,9 @@ namespace Flotsam.RegionModules.AssetCache
481 /// removes empty tier directories. 526 /// removes empty tier directories.
482 /// </summary> 527 /// </summary>
483 /// <param name="dir"></param> 528 /// <param name="dir"></param>
529 /// <param name="purgeLine"></param>
484 private void CleanExpiredFiles(string dir, DateTime purgeLine) 530 private void CleanExpiredFiles(string dir, DateTime purgeLine)
485 { 531 {
486
487 foreach (string file in Directory.GetFiles(dir)) 532 foreach (string file in Directory.GetFiles(dir))
488 { 533 {
489 if (File.GetLastAccessTime(file) < purgeLine) 534 if (File.GetLastAccessTime(file) < purgeLine)
@@ -721,18 +766,28 @@ namespace Flotsam.RegionModules.AssetCache
721 switch (cmd) 766 switch (cmd)
722 { 767 {
723 case "status": 768 case "status":
724 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache : {0} assets", m_MemoryCache.Count); 769 if (m_MemoryCacheEnabled)
725 770 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count);
726 int fileCount = GetFileCacheCount(m_CacheDirectory); 771 else
727 m_log.InfoFormat("[FLOTSAM ASSET CACHE] File Cache : {0} assets", fileCount); 772 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled");
728 773
729 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) 774 if (m_FileCacheEnabled)
730 { 775 {
731 m_log.Info("[FLOTSAM ASSET CACHE] Deep Scans were performed on the following regions:"); 776 int fileCount = GetFileCacheCount(m_CacheDirectory);
732 777 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount);
733 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); 778
734 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); 779 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
735 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); 780 {
781 m_log.Info("[FLOTSAM ASSET CACHE]: Deep Scans were performed on the following regions:");
782
783 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
784 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
785 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
786 }
787 }
788 else
789 {
790 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
736 } 791 }
737 792
738 break; 793 break;
@@ -740,7 +795,7 @@ namespace Flotsam.RegionModules.AssetCache
740 case "clear": 795 case "clear":
741 if (cmdparams.Length < 2) 796 if (cmdparams.Length < 2)
742 { 797 {
743 m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]"); 798 m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]");
744 break; 799 break;
745 } 800 }
746 801
@@ -761,36 +816,48 @@ namespace Flotsam.RegionModules.AssetCache
761 816
762 if (clearMemory) 817 if (clearMemory)
763 { 818 {
764 m_MemoryCache.Clear(); 819 if (m_MemoryCacheEnabled)
765 m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); 820 {
821 m_MemoryCache.Clear();
822 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared.");
823 }
824 else
825 {
826 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled.");
827 }
766 } 828 }
767 829
768 if (clearFile) 830 if (clearFile)
769 { 831 {
770 ClearFileCache(); 832 if (m_FileCacheEnabled)
771 m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); 833 {
834 ClearFileCache();
835 m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared.");
836 }
837 else
838 {
839 m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled.");
840 }
772 } 841 }
773 842
774 break; 843 break;
775 844
776 845
777 case "assets": 846 case "assets":
778 m_log.Info("[FLOTSAM ASSET CACHE] Caching all assets, in all scenes."); 847 m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes.");
779 848
780 Util.FireAndForget(delegate { 849 Util.FireAndForget(delegate {
781 int assetsCached = CacheScenes(); 850 int assetsCached = CacheScenes();
782 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Completed Scene Caching, {0} assets found.", assetsCached); 851 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached);
783 852
784 }); 853 });
785 854
786 break; 855 break;
787 856
788 case "expire": 857 case "expire":
789
790
791 if (cmdparams.Length < 3) 858 if (cmdparams.Length < 3)
792 { 859 {
793 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Invalid parameters for Expire, please specify a valid date & time", cmd); 860 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd);
794 break; 861 break;
795 } 862 }
796 863
@@ -808,26 +875,28 @@ namespace Flotsam.RegionModules.AssetCache
808 875
809 if (!DateTime.TryParse(s_expirationDate, out expirationDate)) 876 if (!DateTime.TryParse(s_expirationDate, out expirationDate))
810 { 877 {
811 m_log.InfoFormat("[FLOTSAM ASSET CACHE] {0} is not a valid date & time", cmd); 878 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd);
812 break; 879 break;
813 } 880 }
814 881
815 CleanExpiredFiles(m_CacheDirectory, expirationDate); 882 if (m_FileCacheEnabled)
883 CleanExpiredFiles(m_CacheDirectory, expirationDate);
884 else
885 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing.");
816 886
817 break; 887 break;
818 default: 888 default:
819 m_log.InfoFormat("[FLOTSAM ASSET CACHE] Unknown command {0}", cmd); 889 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd);
820 break; 890 break;
821 } 891 }
822 } 892 }
823 else if (cmdparams.Length == 1) 893 else if (cmdparams.Length == 1)
824 { 894 {
825 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache status - Display cache status"); 895 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status");
826 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearmem - Remove all assets cached in memory"); 896 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory");
827 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearfile - Remove all assets cached on disk"); 897 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk");
828 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache cachescenes - Attempt a deep cache of all assets in all scenes"); 898 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes");
829 m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache <datetime> - Purge assets older then the specified date & time"); 899 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache <datetime> - Purge assets older then the specified date & time");
830
831 } 900 }
832 } 901 }
833 902