| // 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 <vector> | 
 |  | 
 | #include "base/callback.h" | 
 | #include "base/containers/hash_tables.h" | 
 | #include "base/files/file_path.h" | 
 | #include "base/gtest_prod_util.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/memory/scoped_ptr.h" | 
 | #include "base/memory/weak_ptr.h" | 
 | #include "base/single_thread_task_runner.h" | 
 | #include "base/threading/thread_checker.h" | 
 | #include "base/time/time.h" | 
 | #include "base/timer/timer.h" | 
 | #include "net/base/cache_type.h" | 
 | #include "net/base/completion_callback.h" | 
 | #include "net/base/net_export.h" | 
 |  | 
 | #if defined(OS_ANDROID) | 
 | #include "base/android/application_status_listener.h" | 
 | #endif | 
 |  | 
 | namespace base { | 
 | class Pickle; | 
 | class PickleIterator; | 
 | } | 
 |  | 
 | namespace disk_cache { | 
 |  | 
 | class SimpleIndexDelegate; | 
 | class SimpleIndexFile; | 
 | struct SimpleIndexLoadResult; | 
 |  | 
 | class NET_EXPORT_PRIVATE EntryMetadata { | 
 |  public: | 
 |   EntryMetadata(); | 
 |   EntryMetadata(base::Time last_used_time, uint64_t entry_size); | 
 |  | 
 |   base::Time GetLastUsedTime() const; | 
 |   void SetLastUsedTime(const base::Time& last_used_time); | 
 |  | 
 |   uint64_t GetEntrySize() const; | 
 |   void SetEntrySize(uint64_t entry_size); | 
 |  | 
 |   // Serialize the data into the provided pickle. | 
 |   void Serialize(base::Pickle* pickle) const; | 
 |   bool Deserialize(base::PickleIterator* it); | 
 |  | 
 |   static base::TimeDelta GetLowerEpsilonForTimeComparisons() { | 
 |     return base::TimeDelta::FromSeconds(1); | 
 |   } | 
 |   static base::TimeDelta GetUpperEpsilonForTimeComparisons() { | 
 |     return base::TimeDelta(); | 
 |   } | 
 |  | 
 |  private: | 
 |   friend class SimpleIndexFileTest; | 
 |  | 
 |   // 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. | 
 |   uint32_t last_used_time_seconds_since_epoch_; | 
 |   int32_t entry_size_;  // Storage size in bytes. | 
 | }; | 
 | static_assert(sizeof(EntryMetadata) == 8, "incorrect metadata size"); | 
 |  | 
 | // This class is not Thread-safe. | 
 | class NET_EXPORT_PRIVATE SimpleIndex | 
 |     : public base::SupportsWeakPtr<SimpleIndex> { | 
 |  public: | 
 |   typedef std::vector<uint64_t> HashList; | 
 |  | 
 |   SimpleIndex(const scoped_refptr<base::SingleThreadTaskRunner>& io_thread, | 
 |               SimpleIndexDelegate* delegate, | 
 |               net::CacheType cache_type, | 
 |               scoped_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); | 
 |  | 
 |   void WriteToDisk(); | 
 |  | 
 |   // 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, int64_t entry_size); | 
 |  | 
 |   typedef base::hash_map<uint64_t, EntryMetadata> EntrySet; | 
 |  | 
 |   static void InsertInEntrySet(uint64_t entry_hash, | 
 |                                const EntryMetadata& entry_metadata, | 
 |                                EntrySet* entry_set); | 
 |  | 
 |   // Executes the |callback| when the index is ready. Allows multiple callbacks. | 
 |   int ExecuteWhenReady(const net::CompletionCallback& 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. | 
 |   scoped_ptr<HashList> GetEntriesBetween(const base::Time initial_time, | 
 |                                          const base::Time end_time); | 
 |  | 
 |   // Returns the list of all entries key hash. | 
 |   scoped_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 whether the index has been initialized yet. | 
 |   bool initialized() const { return initialized_; } | 
 |  | 
 |  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); | 
 |  | 
 |   void StartEvictionIfNeeded(); | 
 |   void EvictionDone(int result); | 
 |  | 
 |   void PostponeWritingToDisk(); | 
 |  | 
 |   void UpdateEntryIteratorSize(EntrySet::iterator* it, int64_t entry_size); | 
 |  | 
 |   // Must run on IO Thread. | 
 |   void MergeInitializingSet(scoped_ptr<SimpleIndexLoadResult> load_result); | 
 |  | 
 | #if defined(OS_ANDROID) | 
 |   void OnApplicationStateChange(base::android::ApplicationState state); | 
 |  | 
 |   scoped_ptr<base::android::ApplicationStatusListener> app_status_listener_; | 
 | #endif | 
 |  | 
 |   // The owner of |this| must ensure the |delegate_| outlives |this|. | 
 |   SimpleIndexDelegate* delegate_; | 
 |  | 
 |   EntrySet entries_set_; | 
 |  | 
 |   const net::CacheType cache_type_; | 
 |   uint64_t cache_size_;  // Total cache storage size in bytes. | 
 |   uint64_t max_size_; | 
 |   uint64_t high_watermark_; | 
 |   uint64_t low_watermark_; | 
 |   bool eviction_in_progress_; | 
 |   base::TimeTicks eviction_start_time_; | 
 |  | 
 |   // This stores all the entry_hash of entries that are removed during | 
 |   // initialization. | 
 |   base::hash_set<uint64_t> removed_entries_; | 
 |   bool initialized_; | 
 |  | 
 |   scoped_ptr<SimpleIndexFile> index_file_; | 
 |  | 
 |   scoped_refptr<base::SingleThreadTaskRunner> io_thread_; | 
 |  | 
 |   // All nonstatic SimpleEntryImpl methods should always be called on the IO | 
 |   // thread, in all cases. |io_thread_checker_| documents and enforces this. | 
 |   base::ThreadChecker io_thread_checker_; | 
 |  | 
 |   // Timestamp of the last time we wrote the index to disk. | 
 |   // PostponeWritingToDisk() may give up postponing and allow the write if it | 
 |   // has been a while since last time we wrote. | 
 |   base::TimeTicks last_write_to_disk_; | 
 |  | 
 |   base::OneShotTimer write_to_disk_timer_; | 
 |   base::Closure write_to_disk_cb_; | 
 |  | 
 |   typedef std::list<net::CompletionCallback> 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_; | 
 | }; | 
 |  | 
 | }  // namespace disk_cache | 
 |  | 
 | #endif  // NET_DISK_CACHE_SIMPLE_SIMPLE_INDEX_H_ |