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
3 // found in the LICENSE file.
5 #include "net/disk_cache/in_flight_backend_io.h"
8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h"
10 #include "base/logging.h"
11 #include "net/base/net_errors.h"
12 #include "net/disk_cache/backend_impl.h"
13 #include "net/disk_cache/entry_impl.h"
14 #include "net/disk_cache/histogram_macros.h"
16 // Provide a BackendImpl object to macros from histogram_macros.h.
17 #define CACHE_UMA_BACKEND_IMPL_OBJ backend_
19 namespace disk_cache {
21 BackendIO::BackendIO(InFlightIO* controller, BackendImpl* backend,
22 const net::CompletionCallback& callback)
23 : BackgroundIO(controller),
37 start_time_ = base::TimeTicks::Now();
40 // Runs on the background thread.
41 void BackendIO::ExecuteOperation() {
42 if (IsEntryOperation())
43 return ExecuteEntryOperation();
45 ExecuteBackendOperation();
48 // Runs on the background thread.
49 void BackendIO::OnIOComplete(int result) {
50 DCHECK(IsEntryOperation());
51 DCHECK_NE(result, net::ERR_IO_PENDING);
56 // Runs on the primary thread.
57 void BackendIO::OnDone(bool cancel) {
58 if (IsEntryOperation()) {
59 CACHE_UMA(TIMES, "TotalIOTime", 0, ElapsedTime());
65 if (result() == net::OK) {
66 static_cast<EntryImpl*>(*entry_ptr_)->OnEntryCreated(backend_);
68 (*entry_ptr_)->Close();
72 bool BackendIO::IsEntryOperation() {
73 return operation_ > OP_MAX_BACKEND;
76 // Runs on the background thread.
77 void BackendIO::ReferenceEntry() {
81 void BackendIO::Init() {
85 void BackendIO::OpenEntry(const std::string& key, Entry** entry) {
91 void BackendIO::CreateEntry(const std::string& key, Entry** entry) {
92 operation_ = OP_CREATE;
97 void BackendIO::DoomEntry(const std::string& key) {
102 void BackendIO::DoomAllEntries() {
103 operation_ = OP_DOOM_ALL;
106 void BackendIO::DoomEntriesBetween(const base::Time initial_time,
107 const base::Time end_time) {
108 operation_ = OP_DOOM_BETWEEN;
109 initial_time_ = initial_time;
110 end_time_ = end_time;
113 void BackendIO::DoomEntriesSince(const base::Time initial_time) {
114 operation_ = OP_DOOM_SINCE;
115 initial_time_ = initial_time;
118 void BackendIO::OpenNextEntry(void** iter, Entry** next_entry) {
119 operation_ = OP_OPEN_NEXT;
121 entry_ptr_ = next_entry;
124 void BackendIO::OpenPrevEntry(void** iter, Entry** prev_entry) {
125 operation_ = OP_OPEN_PREV;
127 entry_ptr_ = prev_entry;
130 void BackendIO::EndEnumeration(void* iterator) {
131 operation_ = OP_END_ENUMERATION;
135 void BackendIO::OnExternalCacheHit(const std::string& key) {
136 operation_ = OP_ON_EXTERNAL_CACHE_HIT;
140 void BackendIO::CloseEntryImpl(EntryImpl* entry) {
141 operation_ = OP_CLOSE_ENTRY;
145 void BackendIO::DoomEntryImpl(EntryImpl* entry) {
146 operation_ = OP_DOOM_ENTRY;
150 void BackendIO::FlushQueue() {
151 operation_ = OP_FLUSH_QUEUE;
154 void BackendIO::RunTask(const base::Closure& task) {
155 operation_ = OP_RUN_TASK;
159 void BackendIO::ReadData(EntryImpl* entry, int index, int offset,
160 net::IOBuffer* buf, int buf_len) {
161 operation_ = OP_READ;
169 void BackendIO::WriteData(EntryImpl* entry, int index, int offset,
170 net::IOBuffer* buf, int buf_len, bool truncate) {
171 operation_ = OP_WRITE;
177 truncate_ = truncate;
180 void BackendIO::ReadSparseData(EntryImpl* entry, int64 offset,
181 net::IOBuffer* buf, int buf_len) {
182 operation_ = OP_READ_SPARSE;
189 void BackendIO::WriteSparseData(EntryImpl* entry, int64 offset,
190 net::IOBuffer* buf, int buf_len) {
191 operation_ = OP_WRITE_SPARSE;
198 void BackendIO::GetAvailableRange(EntryImpl* entry, int64 offset, int len,
200 operation_ = OP_GET_RANGE;
207 void BackendIO::CancelSparseIO(EntryImpl* entry) {
208 operation_ = OP_CANCEL_IO;
212 void BackendIO::ReadyForSparseIO(EntryImpl* entry) {
213 operation_ = OP_IS_READY;
217 BackendIO::~BackendIO() {}
219 bool BackendIO::ReturnsEntry() {
220 return (operation_ == OP_OPEN || operation_ == OP_CREATE ||
221 operation_ == OP_OPEN_NEXT || operation_ == OP_OPEN_PREV);
224 base::TimeDelta BackendIO::ElapsedTime() const {
225 return base::TimeTicks::Now() - start_time_;
228 // Runs on the background thread.
229 void BackendIO::ExecuteBackendOperation() {
230 switch (operation_) {
232 result_ = backend_->SyncInit();
235 result_ = backend_->SyncOpenEntry(key_, entry_ptr_);
238 result_ = backend_->SyncCreateEntry(key_, entry_ptr_);
241 result_ = backend_->SyncDoomEntry(key_);
244 result_ = backend_->SyncDoomAllEntries();
246 case OP_DOOM_BETWEEN:
247 result_ = backend_->SyncDoomEntriesBetween(initial_time_, end_time_);
250 result_ = backend_->SyncDoomEntriesSince(initial_time_);
253 result_ = backend_->SyncOpenNextEntry(iter_ptr_, entry_ptr_);
256 result_ = backend_->SyncOpenPrevEntry(iter_ptr_, entry_ptr_);
258 case OP_END_ENUMERATION:
259 backend_->SyncEndEnumeration(iter_);
262 case OP_ON_EXTERNAL_CACHE_HIT:
263 backend_->SyncOnExternalCacheHit(key_);
282 NOTREACHED() << "Invalid Operation";
283 result_ = net::ERR_UNEXPECTED;
285 DCHECK_NE(net::ERR_IO_PENDING, result_);
289 // Runs on the background thread.
290 void BackendIO::ExecuteEntryOperation() {
291 switch (operation_) {
294 entry_->ReadDataImpl(index_, offset_, buf_.get(), buf_len_,
295 base::Bind(&BackendIO::OnIOComplete, this));
299 entry_->WriteDataImpl(index_, offset_, buf_.get(), buf_len_,
300 base::Bind(&BackendIO::OnIOComplete, this),
304 result_ = entry_->ReadSparseDataImpl(
305 offset64_, buf_.get(), buf_len_,
306 base::Bind(&BackendIO::OnIOComplete, this));
308 case OP_WRITE_SPARSE:
309 result_ = entry_->WriteSparseDataImpl(
310 offset64_, buf_.get(), buf_len_,
311 base::Bind(&BackendIO::OnIOComplete, this));
314 result_ = entry_->GetAvailableRangeImpl(offset64_, buf_len_, start_);
317 entry_->CancelSparseIOImpl();
321 result_ = entry_->ReadyForSparseIOImpl(
322 base::Bind(&BackendIO::OnIOComplete, this));
325 NOTREACHED() << "Invalid Operation";
326 result_ = net::ERR_UNEXPECTED;
329 if (result_ != net::ERR_IO_PENDING)
333 InFlightBackendIO::InFlightBackendIO(BackendImpl* backend,
334 base::MessageLoopProxy* background_thread)
336 background_thread_(background_thread),
340 InFlightBackendIO::~InFlightBackendIO() {
343 void InFlightBackendIO::Init(const net::CompletionCallback& callback) {
344 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
346 PostOperation(operation.get());
349 void InFlightBackendIO::OpenEntry(const std::string& key, Entry** entry,
350 const net::CompletionCallback& callback) {
351 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
352 operation->OpenEntry(key, entry);
353 PostOperation(operation.get());
356 void InFlightBackendIO::CreateEntry(const std::string& key, Entry** entry,
357 const net::CompletionCallback& callback) {
358 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
359 operation->CreateEntry(key, entry);
360 PostOperation(operation.get());
363 void InFlightBackendIO::DoomEntry(const std::string& key,
364 const net::CompletionCallback& callback) {
365 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
366 operation->DoomEntry(key);
367 PostOperation(operation.get());
370 void InFlightBackendIO::DoomAllEntries(
371 const net::CompletionCallback& callback) {
372 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
373 operation->DoomAllEntries();
374 PostOperation(operation.get());
377 void InFlightBackendIO::DoomEntriesBetween(const base::Time initial_time,
378 const base::Time end_time,
379 const net::CompletionCallback& callback) {
380 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
381 operation->DoomEntriesBetween(initial_time, end_time);
382 PostOperation(operation.get());
385 void InFlightBackendIO::DoomEntriesSince(
386 const base::Time initial_time, const net::CompletionCallback& callback) {
387 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
388 operation->DoomEntriesSince(initial_time);
389 PostOperation(operation.get());
392 void InFlightBackendIO::OpenNextEntry(void** iter, Entry** next_entry,
393 const net::CompletionCallback& callback) {
394 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
395 operation->OpenNextEntry(iter, next_entry);
396 PostOperation(operation.get());
399 void InFlightBackendIO::OpenPrevEntry(void** iter, Entry** prev_entry,
400 const net::CompletionCallback& callback) {
401 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
402 operation->OpenPrevEntry(iter, prev_entry);
403 PostOperation(operation.get());
406 void InFlightBackendIO::EndEnumeration(void* iterator) {
407 scoped_refptr<BackendIO> operation(
408 new BackendIO(this, backend_, net::CompletionCallback()));
409 operation->EndEnumeration(iterator);
410 PostOperation(operation.get());
413 void InFlightBackendIO::OnExternalCacheHit(const std::string& key) {
414 scoped_refptr<BackendIO> operation(
415 new BackendIO(this, backend_, net::CompletionCallback()));
416 operation->OnExternalCacheHit(key);
417 PostOperation(operation.get());
420 void InFlightBackendIO::CloseEntryImpl(EntryImpl* entry) {
421 scoped_refptr<BackendIO> operation(
422 new BackendIO(this, backend_, net::CompletionCallback()));
423 operation->CloseEntryImpl(entry);
424 PostOperation(operation.get());
427 void InFlightBackendIO::DoomEntryImpl(EntryImpl* entry) {
428 scoped_refptr<BackendIO> operation(
429 new BackendIO(this, backend_, net::CompletionCallback()));
430 operation->DoomEntryImpl(entry);
431 PostOperation(operation.get());
434 void InFlightBackendIO::FlushQueue(const net::CompletionCallback& callback) {
435 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
436 operation->FlushQueue();
437 PostOperation(operation.get());
440 void InFlightBackendIO::RunTask(
441 const base::Closure& task, const net::CompletionCallback& callback) {
442 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
443 operation->RunTask(task);
444 PostOperation(operation.get());
447 void InFlightBackendIO::ReadData(EntryImpl* entry, int index, int offset,
448 net::IOBuffer* buf, int buf_len,
449 const net::CompletionCallback& callback) {
450 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
451 operation->ReadData(entry, index, offset, buf, buf_len);
452 PostOperation(operation.get());
455 void InFlightBackendIO::WriteData(EntryImpl* entry, int index, int offset,
456 net::IOBuffer* buf, int buf_len,
458 const net::CompletionCallback& callback) {
459 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
460 operation->WriteData(entry, index, offset, buf, buf_len, truncate);
461 PostOperation(operation.get());
464 void InFlightBackendIO::ReadSparseData(
465 EntryImpl* entry, int64 offset, net::IOBuffer* buf, int buf_len,
466 const net::CompletionCallback& callback) {
467 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
468 operation->ReadSparseData(entry, offset, buf, buf_len);
469 PostOperation(operation.get());
472 void InFlightBackendIO::WriteSparseData(
473 EntryImpl* entry, int64 offset, net::IOBuffer* buf, int buf_len,
474 const net::CompletionCallback& callback) {
475 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
476 operation->WriteSparseData(entry, offset, buf, buf_len);
477 PostOperation(operation.get());
480 void InFlightBackendIO::GetAvailableRange(
481 EntryImpl* entry, int64 offset, int len, int64* start,
482 const net::CompletionCallback& callback) {
483 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
484 operation->GetAvailableRange(entry, offset, len, start);
485 PostOperation(operation.get());
488 void InFlightBackendIO::CancelSparseIO(EntryImpl* entry) {
489 scoped_refptr<BackendIO> operation(
490 new BackendIO(this, backend_, net::CompletionCallback()));
491 operation->CancelSparseIO(entry);
492 PostOperation(operation.get());
495 void InFlightBackendIO::ReadyForSparseIO(
496 EntryImpl* entry, const net::CompletionCallback& callback) {
497 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
498 operation->ReadyForSparseIO(entry);
499 PostOperation(operation.get());
502 void InFlightBackendIO::WaitForPendingIO() {
503 InFlightIO::WaitForPendingIO();
506 void InFlightBackendIO::OnOperationComplete(BackgroundIO* operation,
508 BackendIO* op = static_cast<BackendIO*>(operation);
511 if (!op->callback().is_null() && (!cancel || op->IsEntryOperation()))
512 op->callback().Run(op->result());
515 void InFlightBackendIO::PostOperation(BackendIO* operation) {
516 background_thread_->PostTask(FROM_HERE,
517 base::Bind(&BackendIO::ExecuteOperation, operation));
518 OnOperationPosted(operation);
521 base::WeakPtr<InFlightBackendIO> InFlightBackendIO::GetWeakPtr() {
522 return ptr_factory_.GetWeakPtr();