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