1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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/macros.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 EntryType { 66 PARENT_ENTRY, 67 CHILD_ENTRY, 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 void Open(); 88 bool InUse() const; 89 type()90 EntryType type() const { return parent_ ? CHILD_ENTRY : PARENT_ENTRY; } key()91 const std::string& key() const { return key_; } parent()92 const MemEntryImpl* parent() const { return parent_; } child_id()93 int64_t child_id() const { return child_id_; } last_used()94 base::Time last_used() const { return last_used_; } 95 96 // The in-memory size of this entry to use for the purposes of eviction. 97 int GetStorageSize() const; 98 99 // Update an entry's position in the backend LRU list and set |last_used_|. If 100 // the entry was modified, also update |last_modified_|. 101 void UpdateStateOnUse(EntryModified modified_enum); 102 103 // From disk_cache::Entry: 104 void Doom() override; 105 void Close() override; 106 std::string GetKey() const override; 107 base::Time GetLastUsed() const override; 108 base::Time GetLastModified() const override; 109 int32_t GetDataSize(int index) const override; 110 int ReadData(int index, 111 int offset, 112 IOBuffer* buf, 113 int buf_len, 114 CompletionOnceCallback callback) override; 115 int WriteData(int index, 116 int offset, 117 IOBuffer* buf, 118 int buf_len, 119 CompletionOnceCallback callback, 120 bool truncate) override; 121 int ReadSparseData(int64_t offset, 122 IOBuffer* buf, 123 int buf_len, 124 CompletionOnceCallback callback) override; 125 int WriteSparseData(int64_t offset, 126 IOBuffer* buf, 127 int buf_len, 128 CompletionOnceCallback callback) override; 129 int GetAvailableRange(int64_t offset, 130 int len, 131 int64_t* start, 132 CompletionOnceCallback callback) override; 133 bool CouldBeSparse() const override; CancelSparseIO()134 void CancelSparseIO() override {} 135 net::Error ReadyForSparseIO(CompletionOnceCallback callback) override; 136 void SetLastUsedTimeForTest(base::Time time) override; 137 size_t EstimateMemoryUsage() const; 138 139 private: 140 MemEntryImpl(base::WeakPtr<MemBackendImpl> backend, 141 const std::string& key, 142 int64_t child_id, 143 MemEntryImpl* parent, 144 net::NetLog* net_log); 145 146 using EntryMap = std::map<int64_t, MemEntryImpl*>; 147 148 static const int kNumStreams = 3; 149 150 ~MemEntryImpl() override; 151 152 // Do all the work for corresponding public functions. Implemented as 153 // separate functions to make logging of results simpler. 154 int InternalReadData(int index, int offset, IOBuffer* buf, int buf_len); 155 int InternalWriteData(int index, int offset, IOBuffer* buf, int buf_len, 156 bool truncate); 157 int InternalReadSparseData(int64_t offset, IOBuffer* buf, int buf_len); 158 int InternalWriteSparseData(int64_t offset, IOBuffer* buf, int buf_len); 159 int InternalGetAvailableRange(int64_t offset, int len, int64_t* start); 160 161 // Initializes the children map and sparse info. This method is only called 162 // on a parent entry. 163 bool InitSparseInfo(); 164 165 // Returns an entry responsible for |offset|. The returned entry can be a 166 // child entry or this entry itself if |offset| points to the first range. 167 // If such entry does not exist and |create| is true, a new child entry is 168 // created. 169 MemEntryImpl* GetChild(int64_t offset, bool create); 170 171 // Returns an interval describing what's stored in the child entry pointed to 172 // by i, in global coordinates. 173 // Precondition: i != children_.end(); 174 net::Interval<int64_t> ChildInterval( 175 MemEntryImpl::EntryMap::const_iterator i); 176 177 // Compact vectors to try to avoid over-allocation due to exponential growth. 178 void Compact(); 179 180 std::string key_; 181 std::vector<char> data_[kNumStreams]; // User data. 182 uint32_t ref_count_; 183 184 int64_t child_id_; // The ID of a child entry. 185 int child_first_pos_; // The position of the first byte in a child 186 // entry. 0 here is beginning of child, not of 187 // the entire file. 188 // Pointer to the parent entry, or nullptr if this entry is a parent entry. 189 MemEntryImpl* parent_; 190 std::unique_ptr<EntryMap> children_; 191 192 base::Time last_modified_; 193 base::Time last_used_; 194 base::WeakPtr<MemBackendImpl> backend_; // Back pointer to the cache. 195 bool doomed_; // True if this entry was removed from the cache. 196 197 net::NetLogWithSource net_log_; 198 199 DISALLOW_COPY_AND_ASSIGN(MemEntryImpl); 200 }; 201 202 } // namespace disk_cache 203 204 #endif // NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_ 205