1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // See net/disk_cache/disk_cache.h for the public interface of the cache. 6 7 #ifndef NET_DISK_CACHE_BLOCKFILE_BACKEND_IMPL_H_ 8 #define NET_DISK_CACHE_BLOCKFILE_BACKEND_IMPL_H_ 9 10 #include <stdint.h> 11 12 #include <unordered_map> 13 14 #include "base/files/file_path.h" 15 #include "base/memory/raw_ptr.h" 16 #include "base/memory/scoped_refptr.h" 17 #include "base/timer/timer.h" 18 #include "net/base/net_export.h" 19 #include "net/disk_cache/blockfile/block_files.h" 20 #include "net/disk_cache/blockfile/eviction.h" 21 #include "net/disk_cache/blockfile/in_flight_backend_io.h" 22 #include "net/disk_cache/blockfile/rankings.h" 23 #include "net/disk_cache/blockfile/stats.h" 24 #include "net/disk_cache/blockfile/stress_support.h" 25 #include "net/disk_cache/disk_cache.h" 26 27 namespace base { 28 class SingleThreadTaskRunner; 29 } // namespace base 30 31 namespace net { 32 class NetLog; 33 } // namespace net 34 35 namespace disk_cache { 36 37 class BackendCleanupTracker; 38 struct Index; 39 40 enum BackendFlags { 41 kNone = 0, 42 kMask = 1, // A mask (for the index table) was specified. 43 kMaxSize = 1 << 1, // A maximum size was provided. 44 kUnitTestMode = 1 << 2, // We are modifying the behavior for testing. 45 kUpgradeMode = 1 << 3, // This is the upgrade tool (dump). 46 kNewEviction = 1 << 4, // Use of new eviction was specified. 47 kNoRandom = 1 << 5, // Don't add randomness to the behavior. 48 kNoLoadProtection = 1 << 6, // Don't act conservatively under load. 49 kNoBuffering = 1 << 7 // Disable extended IO buffering. 50 }; 51 52 // This class implements the Backend interface. An object of this 53 // class handles the operations of the cache for a particular profile. 54 class NET_EXPORT_PRIVATE BackendImpl : public Backend { 55 friend class Eviction; 56 public: 57 BackendImpl(const base::FilePath& path, 58 scoped_refptr<BackendCleanupTracker> cleanup_tracker, 59 const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread, 60 net::CacheType cache_type, 61 net::NetLog* net_log); 62 63 // mask can be used to limit the usable size of the hash table, for testing. 64 BackendImpl(const base::FilePath& path, 65 uint32_t mask, 66 scoped_refptr<BackendCleanupTracker> cleanup_tracker, 67 const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread, 68 net::CacheType cache_type, 69 net::NetLog* net_log); 70 71 BackendImpl(const BackendImpl&) = delete; 72 BackendImpl& operator=(const BackendImpl&) = delete; 73 74 ~BackendImpl() override; 75 76 // Performs general initialization for this current instance of the cache. 77 // `callback` is always invoked asynchronously. 78 void Init(CompletionOnceCallback callback); 79 80 // Performs the actual initialization and final cleanup on destruction. 81 int SyncInit(); 82 void CleanupCache(); 83 84 // Synchronous implementation of the asynchronous interface. 85 int SyncOpenEntry(const std::string& key, scoped_refptr<EntryImpl>* entry); 86 int SyncCreateEntry(const std::string& key, scoped_refptr<EntryImpl>* entry); 87 int SyncDoomEntry(const std::string& key); 88 int SyncDoomAllEntries(); 89 int SyncDoomEntriesBetween(base::Time initial_time, 90 base::Time end_time); 91 int SyncCalculateSizeOfAllEntries(); 92 int SyncDoomEntriesSince(base::Time initial_time); 93 int SyncOpenNextEntry(Rankings::Iterator* iterator, 94 scoped_refptr<EntryImpl>* next_entry); 95 void SyncEndEnumeration(std::unique_ptr<Rankings::Iterator> iterator); 96 void SyncOnExternalCacheHit(const std::string& key); 97 98 // Called at end of any backend operation on the background thread. 99 void OnSyncBackendOpComplete(); 100 101 // Open or create an entry for the given |key| or |iter|. 102 scoped_refptr<EntryImpl> OpenEntryImpl(const std::string& key); 103 scoped_refptr<EntryImpl> CreateEntryImpl(const std::string& key); 104 scoped_refptr<EntryImpl> OpenNextEntryImpl(Rankings::Iterator* iter); 105 106 // Sets the maximum size for the total amount of data stored by this instance. 107 bool SetMaxSize(int64_t max_bytes); 108 109 // Returns the full name for an external storage file. 110 base::FilePath GetFileName(Addr address) const; 111 112 // Returns the actual file used to store a given (non-external) address. 113 MappedFile* File(Addr address); 114 115 // Returns a weak pointer to the background queue. 116 base::WeakPtr<InFlightBackendIO> GetBackgroundQueue(); 117 118 // Creates an external storage file. 119 bool CreateExternalFile(Addr* address); 120 121 // Creates a new storage block of size block_count. 122 bool CreateBlock(FileType block_type, int block_count, 123 Addr* block_address); 124 125 // Deletes a given storage block. deep set to true can be used to zero-fill 126 // the related storage in addition of releasing the related block. 127 void DeleteBlock(Addr block_address, bool deep); 128 129 // Retrieves a pointer to the LRU-related data. 130 LruData* GetLruData(); 131 132 // Updates the ranking information for an entry. 133 void UpdateRank(EntryImpl* entry, bool modified); 134 135 // A node was recovered from a crash, it may not be on the index, so this 136 // method checks it and takes the appropriate action. 137 void RecoveredEntry(CacheRankingsBlock* rankings); 138 139 // Permanently deletes an entry, but still keeps track of it. 140 void InternalDoomEntry(EntryImpl* entry); 141 142 #if defined(NET_BUILD_STRESS_CACHE) 143 // Returns the address of the entry linked to the entry at a given |address|. 144 CacheAddr GetNextAddr(Addr address); 145 146 // Verifies that |entry| is not currently reachable through the index. 147 void NotLinked(EntryImpl* entry); 148 #endif 149 150 // Removes all references to this entry. 151 void RemoveEntry(EntryImpl* entry); 152 153 // This method must be called when an entry is released for the last time, so 154 // the entry should not be used anymore. |address| is the cache address of the 155 // entry. 156 void OnEntryDestroyBegin(Addr address); 157 158 // This method must be called after all resources for an entry have been 159 // released. 160 void OnEntryDestroyEnd(); 161 162 // If the data stored by the provided |rankings| points to an open entry, 163 // returns a pointer to that entry, otherwise returns NULL. Note that this 164 // method does NOT increase the ref counter for the entry. 165 EntryImpl* GetOpenEntry(CacheRankingsBlock* rankings) const; 166 167 // Returns the id being used on this run of the cache. 168 int32_t GetCurrentEntryId() const; 169 170 // Returns the maximum size for a file to reside on the cache. 171 int64_t MaxFileSize() const override; 172 173 // A user data block is being created, extended or truncated. 174 void ModifyStorageSize(int32_t old_size, int32_t new_size); 175 176 // Logs requests that are denied due to being too big. 177 void TooMuchStorageRequested(int32_t size); 178 179 // Returns true if a temporary buffer is allowed to be extended. 180 bool IsAllocAllowed(int current_size, int new_size); 181 182 // Tracks the release of |size| bytes by an entry buffer. 183 void BufferDeleted(int size); 184 185 // Only intended for testing the two previous methods. GetTotalBuffersSize()186 int GetTotalBuffersSize() const { 187 return buffer_bytes_; 188 } 189 190 // Returns true if this instance seems to be under heavy load. 191 bool IsLoaded() const; 192 read_only()193 bool read_only() const { 194 return read_only_; 195 } 196 197 // Returns a weak pointer to this object. 198 base::WeakPtr<BackendImpl> GetWeakPtr(); 199 200 // Returns true if we should perform a periodic stat update. The caller must 201 // call this function only once per run (because it returns always the same 202 // thing on a given run). 203 bool ShouldUpdateStats(); 204 205 // Reset stat ratios on first eviction. 206 void FirstEviction(); 207 208 // Reports a critical error (and disables the cache). 209 void CriticalError(int error); 210 211 // Reports an uncommon, recoverable error. 212 void ReportError(int error); 213 214 // Called when an interesting event should be logged (counted). 215 void OnEvent(Stats::Counters an_event); 216 217 // Keeps track of payload access (doesn't include metadata). 218 void OnRead(int bytes); 219 void OnWrite(int bytes); 220 221 // Timer callback to calculate usage statistics. 222 void OnStatsTimer(); 223 224 // Handles the pending asynchronous IO count. 225 void IncrementIoCount(); 226 void DecrementIoCount(); 227 228 // Sets internal parameters to enable unit testing mode. 229 void SetUnitTestMode(); 230 231 // Sets internal parameters to enable upgrade mode (for internal tools). 232 void SetUpgradeMode(); 233 234 // Sets the eviction algorithm to version 2. 235 void SetNewEviction(); 236 237 // Sets an explicit set of BackendFlags. 238 void SetFlags(uint32_t flags); 239 240 // Clears the counter of references to test handling of corruptions. 241 void ClearRefCountForTest(); 242 243 // Sends a dummy operation through the operation queue, for unit tests. 244 int FlushQueueForTest(CompletionOnceCallback callback); 245 246 // Runs the provided task on the cache thread. The task will be automatically 247 // deleted after it runs. 248 int RunTaskForTest(base::OnceClosure task, CompletionOnceCallback callback); 249 250 // Trims an entry (all if |empty| is true) from the list of deleted 251 // entries. This method should be called directly on the cache thread. 252 void TrimForTest(bool empty); 253 254 // Trims an entry (all if |empty| is true) from the list of deleted 255 // entries. This method should be called directly on the cache thread. 256 void TrimDeletedListForTest(bool empty); 257 258 // Only intended for testing 259 base::RepeatingTimer* GetTimerForTest(); 260 261 // Performs a simple self-check, and returns the number of dirty items 262 // or an error code (negative value). 263 int SelfCheck(); 264 265 // Ensures the index is flushed to disk (a no-op on platforms with mmap). 266 void FlushIndex(); 267 268 // Ensures that the private cache thread completes work. 269 static void FlushForTesting(); 270 271 // Ensures that the private cache thread completes work. 272 static void FlushAsynchronouslyForTesting(base::OnceClosure callback); 273 274 // Backend implementation. 275 int32_t GetEntryCount() const override; 276 EntryResult OpenOrCreateEntry(const std::string& key, 277 net::RequestPriority request_priority, 278 EntryResultCallback callback) override; 279 EntryResult OpenEntry(const std::string& key, 280 net::RequestPriority request_priority, 281 EntryResultCallback callback) override; 282 EntryResult CreateEntry(const std::string& key, 283 net::RequestPriority request_priority, 284 EntryResultCallback callback) override; 285 net::Error DoomEntry(const std::string& key, 286 net::RequestPriority priority, 287 CompletionOnceCallback callback) override; 288 net::Error DoomAllEntries(CompletionOnceCallback callback) override; 289 net::Error DoomEntriesBetween(base::Time initial_time, 290 base::Time end_time, 291 CompletionOnceCallback callback) override; 292 net::Error DoomEntriesSince(base::Time initial_time, 293 CompletionOnceCallback callback) override; 294 int64_t CalculateSizeOfAllEntries( 295 Int64CompletionOnceCallback callback) override; 296 // NOTE: The blockfile Backend::Iterator::OpenNextEntry method does not modify 297 // the last_used field of the entry, and therefore it does not impact the 298 // eviction ranking of the entry. However, an enumeration will go through all 299 // entries on the cache only if the cache is not modified while the 300 // enumeration is taking place. Significantly altering the entry pointed by 301 // the iterator (for example, deleting the entry) will invalidate the 302 // iterator. Performing operations on an entry that modify the entry may 303 // result in loops in the iteration, skipped entries or similar. 304 std::unique_ptr<Iterator> CreateIterator() override; 305 void GetStats(StatsItems* stats) override; 306 void OnExternalCacheHit(const std::string& key) override; 307 308 private: 309 using EntriesMap = std::unordered_map<CacheAddr, EntryImpl*>; 310 class IteratorImpl; 311 312 // Creates a new backing file for the cache index. 313 bool CreateBackingStore(disk_cache::File* file); 314 bool InitBackingStore(bool* file_created); 315 void AdjustMaxCacheSize(int table_len); 316 317 bool InitStats(); 318 void StoreStats(); 319 320 // Deletes the cache and starts again. 321 void RestartCache(bool failure); 322 void PrepareForRestart(); 323 324 // Creates a new entry object. Returns zero on success, or a disk_cache error 325 // on failure. 326 int NewEntry(Addr address, scoped_refptr<EntryImpl>* entry); 327 328 // Returns a given entry from the cache. The entry to match is determined by 329 // key and hash, and the returned entry may be the matched one or it's parent 330 // on the list of entries with the same hash (or bucket). To look for a parent 331 // of a given entry, |entry_addr| should be grabbed from that entry, so that 332 // if it doesn't match the entry on the index, we know that it was replaced 333 // with a new entry; in this case |*match_error| will be set to true and the 334 // return value will be NULL. 335 scoped_refptr<EntryImpl> MatchEntry(const std::string& key, 336 uint32_t hash, 337 bool find_parent, 338 Addr entry_addr, 339 bool* match_error); 340 341 // Opens the next or previous entry on a single list. If successful, 342 // |from_entry| will be updated to point to the new entry, otherwise it will 343 // be set to NULL; in other words, it is used as an explicit iterator. 344 bool OpenFollowingEntryFromList(Rankings::List list, 345 CacheRankingsBlock** from_entry, 346 scoped_refptr<EntryImpl>* next_entry); 347 348 // Returns the entry that is pointed by |next|, from the given |list|. 349 scoped_refptr<EntryImpl> GetEnumeratedEntry(CacheRankingsBlock* next, 350 Rankings::List list); 351 352 // Re-opens an entry that was previously deleted. 353 scoped_refptr<EntryImpl> ResurrectEntry( 354 scoped_refptr<EntryImpl> deleted_entry); 355 356 void DestroyInvalidEntry(EntryImpl* entry); 357 358 // Handles the used storage count. 359 void AddStorageSize(int32_t bytes); 360 void SubstractStorageSize(int32_t bytes); 361 362 // Update the number of referenced cache entries. 363 void IncreaseNumRefs(); 364 void DecreaseNumRefs(); 365 void IncreaseNumEntries(); 366 void DecreaseNumEntries(); 367 368 // Dumps current cache statistics to the log. 369 void LogStats(); 370 371 // Perform some periodic upkeep tasks on the stats. 372 void UpdateStats(); 373 374 // Upgrades the index file to version 2.1 (from 2.0) 375 void UpgradeTo2_1(); 376 377 // Upgrades the index file to version 3.0 378 // (from 2.1/2.0 depending on eviction algorithm) 379 void UpgradeTo3_0(); 380 381 // Performs basic checks on the index file. Returns false on failure. 382 bool CheckIndex(); 383 384 // Part of the self test. Returns the number or dirty entries, or an error. 385 int CheckAllEntries(); 386 387 // Part of the self test. Returns false if the entry is corrupt. 388 bool CheckEntry(EntryImpl* cache_entry); 389 390 // Returns the maximum total memory for the memory buffers. 391 static int MaxBuffersSize(); 392 393 // We want this destroyed after every other field. 394 scoped_refptr<BackendCleanupTracker> cleanup_tracker_; 395 396 InFlightBackendIO background_queue_; // The controller of pending operations. 397 scoped_refptr<MappedFile> index_; // The main cache index. 398 base::FilePath path_; // Path to the folder used as backing storage. 399 400 // Pointer to the index data. 401 // May point to a mapped file's unmapped memory at destruction time. 402 raw_ptr<Index, DisableDanglingPtrDetection> data_; 403 404 BlockFiles block_files_; // Set of files used to store all data. 405 Rankings rankings_; // Rankings to be able to trim the cache. 406 uint32_t mask_ = 0; // Binary mask to map a hash to the hash table. 407 int32_t max_size_ = 0; // Maximum data size for this instance. 408 Eviction eviction_; // Handler of the eviction algorithm. 409 EntriesMap open_entries_; // Map of open entries. 410 int num_refs_; // Number of referenced cache entries. 411 int max_refs_; // Max number of referenced cache entries. 412 int num_pending_io_; // Number of pending IO operations. 413 int entry_count_; // Number of entries accessed lately. 414 int byte_count_; // Number of bytes read/written lately. 415 int buffer_bytes_; // Total size of the temporary entries' buffers. 416 int up_ticks_ = 0; // The number of timer ticks received (OnStatsTimer). 417 int should_update_ = 0; // Used to determine when to reset statistics. 418 uint32_t user_flags_; // Flags set by the user. 419 bool init_ = false; // controls the initialization of the system. 420 bool restarted_ = false; 421 bool unit_test_ = false; 422 bool read_only_ = 423 false; // Prevents updates of the rankings data (used by tools). 424 bool disabled_ = false; 425 bool new_eviction_ = false; // What eviction algorithm should be used. 426 bool first_timer_ = true; // True if the timer has not been called. 427 bool user_load_ = 428 false; // True if we see a high load coming from the caller. 429 430 // True if we should consider doing eviction at end of current operation. 431 bool consider_evicting_at_op_end_ = false; 432 433 raw_ptr<net::NetLog> net_log_; 434 435 Stats stats_; // Usage statistics. 436 std::unique_ptr<base::RepeatingTimer> timer_; // Usage timer. 437 base::WeakPtrFactory<BackendImpl> ptr_factory_{this}; 438 }; 439 440 } // namespace disk_cache 441 442 #endif // NET_DISK_CACHE_BLOCKFILE_BACKEND_IMPL_H_ 443