aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to 'OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs')
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs400
1 files changed, 264 insertions, 136 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 8e800cb..7d9c9a9 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -31,26 +31,26 @@
31using System; 31using System;
32using System.IO; 32using System.IO;
33using System.Collections.Generic; 33using System.Collections.Generic;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Runtime.Serialization; 36using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary; 37using System.Runtime.Serialization.Formatters.Binary;
37using System.Threading; 38using System.Threading;
38using System.Timers; 39using System.Timers;
39
40using log4net; 40using log4net;
41using Nini.Config; 41using Nini.Config;
42using Mono.Addins; 42using Mono.Addins;
43using OpenMetaverse; 43using OpenMetaverse;
44
45using OpenSim.Framework; 44using OpenSim.Framework;
46using OpenSim.Framework.Console; 45using OpenSim.Framework.Console;
46using OpenSim.Framework.Monitoring;
47using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Services.Interfaces; 49using OpenSim.Services.Interfaces;
50 50
51 51
52//[assembly: Addin("FlotsamAssetCache", "1.1")] 52//[assembly: Addin("FlotsamAssetCache", "1.1")]
53//[assembly: AddinDependency("OpenSim", "0.5")] 53//[assembly: AddinDependency("OpenSim", "0.8.1")]
54 54
55namespace OpenSim.Region.CoreModules.Asset 55namespace OpenSim.Region.CoreModules.Asset
56{ 56{
@@ -76,8 +76,6 @@ namespace OpenSim.Region.CoreModules.Asset
76 private static ulong m_RequestsForInprogress; 76 private static ulong m_RequestsForInprogress;
77 private static ulong m_DiskHits; 77 private static ulong m_DiskHits;
78 private static ulong m_MemoryHits; 78 private static ulong m_MemoryHits;
79 private static double m_HitRateMemory;
80 private static double m_HitRateFile;
81 79
82#if WAIT_ON_INPROGRESS_REQUESTS 80#if WAIT_ON_INPROGRESS_REQUESTS
83 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>(); 81 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>();
@@ -251,23 +249,19 @@ namespace OpenSim.Region.CoreModules.Asset
251 249
252 private void UpdateFileCache(string key, AssetBase asset) 250 private void UpdateFileCache(string key, AssetBase asset)
253 { 251 {
254 string filename = GetFileName(asset.ID); 252 string filename = GetFileName(key);
255 253
256 try 254 try
257 { 255 {
258 // If the file is already cached just update access time. 256 // If the file is already cached, don't cache it, just touch it so access time is updated
259 if (File.Exists(filename)) 257 if (File.Exists(filename))
260 { 258 {
261 lock (m_CurrentlyWriting) 259 UpdateFileLastAccessTime(filename);
262 { 260 }
263 if (!m_CurrentlyWriting.Contains(filename)) 261 else
264 File.SetLastAccessTime(filename, DateTime.Now);
265 }
266 }
267 else
268 { 262 {
269 // Once we start writing, make sure we flag that we're writing 263 // Once we start writing, make sure we flag that we're writing
270 // that object to the cache so that we don't try to write the 264 // that object to the cache so that we don't try to write the
271 // same file multiple times. 265 // same file multiple times.
272 lock (m_CurrentlyWriting) 266 lock (m_CurrentlyWriting)
273 { 267 {
@@ -279,7 +273,7 @@ namespace OpenSim.Region.CoreModules.Asset
279 else 273 else
280 { 274 {
281 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); 275 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
282 } 276 }
283 277
284#else 278#else
285 if (m_CurrentlyWriting.Contains(filename)) 279 if (m_CurrentlyWriting.Contains(filename))
@@ -291,10 +285,11 @@ namespace OpenSim.Region.CoreModules.Asset
291 m_CurrentlyWriting.Add(filename); 285 m_CurrentlyWriting.Add(filename);
292 } 286 }
293#endif 287#endif
288
294 } 289 }
295 290
296 Util.FireAndForget( 291 Util.FireAndForget(
297 delegate { WriteFileCache(filename, asset); }); 292 delegate { WriteFileCache(filename, asset); }, null, "FlotsamAssetCache.UpdateFileCache");
298 } 293 }
299 } 294 }
300 catch (Exception e) 295 catch (Exception e)
@@ -321,6 +316,24 @@ namespace OpenSim.Region.CoreModules.Asset
321 } 316 }
322 317
323 /// <summary> 318 /// <summary>
319 /// Updates the cached file with the current time.
320 /// </summary>
321 /// <param name="filename">Filename.</param>
322 /// <returns><c>true</c>, if the update was successful, false otherwise.</returns>
323 private bool UpdateFileLastAccessTime(string filename)
324 {
325 try
326 {
327 File.SetLastAccessTime(filename, DateTime.Now);
328 return true;
329 }
330 catch
331 {
332 return false;
333 }
334 }
335
336 /// <summary>
324 /// Try to get an asset from the in-memory cache. 337 /// Try to get an asset from the in-memory cache.
325 /// </summary> 338 /// </summary>
326 /// <param name="id"></param> 339 /// <param name="id"></param>
@@ -335,31 +348,62 @@ namespace OpenSim.Region.CoreModules.Asset
335 return asset; 348 return asset;
336 } 349 }
337 350
351 private bool CheckFromMemoryCache(string id)
352 {
353 return m_MemoryCache.Contains(id);
354 }
355
338 /// <summary> 356 /// <summary>
339 /// Try to get an asset from the file cache. 357 /// Try to get an asset from the file cache.
340 /// </summary> 358 /// </summary>
341 /// <param name="id"></param> 359 /// <param name="id"></param>
342 /// <returns></returns> 360 /// <returns>An asset retrieved from the file cache. null if there was a problem retrieving an asset.</returns>
343 private AssetBase GetFromFileCache(string id) 361 private AssetBase GetFromFileCache(string id)
344 { 362 {
363 string filename = GetFileName(id);
364
365#if WAIT_ON_INPROGRESS_REQUESTS
366 // Check if we're already downloading this asset. If so, try to wait for it to
367 // download.
368 if (m_WaitOnInprogressTimeout > 0)
369 {
370 m_RequestsForInprogress++;
371
372 ManualResetEvent waitEvent;
373 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent))
374 {
375 waitEvent.WaitOne(m_WaitOnInprogressTimeout);
376 return Get(id);
377 }
378 }
379#else
380 // Track how often we have the problem that an asset is requested while
381 // it is still being downloaded by a previous request.
382 if (m_CurrentlyWriting.Contains(filename))
383 {
384 m_RequestsForInprogress++;
385 return null;
386 }
387#endif
388
345 AssetBase asset = null; 389 AssetBase asset = null;
346 390
347 string filename = GetFileName(id);
348 if (File.Exists(filename)) 391 if (File.Exists(filename))
349 { 392 {
350 FileStream stream = null;
351 try 393 try
352 { 394 {
353 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 395 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
354 BinaryFormatter bformatter = new BinaryFormatter(); 396 {
397 BinaryFormatter bformatter = new BinaryFormatter();
355 398
356 asset = (AssetBase)bformatter.Deserialize(stream); 399 asset = (AssetBase)bformatter.Deserialize(stream);
357 400
358 m_DiskHits++; 401 m_DiskHits++;
402 }
359 } 403 }
360 catch (System.Runtime.Serialization.SerializationException e) 404 catch (System.Runtime.Serialization.SerializationException e)
361 { 405 {
362 m_log.ErrorFormat( 406 m_log.WarnFormat(
363 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 407 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
364 filename, id, e.Message, e.StackTrace); 408 filename, id, e.Message, e.StackTrace);
365 409
@@ -371,40 +415,40 @@ namespace OpenSim.Region.CoreModules.Asset
371 } 415 }
372 catch (Exception e) 416 catch (Exception e)
373 { 417 {
374 m_log.ErrorFormat( 418 m_log.WarnFormat(
375 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 419 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
376 filename, id, e.Message, e.StackTrace); 420 filename, id, e.Message, e.StackTrace);
377 } 421 }
378 finally
379 {
380 if (stream != null)
381 stream.Close();
382 }
383 } 422 }
384 423
385#if WAIT_ON_INPROGRESS_REQUESTS 424 return asset;
386 // Check if we're already downloading this asset. If so, try to wait for it to 425 }
387 // download.
388 if (m_WaitOnInprogressTimeout > 0)
389 {
390 m_RequestsForInprogress++;
391 426
392 ManualResetEvent waitEvent; 427 private bool CheckFromFileCache(string id)
393 if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) 428 {
429 bool found = false;
430
431 string filename = GetFileName(id);
432
433 if (File.Exists(filename))
434 {
435 try
394 { 436 {
395 waitEvent.WaitOne(m_WaitOnInprogressTimeout); 437 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
396 return Get(id); 438 {
439 if (stream != null)
440 found = true;
441 }
442 }
443 catch (Exception e)
444 {
445 m_log.ErrorFormat(
446 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
447 filename, id, e.Message, e.StackTrace);
397 } 448 }
398 } 449 }
399#else 450
400 // Track how often we have the problem that an asset is requested while 451 return found;
401 // it is still being downloaded by a previous request.
402 if (m_CurrentlyWriting.Contains(filename))
403 {
404 m_RequestsForInprogress++;
405 }
406#endif
407 return asset;
408 } 452 }
409 453
410 public AssetBase Get(string id) 454 public AssetBase Get(string id)
@@ -426,23 +470,24 @@ namespace OpenSim.Region.CoreModules.Asset
426 470
427 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 471 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
428 { 472 {
429 m_HitRateFile = (double)m_DiskHits / m_Requests * 100.0;
430
431 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); 473 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit");
432 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests);
433
434 if (m_MemoryCacheEnabled)
435 {
436 m_HitRateMemory = (double)m_MemoryHits / m_Requests * 100.0;
437 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests);
438 }
439 474
440 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress); 475 GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l));
441 } 476 }
442 477
443 return asset; 478 return asset;
444 } 479 }
445 480
481 public bool Check(string id)
482 {
483 if (m_MemoryCacheEnabled && CheckFromMemoryCache(id))
484 return true;
485
486 if (m_FileCacheEnabled && CheckFromFileCache(id))
487 return true;
488 return false;
489 }
490
446 public AssetBase GetCached(string id) 491 public AssetBase GetCached(string id)
447 { 492 {
448 return Get(id); 493 return Get(id);
@@ -469,7 +514,7 @@ namespace OpenSim.Region.CoreModules.Asset
469 } 514 }
470 catch (Exception e) 515 catch (Exception e)
471 { 516 {
472 m_log.ErrorFormat( 517 m_log.WarnFormat(
473 "[FLOTSAM ASSET CACHE]: Failed to expire cached file {0}. Exception {1} {2}", 518 "[FLOTSAM ASSET CACHE]: Failed to expire cached file {0}. Exception {1} {2}",
474 id, e.Message, e.StackTrace); 519 id, e.Message, e.StackTrace);
475 } 520 }
@@ -520,29 +565,39 @@ namespace OpenSim.Region.CoreModules.Asset
520 /// <param name="purgeLine"></param> 565 /// <param name="purgeLine"></param>
521 private void CleanExpiredFiles(string dir, DateTime purgeLine) 566 private void CleanExpiredFiles(string dir, DateTime purgeLine)
522 { 567 {
523 foreach (string file in Directory.GetFiles(dir)) 568 try
524 { 569 {
525 if (File.GetLastAccessTime(file) < purgeLine) 570 foreach (string file in Directory.GetFiles(dir))
526 { 571 {
527 File.Delete(file); 572 if (File.GetLastAccessTime(file) < purgeLine)
573 {
574 File.Delete(file);
575 }
528 } 576 }
529 }
530 577
531 // Recurse into lower tiers 578 // Recurse into lower tiers
532 foreach (string subdir in Directory.GetDirectories(dir)) 579 foreach (string subdir in Directory.GetDirectories(dir))
533 { 580 {
534 CleanExpiredFiles(subdir, purgeLine); 581 CleanExpiredFiles(subdir, purgeLine);
535 } 582 }
536 583
537 // Check if a tier directory is empty, if so, delete it 584 // Check if a tier directory is empty, if so, delete it
538 int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length; 585 int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length;
539 if (dirSize == 0) 586 if (dirSize == 0)
540 { 587 {
541 Directory.Delete(dir); 588 Directory.Delete(dir);
589 }
590 else if (dirSize >= m_CacheWarnAt)
591 {
592 m_log.WarnFormat(
593 "[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration",
594 dir, dirSize);
595 }
542 } 596 }
543 else if (dirSize >= m_CacheWarnAt) 597 catch (Exception e)
544 { 598 {
545 m_log.WarnFormat("[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", dir, dirSize); 599 m_log.Warn(
600 string.Format("[FLOTSAM ASSET CACHE]: Could not complete clean of expired files in {0}, exception ", dir), e);
546 } 601 }
547 } 602 }
548 603
@@ -601,7 +656,7 @@ namespace OpenSim.Region.CoreModules.Asset
601 } 656 }
602 catch (IOException e) 657 catch (IOException e)
603 { 658 {
604 m_log.ErrorFormat( 659 m_log.WarnFormat(
605 "[FLOTSAM ASSET CACHE]: Failed to write asset {0} to temporary location {1} (final {2}) on cache in {3}. Exception {4} {5}.", 660 "[FLOTSAM ASSET CACHE]: Failed to write asset {0} to temporary location {1} (final {2}) on cache in {3}. Exception {4} {5}.",
606 asset.ID, tempname, filename, directory, e.Message, e.StackTrace); 661 asset.ID, tempname, filename, directory, e.Message, e.StackTrace);
607 662
@@ -680,17 +735,31 @@ namespace OpenSim.Region.CoreModules.Asset
680 /// <summary> 735 /// <summary>
681 /// This notes the last time the Region had a deep asset scan performed on it. 736 /// This notes the last time the Region had a deep asset scan performed on it.
682 /// </summary> 737 /// </summary>
683 /// <param name="RegionID"></param> 738 /// <param name="regionID"></param>
684 private void StampRegionStatusFile(UUID RegionID) 739 private void StampRegionStatusFile(UUID regionID)
685 { 740 {
686 string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + RegionID.ToString() + ".fac"); 741 string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + regionID.ToString() + ".fac");
687 if (File.Exists(RegionCacheStatusFile)) 742
743 try
688 { 744 {
689 File.SetLastWriteTime(RegionCacheStatusFile, DateTime.Now); 745 if (File.Exists(RegionCacheStatusFile))
746 {
747 File.SetLastWriteTime(RegionCacheStatusFile, DateTime.Now);
748 }
749 else
750 {
751 File.WriteAllText(
752 RegionCacheStatusFile,
753 "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache.");
754 }
690 } 755 }
691 else 756 catch (Exception e)
692 { 757 {
693 File.WriteAllText(RegionCacheStatusFile, "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache."); 758 m_log.Warn(
759 string.Format(
760 "[FLOTSAM ASSET CACHE]: Could not stamp region status file for region {0}. Exception ",
761 regionID),
762 e);
694 } 763 }
695 } 764 }
696 765
@@ -707,32 +776,49 @@ namespace OpenSim.Region.CoreModules.Asset
707 { 776 {
708 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 777 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
709 778
710 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 779 Dictionary<UUID, bool> assetsFound = new Dictionary<UUID, bool>();
780
711 foreach (Scene s in m_Scenes) 781 foreach (Scene s in m_Scenes)
712 { 782 {
713 StampRegionStatusFile(s.RegionInfo.RegionID); 783 StampRegionStatusFile(s.RegionInfo.RegionID);
714 784
715 s.ForEachSOG(delegate(SceneObjectGroup e) 785 s.ForEachSOG(delegate(SceneObjectGroup e)
716 { 786 {
717 gatherer.GatherAssetUuids(e, assets); 787 gatherer.AddForInspection(e);
718 }); 788 gatherer.GatherAll();
719 }
720 789
721 foreach (UUID assetID in assets.Keys) 790 foreach (UUID assetID in gatherer.GatheredUuids.Keys)
722 { 791 {
723 string filename = GetFileName(assetID.ToString()); 792 if (!assetsFound.ContainsKey(assetID))
793 {
794 string filename = GetFileName(assetID.ToString());
724 795
725 if (File.Exists(filename)) 796 if (File.Exists(filename))
726 { 797 {
727 File.SetLastAccessTime(filename, DateTime.Now); 798 UpdateFileLastAccessTime(filename);
728 } 799 }
729 else if (storeUncached) 800 else if (storeUncached)
730 { 801 {
731 m_AssetService.Get(assetID.ToString()); 802 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
732 } 803 if (cachedAsset == null && gatherer.GatheredUuids[assetID] != (sbyte)AssetType.Unknown)
804 assetsFound[assetID] = false;
805 else
806 assetsFound[assetID] = true;
807 }
808 }
809 else if (!assetsFound[assetID])
810 {
811 m_log.DebugFormat(
812 "[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",
813 assetID, gatherer.GatheredUuids[assetID], e.Name, e.AbsolutePosition, s.Name);
814 }
815 }
816
817 gatherer.GatheredUuids.Clear();
818 });
733 } 819 }
734 820
735 return assets.Keys.Count; 821 return assetsFound.Count;
736 } 822 }
737 823
738 /// <summary> 824 /// <summary>
@@ -748,7 +834,7 @@ namespace OpenSim.Region.CoreModules.Asset
748 } 834 }
749 catch (Exception e) 835 catch (Exception e)
750 { 836 {
751 m_log.ErrorFormat( 837 m_log.WarnFormat(
752 "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache directory {0} from {1}. Exception {2} {3}", 838 "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache directory {0} from {1}. Exception {2} {3}",
753 dir, m_CacheDirectory, e.Message, e.StackTrace); 839 dir, m_CacheDirectory, e.Message, e.StackTrace);
754 } 840 }
@@ -762,52 +848,84 @@ namespace OpenSim.Region.CoreModules.Asset
762 } 848 }
763 catch (Exception e) 849 catch (Exception e)
764 { 850 {
765 m_log.ErrorFormat( 851 m_log.WarnFormat(
766 "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache file {0} from {1}. Exception {1} {2}", 852 "[FLOTSAM ASSET CACHE]: Couldn't clear asset cache file {0} from {1}. Exception {1} {2}",
767 file, m_CacheDirectory, e.Message, e.StackTrace); 853 file, m_CacheDirectory, e.Message, e.StackTrace);
768 } 854 }
769 } 855 }
770 } 856 }
771 857
858 private List<string> GenerateCacheHitReport()
859 {
860 List<string> outputLines = new List<string>();
861
862 double fileHitRate = (double)m_DiskHits / m_Requests * 100.0;
863 outputLines.Add(
864 string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests));
865
866 if (m_MemoryCacheEnabled)
867 {
868 double memHitRate = (double)m_MemoryHits / m_Requests * 100.0;
869
870 outputLines.Add(
871 string.Format("Memory Hit Rate: {0}% for {1} requests", memHitRate.ToString("0.00"), m_Requests));
872 }
873
874 outputLines.Add(
875 string.Format(
876 "Unnecessary requests due to requests for assets that are currently downloading: {0}",
877 m_RequestsForInprogress));
878
879 return outputLines;
880 }
881
772 #region Console Commands 882 #region Console Commands
773 private void HandleConsoleCommand(string module, string[] cmdparams) 883 private void HandleConsoleCommand(string module, string[] cmdparams)
774 { 884 {
885 ICommandConsole con = MainConsole.Instance;
886
775 if (cmdparams.Length >= 2) 887 if (cmdparams.Length >= 2)
776 { 888 {
777 string cmd = cmdparams[1]; 889 string cmd = cmdparams[1];
890
778 switch (cmd) 891 switch (cmd)
779 { 892 {
780 case "status": 893 case "status":
781 if (m_MemoryCacheEnabled) 894 if (m_MemoryCacheEnabled)
782 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count); 895 con.OutputFormat("Memory Cache: {0} assets", m_MemoryCache.Count);
783 else 896 else
784 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled"); 897 con.OutputFormat("Memory cache disabled");
785 898
786 if (m_FileCacheEnabled) 899 if (m_FileCacheEnabled)
787 { 900 {
788 int fileCount = GetFileCacheCount(m_CacheDirectory); 901 int fileCount = GetFileCacheCount(m_CacheDirectory);
789 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount); 902 con.OutputFormat("File Cache: {0} assets", fileCount);
903 }
904 else
905 {
906 con.Output("File cache disabled");
907 }
908
909 GenerateCacheHitReport().ForEach(l => con.Output(l));
910
911 if (m_FileCacheEnabled)
912 {
913 con.Output("Deep scans have previously been performed on the following regions:");
790 914
791 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) 915 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
792 { 916 {
793 m_log.Info("[FLOTSAM ASSET CACHE]: Deep scans have previously been performed on the following regions:");
794
795 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); 917 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
796 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); 918 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
797 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); 919 con.OutputFormat("Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
798 } 920 }
799 } 921 }
800 else
801 {
802 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
803 }
804 922
805 break; 923 break;
806 924
807 case "clear": 925 case "clear":
808 if (cmdparams.Length < 2) 926 if (cmdparams.Length < 2)
809 { 927 {
810 m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]"); 928 con.Output("Usage is fcache clear [file] [memory]");
811 break; 929 break;
812 } 930 }
813 931
@@ -831,11 +949,11 @@ namespace OpenSim.Region.CoreModules.Asset
831 if (m_MemoryCacheEnabled) 949 if (m_MemoryCacheEnabled)
832 { 950 {
833 m_MemoryCache.Clear(); 951 m_MemoryCache.Clear();
834 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared."); 952 con.Output("Memory cache cleared.");
835 } 953 }
836 else 954 else
837 { 955 {
838 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled."); 956 con.Output("Memory cache not enabled.");
839 } 957 }
840 } 958 }
841 959
@@ -844,32 +962,31 @@ namespace OpenSim.Region.CoreModules.Asset
844 if (m_FileCacheEnabled) 962 if (m_FileCacheEnabled)
845 { 963 {
846 ClearFileCache(); 964 ClearFileCache();
847 m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared."); 965 con.Output("File cache cleared.");
848 } 966 }
849 else 967 else
850 { 968 {
851 m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled."); 969 con.Output("File cache not enabled.");
852 } 970 }
853 } 971 }
854 972
855 break; 973 break;
856 974
857 case "assets": 975 case "assets":
858 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); 976 con.Output("Ensuring assets are cached for all scenes.");
859 977
860 Util.FireAndForget(delegate { 978 WorkManager.RunInThread(delegate
979 {
861 int assetReferenceTotal = TouchAllSceneAssets(true); 980 int assetReferenceTotal = TouchAllSceneAssets(true);
862 m_log.InfoFormat( 981 con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal);
863 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.", 982 }, null, "TouchAllSceneAssets");
864 assetReferenceTotal);
865 });
866 983
867 break; 984 break;
868 985
869 case "expire": 986 case "expire":
870 if (cmdparams.Length < 3) 987 if (cmdparams.Length < 3)
871 { 988 {
872 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd); 989 con.OutputFormat("Invalid parameters for Expire, please specify a valid date & time", cmd);
873 break; 990 break;
874 } 991 }
875 992
@@ -887,28 +1004,27 @@ namespace OpenSim.Region.CoreModules.Asset
887 1004
888 if (!DateTime.TryParse(s_expirationDate, out expirationDate)) 1005 if (!DateTime.TryParse(s_expirationDate, out expirationDate))
889 { 1006 {
890 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd); 1007 con.OutputFormat("{0} is not a valid date & time", cmd);
891 break; 1008 break;
892 } 1009 }
893 1010
894 if (m_FileCacheEnabled) 1011 if (m_FileCacheEnabled)
895 CleanExpiredFiles(m_CacheDirectory, expirationDate); 1012 CleanExpiredFiles(m_CacheDirectory, expirationDate);
896 else 1013 else
897 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing."); 1014 con.OutputFormat("File cache not active, not clearing.");
898 1015
899 break; 1016 break;
900 default: 1017 default:
901 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd); 1018 con.OutputFormat("Unknown command {0}", cmd);
902 break; 1019 break;
903 } 1020 }
904 } 1021 }
905 else if (cmdparams.Length == 1) 1022 else if (cmdparams.Length == 1)
906 { 1023 {
907 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status"); 1024 con.Output("fcache assets - Attempt a deep cache of all assets in all scenes");
908 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory"); 1025 con.Output("fcache expire <datetime> - Purge assets older then the specified date & time");
909 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk"); 1026 con.Output("fcache clear [file] [memory] - Remove cached assets");
910 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes"); 1027 con.Output("fcache status - Display cache status");
911 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache <datetime> - Purge assets older then the specified date & time");
912 } 1028 }
913 } 1029 }
914 1030
@@ -935,6 +1051,18 @@ namespace OpenSim.Region.CoreModules.Asset
935 return true; 1051 return true;
936 } 1052 }
937 1053
1054 public bool[] AssetsExist(string[] ids)
1055 {
1056 bool[] exist = new bool[ids.Length];
1057
1058 for (int i = 0; i < ids.Length; i++)
1059 {
1060 exist[i] = Check(ids[i]);
1061 }
1062
1063 return exist;
1064 }
1065
938 public string Store(AssetBase asset) 1066 public string Store(AssetBase asset)
939 { 1067 {
940 if (asset.FullID == UUID.Zero) 1068 if (asset.FullID == UUID.Zero)