• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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