Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(840)

Side by Side Diff: net/disk_cache/memory/mem_entry_impl.cc

Issue 1715833002: Reland: Refactor and shorten in-memory cache. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix typo in comment Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/disk_cache/memory/mem_entry_impl.h ('k') | net/disk_cache/memory/mem_rankings.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/disk_cache/memory/mem_entry_impl.h" 5 #include "net/disk_cache/memory/mem_entry_impl.h"
6 6
7 #include <algorithm>
7 #include <utility> 8 #include <utility>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
12 #include "base/values.h" 13 #include "base/values.h"
13 #include "net/base/io_buffer.h" 14 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
15 #include "net/disk_cache/memory/mem_backend_impl.h" 16 #include "net/disk_cache/memory/mem_backend_impl.h"
16 #include "net/disk_cache/net_log_parameters.h" 17 #include "net/disk_cache/net_log_parameters.h"
17 18
18 using base::Time; 19 using base::Time;
19 20
21 namespace disk_cache {
22
20 namespace { 23 namespace {
21 24
22 const int kSparseData = 1; 25 const int kSparseData = 1;
23 26
24 // Maximum size of a sparse entry is 2 to the power of this number. 27 // Maximum size of a sparse entry is 2 to the power of this number.
25 const int kMaxSparseEntryBits = 12; 28 const int kMaxSparseEntryBits = 12;
26 29
27 // Sparse entry has maximum size of 4KB. 30 // Sparse entry has maximum size of 4KB.
28 const int kMaxSparseEntrySize = 1 << kMaxSparseEntryBits; 31 const int kMaxSparseEntrySize = 1 << kMaxSparseEntryBits;
29 32
30 // Convert global offset to child index. 33 // Convert global offset to child index.
31 inline int ToChildIndex(int64_t offset) { 34 int ToChildIndex(int64_t offset) {
32 return static_cast<int>(offset >> kMaxSparseEntryBits); 35 return static_cast<int>(offset >> kMaxSparseEntryBits);
33 } 36 }
34 37
35 // Convert global offset to offset in child entry. 38 // Convert global offset to offset in child entry.
36 inline int ToChildOffset(int64_t offset) { 39 int ToChildOffset(int64_t offset) {
37 return static_cast<int>(offset & (kMaxSparseEntrySize - 1)); 40 return static_cast<int>(offset & (kMaxSparseEntrySize - 1));
38 } 41 }
39 42
40 // Returns a name for a child entry given the base_name of the parent and the 43 // Returns a name for a child entry given the base_name of the parent and the
41 // child_id. This name is only used for logging purposes. 44 // child_id. This name is only used for logging purposes.
42 // If the entry is called entry_name, child entries will be named something 45 // If the entry is called entry_name, child entries will be named something
43 // like Range_entry_name:YYY where YYY is the number of the particular child. 46 // like Range_entry_name:YYY where YYY is the number of the particular child.
44 std::string GenerateChildName(const std::string& base_name, int child_id) { 47 std::string GenerateChildName(const std::string& base_name, int child_id) {
45 return base::StringPrintf("Range_%s:%i", base_name.c_str(), child_id); 48 return base::StringPrintf("Range_%s:%i", base_name.c_str(), child_id);
46 } 49 }
47 50
48 // Returns NetLog parameters for the creation of a child MemEntryImpl. Separate 51 // Returns NetLog parameters for the creation of a MemEntryImpl. A separate
49 // function needed because child entries don't suppport GetKey(). 52 // function is needed because child entries don't store their key().
50 scoped_ptr<base::Value> NetLogChildEntryCreationCallback( 53 scoped_ptr<base::Value> NetLogEntryCreationCallback(
51 const disk_cache::MemEntryImpl* parent, 54 const MemEntryImpl* entry,
52 int child_id,
53 net::NetLogCaptureMode /* capture_mode */) { 55 net::NetLogCaptureMode /* capture_mode */) {
54 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 56 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
55 dict->SetString("key", GenerateChildName(parent->GetKey(), child_id)); 57 std::string key;
58 switch (entry->type()) {
59 case MemEntryImpl::PARENT_ENTRY:
60 key = entry->key();
61 break;
62 case MemEntryImpl::CHILD_ENTRY:
63 key = GenerateChildName(entry->parent()->key(), entry->child_id());
64 break;
65 }
66 dict->SetString("key", key);
56 dict->SetBoolean("created", true); 67 dict->SetBoolean("created", true);
57 return std::move(dict); 68 return std::move(dict);
58 } 69 }
59 70
60 } // namespace 71 } // namespace
61 72
62 namespace disk_cache { 73 MemEntryImpl::MemEntryImpl(MemBackendImpl* backend,
63 74 const std::string& key,
64 MemEntryImpl::MemEntryImpl(MemBackendImpl* backend) { 75 net::NetLog* net_log)
65 doomed_ = false; 76 : MemEntryImpl(backend,
66 backend_ = backend; 77 key,
67 ref_count_ = 0; 78 0, // child_id
68 parent_ = NULL; 79 nullptr, // parent
69 child_id_ = 0; 80 net_log) {
70 child_first_pos_ = 0; 81 Open();
71 next_ = NULL; 82 backend_->ModifyStorageSize(GetStorageSize());
72 prev_ = NULL;
73 for (int i = 0; i < NUM_STREAMS; i++)
74 data_size_[i] = 0;
75 } 83 }
76 84
77 // ------------------------------------------------------------------------ 85 MemEntryImpl::MemEntryImpl(MemBackendImpl* backend,
78 86 int child_id,
79 bool MemEntryImpl::CreateEntry(const std::string& key, net::NetLog* net_log) { 87 MemEntryImpl* parent,
80 key_ = key; 88 net::NetLog* net_log)
81 Time current = Time::Now(); 89 : MemEntryImpl(backend,
82 last_modified_ = current; 90 std::string(), // key
83 last_used_ = current; 91 child_id,
84 92 parent,
85 net_log_ = net::BoundNetLog::Make(net_log, 93 net_log) {
86 net::NetLog::SOURCE_MEMORY_CACHE_ENTRY); 94 (*parent_->children_)[child_id] = this;
87 // Must be called after |key_| is set, so GetKey() works.
88 net_log_.BeginEvent(
89 net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
90 CreateNetLogEntryCreationCallback(this, true));
91
92 Open();
93 backend_->ModifyStorageSize(0, static_cast<int32_t>(key.size()));
94 return true;
95 }
96
97 void MemEntryImpl::InternalDoom() {
98 net_log_.AddEvent(net::NetLog::TYPE_ENTRY_DOOM);
99 doomed_ = true;
100 if (!ref_count_) {
101 if (type() == kParentEntry) {
102 // If this is a parent entry, we need to doom all the child entries.
103 if (children_.get()) {
104 EntryMap children;
105 children.swap(*children_);
106 for (EntryMap::iterator i = children.begin();
107 i != children.end(); ++i) {
108 // Since a pointer to this object is also saved in the map, avoid
109 // dooming it.
110 if (i->second != this)
111 i->second->Doom();
112 }
113 DCHECK(children_->empty());
114 }
115 } else {
116 // If this is a child entry, detach it from the parent.
117 parent_->DetachChild(child_id_);
118 }
119 delete this;
120 }
121 } 95 }
122 96
123 void MemEntryImpl::Open() { 97 void MemEntryImpl::Open() {
124 // Only a parent entry can be opened. 98 // Only a parent entry can be opened.
125 // TODO(hclam): make sure it's correct to not apply the concept of ref 99 DCHECK_EQ(PARENT_ENTRY, type());
126 // counting to child entry. 100 ++ref_count_;
127 DCHECK(type() == kParentEntry); 101 DCHECK_GE(ref_count_, 1);
128 ref_count_++;
129 DCHECK_GE(ref_count_, 0);
130 DCHECK(!doomed_); 102 DCHECK(!doomed_);
131 } 103 }
132 104
133 bool MemEntryImpl::InUse() { 105 bool MemEntryImpl::InUse() const {
134 if (type() == kParentEntry) { 106 if (type() == PARENT_ENTRY) {
135 return ref_count_ > 0; 107 return ref_count_ > 0;
136 } else { 108 } else {
137 // A child entry is always not in use. The consequence is that a child entry 109 // TODO(gavinp): Can't this just be a DCHECK? How would ref_count_ not be
138 // can always be evicted while the associated parent entry is currently in 110 // zero?
139 // used (i.e. opened). 111
112 // A child entry is never in use. Thus one can always be evicted, even while
113 // its parent entry is open and in use.
140 return false; 114 return false;
141 } 115 }
142 } 116 }
143 117
144 // ------------------------------------------------------------------------ 118 int MemEntryImpl::GetStorageSize() const {
119 int storage_size = static_cast<int32_t>(key_.size());
120 for (const auto& i : data_)
121 storage_size += i.size();
122 return storage_size;
123 }
124
125 void MemEntryImpl::UpdateStateOnUse(EntryModified modified_enum) {
126 if (!doomed_)
127 backend_->OnEntryUpdated(this);
128
129 last_used_ = Time::Now();
130 if (modified_enum == ENTRY_WAS_MODIFIED)
131 last_modified_ = last_used_;
132 }
145 133
146 void MemEntryImpl::Doom() { 134 void MemEntryImpl::Doom() {
147 if (doomed_) 135 if (!doomed_) {
148 return; 136 doomed_ = true;
149 if (type() == kParentEntry) { 137 backend_->OnEntryDoomed(this);
150 // Perform internal doom from the backend if this is a parent entry. 138 net_log_.AddEvent(net::NetLog::TYPE_ENTRY_DOOM);
151 backend_->InternalDoomEntry(this);
152 } else {
153 // Manually detach from the backend and perform internal doom.
154 backend_->RemoveFromRankingList(this);
155 InternalDoom();
156 } 139 }
140 if (!ref_count_)
141 delete this;
157 } 142 }
158 143
159 void MemEntryImpl::Close() { 144 void MemEntryImpl::Close() {
160 // Only a parent entry can be closed. 145 DCHECK_EQ(PARENT_ENTRY, type());
161 DCHECK(type() == kParentEntry); 146 --ref_count_;
162 ref_count_--;
163 DCHECK_GE(ref_count_, 0); 147 DCHECK_GE(ref_count_, 0);
164 if (!ref_count_ && doomed_) 148 if (!ref_count_ && doomed_)
165 InternalDoom(); 149 delete this;
166 } 150 }
167 151
168 std::string MemEntryImpl::GetKey() const { 152 std::string MemEntryImpl::GetKey() const {
169 // A child entry doesn't have key so this method should not be called. 153 // A child entry doesn't have key so this method should not be called.
170 DCHECK(type() == kParentEntry); 154 DCHECK_EQ(PARENT_ENTRY, type());
171 return key_; 155 return key_;
172 } 156 }
173 157
174 Time MemEntryImpl::GetLastUsed() const { 158 Time MemEntryImpl::GetLastUsed() const {
175 return last_used_; 159 return last_used_;
176 } 160 }
177 161
178 Time MemEntryImpl::GetLastModified() const { 162 Time MemEntryImpl::GetLastModified() const {
179 return last_modified_; 163 return last_modified_;
180 } 164 }
181 165
182 int32_t MemEntryImpl::GetDataSize(int index) const { 166 int32_t MemEntryImpl::GetDataSize(int index) const {
183 if (index < 0 || index >= NUM_STREAMS) 167 if (index < 0 || index >= kNumStreams)
184 return 0; 168 return 0;
185 return data_size_[index]; 169 return data_[index].size();
186 } 170 }
187 171
188 int MemEntryImpl::ReadData(int index, int offset, IOBuffer* buf, int buf_len, 172 int MemEntryImpl::ReadData(int index, int offset, IOBuffer* buf, int buf_len,
189 const CompletionCallback& callback) { 173 const CompletionCallback& callback) {
190 if (net_log_.IsCapturing()) { 174 if (net_log_.IsCapturing()) {
191 net_log_.BeginEvent( 175 net_log_.BeginEvent(
192 net::NetLog::TYPE_ENTRY_READ_DATA, 176 net::NetLog::TYPE_ENTRY_READ_DATA,
193 CreateNetLogReadWriteDataCallback(index, offset, buf_len, false)); 177 CreateNetLogReadWriteDataCallback(index, offset, buf_len, false));
194 } 178 }
195 179
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 237
254 int MemEntryImpl::GetAvailableRange(int64_t offset, 238 int MemEntryImpl::GetAvailableRange(int64_t offset,
255 int len, 239 int len,
256 int64_t* start, 240 int64_t* start,
257 const CompletionCallback& callback) { 241 const CompletionCallback& callback) {
258 if (net_log_.IsCapturing()) { 242 if (net_log_.IsCapturing()) {
259 net_log_.BeginEvent( 243 net_log_.BeginEvent(
260 net::NetLog::TYPE_SPARSE_GET_RANGE, 244 net::NetLog::TYPE_SPARSE_GET_RANGE,
261 CreateNetLogSparseOperationCallback(offset, len)); 245 CreateNetLogSparseOperationCallback(offset, len));
262 } 246 }
263 int result = GetAvailableRange(offset, len, start); 247 int result = InternalGetAvailableRange(offset, len, start);
264 if (net_log_.IsCapturing()) { 248 if (net_log_.IsCapturing()) {
265 net_log_.EndEvent( 249 net_log_.EndEvent(
266 net::NetLog::TYPE_SPARSE_GET_RANGE, 250 net::NetLog::TYPE_SPARSE_GET_RANGE,
267 CreateNetLogGetAvailableRangeResultCallback(*start, result)); 251 CreateNetLogGetAvailableRangeResultCallback(*start, result));
268 } 252 }
269 return result; 253 return result;
270 } 254 }
271 255
272 bool MemEntryImpl::CouldBeSparse() const { 256 bool MemEntryImpl::CouldBeSparse() const {
273 DCHECK_EQ(kParentEntry, type()); 257 DCHECK_EQ(PARENT_ENTRY, type());
274 return (children_.get() != NULL); 258 return (children_.get() != nullptr);
275 } 259 }
276 260
277 int MemEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { 261 int MemEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
278 return net::OK; 262 return net::OK;
279 } 263 }
280 264
281 // ------------------------------------------------------------------------ 265 // ------------------------------------------------------------------------
282 266
267 MemEntryImpl::MemEntryImpl(MemBackendImpl* backend,
268 const ::std::string& key,
269 int child_id,
270 MemEntryImpl* parent,
271 net::NetLog* net_log)
272 : key_(key),
273 ref_count_(0),
274 child_id_(child_id),
275 child_first_pos_(0),
276 parent_(parent),
277 last_modified_(Time::Now()),
278 last_used_(last_modified_),
279 backend_(backend),
280 doomed_(false) {
281 backend_->OnEntryInserted(this);
282 net_log_ =
283 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
284 net_log_.BeginEvent(net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
285 base::Bind(&NetLogEntryCreationCallback, this));
286 }
287
283 MemEntryImpl::~MemEntryImpl() { 288 MemEntryImpl::~MemEntryImpl() {
284 for (int i = 0; i < NUM_STREAMS; i++) 289 backend_->ModifyStorageSize(-GetStorageSize());
285 backend_->ModifyStorageSize(data_size_[i], 0); 290
286 backend_->ModifyStorageSize(static_cast<int32_t>(key_.size()), 0); 291 if (type() == PARENT_ENTRY) {
292 if (children_) {
293 EntryMap children;
294 children_->swap(children);
295
296 for (auto& it : children) {
297 // Since |this| is stored in the map, it should be guarded against
298 // double dooming, which will result in double destruction.
299 if (it.second != this)
300 it.second->Doom();
mmenke 2016/02/19 19:08:32 So the problem was the child calling backend_->Mod
gavinp 2016/02/19 19:18:01 No child should report a zero size. Nor is that ve
mmenke 2016/02/19 19:20:43 Oh! For some reason I read it (twice) as "== 0",
301 }
302 }
303 } else {
304 parent_->children_->erase(child_id_);
305 }
287 net_log_.EndEvent(net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL); 306 net_log_.EndEvent(net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL);
288 } 307 }
289 308
290 int MemEntryImpl::InternalReadData(int index, int offset, IOBuffer* buf, 309 int MemEntryImpl::InternalReadData(int index, int offset, IOBuffer* buf,
291 int buf_len) { 310 int buf_len) {
292 DCHECK(type() == kParentEntry || index == kSparseData); 311 DCHECK(type() == PARENT_ENTRY || index == kSparseData);
293 312
294 if (index < 0 || index >= NUM_STREAMS) 313 if (index < 0 || index >= kNumStreams || buf_len < 0)
295 return net::ERR_INVALID_ARGUMENT; 314 return net::ERR_INVALID_ARGUMENT;
296 315
297 int entry_size = GetDataSize(index); 316 int entry_size = data_[index].size();
298 if (offset >= entry_size || offset < 0 || !buf_len) 317 if (offset >= entry_size || offset < 0 || !buf_len)
299 return 0; 318 return 0;
300 319
301 if (buf_len < 0)
302 return net::ERR_INVALID_ARGUMENT;
303
304 if (offset + buf_len > entry_size) 320 if (offset + buf_len > entry_size)
305 buf_len = entry_size - offset; 321 buf_len = entry_size - offset;
306 322
307 UpdateRank(false); 323 UpdateStateOnUse(ENTRY_WAS_NOT_MODIFIED);
308 324 std::copy(data_[index].begin() + offset,
309 memcpy(buf->data(), &(data_[index])[offset], buf_len); 325 data_[index].begin() + offset + buf_len, buf->data());
310 return buf_len; 326 return buf_len;
311 } 327 }
312 328
313 int MemEntryImpl::InternalWriteData(int index, int offset, IOBuffer* buf, 329 int MemEntryImpl::InternalWriteData(int index, int offset, IOBuffer* buf,
314 int buf_len, bool truncate) { 330 int buf_len, bool truncate) {
315 DCHECK(type() == kParentEntry || index == kSparseData); 331 DCHECK(type() == PARENT_ENTRY || index == kSparseData);
316 332
317 if (index < 0 || index >= NUM_STREAMS) 333 if (index < 0 || index >= kNumStreams)
318 return net::ERR_INVALID_ARGUMENT; 334 return net::ERR_INVALID_ARGUMENT;
319 335
320 if (offset < 0 || buf_len < 0) 336 if (offset < 0 || buf_len < 0)
321 return net::ERR_INVALID_ARGUMENT; 337 return net::ERR_INVALID_ARGUMENT;
322 338
323 int max_file_size = backend_->MaxFileSize(); 339 int max_file_size = backend_->MaxFileSize();
324 340
325 // offset of buf_len could be negative numbers. 341 // offset of buf_len could be negative numbers.
326 if (offset > max_file_size || buf_len > max_file_size || 342 if (offset > max_file_size || buf_len > max_file_size ||
327 offset + buf_len > max_file_size) { 343 offset + buf_len > max_file_size) {
328 return net::ERR_FAILED; 344 return net::ERR_FAILED;
329 } 345 }
330 346
331 // Read the size at this point. 347 int old_data_size = data_[index].size();
332 int entry_size = GetDataSize(index); 348 if (truncate || old_data_size < offset + buf_len) {
349 data_[index].resize(offset + buf_len);
333 350
334 PrepareTarget(index, offset, buf_len); 351 // Zero fill any hole.
352 if (old_data_size < offset) {
353 std::fill(data_[index].begin() + old_data_size,
354 data_[index].begin() + offset, 0);
355 }
335 356
336 if (entry_size < offset + buf_len) { 357 backend_->ModifyStorageSize(data_[index].size() - old_data_size);
mmenke 2016/02/19 19:36:53 Hrm...Wait...So if we're a child entry, we are not
337 backend_->ModifyStorageSize(entry_size, offset + buf_len);
338 data_size_[index] = offset + buf_len;
339 } else if (truncate) {
340 if (entry_size > offset + buf_len) {
341 backend_->ModifyStorageSize(entry_size, offset + buf_len);
342 data_size_[index] = offset + buf_len;
343 }
344 } 358 }
345 359
346 UpdateRank(true); 360 UpdateStateOnUse(ENTRY_WAS_MODIFIED);
347 361
348 if (!buf_len) 362 if (!buf_len)
349 return 0; 363 return 0;
350 364
351 memcpy(&(data_[index])[offset], buf->data(), buf_len); 365 std::copy(buf->data(), buf->data() + buf_len, data_[index].begin() + offset);
352 return buf_len; 366 return buf_len;
353 } 367 }
354 368
355 int MemEntryImpl::InternalReadSparseData(int64_t offset, 369 int MemEntryImpl::InternalReadSparseData(int64_t offset,
356 IOBuffer* buf, 370 IOBuffer* buf,
357 int buf_len) { 371 int buf_len) {
358 DCHECK(type() == kParentEntry); 372 DCHECK_EQ(PARENT_ENTRY, type());
359 373
360 if (!InitSparseInfo()) 374 if (!InitSparseInfo())
361 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 375 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
362 376
363 if (offset < 0 || buf_len < 0) 377 if (offset < 0 || buf_len < 0)
364 return net::ERR_INVALID_ARGUMENT; 378 return net::ERR_INVALID_ARGUMENT;
365 379
366 // We will keep using this buffer and adjust the offset in this buffer. 380 // We will keep using this buffer and adjust the offset in this buffer.
367 scoped_refptr<net::DrainableIOBuffer> io_buf( 381 scoped_refptr<net::DrainableIOBuffer> io_buf(
368 new net::DrainableIOBuffer(buf, buf_len)); 382 new net::DrainableIOBuffer(buf, buf_len));
369 383
370 // Iterate until we have read enough. 384 // Iterate until we have read enough.
371 while (io_buf->BytesRemaining()) { 385 while (io_buf->BytesRemaining()) {
372 MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), false); 386 MemEntryImpl* child = GetChild(offset + io_buf->BytesConsumed(), false);
373 387
374 // No child present for that offset. 388 // No child present for that offset.
375 if (!child) 389 if (!child)
376 break; 390 break;
377 391
378 // We then need to prepare the child offset and len. 392 // We then need to prepare the child offset and len.
379 int child_offset = ToChildOffset(offset + io_buf->BytesConsumed()); 393 int child_offset = ToChildOffset(offset + io_buf->BytesConsumed());
380 394
381 // If we are trying to read from a position that the child entry has no data 395 // If we are trying to read from a position that the child entry has no data
382 // we should stop. 396 // we should stop.
383 if (child_offset < child->child_first_pos_) 397 if (child_offset < child->child_first_pos_)
384 break; 398 break;
385 if (net_log_.IsCapturing()) { 399 if (net_log_.IsCapturing()) {
386 net_log_.BeginEvent( 400 net_log_.BeginEvent(
387 net::NetLog::TYPE_SPARSE_READ_CHILD_DATA, 401 net::NetLog::TYPE_SPARSE_READ_CHILD_DATA,
388 CreateNetLogSparseReadWriteCallback(child->net_log().source(), 402 CreateNetLogSparseReadWriteCallback(child->net_log_.source(),
389 io_buf->BytesRemaining())); 403 io_buf->BytesRemaining()));
390 } 404 }
391 int ret = child->ReadData(kSparseData, child_offset, io_buf.get(), 405 int ret = child->ReadData(kSparseData, child_offset, io_buf.get(),
392 io_buf->BytesRemaining(), CompletionCallback()); 406 io_buf->BytesRemaining(), CompletionCallback());
393 if (net_log_.IsCapturing()) { 407 if (net_log_.IsCapturing()) {
394 net_log_.EndEventWithNetErrorCode( 408 net_log_.EndEventWithNetErrorCode(
395 net::NetLog::TYPE_SPARSE_READ_CHILD_DATA, ret); 409 net::NetLog::TYPE_SPARSE_READ_CHILD_DATA, ret);
396 } 410 }
397 411
398 // If we encounter an error in one entry, return immediately. 412 // If we encounter an error in one entry, return immediately.
399 if (ret < 0) 413 if (ret < 0)
400 return ret; 414 return ret;
401 else if (ret == 0) 415 else if (ret == 0)
402 break; 416 break;
403 417
404 // Increment the counter by number of bytes read in the child entry. 418 // Increment the counter by number of bytes read in the child entry.
405 io_buf->DidConsume(ret); 419 io_buf->DidConsume(ret);
406 } 420 }
407 421
408 UpdateRank(false); 422 UpdateStateOnUse(ENTRY_WAS_NOT_MODIFIED);
409
410 return io_buf->BytesConsumed(); 423 return io_buf->BytesConsumed();
411 } 424 }
412 425
413 int MemEntryImpl::InternalWriteSparseData(int64_t offset, 426 int MemEntryImpl::InternalWriteSparseData(int64_t offset,
414 IOBuffer* buf, 427 IOBuffer* buf,
415 int buf_len) { 428 int buf_len) {
416 DCHECK(type() == kParentEntry); 429 DCHECK_EQ(PARENT_ENTRY, type());
417 430
418 if (!InitSparseInfo()) 431 if (!InitSparseInfo())
419 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 432 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
420 433
421 if (offset < 0 || buf_len < 0) 434 if (offset < 0 || buf_len < 0)
422 return net::ERR_INVALID_ARGUMENT; 435 return net::ERR_INVALID_ARGUMENT;
423 436
424 scoped_refptr<net::DrainableIOBuffer> io_buf( 437 scoped_refptr<net::DrainableIOBuffer> io_buf(
425 new net::DrainableIOBuffer(buf, buf_len)); 438 new net::DrainableIOBuffer(buf, buf_len));
426 439
427 // This loop walks through child entries continuously starting from |offset| 440 // This loop walks through child entries continuously starting from |offset|
428 // and writes blocks of data (of maximum size kMaxSparseEntrySize) into each 441 // and writes blocks of data (of maximum size kMaxSparseEntrySize) into each
429 // child entry until all |buf_len| bytes are written. The write operation can 442 // child entry until all |buf_len| bytes are written. The write operation can
430 // start in the middle of an entry. 443 // start in the middle of an entry.
431 while (io_buf->BytesRemaining()) { 444 while (io_buf->BytesRemaining()) {
432 MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), true); 445 MemEntryImpl* child = GetChild(offset + io_buf->BytesConsumed(), true);
433 int child_offset = ToChildOffset(offset + io_buf->BytesConsumed()); 446 int child_offset = ToChildOffset(offset + io_buf->BytesConsumed());
434 447
435 // Find the right amount to write, this evaluates the remaining bytes to 448 // Find the right amount to write, this evaluates the remaining bytes to
436 // write and remaining capacity of this child entry. 449 // write and remaining capacity of this child entry.
437 int write_len = std::min(static_cast<int>(io_buf->BytesRemaining()), 450 int write_len = std::min(static_cast<int>(io_buf->BytesRemaining()),
438 kMaxSparseEntrySize - child_offset); 451 kMaxSparseEntrySize - child_offset);
439 452
440 // Keep a record of the last byte position (exclusive) in the child. 453 // Keep a record of the last byte position (exclusive) in the child.
441 int data_size = child->GetDataSize(kSparseData); 454 int data_size = child->GetDataSize(kSparseData);
442 455
443 if (net_log_.IsCapturing()) { 456 if (net_log_.IsCapturing()) {
444 net_log_.BeginEvent( 457 net_log_.BeginEvent(net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA,
445 net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA, 458 CreateNetLogSparseReadWriteCallback(
446 CreateNetLogSparseReadWriteCallback(child->net_log().source(), 459 child->net_log_.source(), write_len));
447 write_len));
448 } 460 }
449 461
450 // Always writes to the child entry. This operation may overwrite data 462 // Always writes to the child entry. This operation may overwrite data
451 // previously written. 463 // previously written.
452 // TODO(hclam): if there is data in the entry and this write is not 464 // TODO(hclam): if there is data in the entry and this write is not
453 // continuous we may want to discard this write. 465 // continuous we may want to discard this write.
454 int ret = child->WriteData(kSparseData, child_offset, io_buf.get(), 466 int ret = child->WriteData(kSparseData, child_offset, io_buf.get(),
455 write_len, CompletionCallback(), true); 467 write_len, CompletionCallback(), true);
456 if (net_log_.IsCapturing()) { 468 if (net_log_.IsCapturing()) {
457 net_log_.EndEventWithNetErrorCode( 469 net_log_.EndEventWithNetErrorCode(
458 net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA, ret); 470 net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA, ret);
459 } 471 }
460 if (ret < 0) 472 if (ret < 0)
461 return ret; 473 return ret;
462 else if (ret == 0) 474 else if (ret == 0)
463 break; 475 break;
464 476
465 // Keep a record of the first byte position in the child if the write was 477 // Keep a record of the first byte position in the child if the write was
466 // not aligned nor continuous. This is to enable witting to the middle 478 // not aligned nor continuous. This is to enable witting to the middle
467 // of an entry and still keep track of data off the aligned edge. 479 // of an entry and still keep track of data off the aligned edge.
468 if (data_size != child_offset) 480 if (data_size != child_offset)
469 child->child_first_pos_ = child_offset; 481 child->child_first_pos_ = child_offset;
470 482
471 // Adjust the offset in the IO buffer. 483 // Adjust the offset in the IO buffer.
472 io_buf->DidConsume(ret); 484 io_buf->DidConsume(ret);
473 } 485 }
474 486
475 UpdateRank(true); 487 UpdateStateOnUse(ENTRY_WAS_MODIFIED);
476
477 return io_buf->BytesConsumed(); 488 return io_buf->BytesConsumed();
478 } 489 }
479 490
480 int MemEntryImpl::GetAvailableRange(int64_t offset, int len, int64_t* start) { 491 int MemEntryImpl::InternalGetAvailableRange(int64_t offset,
481 DCHECK(type() == kParentEntry); 492 int len,
493 int64_t* start) {
494 DCHECK_EQ(PARENT_ENTRY, type());
482 DCHECK(start); 495 DCHECK(start);
483 496
484 if (!InitSparseInfo()) 497 if (!InitSparseInfo())
485 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 498 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
486 499
487 if (offset < 0 || len < 0 || !start) 500 if (offset < 0 || len < 0 || !start)
488 return net::ERR_INVALID_ARGUMENT; 501 return net::ERR_INVALID_ARGUMENT;
489 502
490 MemEntryImpl* current_child = NULL; 503 MemEntryImpl* current_child = nullptr;
491 504
492 // Find the first child and record the number of empty bytes. 505 // Find the first child and record the number of empty bytes.
493 int empty = FindNextChild(offset, len, &current_child); 506 int empty = FindNextChild(offset, len, &current_child);
494 if (current_child && empty < len) { 507 if (current_child && empty < len) {
495 *start = offset + empty; 508 *start = offset + empty;
496 len -= empty; 509 len -= empty;
497 510
498 // Counts the number of continuous bytes. 511 // Counts the number of continuous bytes.
499 int continuous = 0; 512 int continuous = 0;
500 513
(...skipping 13 matching lines...) Expand all
514 // If the next child is discontinuous, break the loop. 527 // If the next child is discontinuous, break the loop.
515 if (FindNextChild(*start + continuous, len, &current_child)) 528 if (FindNextChild(*start + continuous, len, &current_child))
516 break; 529 break;
517 } 530 }
518 return continuous; 531 return continuous;
519 } 532 }
520 *start = offset; 533 *start = offset;
521 return 0; 534 return 0;
522 } 535 }
523 536
524 void MemEntryImpl::PrepareTarget(int index, int offset, int buf_len) { 537 bool MemEntryImpl::InitSparseInfo() {
525 int entry_size = GetDataSize(index); 538 DCHECK_EQ(PARENT_ENTRY, type());
526 539
527 if (entry_size >= offset + buf_len) 540 if (!children_) {
528 return; // Not growing the stored data.
529
530 if (static_cast<int>(data_[index].size()) < offset + buf_len)
531 data_[index].resize(offset + buf_len);
532
533 if (offset <= entry_size)
534 return; // There is no "hole" on the stored data.
535
536 // Cleanup the hole not written by the user. The point is to avoid returning
537 // random stuff later on.
538 memset(&(data_[index])[entry_size], 0, offset - entry_size);
539 }
540
541 void MemEntryImpl::UpdateRank(bool modified) {
542 Time current = Time::Now();
543 last_used_ = current;
544
545 if (modified)
546 last_modified_ = current;
547
548 if (!doomed_)
549 backend_->UpdateRank(this);
550 }
551
552 bool MemEntryImpl::InitSparseInfo() {
553 DCHECK(type() == kParentEntry);
554
555 if (!children_.get()) {
556 // If we already have some data in sparse stream but we are being 541 // If we already have some data in sparse stream but we are being
557 // initialized as a sparse entry, we should fail. 542 // initialized as a sparse entry, we should fail.
558 if (GetDataSize(kSparseData)) 543 if (GetDataSize(kSparseData))
559 return false; 544 return false;
560 children_.reset(new EntryMap()); 545 children_.reset(new EntryMap());
561 546
562 // The parent entry stores data for the first block, so save this object to 547 // The parent entry stores data for the first block, so save this object to
563 // index 0. 548 // index 0.
564 (*children_)[0] = this; 549 (*children_)[0] = this;
565 } 550 }
566 return true; 551 return true;
567 } 552 }
568 553
569 bool MemEntryImpl::InitChildEntry(MemEntryImpl* parent, int child_id, 554 MemEntryImpl* MemEntryImpl::GetChild(int64_t offset, bool create) {
570 net::NetLog* net_log) { 555 DCHECK_EQ(PARENT_ENTRY, type());
571 DCHECK(!parent_);
572 DCHECK(!child_id_);
573
574 net_log_ = net::BoundNetLog::Make(net_log,
575 net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
576 net_log_.BeginEvent(
577 net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
578 base::Bind(&NetLogChildEntryCreationCallback, parent, child_id_));
579
580 parent_ = parent;
581 child_id_ = child_id;
582 Time current = Time::Now();
583 last_modified_ = current;
584 last_used_ = current;
585 // Insert this to the backend's ranking list.
586 backend_->InsertIntoRankingList(this);
587 return true;
588 }
589
590 MemEntryImpl* MemEntryImpl::OpenChild(int64_t offset, bool create) {
591 DCHECK(type() == kParentEntry);
592 int index = ToChildIndex(offset); 556 int index = ToChildIndex(offset);
593 EntryMap::iterator i = children_->find(index); 557 EntryMap::iterator i = children_->find(index);
594 if (i != children_->end()) { 558 if (i != children_->end())
595 return i->second; 559 return i->second;
596 } else if (create) { 560 if (create)
597 MemEntryImpl* child = new MemEntryImpl(backend_); 561 return new MemEntryImpl(backend_, index, this, net_log_.net_log());
598 child->InitChildEntry(this, index, net_log_.net_log()); 562 return nullptr;
599 (*children_)[index] = child;
600 return child;
601 }
602 return NULL;
603 } 563 }
604 564
605 int MemEntryImpl::FindNextChild(int64_t offset, int len, MemEntryImpl** child) { 565 int MemEntryImpl::FindNextChild(int64_t offset, int len, MemEntryImpl** child) {
606 DCHECK(child); 566 DCHECK(child);
607 *child = NULL; 567 *child = nullptr;
608 int scanned_len = 0; 568 int scanned_len = 0;
609 569
610 // This loop tries to find the first existing child. 570 // This loop tries to find the first existing child.
611 while (scanned_len < len) { 571 while (scanned_len < len) {
612 // This points to the current offset in the child. 572 // This points to the current offset in the child.
613 int current_child_offset = ToChildOffset(offset + scanned_len); 573 int current_child_offset = ToChildOffset(offset + scanned_len);
614 MemEntryImpl* current_child = OpenChild(offset + scanned_len, false); 574 MemEntryImpl* current_child = GetChild(offset + scanned_len, false);
615 if (current_child) { 575 if (current_child) {
616 int child_first_pos = current_child->child_first_pos_; 576 int child_first_pos = current_child->child_first_pos_;
617 577
618 // This points to the first byte that we should be reading from, we need 578 // This points to the first byte that we should be reading from, we need
619 // to take care of the filled region and the current offset in the child. 579 // to take care of the filled region and the current offset in the child.
620 int first_pos = std::max(current_child_offset, child_first_pos); 580 int first_pos = std::max(current_child_offset, child_first_pos);
621 581
622 // If the first byte position we should read from doesn't exceed the 582 // If the first byte position we should read from doesn't exceed the
623 // filled region, we have found the first child. 583 // filled region, we have found the first child.
624 if (first_pos < current_child->GetDataSize(kSparseData)) { 584 if (first_pos < current_child->GetDataSize(kSparseData)) {
625 *child = current_child; 585 *child = current_child;
626 586
627 // We need to advance the scanned length. 587 // We need to advance the scanned length.
628 scanned_len += first_pos - current_child_offset; 588 scanned_len += first_pos - current_child_offset;
629 break; 589 break;
630 } 590 }
631 } 591 }
632 scanned_len += kMaxSparseEntrySize - current_child_offset; 592 scanned_len += kMaxSparseEntrySize - current_child_offset;
633 } 593 }
634 return scanned_len; 594 return scanned_len;
635 } 595 }
636 596
637 void MemEntryImpl::DetachChild(int child_id) {
638 children_->erase(child_id);
639 }
640
641 } // namespace disk_cache 597 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/memory/mem_entry_impl.h ('k') | net/disk_cache/memory/mem_rankings.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698