123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- // Copyright (c) 2013 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef NET_DISK_CACHE_SIMPLE_SIMPLE_INDEX_H_
- #define NET_DISK_CACHE_SIMPLE_SIMPLE_INDEX_H_
- #include <stdint.h>
- #include <list>
- #include <memory>
- #include <unordered_map>
- #include <unordered_set>
- #include <vector>
- #include "base/callback.h"
- #include "base/gtest_prod_util.h"
- #include "base/memory/raw_ptr.h"
- #include "base/memory/ref_counted.h"
- #include "base/memory/weak_ptr.h"
- #include "base/numerics/safe_conversions.h"
- #include "base/sequence_checker.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/time/time.h"
- #include "base/timer/timer.h"
- #include "build/build_config.h"
- #include "net/base/cache_type.h"
- #include "net/base/completion_once_callback.h"
- #include "net/base/net_errors.h"
- #include "net/base/net_export.h"
- #if BUILDFLAG(IS_ANDROID)
- #include "base/android/application_status_listener.h"
- #endif
- namespace base {
- class Pickle;
- class PickleIterator;
- }
- namespace disk_cache {
- class BackendCleanupTracker;
- class SimpleIndexDelegate;
- class SimpleIndexFile;
- struct SimpleIndexLoadResult;
- class NET_EXPORT_PRIVATE EntryMetadata {
- public:
- EntryMetadata();
- EntryMetadata(base::Time last_used_time,
- base::StrictNumeric<uint32_t> entry_size);
- EntryMetadata(int32_t trailer_prefetch_size,
- base::StrictNumeric<uint32_t> entry_size);
- base::Time GetLastUsedTime() const;
- void SetLastUsedTime(const base::Time& last_used_time);
- int32_t GetTrailerPrefetchSize() const;
- void SetTrailerPrefetchSize(int32_t size);
- uint32_t RawTimeForSorting() const {
- return last_used_time_seconds_since_epoch_;
- }
- uint32_t GetEntrySize() const;
- void SetEntrySize(base::StrictNumeric<uint32_t> entry_size);
- uint8_t GetInMemoryData() const { return in_memory_data_; }
- void SetInMemoryData(uint8_t val) { in_memory_data_ = val; }
- // Serialize the data into the provided pickle.
- void Serialize(net::CacheType cache_type, base::Pickle* pickle) const;
- bool Deserialize(net::CacheType cache_type,
- base::PickleIterator* it,
- bool has_entry_in_memory_data,
- bool app_cache_has_trailer_prefetch_size);
- static base::TimeDelta GetLowerEpsilonForTimeComparisons() {
- return base::Seconds(1);
- }
- static base::TimeDelta GetUpperEpsilonForTimeComparisons() {
- return base::TimeDelta();
- }
- static const int kOnDiskSizeBytes = 16;
- private:
- friend class SimpleIndexFileTest;
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexFileTest, ReadV8Format);
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexFileTest, ReadV8FormatAppCache);
- // There are tens of thousands of instances of EntryMetadata in memory, so the
- // size of each entry matters. Even when the values used to set these members
- // are originally calculated as >32-bit types, the actual necessary size for
- // each shouldn't exceed 32 bits, so we use 32-bit types here.
- // In most modes we track the last access time in order to support automatic
- // eviction. In APP_CACHE mode, however, eviction is disabled. Instead of
- // storing the access time in APP_CACHE mode we instead store a hint about
- // how much entry file trailer should be prefetched when its opened.
- union {
- uint32_t last_used_time_seconds_since_epoch_;
- int32_t trailer_prefetch_size_; // in bytes
- };
- uint32_t entry_size_256b_chunks_ : 24; // in 256-byte blocks, rounded up.
- uint32_t in_memory_data_ : 8;
- };
- static_assert(sizeof(EntryMetadata) == 8, "incorrect metadata size");
- // This class is not Thread-safe.
- class NET_EXPORT_PRIVATE SimpleIndex
- : public base::SupportsWeakPtr<SimpleIndex> {
- public:
- // Used in histograms. Please only add entries at the end.
- enum IndexInitMethod {
- INITIALIZE_METHOD_RECOVERED = 0,
- INITIALIZE_METHOD_LOADED = 1,
- INITIALIZE_METHOD_NEWCACHE = 2,
- INITIALIZE_METHOD_MAX = 3,
- };
- // Used in histograms. Please only add entries at the end.
- enum IndexWriteToDiskReason {
- INDEX_WRITE_REASON_SHUTDOWN = 0,
- INDEX_WRITE_REASON_STARTUP_MERGE = 1,
- INDEX_WRITE_REASON_IDLE = 2,
- INDEX_WRITE_REASON_ANDROID_STOPPED = 3,
- INDEX_WRITE_REASON_MAX = 4,
- };
- typedef std::vector<uint64_t> HashList;
- SimpleIndex(const scoped_refptr<base::SequencedTaskRunner>& task_runner,
- scoped_refptr<BackendCleanupTracker> cleanup_tracker,
- SimpleIndexDelegate* delegate,
- net::CacheType cache_type,
- std::unique_ptr<SimpleIndexFile> simple_index_file);
- virtual ~SimpleIndex();
- void Initialize(base::Time cache_mtime);
- void SetMaxSize(uint64_t max_bytes);
- uint64_t max_size() const { return max_size_; }
- void Insert(uint64_t entry_hash);
- void Remove(uint64_t entry_hash);
- // Check whether the index has the entry given the hash of its key.
- bool Has(uint64_t entry_hash) const;
- // Update the last used time of the entry with the given key and return true
- // iff the entry exist in the index.
- bool UseIfExists(uint64_t entry_hash);
- uint8_t GetEntryInMemoryData(uint64_t entry_hash) const;
- void SetEntryInMemoryData(uint64_t entry_hash, uint8_t value);
- void WriteToDisk(IndexWriteToDiskReason reason);
- int32_t GetTrailerPrefetchSize(uint64_t entry_hash) const;
- void SetTrailerPrefetchSize(uint64_t entry_hash, int32_t size);
- // Update the size (in bytes) of an entry, in the metadata stored in the
- // index. This should be the total disk-file size including all streams of the
- // entry.
- bool UpdateEntrySize(uint64_t entry_hash,
- base::StrictNumeric<uint32_t> entry_size);
- using EntrySet = std::unordered_map<uint64_t, EntryMetadata>;
- // Insert an entry in the given set if there is not already entry present.
- // Returns true if the set was modified.
- static bool InsertInEntrySet(uint64_t entry_hash,
- const EntryMetadata& entry_metadata,
- EntrySet* entry_set);
- // For use in tests only. Updates cache_size_, but will not start evictions
- // or adjust index writing time. Requires entry to not already be in the set.
- void InsertEntryForTesting(uint64_t entry_hash,
- const EntryMetadata& entry_metadata);
- // Executes the |callback| when the index is ready. Allows multiple callbacks.
- // Never synchronous.
- void ExecuteWhenReady(net::CompletionOnceCallback callback);
- // Returns entries from the index that have last accessed time matching the
- // range between |initial_time| and |end_time| where open intervals are
- // possible according to the definition given in |DoomEntriesBetween()| in the
- // disk cache backend interface.
- //
- // Access times are not updated in net::APP_CACHE mode. GetEntriesBetween()
- // should only be called with null times indicating the full range when in
- // this mode.
- std::unique_ptr<HashList> GetEntriesBetween(const base::Time initial_time,
- const base::Time end_time);
- // Returns the list of all entries key hash.
- std::unique_ptr<HashList> GetAllHashes();
- // Returns number of indexed entries.
- int32_t GetEntryCount() const;
- // Returns the size of the entire cache in bytes. Can only be called after the
- // index has been initialized.
- uint64_t GetCacheSize() const;
- // Returns the size of the cache entries accessed between |initial_time| and
- // |end_time| in bytes. Can only be called after the index has been
- // initialized.
- uint64_t GetCacheSizeBetween(const base::Time initial_time,
- const base::Time end_time) const;
- // Returns whether the index has been initialized yet.
- bool initialized() const { return initialized_; }
- IndexInitMethod init_method() const { return init_method_; }
- // Returns base::Time() if hash not known.
- base::Time GetLastUsedTime(uint64_t entry_hash);
- void SetLastUsedTimeForTest(uint64_t entry_hash, const base::Time last_used);
- #if BUILDFLAG(IS_ANDROID)
- void set_app_status_listener(
- base::android::ApplicationStatusListener* app_status_listener) {
- app_status_listener_ = app_status_listener;
- }
- #endif
- // Return true if a pending disk write has been scheduled from
- // PostponeWritingToDisk().
- bool HasPendingWrite() const;
- private:
- friend class SimpleIndexTest;
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexTest, IndexSizeCorrectOnMerge);
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexTest, DiskWriteQueued);
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexTest, DiskWriteExecuted);
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexTest, DiskWritePostponed);
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexAppCacheTest, DiskWriteQueued);
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexCodeCacheTest, DisableEvictBySize);
- FRIEND_TEST_ALL_PREFIXES(SimpleIndexCodeCacheTest, EnableEvictBySize);
- void StartEvictionIfNeeded();
- void EvictionDone(int result);
- void PostponeWritingToDisk();
- // Update the size of the entry pointed to by the given iterator. Return
- // true if the new size actually results in a change.
- bool UpdateEntryIteratorSize(EntrySet::iterator* it,
- base::StrictNumeric<uint32_t> entry_size);
- // Must run on IO Thread.
- void MergeInitializingSet(std::unique_ptr<SimpleIndexLoadResult> load_result);
- #if BUILDFLAG(IS_ANDROID)
- void OnApplicationStateChange(base::android::ApplicationState state);
- std::unique_ptr<base::android::ApplicationStatusListener>
- owned_app_status_listener_;
- raw_ptr<base::android::ApplicationStatusListener> app_status_listener_ =
- nullptr;
- #endif
- scoped_refptr<BackendCleanupTracker> cleanup_tracker_;
- // The owner of |this| must ensure the |delegate_| outlives |this|.
- raw_ptr<SimpleIndexDelegate> delegate_;
- EntrySet entries_set_;
- const net::CacheType cache_type_;
- uint64_t cache_size_ = 0; // Total cache storage size in bytes.
- uint64_t max_size_ = 0;
- uint64_t high_watermark_ = 0;
- uint64_t low_watermark_ = 0;
- bool eviction_in_progress_ = false;
- base::TimeTicks eviction_start_time_;
- // This stores all the entry_hash of entries that are removed during
- // initialization.
- std::unordered_set<uint64_t> removed_entries_;
- bool initialized_ = false;
- IndexInitMethod init_method_ = INITIALIZE_METHOD_MAX;
- std::unique_ptr<SimpleIndexFile> index_file_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- // All nonstatic SimpleEntryImpl methods should always be called on its
- // creation sequance, in all cases. |sequence_checker_| documents and
- // enforces this.
- SEQUENCE_CHECKER(sequence_checker_);
- base::OneShotTimer write_to_disk_timer_;
- base::RepeatingClosure write_to_disk_cb_;
- typedef std::list<net::CompletionOnceCallback> CallbackList;
- CallbackList to_run_when_initialized_;
- // Set to true when the app is on the background. When the app is in the
- // background we can write the index much more frequently, to insure fresh
- // index on next startup.
- bool app_on_background_ = false;
- };
- } // namespace disk_cache
- #endif // NET_DISK_CACHE_SIMPLE_SIMPLE_INDEX_H_
|