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 #ifndef NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_ 6 #define NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_ 7 8 #include <stdint.h> 9 10 #include <map> 11 #include <memory> 12 #include <string> 13 #include <vector> 14 15 #include "base/containers/linked_list.h" 16 #include "base/gtest_prod_util.h" 17 #include "base/memory/raw_ptr.h" 18 #include "base/memory/weak_ptr.h" 19 #include "base/time/time.h" 20 #include "base/trace_event/memory_usage_estimator.h" 21 #include "net/base/interval.h" 22 #include "net/base/net_export.h" 23 #include "net/disk_cache/disk_cache.h" 24 #include "net/log/net_log_with_source.h" 25 26 namespace net { 27 class NetLog; 28 } 29 30 namespace disk_cache { 31 32 class MemBackendImpl; 33 34 // This class implements the Entry interface for the memory-only cache. An 35 // object of this class represents a single entry on the cache. We use two types 36 // of entries, parent and child to support sparse caching. 37 // 38 // A parent entry is non-sparse until a sparse method is invoked (i.e. 39 // ReadSparseData, WriteSparseData, GetAvailableRange) when sparse information 40 // is initialized. It then manages a list of child entries and delegates the 41 // sparse API calls to the child entries. It creates and deletes child entries 42 // and updates the list when needed. 43 // 44 // A child entry is used to carry partial cache content, non-sparse methods like 45 // ReadData and WriteData cannot be applied to them. The lifetime of a child 46 // entry is managed by the parent entry that created it except that the entry 47 // can be evicted independently. A child entry does not have a key and it is not 48 // registered in the backend's entry map. 49 // 50 // A sparse child entry has a fixed maximum size and can be partially 51 // filled. There can only be one continous filled region in a sparse entry, as 52 // illustrated by the following example: 53 // | xxx ooooo | 54 // x = unfilled region 55 // o = filled region 56 // It is guaranteed that there is at most one unfilled region and one filled 57 // region, and the unfilled region (if there is one) is always before the filled 58 // region. The book keeping for filled region in a sparse entry is done by using 59 // the variable |child_first_pos_|. 60 61 class NET_EXPORT_PRIVATE MemEntryImpl final 62 : public Entry, 63 public base::LinkNode<MemEntryImpl> { 64 public: 65 enum class EntryType { 66 kParent, 67 kChild, 68 }; 69 70 // Provided to better document calls to |UpdateStateOnUse()|. 71 enum EntryModified { 72 ENTRY_WAS_NOT_MODIFIED, 73 ENTRY_WAS_MODIFIED, 74 }; 75 76 // Constructor for parent entries. 77 MemEntryImpl(base::WeakPtr<MemBackendImpl> backend, 78 const std::string& key, 79 net::NetLog* net_log); 80 81 // Constructor for child entries. 82 MemEntryImpl(base::WeakPtr<MemBackendImpl> backend, 83 int64_t child_id, 84 MemEntryImpl* parent, 85 net::NetLog* net_log); 86 87 MemEntryImpl(const MemEntryImpl&) = delete; 88 MemEntryImpl& operator=(const MemEntryImpl&) = delete; 89 90 void Open(); 91 bool InUse() const; 92 type()93 EntryType type() const { 94 return parent_ ? EntryType::kChild : EntryType::kParent; 95 } key()96 const std::string& key() const { return key_; } parent()97 const MemEntryImpl* parent() const { return parent_; } child_id()98 int64_t child_id() const { return child_id_; } last_used()99 base::Time last_used() const { return last_used_; } 100 101 // The in-memory size of this entry to use for the purposes of eviction. 102 int GetStorageSize() const; 103 104 // Update an entry's position in the backend LRU list and set |last_used_|. If 105 // the entry was modified, also update |last_modified_|. 106 void UpdateStateOnUse(EntryModified modified_enum); 107 108 // From disk_cache::Entry: 109 void Doom() override; 110 void Close() override; 111 std::string GetKey() const override; 112 base::Time GetLastUsed() const override; 113 base::Time GetLastModified() const override; 114 int32_t GetDataSize(int index) const override; 115 int ReadData(int index, 116 int offset, 117 IOBuffer* buf, 118 int buf_len, 119 CompletionOnceCallback callback) override; 120 int WriteData(int index, 121 int offset, 122 IOBuffer* buf, 123 int buf_len, 124 CompletionOnceCallback callback, 125 bool truncate) override; 126 int ReadSparseData(int64_t offset, 127 IOBuffer* buf, 128 int buf_len, 129 CompletionOnceCallback callback) override; 130 int WriteSparseData(int64_t offset, 131 IOBuffer* buf, 132 int buf_len, 133 CompletionOnceCallback callback) override; 134 RangeResult GetAvailableRange(int64_t offset, 135 int len, 136 RangeResultCallback callback) override; 137 bool CouldBeSparse() const override; CancelSparseIO()138 void CancelSparseIO() override {} 139 net::Error ReadyForSparseIO(CompletionOnceCallback callback) override; 140 void SetLastUsedTimeForTest(base::Time time) override; 141 142 private: 143 MemEntryImpl(base::WeakPtr<MemBackendImpl> backend, 144 const std::string& key, 145 int64_t child_id, 146 MemEntryImpl* parent, 147 net::NetLog* net_log); 148 149 using EntryMap = std::map<int64_t, MemEntryImpl*>; 150 151 static const int kNumStreams = 3; 152 153 ~MemEntryImpl() override; 154 155 // Do all the work for corresponding public functions. Implemented as 156 // separate functions to make logging of results simpler. 157 int InternalReadData(int index, int offset, IOBuffer* buf, int buf_len); 158 int InternalWriteData(int index, int offset, IOBuffer* buf, int buf_len, 159 bool truncate); 160 int InternalReadSparseData(int64_t offset, IOBuffer* buf, int buf_len); 161 int InternalWriteSparseData(int64_t offset, IOBuffer* buf, int buf_len); 162 RangeResult InternalGetAvailableRange(int64_t offset, int len); 163 164 // Initializes the children map and sparse info. This method is only called 165 // on a parent entry. 166 bool InitSparseInfo(); 167 168 // Returns an entry responsible for |offset|. The returned entry can be a 169 // child entry or this entry itself if |offset| points to the first range. 170 // If such entry does not exist and |create| is true, a new child entry is 171 // created. 172 MemEntryImpl* GetChild(int64_t offset, bool create); 173 174 // Returns an interval describing what's stored in the child entry pointed to 175 // by i, in global coordinates. 176 // Precondition: i != children_.end(); 177 net::Interval<int64_t> ChildInterval( 178 MemEntryImpl::EntryMap::const_iterator i); 179 180 // Compact vectors to try to avoid over-allocation due to exponential growth. 181 void Compact(); 182 183 std::string key_; 184 std::vector<char> data_[kNumStreams]; // User data. 185 uint32_t ref_count_ = 0; 186 187 int64_t child_id_; // The ID of a child entry. 188 int child_first_pos_ = 0; // The position of the first byte in a child 189 // entry. 0 here is beginning of child, not of 190 // the entire file. 191 // Pointer to the parent entry, or nullptr if this entry is a parent entry. 192 raw_ptr<MemEntryImpl> parent_; 193 std::unique_ptr<EntryMap> children_; 194 195 base::Time last_modified_; 196 base::Time last_used_; 197 base::WeakPtr<MemBackendImpl> backend_; // Back pointer to the cache. 198 bool doomed_ = false; // True if this entry was removed from the cache. 199 200 net::NetLogWithSource net_log_; 201 }; 202 203 } // namespace disk_cache 204 205 #endif // NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_ 206