aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/Communications/Cache/AssetCache.cs268
1 files changed, 77 insertions, 191 deletions
diff --git a/OpenSim/Framework/Communications/Cache/AssetCache.cs b/OpenSim/Framework/Communications/Cache/AssetCache.cs
index dfdb0e7..0581cc6 100644
--- a/OpenSim/Framework/Communications/Cache/AssetCache.cs
+++ b/OpenSim/Framework/Communications/Cache/AssetCache.cs
@@ -33,6 +33,7 @@ using OpenMetaverse;
33using OpenMetaverse.Packets; 33using OpenMetaverse.Packets;
34using log4net; 34using log4net;
35using OpenSim.Framework.Statistics; 35using OpenSim.Framework.Statistics;
36using GlynnTucker.Cache;
36 37
37namespace OpenSim.Framework.Communications.Cache 38namespace OpenSim.Framework.Communications.Cache
38{ 39{
@@ -52,18 +53,20 @@ namespace OpenSim.Framework.Communications.Cache
52 /// </summary> 53 /// </summary>
53 public class AssetCache : IAssetReceiver 54 public class AssetCache : IAssetReceiver
54 { 55 {
56 protected ICache m_memcache = new SimpleMemoryCache();
57
55 private static readonly ILog m_log 58 private static readonly ILog m_log
56 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 59 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57 60
58 /// <summary> 61 /// <summary>
59 /// The cache of assets. This does not include textures. 62 /// The cache of assets. This does not include textures.
60 /// </summary> 63 /// </summary>
61 private Dictionary<UUID, AssetInfo> Assets; 64 //private Dictionary<UUID, AssetInfo> Assets;
62 65
63 /// <summary> 66 /// <summary>
64 /// The cache of textures. 67 /// The cache of textures.
65 /// </summary> 68 /// </summary>
66 private Dictionary<UUID, TextureImage> Textures; 69 //private Dictionary<UUID, TextureImage> Textures;
67 70
68 /// <summary> 71 /// <summary>
69 /// Assets requests which are waiting for asset server data. This includes texture requests 72 /// Assets requests which are waiting for asset server data. This includes texture requests
@@ -95,52 +98,11 @@ namespace OpenSim.Framework.Communications.Cache
95 /// </summary> 98 /// </summary>
96 public void ShowState() 99 public void ShowState()
97 { 100 {
98 m_log.InfoFormat("Assets:{0} Textures:{1} RequestLists:{2}", 101 m_log.InfoFormat("Memcache:{1} RequestLists:{2}",
99 Assets.Count, 102 m_memcache.Count,
100 Textures.Count,
101 // AssetRequests.Count, 103 // AssetRequests.Count,
102 // RequestedAssets.Count, 104 // RequestedAssets.Count,
103 RequestLists.Count); 105 RequestLists.Count);
104
105 int temporaryImages = 0;
106 int temporaryAssets = 0;
107
108 long imageBytes = 0;
109 long assetBytes = 0;
110
111 foreach (TextureImage texture in Textures.Values)
112 {
113 if (texture != null)
114 {
115 if (texture.Temporary)
116 {
117 temporaryImages++;
118 }
119
120 imageBytes += texture.Data.GetLongLength(0);
121 }
122 }
123
124 foreach (AssetInfo asset in Assets.Values)
125 {
126 if (asset != null)
127 {
128 if (asset.Temporary)
129 {
130 temporaryAssets++;
131 }
132
133 assetBytes += asset.Data.GetLongLength(0);
134 }
135 }
136
137 m_log.InfoFormat("Temporary Images: {0} Temporary Assets: {1}",
138 temporaryImages,
139 temporaryAssets);
140
141 m_log.InfoFormat("Image data: {0}kb Asset data: {1}kb",
142 imageBytes / 1024,
143 assetBytes / 1024);
144 } 106 }
145 107
146 /// <summary> 108 /// <summary>
@@ -161,8 +123,6 @@ namespace OpenSim.Framework.Communications.Cache
161 /// </summary> 123 /// </summary>
162 private void Initialize() 124 private void Initialize()
163 { 125 {
164 Assets = new Dictionary<UUID, AssetInfo>();
165 Textures = new Dictionary<UUID, TextureImage>();
166 AssetRequests = new List<AssetRequest>(); 126 AssetRequests = new List<AssetRequest>();
167 127
168 RequestedAssets = new Dictionary<UUID, AssetRequest>(); 128 RequestedAssets = new Dictionary<UUID, AssetRequest>();
@@ -181,7 +141,7 @@ namespace OpenSim.Framework.Communications.Cache
181 m_assetServer = assetServer; 141 m_assetServer = assetServer;
182 m_assetServer.SetReceiver(this); 142 m_assetServer.SetReceiver(this);
183 143
184 Thread assetCacheThread = new Thread(new ThreadStart(RunAssetManager)); 144 Thread assetCacheThread = new Thread(RunAssetManager);
185 assetCacheThread.Name = "AssetCacheThread"; 145 assetCacheThread.Name = "AssetCacheThread";
186 assetCacheThread.IsBackground = true; 146 assetCacheThread.IsBackground = true;
187 assetCacheThread.Start(); 147 assetCacheThread.Start();
@@ -203,7 +163,7 @@ namespace OpenSim.Framework.Communications.Cache
203 } 163 }
204 catch (Exception e) 164 catch (Exception e)
205 { 165 {
206 m_log.Error("[ASSET CACHE]: " + e.ToString()); 166 m_log.Error("[ASSET CACHE]: " + e);
207 } 167 }
208 } 168 }
209 } 169 }
@@ -216,14 +176,11 @@ namespace OpenSim.Framework.Communications.Cache
216 /// <returns>true if the asset was in the cache, false if it was not</returns> 176 /// <returns>true if the asset was in the cache, false if it was not</returns>
217 public bool TryGetCachedAsset(UUID assetId, out AssetBase asset) 177 public bool TryGetCachedAsset(UUID assetId, out AssetBase asset)
218 { 178 {
219 if (Textures.ContainsKey(assetId)) 179 Object tmp;
220 { 180 if(m_memcache.TryGet(assetId, out tmp))
221 asset = Textures[assetId];
222 return true;
223 }
224 else if (Assets.ContainsKey(assetId))
225 { 181 {
226 asset = Assets[assetId]; 182 asset = (AssetBase)tmp;
183 //m_log.Info("Retrieved from cache " + assetId);
227 return true; 184 return true;
228 } 185 }
229 186
@@ -312,25 +269,22 @@ namespace OpenSim.Framework.Communications.Cache
312 { 269 {
313 return asset; 270 return asset;
314 } 271 }
315 else 272 m_assetServer.RequestAsset(assetID, isTexture);
273
274 do
316 { 275 {
317 m_assetServer.RequestAsset(assetID, isTexture); 276 Thread.Sleep(pollPeriod);
318 277
319 do 278 if (TryGetCachedAsset(assetID, out asset))
320 { 279 {
321 Thread.Sleep(pollPeriod); 280 return asset;
322 281 }
323 if (TryGetCachedAsset(assetID, out asset)) 282 } while (--maxPolls > 0);
324 {
325 return asset;
326 }
327 } while (--maxPolls > 0);
328 283
329 m_log.WarnFormat("[ASSET CACHE]: {0} {1} was not received before the retrieval timeout was reached", 284 m_log.WarnFormat("[ASSET CACHE]: {0} {1} was not received before the retrieval timeout was reached",
330 isTexture ? "texture" : "asset", assetID.ToString()); 285 isTexture ? "texture" : "asset", assetID.ToString());
331 286
332 return null; 287 return null;
333 }
334 } 288 }
335 289
336 /// <summary> 290 /// <summary>
@@ -339,68 +293,34 @@ namespace OpenSim.Framework.Communications.Cache
339 /// <param name="asset"></param> 293 /// <param name="asset"></param>
340 public void AddAsset(AssetBase asset) 294 public void AddAsset(AssetBase asset)
341 { 295 {
342// m_log.DebugFormat( 296 if (!m_memcache.Contains(asset.FullID))
343// "[ASSET CACHE]: Uploaded asset {0}, temporary {1}, store local {2}",
344// asset.ID, asset.Temporary, asset.Local);
345
346 if (asset.Type == (int)AssetType.Texture)
347 { 297 {
348 if (!Textures.ContainsKey(asset.FullID)) 298 m_log.Info("[CACHE] Caching " + asset.FullID + " for 24 hours from last access");
299 // Use 24 hour rolling asset cache.
300 m_memcache.AddOrUpdate(asset.FullID, asset, TimeSpan.FromHours(24));
301
302 // According to http://wiki.secondlife.com/wiki/AssetUploadRequest, Local signifies that the
303 // information is stored locally. It could disappear, in which case we could send the
304 // ImageNotInDatabase packet to tell the client this.
305 //
306 // However, this doesn't quite appear to work with local textures that are part of an avatar's
307 // appearance texture set. Whilst sending an ImageNotInDatabase does trigger an automatic rebake
308 // and reupload by the client, if those assets aren't pushed to the asset server anyway, then
309 // on crossing onto another region server, other avatars can no longer get the required textures.
310 // There doesn't appear to be any signal from the sim to the newly region border crossed client
311 // asking it to reupload its local texture assets to that region server.
312 //
313 // One can think of other cunning ways around this. For instance, on a region crossing or teleport,
314 // the original sim could squirt local assets to the new sim. Or the new sim could have pointers
315 // to the original sim to fetch the 'local' assets (this is getting more complicated).
316 //
317 // But for now, we're going to take the easy way out and store local assets globally.
318 //
319 // TODO: Also, Temporary is now deprecated. We should start ignoring it and not passing it out from LLClientView.
320 if (!asset.Temporary || asset.Local)
349 { 321 {
350 TextureImage textur = new TextureImage(asset); 322 m_assetServer.StoreAsset(asset);
351 Textures.Add(textur.FullID, textur);
352
353 if (StatsManager.SimExtraStats != null)
354 StatsManager.SimExtraStats.AddTexture(textur);
355
356 // According to http://wiki.secondlife.com/wiki/AssetUploadRequest, Local signifies that the
357 // information is stored locally. It could disappear, in which case we could send the
358 // ImageNotInDatabase packet to tell the client this.
359 //
360 // However, this doesn't quite appear to work with local textures that are part of an avatar's
361 // appearance texture set. Whilst sending an ImageNotInDatabase does trigger an automatic rebake
362 // and reupload by the client, if those assets aren't pushed to the asset server anyway, then
363 // on crossing onto another region server, other avatars can no longer get the required textures.
364 // There doesn't appear to be any signal from the sim to the newly region border crossed client
365 // asking it to reupload its local texture assets to that region server.
366 //
367 // One can think of other cunning ways around this. For instance, on a region crossing or teleport,
368 // the original sim could squirt local assets to the new sim. Or the new sim could have pointers
369 // to the original sim to fetch the 'local' assets (this is getting more complicated).
370 //
371 // But for now, we're going to take the easy way out and store local assets globally.
372 //
373 // TODO: Also, Temporary is now deprecated. We should start ignoring it and not passing it out from LLClientView.
374 if (!asset.Temporary || asset.Local)
375 {
376 m_assetServer.StoreAsset(asset);
377 }
378 } 323 }
379// else
380// {
381// m_log.DebugFormat("[ASSET CACHE]: Textures already contains {0}", asset.ID);
382// }
383 }
384 else
385 {
386 if (!Assets.ContainsKey(asset.FullID))
387 {
388 AssetInfo assetInf = new AssetInfo(asset);
389 Assets.Add(assetInf.FullID, assetInf);
390
391 if (StatsManager.SimExtraStats != null)
392 StatsManager.SimExtraStats.AddAsset(assetInf);
393
394 // See comment above.
395 if (!asset.Temporary || asset.Local)
396 {
397 m_assetServer.StoreAsset(asset);
398 }
399 }
400// else
401// {
402// m_log.DebugFormat("[ASSET CACHE]: Assets already contains {0}", asset.ID);
403// }
404 } 324 }
405 } 325 }
406 326
@@ -417,71 +337,46 @@ namespace OpenSim.Framework.Communications.Cache
417 // in the 2 caches differently. Also, locks are probably 337 // in the 2 caches differently. Also, locks are probably
418 // needed in all of this, or move to synchronized non 338 // needed in all of this, or move to synchronized non
419 // generic forms for Dictionaries. 339 // generic forms for Dictionaries.
420 if (Textures.ContainsKey(uuid)) 340 if(m_memcache.Contains(uuid))
421 {
422 Textures.Remove(uuid);
423 }
424 else if (Assets.ContainsKey(uuid))
425 { 341 {
426 Assets.Remove(uuid); 342 m_memcache.Remove(uuid);
427 } 343 }
428 } 344 }
429 345
430 // See IAssetReceiver 346 // See IAssetReceiver
431 public void AssetReceived(AssetBase asset, bool IsTexture) 347 public void AssetReceived(AssetBase asset, bool IsTexture)
432 { 348 {
433// m_log.DebugFormat("[ASSET CACHE]: Received asset {0}", asset.ID);
434
435 //check if it is a texture or not
436 //then add to the correct cache list
437 //then check for waiting requests for this asset/texture (in the Requested lists)
438 //and move those requests into the Requests list.
439 if (IsTexture)
440 {
441 TextureImage image = new TextureImage(asset);
442 if (!Textures.ContainsKey(image.FullID))
443 {
444 Textures.Add(image.FullID, image);
445 349
446 if (StatsManager.SimExtraStats != null) 350 AssetInfo assetInf = new AssetInfo(asset);
447 { 351 if (!m_memcache.Contains(assetInf.FullID))
448 StatsManager.SimExtraStats.AddTexture(image);
449 }
450 }
451 }
452 else
453 { 352 {
454 AssetInfo assetInf = new AssetInfo(asset); 353 m_memcache.AddOrUpdate(assetInf.FullID, assetInf, TimeSpan.FromHours(24));
455 if (!Assets.ContainsKey(assetInf.FullID))
456 {
457 Assets.Add(assetInf.FullID, assetInf);
458 354
459 if (StatsManager.SimExtraStats != null) 355 if (StatsManager.SimExtraStats != null)
460 { 356 {
461 StatsManager.SimExtraStats.AddAsset(assetInf); 357 StatsManager.SimExtraStats.AddAsset(assetInf);
462 } 358 }
463 359
464 if (RequestedAssets.ContainsKey(assetInf.FullID)) 360 if (RequestedAssets.ContainsKey(assetInf.FullID))
465 { 361 {
466 AssetRequest req = RequestedAssets[assetInf.FullID]; 362 AssetRequest req = RequestedAssets[assetInf.FullID];
467 req.AssetInf = assetInf; 363 req.AssetInf = assetInf;
468 req.NumPackets = CalculateNumPackets(assetInf.Data); 364 req.NumPackets = CalculateNumPackets(assetInf.Data);
469 365
470 RequestedAssets.Remove(assetInf.FullID); 366 RequestedAssets.Remove(assetInf.FullID);
471 // If it's a direct request for a script, drop it 367 // If it's a direct request for a script, drop it
472 // because it's a hacked client 368 // because it's a hacked client
473 if (req.AssetRequestSource != 2 || assetInf.Type != 10) 369 if (req.AssetRequestSource != 2 || assetInf.Type != 10)
474 AssetRequests.Add(req); 370 AssetRequests.Add(req);
475 }
476 } 371 }
477 } 372 }
478 373
479 // Notify requesters for this asset 374 // Notify requesters for this asset
480 AssetRequestsList reqList = null; 375 AssetRequestsList reqList;
481 376
482 lock (RequestLists) 377 lock (RequestLists)
483 { 378 {
484 if (RequestLists.TryGetValue(asset.FullID, out reqList)) 379 if (RequestLists.TryGetValue(asset.FullID, out reqList))
485 RequestLists.Remove(asset.FullID); 380 RequestLists.Remove(asset.FullID);
486 } 381 }
487 382
@@ -489,7 +384,7 @@ namespace OpenSim.Framework.Communications.Cache
489 { 384 {
490 if (StatsManager.SimExtraStats != null) 385 if (StatsManager.SimExtraStats != null)
491 StatsManager.SimExtraStats.AddAssetRequestTimeAfterCacheMiss(DateTime.Now - reqList.TimeRequested); 386 StatsManager.SimExtraStats.AddAssetRequestTimeAfterCacheMiss(DateTime.Now - reqList.TimeRequested);
492 387
493 foreach (NewAssetRequest req in reqList.Requests) 388 foreach (NewAssetRequest req in reqList.Requests)
494 { 389 {
495 // Xantor 20080526 are we really calling all the callbacks if multiple queued for 1 request? -- Yes, checked 390 // Xantor 20080526 are we really calling all the callbacks if multiple queued for 1 request? -- Yes, checked
@@ -504,17 +399,8 @@ namespace OpenSim.Framework.Communications.Cache
504 { 399 {
505// m_log.WarnFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID); 400// m_log.WarnFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID);
506 401
507 if (IsTexture)
508 {
509 Textures[assetID] = null;
510 }
511 else
512 {
513 Assets[assetID] = null;
514 }
515
516 // Notify requesters for this asset 402 // Notify requesters for this asset
517 AssetRequestsList reqList = null; 403 AssetRequestsList reqList;
518 lock (RequestLists) 404 lock (RequestLists)
519 { 405 {
520 if (RequestLists.TryGetValue(assetID, out reqList)) 406 if (RequestLists.TryGetValue(assetID, out reqList))
@@ -578,7 +464,7 @@ namespace OpenSim.Framework.Communications.Cache
578 464
579 //check to see if asset is in local cache, if not we need to request it from asset server. 465 //check to see if asset is in local cache, if not we need to request it from asset server.
580 //Console.WriteLine("asset request " + requestID); 466 //Console.WriteLine("asset request " + requestID);
581 if (!Assets.ContainsKey(requestID)) 467 if (!m_memcache.Contains(requestID))
582 { 468 {
583 //not found asset 469 //not found asset
584 // so request from asset server 470 // so request from asset server
@@ -598,7 +484,7 @@ namespace OpenSim.Framework.Communications.Cache
598 } 484 }
599 485
600 // It has an entry in our cache 486 // It has an entry in our cache
601 AssetInfo asset = Assets[requestID]; 487 AssetInfo asset = (AssetInfo)m_memcache[requestID];
602 488
603 // FIXME: We never tell the client about assets which do not exist when requested by this transfer mechanism, which can't be right. 489 // FIXME: We never tell the client about assets which do not exist when requested by this transfer mechanism, which can't be right.
604 if (null == asset) 490 if (null == asset)