| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |