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