aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
diff options
context:
space:
mode:
authorMelanie Thielker2014-06-21 00:39:55 +0200
committerMelanie Thielker2014-06-21 00:39:55 +0200
commit159fcbf150b7da0e229b29aa7b94793484543d12 (patch)
treeb8c0ff3b4c758a3fba8315b556c923ef4c02a185 /OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
parentMerge commit '68c8633ba18f0a11cfc0ed04d1d0c7c59e6cec76' (diff)
parentMerge branch 'master' into careminster (diff)
downloadopensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.zip
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.gz
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.bz2
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.xz
Merge branch 'master' of ssh://3dhosting.de/var/git/careminster
Conflicts: OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
Diffstat (limited to 'OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs')
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs264
1 files changed, 120 insertions, 144 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index d510d82..b270de9 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -31,17 +31,16 @@
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;
47using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
@@ -76,8 +75,6 @@ namespace OpenSim.Region.CoreModules.Asset
76 private static ulong m_RequestsForInprogress; 75 private static ulong m_RequestsForInprogress;
77 private static ulong m_DiskHits; 76 private static ulong m_DiskHits;
78 private static ulong m_MemoryHits; 77 private static ulong m_MemoryHits;
79 private static double m_HitRateMemory;
80 private static double m_HitRateFile;
81 78
82#if WAIT_ON_INPROGRESS_REQUESTS 79#if WAIT_ON_INPROGRESS_REQUESTS
83 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>(); 80 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>();
@@ -251,71 +248,68 @@ namespace OpenSim.Region.CoreModules.Asset
251 248
252 private void UpdateFileCache(string key, AssetBase asset) 249 private void UpdateFileCache(string key, AssetBase asset)
253 { 250 {
254 // TODO: Spawn this off to some seperate thread to do the actual writing 251 string filename = GetFileName(key);
255 if (asset != null)
256 {
257 string filename = GetFileName(key);
258 252
259 try 253 try
254 {
255 // If the file is already cached, don't cache it, just touch it so access time is updated
256 if (File.Exists(filename))
260 { 257 {
261 // If the file is already cached, don't cache it, just touch it so access time is updated 258 // We don't really want to know about sharing
262 if (File.Exists(filename)) 259 // violations here. If the file is locked, then
260 // the other thread has updated the time for us.
261 try
263 { 262 {
264 // We don't really want to know about sharing 263 lock (m_CurrentlyWriting)
265 // violations here. If the file is locked, then
266 // the other thread has updated the time for us.
267 try
268 { 264 {
269 lock (m_CurrentlyWriting) 265 if (!m_CurrentlyWriting.Contains(filename))
270 { 266 File.SetLastAccessTime(filename, DateTime.Now);
271 if (!m_CurrentlyWriting.Contains(filename))
272 File.SetLastAccessTime(filename, DateTime.Now);
273 }
274 } 267 }
275 catch 268 }
269 catch
270 {
271 }
272 }
273 else
274 {
275 // Once we start writing, make sure we flag that we're writing
276 // that object to the cache so that we don't try to write the
277 // same file multiple times.
278 lock (m_CurrentlyWriting)
279 {
280#if WAIT_ON_INPROGRESS_REQUESTS
281 if (m_CurrentlyWriting.ContainsKey(filename))
276 { 282 {
283 return;
277 } 284 }
278 } else { 285 else
279
280 // Once we start writing, make sure we flag that we're writing
281 // that object to the cache so that we don't try to write the
282 // same file multiple times.
283 lock (m_CurrentlyWriting)
284 { 286 {
285#if WAIT_ON_INPROGRESS_REQUESTS 287 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
286 if (m_CurrentlyWriting.ContainsKey(filename)) 288 }
287 {
288 return;
289 }
290 else
291 {
292 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
293 }
294 289
295#else 290#else
296 if (m_CurrentlyWriting.Contains(filename)) 291 if (m_CurrentlyWriting.Contains(filename))
297 { 292 {
298 return; 293 return;
299 }
300 else
301 {
302 m_CurrentlyWriting.Add(filename);
303 }
304#endif
305
306 } 294 }
295 else
296 {
297 m_CurrentlyWriting.Add(filename);
298 }
299#endif
307 300
308 Util.FireAndForget(
309 delegate { WriteFileCache(filename, asset); });
310 } 301 }
311 } 302
312 catch (Exception e) 303 Util.FireAndForget(
313 { 304 delegate { WriteFileCache(filename, asset); });
314 m_log.ErrorFormat(
315 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
316 asset.ID, e.Message, e.StackTrace);
317 } 305 }
318 } 306 }
307 catch (Exception e)
308 {
309 m_log.ErrorFormat(
310 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
311 asset.ID, e.Message, e.StackTrace);
312 }
319 } 313 }
320 314
321 public void Cache(AssetBase asset) 315 public void Cache(AssetBase asset)
@@ -350,15 +344,9 @@ namespace OpenSim.Region.CoreModules.Asset
350 344
351 private bool CheckFromMemoryCache(string id) 345 private bool CheckFromMemoryCache(string id)
352 { 346 {
353 AssetBase asset = null; 347 return m_MemoryCache.Contains(id);
354
355 if (m_MemoryCache.TryGetValue(id, out asset))
356 return true;
357
358 return false;
359 } 348 }
360 349
361
362 /// <summary> 350 /// <summary>
363 /// Try to get an asset from the file cache. 351 /// Try to get an asset from the file cache.
364 /// </summary> 352 /// </summary>
@@ -396,15 +384,16 @@ namespace OpenSim.Region.CoreModules.Asset
396 384
397 if (File.Exists(filename)) 385 if (File.Exists(filename))
398 { 386 {
399 FileStream stream = null;
400 try 387 try
401 { 388 {
402 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 389 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
403 BinaryFormatter bformatter = new BinaryFormatter(); 390 {
391 BinaryFormatter bformatter = new BinaryFormatter();
404 392
405 asset = (AssetBase)bformatter.Deserialize(stream); 393 asset = (AssetBase)bformatter.Deserialize(stream);
406 394
407 m_DiskHits++; 395 m_DiskHits++;
396 }
408 } 397 }
409 catch (System.Runtime.Serialization.SerializationException e) 398 catch (System.Runtime.Serialization.SerializationException e)
410 { 399 {
@@ -423,12 +412,6 @@ namespace OpenSim.Region.CoreModules.Asset
423 m_log.WarnFormat( 412 m_log.WarnFormat(
424 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 413 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
425 filename, id, e.Message, e.StackTrace); 414 filename, id, e.Message, e.StackTrace);
426
427 }
428 finally
429 {
430 if (stream != null)
431 stream.Close();
432 } 415 }
433 } 416 }
434 417
@@ -440,36 +423,19 @@ namespace OpenSim.Region.CoreModules.Asset
440 bool found = false; 423 bool found = false;
441 424
442 string filename = GetFileName(id); 425 string filename = GetFileName(id);
426
443 if (File.Exists(filename)) 427 if (File.Exists(filename))
444 { 428 {
445 // actually check if we can open it, and so update expire
446 FileStream stream = null;
447 try 429 try
448 { 430 {
449 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 431 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
450 if (stream != null)
451 { 432 {
452 found = true; 433 if (stream != null)
453 stream.Close(); 434 found = true;
454 } 435 }
455
456 }
457 catch (System.Runtime.Serialization.SerializationException e)
458 {
459 found = false;
460 m_log.ErrorFormat(
461 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
462 filename, id, e.Message, e.StackTrace);
463
464 // If there was a problem deserializing the asset, the asset may
465 // either be corrupted OR was serialized under an old format
466 // {different version of AssetBase} -- we should attempt to
467 // delete it and re-cache
468 File.Delete(filename);
469 } 436 }
470 catch (Exception e) 437 catch (Exception e)
471 { 438 {
472 found = false;
473 m_log.ErrorFormat( 439 m_log.ErrorFormat(
474 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", 440 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
475 filename, id, e.Message, e.StackTrace); 441 filename, id, e.Message, e.StackTrace);
@@ -498,18 +464,9 @@ namespace OpenSim.Region.CoreModules.Asset
498 464
499 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 465 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
500 { 466 {
501 m_HitRateFile = (double)m_DiskHits / m_Requests * 100.0;
502
503 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); 467 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit");
504 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests);
505 468
506 if (m_MemoryCacheEnabled) 469 GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l));
507 {
508 m_HitRateMemory = (double)m_MemoryHits / m_Requests * 100.0;
509 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests);
510 }
511
512 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress);
513 } 470 }
514 471
515 return asset; 472 return asset;
@@ -530,11 +487,6 @@ namespace OpenSim.Region.CoreModules.Asset
530 return Get(id); 487 return Get(id);
531 } 488 }
532 489
533 public AssetBase CheckCached(string id)
534 {
535 return Get(id);
536 }
537
538 public void Expire(string id) 490 public void Expire(string id)
539 { 491 {
540 if (m_LogLevel >= 2) 492 if (m_LogLevel >= 2)
@@ -819,7 +771,7 @@ namespace OpenSim.Region.CoreModules.Asset
819 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 771 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
820 772
821 HashSet<UUID> uniqueUuids = new HashSet<UUID>(); 773 HashSet<UUID> uniqueUuids = new HashSet<UUID>();
822 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 774 Dictionary<UUID, sbyte> assets = new Dictionary<UUID, sbyte>();
823 775
824 foreach (Scene s in m_Scenes) 776 foreach (Scene s in m_Scenes)
825 { 777 {
@@ -842,7 +794,7 @@ namespace OpenSim.Region.CoreModules.Asset
842 else if (storeUncached) 794 else if (storeUncached)
843 { 795 {
844 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); 796 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
845 if (cachedAsset == null && assets[assetID] != AssetType.Unknown) 797 if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
846 m_log.DebugFormat( 798 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", 799 "[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); 800 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
@@ -891,45 +843,77 @@ namespace OpenSim.Region.CoreModules.Asset
891 } 843 }
892 } 844 }
893 845
846 private List<string> GenerateCacheHitReport()
847 {
848 List<string> outputLines = new List<string>();
849
850 double fileHitRate = (double)m_DiskHits / m_Requests * 100.0;
851 outputLines.Add(
852 string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests));
853
854 if (m_MemoryCacheEnabled)
855 {
856 double memHitRate = (double)m_MemoryHits / m_Requests * 100.0;
857
858 outputLines.Add(
859 string.Format("Memory Hit Rate: {0}% for {1} requests", memHitRate.ToString("0.00"), m_Requests));
860 }
861
862 outputLines.Add(
863 string.Format(
864 "Unnecessary requests due to requests for assets that are currently downloading: {0}",
865 m_RequestsForInprogress));
866
867 return outputLines;
868 }
869
894 #region Console Commands 870 #region Console Commands
895 private void HandleConsoleCommand(string module, string[] cmdparams) 871 private void HandleConsoleCommand(string module, string[] cmdparams)
896 { 872 {
873 ICommandConsole con = MainConsole.Instance;
874
897 if (cmdparams.Length >= 2) 875 if (cmdparams.Length >= 2)
898 { 876 {
899 string cmd = cmdparams[1]; 877 string cmd = cmdparams[1];
878
900 switch (cmd) 879 switch (cmd)
901 { 880 {
902 case "status": 881 case "status":
903 if (m_MemoryCacheEnabled) 882 if (m_MemoryCacheEnabled)
904 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count); 883 con.OutputFormat("Memory Cache: {0} assets", m_MemoryCache.Count);
905 else 884 else
906 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled"); 885 con.OutputFormat("Memory cache disabled");
907 886
908 if (m_FileCacheEnabled) 887 if (m_FileCacheEnabled)
909 { 888 {
910 int fileCount = GetFileCacheCount(m_CacheDirectory); 889 int fileCount = GetFileCacheCount(m_CacheDirectory);
911 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount); 890 con.OutputFormat("File Cache: {0} assets", fileCount);
891 }
892 else
893 {
894 con.Output("File cache disabled");
895 }
896
897 GenerateCacheHitReport().ForEach(l => con.Output(l));
898
899 if (m_FileCacheEnabled)
900 {
901 con.Output("Deep scans have previously been performed on the following regions:");
912 902
913 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) 903 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
914 { 904 {
915 m_log.Info("[FLOTSAM ASSET CACHE]: Deep scans have previously been performed on the following regions:");
916
917 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); 905 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
918 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); 906 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
919 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); 907 con.OutputFormat("Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
920 } 908 }
921 } 909 }
922 else
923 {
924 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
925 }
926 910
927 break; 911 break;
928 912
929 case "clear": 913 case "clear":
930 if (cmdparams.Length < 2) 914 if (cmdparams.Length < 2)
931 { 915 {
932 m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]"); 916 con.Output("Usage is fcache clear [file] [memory]");
933 break; 917 break;
934 } 918 }
935 919
@@ -953,11 +937,11 @@ namespace OpenSim.Region.CoreModules.Asset
953 if (m_MemoryCacheEnabled) 937 if (m_MemoryCacheEnabled)
954 { 938 {
955 m_MemoryCache.Clear(); 939 m_MemoryCache.Clear();
956 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared."); 940 con.Output("Memory cache cleared.");
957 } 941 }
958 else 942 else
959 { 943 {
960 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled."); 944 con.Output("Memory cache not enabled.");
961 } 945 }
962 } 946 }
963 947
@@ -966,24 +950,22 @@ namespace OpenSim.Region.CoreModules.Asset
966 if (m_FileCacheEnabled) 950 if (m_FileCacheEnabled)
967 { 951 {
968 ClearFileCache(); 952 ClearFileCache();
969 m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared."); 953 con.Output("File cache cleared.");
970 } 954 }
971 else 955 else
972 { 956 {
973 m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled."); 957 con.Output("File cache not enabled.");
974 } 958 }
975 } 959 }
976 960
977 break; 961 break;
978 962
979 case "assets": 963 case "assets":
980 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); 964 con.Output("Ensuring assets are cached for all scenes.");
981 965
982 Util.FireAndForget(delegate { 966 Util.FireAndForget(delegate {
983 int assetReferenceTotal = TouchAllSceneAssets(true); 967 int assetReferenceTotal = TouchAllSceneAssets(true);
984 m_log.InfoFormat( 968 con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal);
985 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
986 assetReferenceTotal);
987 }); 969 });
988 970
989 break; 971 break;
@@ -991,7 +973,7 @@ namespace OpenSim.Region.CoreModules.Asset
991 case "expire": 973 case "expire":
992 if (cmdparams.Length < 3) 974 if (cmdparams.Length < 3)
993 { 975 {
994 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd); 976 con.OutputFormat("Invalid parameters for Expire, please specify a valid date & time", cmd);
995 break; 977 break;
996 } 978 }
997 979
@@ -1009,28 +991,27 @@ namespace OpenSim.Region.CoreModules.Asset
1009 991
1010 if (!DateTime.TryParse(s_expirationDate, out expirationDate)) 992 if (!DateTime.TryParse(s_expirationDate, out expirationDate))
1011 { 993 {
1012 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd); 994 con.OutputFormat("{0} is not a valid date & time", cmd);
1013 break; 995 break;
1014 } 996 }
1015 997
1016 if (m_FileCacheEnabled) 998 if (m_FileCacheEnabled)
1017 CleanExpiredFiles(m_CacheDirectory, expirationDate); 999 CleanExpiredFiles(m_CacheDirectory, expirationDate);
1018 else 1000 else
1019 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing."); 1001 con.OutputFormat("File cache not active, not clearing.");
1020 1002
1021 break; 1003 break;
1022 default: 1004 default:
1023 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd); 1005 con.OutputFormat("Unknown command {0}", cmd);
1024 break; 1006 break;
1025 } 1007 }
1026 } 1008 }
1027 else if (cmdparams.Length == 1) 1009 else if (cmdparams.Length == 1)
1028 { 1010 {
1029 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status"); 1011 con.Output("fcache assets - Attempt a deep cache of all assets in all scenes");
1030 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory"); 1012 con.Output("fcache expire <datetime> - Purge assets older then the specified date & time");
1031 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk"); 1013 con.Output("fcache clear [file] [memory] - Remove cached assets");
1032 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes"); 1014 con.Output("fcache status - Display cache status");
1033 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache <datetime> - Purge assets older then the specified date & time");
1034 } 1015 }
1035 } 1016 }
1036 1017
@@ -1050,11 +1031,6 @@ namespace OpenSim.Region.CoreModules.Asset
1050 return asset.Data; 1031 return asset.Data;
1051 } 1032 }
1052 1033
1053 public bool CheckData(string id)
1054 {
1055 return Check(id); ;
1056 }
1057
1058 public bool Get(string id, object sender, AssetRetrieved handler) 1034 public bool Get(string id, object sender, AssetRetrieved handler)
1059 { 1035 {
1060 AssetBase asset = Get(id); 1036 AssetBase asset = Get(id);