diff options
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 233 |
1 files changed, 131 insertions, 102 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index a8f5c99..a72cf83 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | |||
@@ -226,7 +226,6 @@ namespace Flotsam.RegionModules.AssetCache | |||
226 | if (m_AssetService == null) | 226 | if (m_AssetService == null) |
227 | { | 227 | { |
228 | m_AssetService = scene.RequestModuleInterface<IAssetService>(); | 228 | m_AssetService = scene.RequestModuleInterface<IAssetService>(); |
229 | |||
230 | } | 229 | } |
231 | } | 230 | } |
232 | } | 231 | } |
@@ -250,140 +249,170 @@ namespace Flotsam.RegionModules.AssetCache | |||
250 | 249 | ||
251 | private void UpdateMemoryCache(string key, AssetBase asset) | 250 | private void UpdateMemoryCache(string key, AssetBase asset) |
252 | { | 251 | { |
253 | if (m_MemoryCacheEnabled) | 252 | m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); |
254 | m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); | ||
255 | } | 253 | } |
256 | 254 | ||
257 | public void Cache(AssetBase asset) | 255 | private void UpdateFileCache(string key, AssetBase asset) |
258 | { | 256 | { |
259 | // TODO: Spawn this off to some seperate thread to do the actual writing | 257 | string filename = GetFileName(asset.ID); |
260 | if (asset != null) | ||
261 | { | ||
262 | m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID); | ||
263 | |||
264 | UpdateMemoryCache(asset.ID, asset); | ||
265 | |||
266 | string filename = GetFileName(asset.ID); | ||
267 | 258 | ||
268 | try | 259 | try |
260 | { | ||
261 | // If the file is already cached, don't cache it, just touch it so access time is updated | ||
262 | if (File.Exists(filename)) | ||
269 | { | 263 | { |
270 | // If the file is already cached, don't cache it, just touch it so access time is updated | 264 | File.SetLastAccessTime(filename, DateTime.Now); |
271 | if (File.Exists(filename)) | 265 | } |
266 | else | ||
267 | { | ||
268 | // Once we start writing, make sure we flag that we're writing | ||
269 | // that object to the cache so that we don't try to write the | ||
270 | // same file multiple times. | ||
271 | lock (m_CurrentlyWriting) | ||
272 | { | 272 | { |
273 | File.SetLastAccessTime(filename, DateTime.Now); | ||
274 | } else { | ||
275 | |||
276 | // Once we start writing, make sure we flag that we're writing | ||
277 | // that object to the cache so that we don't try to write the | ||
278 | // same file multiple times. | ||
279 | lock (m_CurrentlyWriting) | ||
280 | { | ||
281 | #if WAIT_ON_INPROGRESS_REQUESTS | 273 | #if WAIT_ON_INPROGRESS_REQUESTS |
282 | if (m_CurrentlyWriting.ContainsKey(filename)) | 274 | if (m_CurrentlyWriting.ContainsKey(filename)) |
283 | { | 275 | { |
284 | return; | 276 | return; |
285 | } | 277 | } |
286 | else | 278 | else |
287 | { | 279 | { |
288 | m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); | 280 | m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); |
289 | } | 281 | } |
290 | 282 | ||
291 | #else | 283 | #else |
292 | if (m_CurrentlyWriting.Contains(filename)) | 284 | if (m_CurrentlyWriting.Contains(filename)) |
293 | { | 285 | { |
294 | return; | 286 | return; |
295 | } | ||
296 | else | ||
297 | { | ||
298 | m_CurrentlyWriting.Add(filename); | ||
299 | } | ||
300 | #endif | ||
301 | |||
302 | } | 287 | } |
303 | 288 | else | |
304 | Util.FireAndForget( | 289 | { |
305 | delegate { WriteFileCache(filename, asset); }); | 290 | m_CurrentlyWriting.Add(filename); |
291 | } | ||
292 | #endif | ||
306 | } | 293 | } |
307 | } | 294 | |
308 | catch (Exception e) | 295 | Util.FireAndForget( |
309 | { | 296 | delegate { WriteFileCache(filename, asset); }); |
310 | LogException(e); | ||
311 | } | 297 | } |
312 | } | 298 | } |
299 | catch (Exception e) | ||
300 | { | ||
301 | LogException(e); | ||
302 | } | ||
313 | } | 303 | } |
314 | 304 | ||
315 | public AssetBase Get(string id) | 305 | public void Cache(AssetBase asset) |
316 | { | 306 | { |
317 | m_Requests++; | 307 | // TODO: Spawn this off to some seperate thread to do the actual writing |
308 | if (asset != null) | ||
309 | { | ||
310 | //m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID); | ||
318 | 311 | ||
312 | if (m_MemoryCacheEnabled) | ||
313 | UpdateMemoryCache(asset.ID, asset); | ||
314 | |||
315 | UpdateFileCache(asset.ID, asset); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /// <summary> | ||
320 | /// Try to get an asset from the in-memory cache. | ||
321 | /// </summary> | ||
322 | /// <param name="id"></param> | ||
323 | /// <returns></returns> | ||
324 | private AssetBase GetFromMemoryCache(string id) | ||
325 | { | ||
319 | AssetBase asset = null; | 326 | AssetBase asset = null; |
320 | 327 | ||
321 | if (m_MemoryCacheEnabled && m_MemoryCache.TryGetValue(id, out asset)) | 328 | if (m_MemoryCache.TryGetValue(id, out asset)) |
322 | { | ||
323 | m_MemoryHits++; | 329 | m_MemoryHits++; |
324 | } | 330 | |
325 | else | 331 | return asset; |
332 | } | ||
333 | |||
334 | /// <summary> | ||
335 | /// Try to get an asset from the file cache. | ||
336 | /// </summary> | ||
337 | /// <param name="id"></param> | ||
338 | /// <returns></returns> | ||
339 | private AssetBase GetFromFileCache(string id) | ||
340 | { | ||
341 | AssetBase asset = null; | ||
342 | |||
343 | string filename = GetFileName(id); | ||
344 | if (File.Exists(filename)) | ||
326 | { | 345 | { |
327 | string filename = GetFileName(id); | 346 | FileStream stream = null; |
328 | if (File.Exists(filename)) | 347 | try |
329 | { | 348 | { |
330 | FileStream stream = null; | 349 | stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); |
331 | try | 350 | BinaryFormatter bformatter = new BinaryFormatter(); |
332 | { | ||
333 | stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); | ||
334 | BinaryFormatter bformatter = new BinaryFormatter(); | ||
335 | 351 | ||
336 | asset = (AssetBase)bformatter.Deserialize(stream); | 352 | asset = (AssetBase)bformatter.Deserialize(stream); |
337 | 353 | ||
338 | UpdateMemoryCache(id, asset); | 354 | UpdateMemoryCache(id, asset); |
339 | 355 | ||
340 | m_DiskHits++; | 356 | m_DiskHits++; |
341 | } | 357 | } |
342 | catch (System.Runtime.Serialization.SerializationException e) | 358 | catch (System.Runtime.Serialization.SerializationException e) |
343 | { | 359 | { |
344 | LogException(e); | 360 | LogException(e); |
345 | 361 | ||
346 | // If there was a problem deserializing the asset, the asset may | 362 | // If there was a problem deserializing the asset, the asset may |
347 | // either be corrupted OR was serialized under an old format | 363 | // either be corrupted OR was serialized under an old format |
348 | // {different version of AssetBase} -- we should attempt to | 364 | // {different version of AssetBase} -- we should attempt to |
349 | // delete it and re-cache | 365 | // delete it and re-cache |
350 | File.Delete(filename); | 366 | File.Delete(filename); |
351 | } | 367 | } |
352 | catch (Exception e) | 368 | catch (Exception e) |
353 | { | 369 | { |
354 | LogException(e); | 370 | LogException(e); |
355 | } | ||
356 | finally | ||
357 | { | ||
358 | if (stream != null) | ||
359 | stream.Close(); | ||
360 | } | ||
361 | } | 371 | } |
372 | finally | ||
373 | { | ||
374 | if (stream != null) | ||
375 | stream.Close(); | ||
376 | } | ||
377 | } | ||
362 | 378 | ||
363 | 379 | ||
364 | #if WAIT_ON_INPROGRESS_REQUESTS | 380 | #if WAIT_ON_INPROGRESS_REQUESTS |
365 | // Check if we're already downloading this asset. If so, try to wait for it to | 381 | // Check if we're already downloading this asset. If so, try to wait for it to |
366 | // download. | 382 | // download. |
367 | if (m_WaitOnInprogressTimeout > 0) | 383 | if (m_WaitOnInprogressTimeout > 0) |
368 | { | 384 | { |
369 | m_RequestsForInprogress++; | 385 | m_RequestsForInprogress++; |
370 | 386 | ||
371 | ManualResetEvent waitEvent; | 387 | ManualResetEvent waitEvent; |
372 | if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) | 388 | if (m_CurrentlyWriting.TryGetValue(filename, out waitEvent)) |
373 | { | ||
374 | waitEvent.WaitOne(m_WaitOnInprogressTimeout); | ||
375 | return Get(id); | ||
376 | } | ||
377 | } | ||
378 | #else | ||
379 | // Track how often we have the problem that an asset is requested while | ||
380 | // it is still being downloaded by a previous request. | ||
381 | if (m_CurrentlyWriting.Contains(filename)) | ||
382 | { | 389 | { |
383 | m_RequestsForInprogress++; | 390 | waitEvent.WaitOne(m_WaitOnInprogressTimeout); |
391 | return Get(id); | ||
384 | } | 392 | } |
385 | #endif | ||
386 | } | 393 | } |
394 | #else | ||
395 | // Track how often we have the problem that an asset is requested while | ||
396 | // it is still being downloaded by a previous request. | ||
397 | if (m_CurrentlyWriting.Contains(filename)) | ||
398 | { | ||
399 | m_RequestsForInprogress++; | ||
400 | } | ||
401 | #endif | ||
402 | |||
403 | return asset; | ||
404 | } | ||
405 | |||
406 | public AssetBase Get(string id) | ||
407 | { | ||
408 | m_Requests++; | ||
409 | |||
410 | AssetBase asset = null; | ||
411 | |||
412 | if (m_MemoryCacheEnabled) | ||
413 | asset = GetFromMemoryCache(id); | ||
414 | else | ||
415 | asset = GetFromFileCache(id); | ||
387 | 416 | ||
388 | if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) | 417 | if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) |
389 | { | 418 | { |
@@ -474,9 +503,9 @@ namespace Flotsam.RegionModules.AssetCache | |||
474 | /// removes empty tier directories. | 503 | /// removes empty tier directories. |
475 | /// </summary> | 504 | /// </summary> |
476 | /// <param name="dir"></param> | 505 | /// <param name="dir"></param> |
506 | /// <param name="purgeLine"></param> | ||
477 | private void CleanExpiredFiles(string dir, DateTime purgeLine) | 507 | private void CleanExpiredFiles(string dir, DateTime purgeLine) |
478 | { | 508 | { |
479 | |||
480 | foreach (string file in Directory.GetFiles(dir)) | 509 | foreach (string file in Directory.GetFiles(dir)) |
481 | { | 510 | { |
482 | if (File.GetLastAccessTime(file) < purgeLine) | 511 | if (File.GetLastAccessTime(file) < purgeLine) |