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

Side by Side Diff: net/disk_cache/sparse_control.cc

Issue 146005: Disk Cache: Implement GetAvailableRange for the regular disk cache.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/sparse_control.h" 5 #include "net/disk_cache/sparse_control.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "net/base/io_buffer.h" 10 #include "net/base/io_buffer.h"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 if (offset < 0 || buf_len < 0) 64 if (offset < 0 || buf_len < 0)
65 return net::ERR_INVALID_ARGUMENT; 65 return net::ERR_INVALID_ARGUMENT;
66 66
67 // We only support up to 64 GB. 67 // We only support up to 64 GB.
68 if (offset + buf_len >= 0x1000000000LL) 68 if (offset + buf_len >= 0x1000000000LL)
69 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 69 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
70 70
71 DCHECK(!user_buf_); 71 DCHECK(!user_buf_);
72 DCHECK(!user_callback_); 72 DCHECK(!user_callback_);
73 73
74 if (!buf && (op == kReadOperation || op == kWriteOperation))
75 return 0;
76
74 // Copy the operation parameters. 77 // Copy the operation parameters.
75 operation_ = op; 78 operation_ = op;
76 offset_ = offset; 79 offset_ = offset;
77 user_buf_ = new net::ReusedIOBuffer(buf, buf_len); 80 user_buf_ = buf ? new net::ReusedIOBuffer(buf, buf_len) : NULL;
78 buf_len_ = buf_len; 81 buf_len_ = buf_len;
82 user_callback_ = callback;
79 83
80 result_ = 0; 84 result_ = 0;
81 pending_ = false; 85 pending_ = false;
82 finished_ = false; 86 finished_ = false;
83 user_callback_ = callback;
84 87
85 DoChildrenIO(); 88 DoChildrenIO();
86 89
87 if (!pending_) { 90 if (!pending_) {
88 // Everything was done synchronously. 91 // Everything was done synchronously.
89 operation_ = kNoOperation; 92 operation_ = kNoOperation;
90 user_buf_ = NULL; 93 user_buf_ = NULL;
91 user_callback_ = NULL; 94 user_callback_ = NULL;
92 return result_; 95 return result_;
93 } 96 }
94 97
95 return net::ERR_IO_PENDING; 98 return net::ERR_IO_PENDING;
96 } 99 }
97 100
98 int SparseControl::GetAvailableRange(int64 offset, int len, int64* start) { 101 int SparseControl::GetAvailableRange(int64 offset, int len, int64* start) {
99 DCHECK(init_); 102 DCHECK(init_);
100 NOTIMPLEMENTED(); 103 // We don't support simultaneous IO for sparse data.
101 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 104 if (operation_ != kNoOperation)
105 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
106
107 DCHECK(start);
108
109 range_found_ = false;
110 int result = StartIO(kGetRangeOperation, offset, NULL, len, NULL);
111 if (range_found_) {
112 *start = offset_;
113 return result;
114 }
115
116 *start = offset;
117 return result < 0 ? result : 0; // Don't mask error codes to the caller.
102 } 118 }
103 119
104 // We are going to start using this entry to store sparse data, so we have to 120 // We are going to start using this entry to store sparse data, so we have to
105 // initialize our control info. 121 // initialize our control info.
106 int SparseControl::CreateSparseEntry() { 122 int SparseControl::CreateSparseEntry() {
107 // TODO(rvargas): Set/check a flag in EntryStore. 123 // TODO(rvargas): Set/check a flag in EntryStore.
108 124
109 memset(&sparse_header_, 0, sizeof(sparse_header_)); 125 memset(&sparse_header_, 0, sizeof(sparse_header_));
110 sparse_header_.signature = Time::Now().ToInternalValue(); 126 sparse_header_.signature = Time::Now().ToInternalValue();
111 sparse_header_.magic = kIndexMagic; 127 sparse_header_.magic = kIndexMagic;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 std::string key = GenerateChildKey(); 190 std::string key = GenerateChildKey();
175 if (child_) { 191 if (child_) {
176 // Keep using the same child or open another one?. 192 // Keep using the same child or open another one?.
177 if (key == child_->GetKey()) 193 if (key == child_->GetKey())
178 return true; 194 return true;
179 CloseChild(); 195 CloseChild();
180 } 196 }
181 197
182 // Se if we are tracking this child. 198 // Se if we are tracking this child.
183 bool child_present = ChildPresent(); 199 bool child_present = ChildPresent();
184 if (kReadOperation == operation_ && !child_present) 200 if (!child_present) {
185 return false; 201 if (kReadOperation == operation_)
202 return false;
203 if (kGetRangeOperation == operation_)
204 return true;
205 }
186 206
187 if (!child_present || !entry_->backend_->OpenEntry(key, &child_)) { 207 if (!child_present || !entry_->backend_->OpenEntry(key, &child_)) {
188 if (!entry_->backend_->CreateEntry(key, &child_)) { 208 if (!entry_->backend_->CreateEntry(key, &child_)) {
189 child_ = NULL; 209 child_ = NULL;
190 result_ = net::ERR_CACHE_READ_FAILURE; 210 result_ = net::ERR_CACHE_READ_FAILURE;
191 return false; 211 return false;
192 } 212 }
193 // Write signature. 213 // Write signature.
194 InitChildData(); 214 InitChildData();
195 return true; 215 return true;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 DLOG(ERROR) << "Unable to save sparse map"; 286 DLOG(ERROR) << "Unable to save sparse map";
267 } 287 }
268 } 288 }
269 289
270 bool SparseControl::VerifyRange() { 290 bool SparseControl::VerifyRange() {
271 DCHECK_GE(result_, 0); 291 DCHECK_GE(result_, 0);
272 292
273 child_offset_ = static_cast<int>(offset_) & 0xfffff; 293 child_offset_ = static_cast<int>(offset_) & 0xfffff;
274 child_len_ = std::min(buf_len_, 0x100000 - child_offset_); 294 child_len_ = std::min(buf_len_, 0x100000 - child_offset_);
275 295
276 // We can write to anywhere in this child. 296 // We can write to (or get info from) anywhere in this child.
277 if (operation_ != kReadOperation) 297 if (operation_ != kReadOperation)
278 return true; 298 return true;
279 299
280 // Check that there are no holes in this range. 300 // Check that there are no holes in this range.
281 int last_bit = (child_offset_ + child_len_ + 1023) >> 10; 301 int last_bit = (child_offset_ + child_len_ + 1023) >> 10;
282 int start = child_offset_ >> 10; 302 int start = child_offset_ >> 10;
283 if (child_map_.FindNextBit(&start, last_bit, false)) { 303 if (child_map_.FindNextBit(&start, last_bit, false)) {
284 // Something is not here. 304 // Something is not here.
285 if (start == child_offset_ >> 10) 305 if (start == child_offset_ >> 10)
286 return false; 306 return false;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 return false; 354 return false;
335 355
336 if (!VerifyRange()) 356 if (!VerifyRange())
337 return false; 357 return false;
338 358
339 // We have more work to do. Let's not trigger a callback to the caller. 359 // We have more work to do. Let's not trigger a callback to the caller.
340 finished_ = false; 360 finished_ = false;
341 net::CompletionCallback* callback = user_callback_ ? &child_callback_ : NULL; 361 net::CompletionCallback* callback = user_callback_ ? &child_callback_ : NULL;
342 362
343 int rv; 363 int rv;
344 if (kReadOperation == operation_) { 364 switch (operation_) {
345 rv = child_->ReadData(kSparseData, child_offset_, user_buf_, child_len_, 365 case kReadOperation:
346 callback); 366 rv = child_->ReadData(kSparseData, child_offset_, user_buf_, child_len_,
347 } else { 367 callback);
348 DCHECK(kWriteOperation == operation_); 368 break;
349 rv = child_->WriteData(kSparseData, child_offset_, user_buf_, child_len_, 369 case kWriteOperation:
350 callback, false); 370 rv = child_->WriteData(kSparseData, child_offset_, user_buf_, child_len_,
371 callback, false);
372 break;
373 case kGetRangeOperation:
374 rv = DoGetAvailableRange();
375 break;
376 default:
377 NOTREACHED();
351 } 378 }
352 379
353 if (rv == net::ERR_IO_PENDING) { 380 if (rv == net::ERR_IO_PENDING) {
354 if (!pending_) { 381 if (!pending_) {
355 pending_ = true; 382 pending_ = true;
356 // The child will protect himself against closing the entry while IO is in 383 // The child will protect himself against closing the entry while IO is in
357 // progress. However, this entry can still be closed, and that would not 384 // progress. However, this entry can still be closed, and that would not
358 // be a good thing for us, so we increase the refcount until we're 385 // be a good thing for us, so we increase the refcount until we're
359 // finished doing sparse stuff. 386 // finished doing sparse stuff.
360 entry_->AddRef(); 387 entry_->AddRef();
361 } 388 }
362 return false; 389 return false;
363 } 390 }
364 391
365 DoChildIOCompleted(rv); 392 DoChildIOCompleted(rv);
366 return true; 393 return true;
367 } 394 }
368 395
396 int SparseControl::DoGetAvailableRange() {
397 if (!child_)
398 return child_len_; // Move on to the next child.
399
400 // Check that there are no holes in this range.
401 int last_bit = (child_offset_ + child_len_ + 1023) >> 10;
402 int start = child_offset_ >> 10;
403 int bits_found = child_map_.FindBits(&start, last_bit, true);
404
405 if (!bits_found)
406 return child_len_;
407
408 // We are done. Just break the loop and reset result_ to our real result.
409 range_found_ = true;
410 int empty_start = (start << 10) - child_offset_;
411 result_ = std::min(bits_found << 10, child_len_ - empty_start);
412 if (empty_start)
413 offset_ += empty_start;
414
415 buf_len_ = 0;
416 return 0;
417 }
418
369 void SparseControl::DoChildIOCompleted(int result) { 419 void SparseControl::DoChildIOCompleted(int result) {
370 if (result < 0) { 420 if (result < 0) {
371 // We fail the whole operation if we encounter an error. 421 // We fail the whole operation if we encounter an error.
372 result_ = result; 422 result_ = result;
373 return; 423 return;
374 } 424 }
375 425
376 UpdateRange(result); 426 UpdateRange(result);
377 427
378 result_ += result; 428 result_ += result;
379 offset_ += result; 429 offset_ += result;
380 buf_len_ -= result; 430 buf_len_ -= result;
381 431
382 // We'll be reusing the user provided buffer for the next chunk. 432 // We'll be reusing the user provided buffer for the next chunk.
383 if (buf_len_) 433 if (buf_len_ && user_buf_)
384 user_buf_->SetOffset(result_); 434 user_buf_->SetOffset(result_);
385 } 435 }
386 436
387 void SparseControl::OnChildIOCompleted(int result) { 437 void SparseControl::OnChildIOCompleted(int result) {
388 DCHECK_NE(net::ERR_IO_PENDING, result); 438 DCHECK_NE(net::ERR_IO_PENDING, result);
389 DoChildIOCompleted(result); 439 DoChildIOCompleted(result);
390 440
391 // We are running a callback from the message loop. It's time to restart what 441 // We are running a callback from the message loop. It's time to restart what
392 // we were doing before. 442 // we were doing before.
393 DoChildrenIO(); 443 DoChildrenIO();
394 } 444 }
395 445
396 void SparseControl::DoUserCallback() { 446 void SparseControl::DoUserCallback() {
397 DCHECK(user_callback_); 447 DCHECK(user_callback_);
398 net::CompletionCallback* c = user_callback_; 448 net::CompletionCallback* c = user_callback_;
399 user_callback_ = NULL; 449 user_callback_ = NULL;
400 user_buf_ = NULL; 450 user_buf_ = NULL;
401 pending_ = false; 451 pending_ = false;
402 operation_ = kNoOperation; 452 operation_ = kNoOperation;
403 entry_->Release(); // Don't touch object after this line. 453 entry_->Release(); // Don't touch object after this line.
404 c->Run(result_); 454 c->Run(result_);
405 } 455 }
406 456
407 } // namespace disk_cache 457 } // namespace disk_cache
OLDNEW
« net/disk_cache/entry_unittest.cc ('K') | « net/disk_cache/sparse_control.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698