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