summaryrefslogtreecommitdiff
path: root/chromium/net/disk_cache/memory/mem_entry_impl.h
blob: efefa4575412204133ae27d494ea67d5dab59e97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_
#define NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/containers/linked_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "net/base/interval.h"
#include "net/base/net_export.h"
#include "net/disk_cache/disk_cache.h"
#include "net/log/net_log_with_source.h"

namespace net {
class NetLog;
}

namespace disk_cache {

class MemBackendImpl;

// This class implements the Entry interface for the memory-only cache. An
// object of this class represents a single entry on the cache. We use two types
// of entries, parent and child to support sparse caching.
//
// A parent entry is non-sparse until a sparse method is invoked (i.e.
// ReadSparseData, WriteSparseData, GetAvailableRange) when sparse information
// is initialized. It then manages a list of child entries and delegates the
// sparse API calls to the child entries. It creates and deletes child entries
// and updates the list when needed.
//
// A child entry is used to carry partial cache content, non-sparse methods like
// ReadData and WriteData cannot be applied to them. The lifetime of a child
// entry is managed by the parent entry that created it except that the entry
// can be evicted independently. A child entry does not have a key and it is not
// registered in the backend's entry map.
//
// A sparse child entry has a fixed maximum size and can be partially
// filled. There can only be one continous filled region in a sparse entry, as
// illustrated by the following example:
// | xxx ooooo |
// x = unfilled region
// o = filled region
// It is guaranteed that there is at most one unfilled region and one filled
// region, and the unfilled region (if there is one) is always before the filled
// region. The book keeping for filled region in a sparse entry is done by using
// the variable |child_first_pos_|.

class NET_EXPORT_PRIVATE MemEntryImpl final
    : public Entry,
      public base::LinkNode<MemEntryImpl> {
 public:
  enum class EntryType {
    kParent,
    kChild,
  };

  // Provided to better document calls to |UpdateStateOnUse()|.
  enum EntryModified {
    ENTRY_WAS_NOT_MODIFIED,
    ENTRY_WAS_MODIFIED,
  };

  // Constructor for parent entries.
  MemEntryImpl(base::WeakPtr<MemBackendImpl> backend,
               const std::string& key,
               net::NetLog* net_log);

  // Constructor for child entries.
  MemEntryImpl(base::WeakPtr<MemBackendImpl> backend,
               int64_t child_id,
               MemEntryImpl* parent,
               net::NetLog* net_log);

  MemEntryImpl(const MemEntryImpl&) = delete;
  MemEntryImpl& operator=(const MemEntryImpl&) = delete;

  void Open();
  bool InUse() const;

  EntryType type() const {
    return parent_ ? EntryType::kChild : EntryType::kParent;
  }
  const std::string& key() const { return key_; }
  const MemEntryImpl* parent() const { return parent_; }
  int64_t child_id() const { return child_id_; }
  base::Time last_used() const { return last_used_; }

  // The in-memory size of this entry to use for the purposes of eviction.
  int GetStorageSize() const;

  // Update an entry's position in the backend LRU list and set |last_used_|. If
  // the entry was modified, also update |last_modified_|.
  void UpdateStateOnUse(EntryModified modified_enum);

  // From disk_cache::Entry:
  void Doom() override;
  void Close() override;
  std::string GetKey() const override;
  base::Time GetLastUsed() const override;
  base::Time GetLastModified() const override;
  int32_t GetDataSize(int index) const override;
  int ReadData(int index,
               int offset,
               IOBuffer* buf,
               int buf_len,
               CompletionOnceCallback callback) override;
  int WriteData(int index,
                int offset,
                IOBuffer* buf,
                int buf_len,
                CompletionOnceCallback callback,
                bool truncate) override;
  int ReadSparseData(int64_t offset,
                     IOBuffer* buf,
                     int buf_len,
                     CompletionOnceCallback callback) override;
  int WriteSparseData(int64_t offset,
                      IOBuffer* buf,
                      int buf_len,
                      CompletionOnceCallback callback) override;
  RangeResult GetAvailableRange(int64_t offset,
                                int len,
                                RangeResultCallback callback) override;
  bool CouldBeSparse() const override;
  void CancelSparseIO() override {}
  net::Error ReadyForSparseIO(CompletionOnceCallback callback) override;
  void SetLastUsedTimeForTest(base::Time time) override;

 private:
  MemEntryImpl(base::WeakPtr<MemBackendImpl> backend,
               const std::string& key,
               int64_t child_id,
               MemEntryImpl* parent,
               net::NetLog* net_log);

  using EntryMap = std::map<int64_t, MemEntryImpl*>;

  static const int kNumStreams = 3;

  ~MemEntryImpl() override;

  // Do all the work for corresponding public functions.  Implemented as
  // separate functions to make logging of results simpler.
  int InternalReadData(int index, int offset, IOBuffer* buf, int buf_len);
  int InternalWriteData(int index, int offset, IOBuffer* buf, int buf_len,
                        bool truncate);
  int InternalReadSparseData(int64_t offset, IOBuffer* buf, int buf_len);
  int InternalWriteSparseData(int64_t offset, IOBuffer* buf, int buf_len);
  RangeResult InternalGetAvailableRange(int64_t offset, int len);

  // Initializes the children map and sparse info. This method is only called
  // on a parent entry.
  bool InitSparseInfo();

  // Returns an entry responsible for |offset|. The returned entry can be a
  // child entry or this entry itself if |offset| points to the first range.
  // If such entry does not exist and |create| is true, a new child entry is
  // created.
  MemEntryImpl* GetChild(int64_t offset, bool create);

  // Returns an interval describing what's stored in the child entry pointed to
  // by i, in global coordinates.
  // Precondition: i != children_.end();
  net::Interval<int64_t> ChildInterval(
      MemEntryImpl::EntryMap::const_iterator i);

  // Compact vectors to try to avoid over-allocation due to exponential growth.
  void Compact();

  std::string key_;
  std::vector<char> data_[kNumStreams];  // User data.
  uint32_t ref_count_ = 0;

  int64_t child_id_;     // The ID of a child entry.
  int child_first_pos_ = 0;  // The position of the first byte in a child
                             // entry. 0 here is beginning of child, not of
                             // the entire file.
  // Pointer to the parent entry, or nullptr if this entry is a parent entry.
  raw_ptr<MemEntryImpl> parent_;
  std::unique_ptr<EntryMap> children_;

  base::Time last_modified_;
  base::Time last_used_;
  base::WeakPtr<MemBackendImpl> backend_;  // Back pointer to the cache.
  bool doomed_ = false;  // True if this entry was removed from the cache.

  net::NetLogWithSource net_log_;
};

}  // namespace disk_cache

#endif  // NET_DISK_CACHE_MEMORY_MEM_ENTRY_IMPL_H_