lldiskcache.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /**
  2. * @file lldiskcache.h
  3. * @brief Definition of the disk cache implementation.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2020, Linden Research, Inc. (c) 2021 Henri Beauchamp.
  8. *
  9. * Modifications by Henri Beauchamp:
  10. * - Pointless per-asset-type file naming removed.
  11. * - Use of LLFile faster operations and of the extended LLDiriterator where
  12. * possible.
  13. * - Cache structure changed to speed up file opening and reduce the risk of
  14. * hitting file-systems limitations (such as the max number of files per
  15. * directory).
  16. * - Proper cache validation and shutdown.
  17. * - Proper catching of throw()s and boost::filesystem errors.
  18. * - Track cache files size in real time (lock-less: just via an atomic
  19. * variable).
  20. * - Proper and threaded auto-purging of the cache when it exceeds 150% of
  21. * its nominal size.
  22. * - Multiple threads and multiple viewer instances deconfliction.
  23. *
  24. * Second Life Viewer Source Code
  25. * The source code in this file ("Source Code") is provided by Linden Lab
  26. * to you under the terms of the GNU General Public License, version 2.0
  27. * ("GPL"), unless you have obtained a separate licensing agreement
  28. * ("Other License"), formally executed by you and Linden Lab. Terms of
  29. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  30. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  31. *
  32. * There are special exceptions to the terms and conditions of the GPL as
  33. * it is applied to this Source Code. View the full text of the exception
  34. * in the file doc/FLOSS-exception.txt in this software distribution, or
  35. * online at
  36. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  37. *
  38. * By copying, modifying or distributing this software, you acknowledge
  39. * that you have read and understood your obligations described above,
  40. * and agree to abide by those obligations.
  41. *
  42. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  43. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  44. * COMPLETENESS OR PERFORMANCE.
  45. * $/LicenseInfo$
  46. */
  47. #ifndef LL_LLDISKCACHE_H
  48. #define LL_LLDISKCACHE_H
  49. #include <utility>
  50. #include "llatomic.h"
  51. #include "lluuid.h"
  52. class LLCachePurgeThread;
  53. // Purely static class
  54. class LLDiskCache
  55. {
  56. protected:
  57. LOG_CLASS(LLDiskCache);
  58. LLDiskCache() = delete;
  59. ~LLDiskCache() = delete;
  60. public:
  61. // Note: when 'second_instance' is true, the cache is purged only after
  62. // reaching a higher size, so that the first running instance of the viewer
  63. // will purge it before this second instance would, and this as long as it
  64. // is running; should the first instance vanish, this second instance will
  65. // then automatically take over the cache purging task.
  66. // Of course, with three or more viewer instances, and should the first one
  67. // vanish, the remaining instances will still fight over the cache purging,
  68. // but there is an additionnal randomization of the max cache size for
  69. // these instances...
  70. static void init(U64 nominal_size_bytes, bool second_instance);
  71. // Clears the cache by removing all the files in the specified cache
  72. // directory individually.
  73. static void clear();
  74. // Purges the oldest items in the cache so that the combined size of all
  75. // files is no bigger than sNominalSizeBytes. May be internally threaded.
  76. static void purge();
  77. // Threaded cache purging. Must be called only from the main thread.
  78. // Called from llappviewer.cpp or internally from addBytesWritten().
  79. static void threadedPurge();
  80. // Shuts down the cache when the viewer closes.
  81. static void shutdown();
  82. // Returns true when the cache is initialized and valid
  83. LL_INLINE static bool isValid() { return sCacheValid; }
  84. // IMPORTANT: the three following methods are called both from the main
  85. // thead and from other threads (e.g. the mesh repository, the texture
  86. // cache worker, etc).
  87. // Constructs a file name and path based on the asset UUID and optional
  88. // extra info.
  89. static std::string getFilePath(const LLUUID& id,
  90. const char* extra_info = NULL);
  91. // Updates the "last write time" of a file to "now". This must be called
  92. // whenever a file in the cache is (going to be) opened (for either reads
  93. // or writes, since we must guard against a possibly ongoing purge before
  94. // an actual read/write would happen) so that the last time the file was
  95. // accessed is up to date; this time stamp is used in the mechanism for
  96. // purging the cache.
  97. static void updateFileAccessTime(const std::string& file_path);
  98. // Used to update the disk cache about file writes ('bytes' may be negative
  99. // when removing or truncating a file).
  100. static void addBytesWritten(S32 bytes);
  101. private:
  102. // Utility method to gather the total size (in bytes) occupied by the cache
  103. // files.
  104. static U64 cacheDirSize();
  105. private:
  106. // Contains the pointer to the cache purging thread.
  107. static LLCachePurgeThread* sPurgeThread;
  108. // Cache directory path
  109. static std::string sCacheDir;
  110. // The nominal size of the cache in bytes. After purging, the total size of
  111. // the cache files in the cache directory will be less than this value.
  112. static U64 sNominalSizeBytes;
  113. // Maximal amount of data in cache beyond which the cache gets purged.
  114. static U64 sMaxSizeBytes;
  115. // Current size of the cache. This is an atomic variable, since it can get
  116. // updated by various threads concurrently, via addBytesWritten() and
  117. // threaded purge().
  118. static LLAtomicU64 sCurrentSizeBytes;
  119. // true while purging, and atomic since used in various threads
  120. static LLAtomicBool sPurging;
  121. // true when the cache directory is valid
  122. static bool sCacheValid;
  123. };
  124. #endif // LL_LLDISKCACHE_H