1 // Copyright (c) 2011 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_MEM_ENTRY_IMPL_H_ 6 #define NET_DISK_CACHE_MEM_ENTRY_IMPL_H_ 7 #pragma once 8 9 #include "base/hash_tables.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "net/base/net_log.h" 12 #include "net/disk_cache/disk_cache.h" 13 #include "testing/gtest/include/gtest/gtest_prod.h" 14 15 namespace disk_cache { 16 17 class MemBackendImpl; 18 19 // This class implements the Entry interface for the memory-only cache. An 20 // object of this class represents a single entry on the cache. We use two 21 // types of entries, parent and child to support sparse caching. 22 // 23 // A parent entry is non-sparse until a sparse method is invoked (i.e. 24 // ReadSparseData, WriteSparseData, GetAvailableRange) when sparse information 25 // is initialized. It then manages a list of child entries and delegates the 26 // sparse API calls to the child entries. It creates and deletes child entries 27 // and updates the list when needed. 28 // 29 // A child entry is used to carry partial cache content, non-sparse methods like 30 // ReadData and WriteData cannot be applied to them. The lifetime of a child 31 // entry is managed by the parent entry that created it except that the entry 32 // can be evicted independently. A child entry does not have a key and it is not 33 // registered in the backend's entry map. It is registered in the backend's 34 // ranking list to enable eviction of a partial content. 35 // 36 // A sparse entry has a fixed maximum size and can be partially filled. There 37 // can only be one continous filled region in a sparse entry, as illustrated by 38 // the following example: 39 // | xxx ooooo | 40 // x = unfilled region 41 // o = filled region 42 // It is guranteed that there is at most one unfilled region and one filled 43 // region, and the unfilled region (if there is one) is always before the filled 44 // region. The book keeping for filled region in a sparse entry is done by using 45 // the variable |child_first_pos_| (inclusive). 46 47 class MemEntryImpl : public Entry { 48 public: 49 enum EntryType { 50 kParentEntry, 51 kChildEntry, 52 }; 53 54 explicit MemEntryImpl(MemBackendImpl* backend); 55 56 // Performs the initialization of a EntryImpl that will be added to the 57 // cache. 58 bool CreateEntry(const std::string& key, net::NetLog* net_log); 59 60 // Permanently destroys this entry. 61 void InternalDoom(); 62 63 void Open(); 64 bool InUse(); 65 next()66 MemEntryImpl* next() const { 67 return next_; 68 } 69 prev()70 MemEntryImpl* prev() const { 71 return prev_; 72 } 73 set_next(MemEntryImpl * next)74 void set_next(MemEntryImpl* next) { 75 next_ = next; 76 } 77 set_prev(MemEntryImpl * prev)78 void set_prev(MemEntryImpl* prev) { 79 prev_ = prev; 80 } 81 type()82 EntryType type() const { 83 return parent_ ? kChildEntry : kParentEntry; 84 } 85 key()86 std::string& key() { 87 return key_; 88 } 89 net_log()90 net::BoundNetLog& net_log() { 91 return net_log_; 92 } 93 94 // Entry interface. 95 virtual void Doom(); 96 virtual void Close(); 97 virtual std::string GetKey() const; 98 virtual base::Time GetLastUsed() const; 99 virtual base::Time GetLastModified() const; 100 virtual int32 GetDataSize(int index) const; 101 virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len, 102 net::CompletionCallback* completion_callback); 103 virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, 104 net::CompletionCallback* completion_callback, 105 bool truncate); 106 virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, 107 net::CompletionCallback* completion_callback); 108 virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, 109 net::CompletionCallback* completion_callback); 110 virtual int GetAvailableRange(int64 offset, int len, int64* start, 111 CompletionCallback* callback); 112 virtual bool CouldBeSparse() const; CancelSparseIO()113 virtual void CancelSparseIO() {} 114 virtual int ReadyForSparseIO(net::CompletionCallback* completion_callback); 115 116 private: 117 typedef base::hash_map<int, MemEntryImpl*> EntryMap; 118 119 enum { 120 NUM_STREAMS = 3 121 }; 122 123 ~MemEntryImpl(); 124 125 // Do all the work for corresponding public functions. Implemented as 126 // separate functions to make logging of results simpler. 127 int InternalReadData(int index, int offset, net::IOBuffer* buf, int buf_len); 128 int InternalWriteData(int index, int offset, net::IOBuffer* buf, int buf_len, 129 bool truncate); 130 int InternalReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len); 131 int InternalWriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len); 132 133 // Old Entry interface. 134 int GetAvailableRange(int64 offset, int len, int64* start); 135 136 // Grows and cleans up the data buffer. 137 void PrepareTarget(int index, int offset, int buf_len); 138 139 // Updates ranking information. 140 void UpdateRank(bool modified); 141 142 // Initializes the children map and sparse info. This method is only called 143 // on a parent entry. 144 bool InitSparseInfo(); 145 146 // Performs the initialization of a MemEntryImpl as a child entry. 147 // |parent| is the pointer to the parent entry. |child_id| is the ID of 148 // the new child. 149 bool InitChildEntry(MemEntryImpl* parent, int child_id, net::NetLog* net_log); 150 151 // Returns an entry responsible for |offset|. The returned entry can be a 152 // child entry or this entry itself if |offset| points to the first range. 153 // If such entry does not exist and |create| is true, a new child entry is 154 // created. 155 MemEntryImpl* OpenChild(int64 offset, bool create); 156 157 // Finds the first child located within the range [|offset|, |offset + len|). 158 // Returns the number of bytes ahead of |offset| to reach the first available 159 // bytes in the entry. The first child found is output to |child|. 160 int FindNextChild(int64 offset, int len, MemEntryImpl** child); 161 162 // Removes child indexed by |child_id| from the children map. 163 void DetachChild(int child_id); 164 165 std::string key_; 166 std::vector<char> data_[NUM_STREAMS]; // User data. 167 int32 data_size_[NUM_STREAMS]; 168 int ref_count_; 169 170 int child_id_; // The ID of a child entry. 171 int child_first_pos_; // The position of the first byte in a child 172 // entry. 173 MemEntryImpl* next_; // Pointers for the LRU list. 174 MemEntryImpl* prev_; 175 MemEntryImpl* parent_; // Pointer to the parent entry. 176 scoped_ptr<EntryMap> children_; 177 178 base::Time last_modified_; // LRU information. 179 base::Time last_used_; 180 MemBackendImpl* backend_; // Back pointer to the cache. 181 bool doomed_; // True if this entry was removed from the cache. 182 183 net::BoundNetLog net_log_; 184 185 DISALLOW_COPY_AND_ASSIGN(MemEntryImpl); 186 }; 187 188 } // namespace disk_cache 189 190 #endif // NET_DISK_CACHE_MEM_ENTRY_IMPL_H_ 191