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 192 // Returns the full histogram name, for the given base |name| and experiment, 193 // and the current cache type. The name will be "DiskCache.t.name_e" where n 194 // is the cache type and e the provided |experiment|. 195 std::string HistogramName(const char* name, int experiment) const; 196 read_only()197 bool read_only() const { 198 return read_only_; 199 } 200 201 // Returns a weak pointer to this object. 202 base::WeakPtr<BackendImpl> GetWeakPtr(); 203 204 // Returns true if we should send histograms for this user again. The caller 205 // must call this function only once per run (because it returns always the 206 // same thing on a given run). 207 bool ShouldReportAgain(); 208 209 // Reports some data when we filled up the cache. 210 void FirstEviction(); 211 212 // Reports a critical error (and disables the cache). 213 void CriticalError(int error); 214 215 // Reports an uncommon, recoverable error. 216 void ReportError(int error); 217 218 // Called when an interesting event should be logged (counted). 219 void OnEvent(Stats::Counters an_event); 220 221 // Keeps track of payload access (doesn't include metadata). 222 void OnRead(int bytes); 223 void OnWrite(int bytes); 224 225 // Timer callback to calculate usage statistics. 226 void OnStatsTimer(); 227 228 // Handles the pending asynchronous IO count. 229 void IncrementIoCount(); 230 void DecrementIoCount(); 231 232 // Sets internal parameters to enable unit testing mode. 233 void SetUnitTestMode(); 234 235 // Sets internal parameters to enable upgrade mode (for internal tools). 236 void SetUpgradeMode(); 237 238 // Sets the eviction algorithm to version 2. 239 void SetNewEviction(); 240 241 // Sets an explicit set of BackendFlags. 242 void SetFlags(uint32_t flags); 243 244 // Clears the counter of references to test handling of corruptions. 245 void ClearRefCountForTest(); 246 247 // Sends a dummy operation through the operation queue, for unit tests. 248 int FlushQueueForTest(CompletionOnceCallback callback); 249 250 // Runs the provided task on the cache thread. The task will be automatically 251 // deleted after it runs. 252 int RunTaskForTest(base::OnceClosure task, CompletionOnceCallback callback); 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 TrimForTest(bool empty); 257 258 // Trims an entry (all if |empty| is true) from the list of deleted 259 // entries. This method should be called directly on the cache thread. 260 void TrimDeletedListForTest(bool empty); 261 262 // Only intended for testing 263 base::RepeatingTimer* GetTimerForTest(); 264 265 // Performs a simple self-check, and returns the number of dirty items 266 // or an error code (negative value). 267 int SelfCheck(); 268 269 // Ensures the index is flushed to disk (a no-op on platforms with mmap). 270 void FlushIndex(); 271 272 // Ensures that the private cache thread completes work. 273 static void FlushForTesting(); 274 275 // Ensures that the private cache thread completes work. 276 static void FlushAsynchronouslyForTesting(base::OnceClosure callback); 277 278 // Backend implementation. 279 int32_t GetEntryCount() const override; 280 EntryResult OpenOrCreateEntry(const std::string& key, 281 net::RequestPriority request_priority, 282 EntryResultCallback callback) override; 283 EntryResult OpenEntry(const std::string& key, 284 net::RequestPriority request_priority, 285 EntryResultCallback callback) override; 286 EntryResult CreateEntry(const std::string& key, 287 net::RequestPriority request_priority, 288 EntryResultCallback callback) override; 289 net::Error DoomEntry(const std::string& key, 290 net::RequestPriority priority, 291 CompletionOnceCallback callback) override; 292 net::Error DoomAllEntries(CompletionOnceCallback callback) override; 293 net::Error DoomEntriesBetween(base::Time initial_time, 294 base::Time end_time, 295 CompletionOnceCallback callback) override; 296 net::Error DoomEntriesSince(base::Time initial_time, 297 CompletionOnceCallback callback) override; 298 int64_t CalculateSizeOfAllEntries( 299 Int64CompletionOnceCallback callback) override; 300 // NOTE: The blockfile Backend::Iterator::OpenNextEntry method does not modify 301 // the last_used field of the entry, and therefore it does not impact the 302 // eviction ranking of the entry. However, an enumeration will go through all 303 // entries on the cache only if the cache is not modified while the 304 // enumeration is taking place. Significantly altering the entry pointed by 305 // the iterator (for example, deleting the entry) will invalidate the 306 // iterator. Performing operations on an entry that modify the entry may 307 // result in loops in the iteration, skipped entries or similar. 308 std::unique_ptr<Iterator> CreateIterator() override; 309 void GetStats(StatsItems* stats) override; 310 void OnExternalCacheHit(const std::string& key) override; 311 312 private: 313 using EntriesMap = std::unordered_map<CacheAddr, EntryImpl*>; 314 class IteratorImpl; 315 316 // Creates a new backing file for the cache index. 317 bool CreateBackingStore(disk_cache::File* file); 318 bool InitBackingStore(bool* file_created); 319 void AdjustMaxCacheSize(int table_len); 320 321 bool InitStats(); 322 void StoreStats(); 323 324 // Deletes the cache and starts again. 325 void RestartCache(bool failure); 326 void PrepareForRestart(); 327 328 // Creates a new entry object. Returns zero on success, or a disk_cache error 329 // on failure. 330 int NewEntry(Addr address, scoped_refptr<EntryImpl>* entry); 331 332 // Returns a given entry from the cache. The entry to match is determined by 333 // key and hash, and the returned entry may be the matched one or it's parent 334 // on the list of entries with the same hash (or bucket). To look for a parent 335 // of a given entry, |entry_addr| should be grabbed from that entry, so that 336 // if it doesn't match the entry on the index, we know that it was replaced 337 // with a new entry; in this case |*match_error| will be set to true and the 338 // return value will be NULL. 339 scoped_refptr<EntryImpl> MatchEntry(const std::string& key, 340 uint32_t hash, 341 bool find_parent, 342 Addr entry_addr, 343 bool* match_error); 344 345 // Opens the next or previous entry on a single list. If successful, 346 // |from_entry| will be updated to point to the new entry, otherwise it will 347 // be set to NULL; in other words, it is used as an explicit iterator. 348 bool OpenFollowingEntryFromList(Rankings::List list, 349 CacheRankingsBlock** from_entry, 350 scoped_refptr<EntryImpl>* next_entry); 351 352 // Returns the entry that is pointed by |next|, from the given |list|. 353 scoped_refptr<EntryImpl> GetEnumeratedEntry(CacheRankingsBlock* next, 354 Rankings::List list); 355 356 // Re-opens an entry that was previously deleted. 357 scoped_refptr<EntryImpl> ResurrectEntry( 358 scoped_refptr<EntryImpl> deleted_entry); 359 360 void DestroyInvalidEntry(EntryImpl* entry); 361 362 // Handles the used storage count. 363 void AddStorageSize(int32_t bytes); 364 void SubstractStorageSize(int32_t bytes); 365 366 // Update the number of referenced cache entries. 367 void IncreaseNumRefs(); 368 void DecreaseNumRefs(); 369 void IncreaseNumEntries(); 370 void DecreaseNumEntries(); 371 372 // Dumps current cache statistics to the log. 373 void LogStats(); 374 375 // Send UMA stats. 376 void ReportStats(); 377 378 // Upgrades the index file to version 2.1 (from 2.0) 379 void UpgradeTo2_1(); 380 381 // Upgrades the index file to version 3.0 382 // (from 2.1/2.0 depending on eviction algorithm) 383 void UpgradeTo3_0(); 384 385 // Performs basic checks on the index file. Returns false on failure. 386 bool CheckIndex(); 387 388 // Part of the self test. Returns the number or dirty entries, or an error. 389 int CheckAllEntries(); 390 391 // Part of the self test. Returns false if the entry is corrupt. 392 bool CheckEntry(EntryImpl* cache_entry); 393 394 // Returns the maximum total memory for the memory buffers. 395 int MaxBuffersSize(); 396 397 // We want this destroyed after every other field. 398 scoped_refptr<BackendCleanupTracker> cleanup_tracker_; 399 400 InFlightBackendIO background_queue_; // The controller of pending operations. 401 scoped_refptr<MappedFile> index_; // The main cache index. 402 base::FilePath path_; // Path to the folder used as backing storage. 403 404 // Pointer to the index data. 405 // May point to a mapped file's unmapped memory at destruction time. 406 raw_ptr<Index, DisableDanglingPtrDetection> data_; 407 408 BlockFiles block_files_; // Set of files used to store all data. 409 Rankings rankings_; // Rankings to be able to trim the cache. 410 uint32_t mask_ = 0; // Binary mask to map a hash to the hash table. 411 int32_t max_size_ = 0; // Maximum data size for this instance. 412 Eviction eviction_; // Handler of the eviction algorithm. 413 EntriesMap open_entries_; // Map of open entries. 414 int num_refs_; // Number of referenced cache entries. 415 int max_refs_; // Max number of referenced cache entries. 416 int num_pending_io_; // Number of pending IO operations. 417 int entry_count_; // Number of entries accessed lately. 418 int byte_count_; // Number of bytes read/written lately. 419 int buffer_bytes_; // Total size of the temporary entries' buffers. 420 int up_ticks_ = 0; // The number of timer ticks received (OnStatsTimer). 421 int uma_report_ = 0; // Controls transmission of UMA data. 422 uint32_t user_flags_; // Flags set by the user. 423 bool init_ = false; // controls the initialization of the system. 424 bool restarted_ = false; 425 bool unit_test_ = false; 426 bool read_only_ = 427 false; // Prevents updates of the rankings data (used by tools). 428 bool disabled_ = false; 429 bool new_eviction_ = false; // What eviction algorithm should be used. 430 bool first_timer_ = true; // True if the timer has not been called. 431 bool user_load_ = 432 false; // True if we see a high load coming from the caller. 433 434 // True if we should consider doing eviction at end of current operation. 435 bool consider_evicting_at_op_end_ = false; 436 437 raw_ptr<net::NetLog> net_log_; 438 439 Stats stats_; // Usage statistics. 440 std::unique_ptr<base::RepeatingTimer> timer_; // Usage timer. 441 base::WeakPtrFactory<BackendImpl> ptr_factory_{this}; 442 }; 443 444 } // namespace disk_cache 445 446 #endif // NET_DISK_CACHE_BLOCKFILE_BACKEND_IMPL_H_ 447