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