diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Asset')
-rw-r--r-- | OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 191 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs | 6 |
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"); |