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