aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Asset
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Asset')
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs191
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs6
2 files changed, 112 insertions, 85 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index ec388f4..d510d82 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -363,13 +363,38 @@ namespace OpenSim.Region.CoreModules.Asset
363 /// Try to get an asset from the file cache. 363 /// Try to get an asset from the file cache.
364 /// </summary> 364 /// </summary>
365 /// <param name="id"></param> 365 /// <param name="id"></param>
366 /// <returns></returns> 366 /// <returns>An asset retrieved from the file cache. null if there was a problem retrieving an asset.</returns>
367 private AssetBase GetFromFileCache(string id) 367 private AssetBase GetFromFileCache(string id)
368 { 368 {
369 string filename = GetFileName(id);
370
371#if WAIT_ON_INPROGRESS_REQUESTS
372 // Check if we're already downloading this asset. If so, try to wait for it to
373 // download.
374 if (m_WaitOnInprogressTimeout > 0)
375 {
376 m_RequestsForInprogress++;
377
378 ManualResetEvent waitEvent;
379 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 {
390 m_RequestsForInprogress++;
391 return null;
392 }
393#endif
394
369 AssetBase asset = null; 395 AssetBase asset = null;
370 396
371 string filename = GetFileName(id); 397 if (File.Exists(filename))
372 while (File.Exists(filename))
373 { 398 {
374 FileStream stream = null; 399 FileStream stream = null;
375 try 400 try
@@ -380,12 +405,10 @@ namespace OpenSim.Region.CoreModules.Asset
380 asset = (AssetBase)bformatter.Deserialize(stream); 405 asset = (AssetBase)bformatter.Deserialize(stream);
381 406
382 m_DiskHits++; 407 m_DiskHits++;
383
384 break;
385 } 408 }
386 catch (System.Runtime.Serialization.SerializationException e) 409 catch (System.Runtime.Serialization.SerializationException e)
387 { 410 {
388 m_log.ErrorFormat( 411 m_log.WarnFormat(
389 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 412 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
390 filename, id, e.Message, e.StackTrace); 413 filename, id, e.Message, e.StackTrace);
391 414
@@ -394,24 +417,13 @@ namespace OpenSim.Region.CoreModules.Asset
394 // {different version of AssetBase} -- we should attempt to 417 // {different version of AssetBase} -- we should attempt to
395 // delete it and re-cache 418 // delete it and re-cache
396 File.Delete(filename); 419 File.Delete(filename);
397
398 break;
399 }
400 catch (IOException e)
401 {
402 // This is a sharing violation: File exists but can't be opened because it's
403 // being written
404 Thread.Sleep(100);
405
406 continue;
407 } 420 }
408 catch (Exception e) 421 catch (Exception e)
409 { 422 {
410 m_log.ErrorFormat( 423 m_log.WarnFormat(
411 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 424 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
412 filename, id, e.Message, e.StackTrace); 425 filename, id, e.Message, e.StackTrace);
413 426
414 break;
415 } 427 }
416 finally 428 finally
417 { 429 {
@@ -420,28 +432,6 @@ namespace OpenSim.Region.CoreModules.Asset
420 } 432 }
421 } 433 }
422 434
423#if WAIT_ON_INPROGRESS_REQUESTS
424 // Check if we're already downloading this asset. If so, try to wait for it to
425 // download.
426 if (m_WaitOnInprogressTimeout > 0)
427 {
428 m_RequestsForInprogress++;
429
430 ManualResetEvent waitEvent;
431 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
432 {
433 waitEvent.WaitOne(m_WaitOnInprogressTimeout);
434 return Get(id);
435 }
436 }
437#else
438 // Track how often we have the problem that an asset is requested while
439 // it is still being downloaded by a previous request.
440 if (m_CurrentlyWriting.Contains(filename))
441 {
442 m_RequestsForInprogress++;
443 }
444#endif
445 return asset; 435 return asset;
446 } 436 }
447 437
@@ -566,7 +556,7 @@ namespace OpenSim.Region.CoreModules.Asset
566 } 556 }
567 catch (Exception e) 557 catch (Exception e)
568 { 558 {
569 m_log.ErrorFormat( 559 m_log.WarnFormat(
570 "[FLOTSAM ASSET CACHE]: Failed to expire cached file {0}. Exception {1} {2}", 560 "[FLOTSAM ASSET CACHE]: Failed to expire cached file {0}. Exception {1} {2}",
571 id, e.Message, e.StackTrace); 561 id, e.Message, e.StackTrace);
572 } 562 }
@@ -617,29 +607,39 @@ namespace OpenSim.Region.CoreModules.Asset
617 /// <param name="purgeLine"></param> 607 /// <param name="purgeLine"></param>
618 private void CleanExpiredFiles(string dir, DateTime purgeLine) 608 private void CleanExpiredFiles(string dir, DateTime purgeLine)
619 { 609 {
620 foreach (string file in Directory.GetFiles(dir)) 610 try
621 { 611 {
622 if (File.GetLastAccessTime(file) < purgeLine) 612 foreach (string file in Directory.GetFiles(dir))
623 { 613 {
624 File.Delete(file); 614 if (File.GetLastAccessTime(file) < purgeLine)
615 {
616 File.Delete(file);
617 }
625 } 618 }
626 }
627 619
628 // Recurse into lower tiers 620 // Recurse into lower tiers
629 foreach (string subdir in Directory.GetDirectories(dir)) 621 foreach (string subdir in Directory.GetDirectories(dir))
630 { 622 {
631 CleanExpiredFiles(subdir, purgeLine); 623 CleanExpiredFiles(subdir, purgeLine);
632 } 624 }
633 625
634 // Check if a tier directory is empty, if so, delete it 626 // Check if a tier directory is empty, if so, delete it
635 int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length; 627 int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length;
636 if (dirSize == 0) 628 if (dirSize == 0)
637 { 629 {
638 Directory.Delete(dir); 630 Directory.Delete(dir);
631 }
632 else if (dirSize >= m_CacheWarnAt)
633 {
634 m_log.WarnFormat(
635 "[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration",
636 dir, dirSize);
637 }
639 } 638 }
640 else if (dirSize >= m_CacheWarnAt) 639 catch (Exception e)
641 { 640 {
642 m_log.WarnFormat("[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", dir, dirSize); 641 m_log.Warn(
642 string.Format("[FLOTSAM ASSET CACHE]: Could not complete clean of expired files in {0}, exception ", dir), e);
643 } 643 }
644 } 644 }
645 645
@@ -698,7 +698,7 @@ namespace OpenSim.Region.CoreModules.Asset
698 } 698 }
699 catch (IOException e) 699 catch (IOException e)
700 { 700 {
701 m_log.ErrorFormat( 701 m_log.WarnFormat(
702 "[FLOTSAM ASSET CACHE]: Failed to write asset {0} to temporary location {1} (final {2}) on cache in {3}. Exception {4} {5}.", 702 "[FLOTSAM ASSET CACHE]: Failed to write asset {0} to temporary location {1} (final {2}) on cache in {3}. Exception {4} {5}.",
703 asset.ID, tempname, filename, directory, e.Message, e.StackTrace); 703 asset.ID, tempname, filename, directory, e.Message, e.StackTrace);
704 704
@@ -777,17 +777,31 @@ namespace OpenSim.Region.CoreModules.Asset
777 /// <summary> 777 /// <summary>
778 /// This notes the last time the Region had a deep asset scan performed on it. 778 /// This notes the last time the Region had a deep asset scan performed on it.
779 /// </summary> 779 /// </summary>
780 /// <param name="RegionID"></param> 780 /// <param name="regionID"></param>
781 private void StampRegionStatusFile(UUID RegionID) 781 private void StampRegionStatusFile(UUID regionID)
782 { 782 {
783 string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + RegionID.ToString() + ".fac"); 783 string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + regionID.ToString() + ".fac");
784 if (File.Exists(RegionCacheStatusFile)) 784
785 try
785 { 786 {
786 File.SetLastWriteTime(RegionCacheStatusFile, DateTime.Now); 787 if (File.Exists(RegionCacheStatusFile))
788 {
789 File.SetLastWriteTime(RegionCacheStatusFile, DateTime.Now);
790 }
791 else
792 {
793 File.WriteAllText(
794 RegionCacheStatusFile,
795 "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache.");
796 }
787 } 797 }
788 else 798 catch (Exception e)
789 { 799 {
790 File.WriteAllText(RegionCacheStatusFile, "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache."); 800 m_log.Warn(
801 string.Format(
802 "[FLOTSAM ASSET CACHE]: Could not stamp region status file for region {0}. Exception ",
803 regionID),
804 e);
791 } 805 }
792 } 806 }
793 807
@@ -804,32 +818,43 @@ namespace OpenSim.Region.CoreModules.Asset
804 { 818 {
805 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 819 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
806 820
821 HashSet<UUID> uniqueUuids = new HashSet<UUID>();
807 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 822 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>();
823
808 foreach (Scene s in m_Scenes) 824 foreach (Scene s in m_Scenes)
809 { 825 {
810 StampRegionStatusFile(s.RegionInfo.RegionID); 826 StampRegionStatusFile(s.RegionInfo.RegionID);
811 827
812 s.ForEachSOG(delegate(SceneObjectGroup e) 828 s.ForEachSOG(delegate(SceneObjectGroup e)
813 { 829 {
814 gatherer.GatherAssetUuids(e, assets); 830 gatherer.GatherAssetUuids(e, assets);
815 });
816 }
817 831
818 foreach (UUID assetID in assets.Keys) 832 foreach (UUID assetID in assets.Keys)
819 { 833 {
820 string filename = GetFileName(assetID.ToString()); 834 uniqueUuids.Add(assetID);
821 835
822 if (File.Exists(filename)) 836 string filename = GetFileName(assetID.ToString());
823 { 837
824 File.SetLastAccessTime(filename, DateTime.Now); 838 if (File.Exists(filename))
825 } 839 {
826 else if (storeUncached) 840 File.SetLastAccessTime(filename, DateTime.Now);
827 { 841 }
828 m_AssetService.Get(assetID.ToString()); 842 else if (storeUncached)
829 } 843 {
844 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
845 if (cachedAsset == null && assets[assetID] != AssetType.Unknown)
846 m_log.DebugFormat(
847 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
848 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
849 }
850 }
851
852 assets.Clear();
853 });
830 } 854 }
831 855
832 return assets.Keys.Count; 856
857 return uniqueUuids.Count;
833 } 858 }
834 859
835 /// <summary> 860 /// <summary>
@@ -845,7 +870,7 @@ namespace OpenSim.Region.CoreModules.Asset
845 } 870 }
846 catch (Exception e) 871 catch (Exception e)
847 { 872 {
848 m_log.ErrorFormat( 873 m_log.WarnFormat(
849 "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache directory {0} from {1}. Exception {2} {3}", 874 "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache directory {0} from {1}. Exception {2} {3}",
850 dir, m_CacheDirectory, e.Message, e.StackTrace); 875 dir, m_CacheDirectory, e.Message, e.StackTrace);
851 } 876 }
@@ -859,7 +884,7 @@ namespace OpenSim.Region.CoreModules.Asset
859 } 884 }
860 catch (Exception e) 885 catch (Exception e)
861 { 886 {
862 m_log.ErrorFormat( 887 m_log.WarnFormat(
863 "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache file {0} from {1}. Exception {1} {2}", 888 "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache file {0} from {1}. Exception {1} {2}",
864 file, m_CacheDirectory, e.Message, e.StackTrace); 889 file, m_CacheDirectory, e.Message, e.StackTrace);
865 } 890 }
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 1c2bfd0..fd02b08 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -47,14 +47,16 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
47 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness. 47 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness.
48 /// </summary> 48 /// </summary>
49 [TestFixture] 49 [TestFixture]
50 public class FlotsamAssetCacheTests 50 public class FlotsamAssetCacheTests : OpenSimTestCase
51 { 51 {
52 protected TestScene m_scene; 52 protected TestScene m_scene;
53 protected FlotsamAssetCache m_cache; 53 protected FlotsamAssetCache m_cache;
54 54
55 [SetUp] 55 [SetUp]
56 public void SetUp() 56 public override void SetUp()
57 { 57 {
58 base.SetUp();
59
58 IConfigSource config = new IniConfigSource(); 60 IConfigSource config = new IniConfigSource();
59 61
60 config.AddConfig("Modules"); 62 config.AddConfig("Modules");