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 namespace disk_cache
{
18 BackendIO::BackendIO(InFlightIO
* controller
, BackendImpl
* backend
,
19 const net::CompletionCallback
& callback
)
20 : BackgroundIO(controller
),
34 start_time_
= base::TimeTicks::Now();
37 // Runs on the background thread.
38 void BackendIO::ExecuteOperation() {
39 if (IsEntryOperation())
40 return ExecuteEntryOperation();
42 ExecuteBackendOperation();
45 // Runs on the background thread.
46 void BackendIO::OnIOComplete(int result
) {
47 DCHECK(IsEntryOperation());
48 DCHECK_NE(result
, net::ERR_IO_PENDING
);
53 // Runs on the primary thread.
54 void BackendIO::OnDone(bool cancel
) {
55 if (IsEntryOperation()) {
56 CACHE_UMA(TIMES
, "TotalIOTime", 0, ElapsedTime());
62 if (result() == net::OK
) {
63 static_cast<EntryImpl
*>(*entry_ptr_
)->OnEntryCreated(backend_
);
65 (*entry_ptr_
)->Close();
69 bool BackendIO::IsEntryOperation() {
70 return operation_
> OP_MAX_BACKEND
;
73 // Runs on the background thread.
74 void BackendIO::ReferenceEntry() {
78 void BackendIO::Init() {
82 void BackendIO::OpenEntry(const std::string
& key
, Entry
** entry
) {
88 void BackendIO::CreateEntry(const std::string
& key
, Entry
** entry
) {
89 operation_
= OP_CREATE
;
94 void BackendIO::DoomEntry(const std::string
& key
) {
99 void BackendIO::DoomAllEntries() {
100 operation_
= OP_DOOM_ALL
;
103 void BackendIO::DoomEntriesBetween(const base::Time initial_time
,
104 const base::Time end_time
) {
105 operation_
= OP_DOOM_BETWEEN
;
106 initial_time_
= initial_time
;
107 end_time_
= end_time
;
110 void BackendIO::DoomEntriesSince(const base::Time initial_time
) {
111 operation_
= OP_DOOM_SINCE
;
112 initial_time_
= initial_time
;
115 void BackendIO::OpenNextEntry(void** iter
, Entry
** next_entry
) {
116 operation_
= OP_OPEN_NEXT
;
118 entry_ptr_
= next_entry
;
121 void BackendIO::OpenPrevEntry(void** iter
, Entry
** prev_entry
) {
122 operation_
= OP_OPEN_PREV
;
124 entry_ptr_
= prev_entry
;
127 void BackendIO::EndEnumeration(void* iterator
) {
128 operation_
= OP_END_ENUMERATION
;
132 void BackendIO::OnExternalCacheHit(const std::string
& key
) {
133 operation_
= OP_ON_EXTERNAL_CACHE_HIT
;
137 void BackendIO::CloseEntryImpl(EntryImpl
* entry
) {
138 operation_
= OP_CLOSE_ENTRY
;
142 void BackendIO::DoomEntryImpl(EntryImpl
* entry
) {
143 operation_
= OP_DOOM_ENTRY
;
147 void BackendIO::FlushQueue() {
148 operation_
= OP_FLUSH_QUEUE
;
151 void BackendIO::RunTask(const base::Closure
& task
) {
152 operation_
= OP_RUN_TASK
;
156 void BackendIO::ReadData(EntryImpl
* entry
, int index
, int offset
,
157 net::IOBuffer
* buf
, int buf_len
) {
158 operation_
= OP_READ
;
166 void BackendIO::WriteData(EntryImpl
* entry
, int index
, int offset
,
167 net::IOBuffer
* buf
, int buf_len
, bool truncate
) {
168 operation_
= OP_WRITE
;
174 truncate_
= truncate
;
177 void BackendIO::ReadSparseData(EntryImpl
* entry
, int64 offset
,
178 net::IOBuffer
* buf
, int buf_len
) {
179 operation_
= OP_READ_SPARSE
;
186 void BackendIO::WriteSparseData(EntryImpl
* entry
, int64 offset
,
187 net::IOBuffer
* buf
, int buf_len
) {
188 operation_
= OP_WRITE_SPARSE
;
195 void BackendIO::GetAvailableRange(EntryImpl
* entry
, int64 offset
, int len
,
197 operation_
= OP_GET_RANGE
;
204 void BackendIO::CancelSparseIO(EntryImpl
* entry
) {
205 operation_
= OP_CANCEL_IO
;
209 void BackendIO::ReadyForSparseIO(EntryImpl
* entry
) {
210 operation_
= OP_IS_READY
;
214 BackendIO::~BackendIO() {}
216 bool BackendIO::ReturnsEntry() {
217 return (operation_
== OP_OPEN
|| operation_
== OP_CREATE
||
218 operation_
== OP_OPEN_NEXT
|| operation_
== OP_OPEN_PREV
);
221 base::TimeDelta
BackendIO::ElapsedTime() const {
222 return base::TimeTicks::Now() - start_time_
;
225 // Runs on the background thread.
226 void BackendIO::ExecuteBackendOperation() {
227 switch (operation_
) {
229 result_
= backend_
->SyncInit();
232 result_
= backend_
->SyncOpenEntry(key_
, entry_ptr_
);
235 result_
= backend_
->SyncCreateEntry(key_
, entry_ptr_
);
238 result_
= backend_
->SyncDoomEntry(key_
);
241 result_
= backend_
->SyncDoomAllEntries();
243 case OP_DOOM_BETWEEN
:
244 result_
= backend_
->SyncDoomEntriesBetween(initial_time_
, end_time_
);
247 result_
= backend_
->SyncDoomEntriesSince(initial_time_
);
250 result_
= backend_
->SyncOpenNextEntry(iter_ptr_
, entry_ptr_
);
253 result_
= backend_
->SyncOpenPrevEntry(iter_ptr_
, entry_ptr_
);
255 case OP_END_ENUMERATION
:
256 backend_
->SyncEndEnumeration(iter_
);
259 case OP_ON_EXTERNAL_CACHE_HIT
:
260 backend_
->SyncOnExternalCacheHit(key_
);
279 NOTREACHED() << "Invalid Operation";
280 result_
= net::ERR_UNEXPECTED
;
282 DCHECK_NE(net::ERR_IO_PENDING
, result_
);
286 // Runs on the background thread.
287 void BackendIO::ExecuteEntryOperation() {
288 switch (operation_
) {
291 entry_
->ReadDataImpl(index_
, offset_
, buf_
.get(), buf_len_
,
292 base::Bind(&BackendIO::OnIOComplete
, this));
296 entry_
->WriteDataImpl(index_
, offset_
, buf_
.get(), buf_len_
,
297 base::Bind(&BackendIO::OnIOComplete
, this),
301 result_
= entry_
->ReadSparseDataImpl(
302 offset64_
, buf_
.get(), buf_len_
,
303 base::Bind(&BackendIO::OnIOComplete
, this));
305 case OP_WRITE_SPARSE
:
306 result_
= entry_
->WriteSparseDataImpl(
307 offset64_
, buf_
.get(), buf_len_
,
308 base::Bind(&BackendIO::OnIOComplete
, this));
311 result_
= entry_
->GetAvailableRangeImpl(offset64_
, buf_len_
, start_
);
314 entry_
->CancelSparseIOImpl();
318 result_
= entry_
->ReadyForSparseIOImpl(
319 base::Bind(&BackendIO::OnIOComplete
, this));
322 NOTREACHED() << "Invalid Operation";
323 result_
= net::ERR_UNEXPECTED
;
326 if (result_
!= net::ERR_IO_PENDING
)
330 InFlightBackendIO::InFlightBackendIO(BackendImpl
* backend
,
331 base::MessageLoopProxy
* background_thread
)
333 background_thread_(background_thread
),
337 InFlightBackendIO::~InFlightBackendIO() {
340 void InFlightBackendIO::Init(const net::CompletionCallback
& callback
) {
341 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
343 PostOperation(operation
.get());
346 void InFlightBackendIO::OpenEntry(const std::string
& key
, Entry
** entry
,
347 const net::CompletionCallback
& callback
) {
348 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
349 operation
->OpenEntry(key
, entry
);
350 PostOperation(operation
.get());
353 void InFlightBackendIO::CreateEntry(const std::string
& key
, Entry
** entry
,
354 const net::CompletionCallback
& callback
) {
355 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
356 operation
->CreateEntry(key
, entry
);
357 PostOperation(operation
.get());
360 void InFlightBackendIO::DoomEntry(const std::string
& key
,
361 const net::CompletionCallback
& callback
) {
362 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
363 operation
->DoomEntry(key
);
364 PostOperation(operation
.get());
367 void InFlightBackendIO::DoomAllEntries(
368 const net::CompletionCallback
& callback
) {
369 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
370 operation
->DoomAllEntries();
371 PostOperation(operation
.get());
374 void InFlightBackendIO::DoomEntriesBetween(const base::Time initial_time
,
375 const base::Time end_time
,
376 const net::CompletionCallback
& callback
) {
377 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
378 operation
->DoomEntriesBetween(initial_time
, end_time
);
379 PostOperation(operation
.get());
382 void InFlightBackendIO::DoomEntriesSince(
383 const base::Time initial_time
, const net::CompletionCallback
& callback
) {
384 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
385 operation
->DoomEntriesSince(initial_time
);
386 PostOperation(operation
.get());
389 void InFlightBackendIO::OpenNextEntry(void** iter
, Entry
** next_entry
,
390 const net::CompletionCallback
& callback
) {
391 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
392 operation
->OpenNextEntry(iter
, next_entry
);
393 PostOperation(operation
.get());
396 void InFlightBackendIO::OpenPrevEntry(void** iter
, Entry
** prev_entry
,
397 const net::CompletionCallback
& callback
) {
398 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
399 operation
->OpenPrevEntry(iter
, prev_entry
);
400 PostOperation(operation
.get());
403 void InFlightBackendIO::EndEnumeration(void* iterator
) {
404 scoped_refptr
<BackendIO
> operation(
405 new BackendIO(this, backend_
, net::CompletionCallback()));
406 operation
->EndEnumeration(iterator
);
407 PostOperation(operation
.get());
410 void InFlightBackendIO::OnExternalCacheHit(const std::string
& key
) {
411 scoped_refptr
<BackendIO
> operation(
412 new BackendIO(this, backend_
, net::CompletionCallback()));
413 operation
->OnExternalCacheHit(key
);
414 PostOperation(operation
.get());
417 void InFlightBackendIO::CloseEntryImpl(EntryImpl
* entry
) {
418 scoped_refptr
<BackendIO
> operation(
419 new BackendIO(this, backend_
, net::CompletionCallback()));
420 operation
->CloseEntryImpl(entry
);
421 PostOperation(operation
.get());
424 void InFlightBackendIO::DoomEntryImpl(EntryImpl
* entry
) {
425 scoped_refptr
<BackendIO
> operation(
426 new BackendIO(this, backend_
, net::CompletionCallback()));
427 operation
->DoomEntryImpl(entry
);
428 PostOperation(operation
.get());
431 void InFlightBackendIO::FlushQueue(const net::CompletionCallback
& callback
) {
432 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
433 operation
->FlushQueue();
434 PostOperation(operation
.get());
437 void InFlightBackendIO::RunTask(
438 const base::Closure
& task
, const net::CompletionCallback
& callback
) {
439 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
440 operation
->RunTask(task
);
441 PostOperation(operation
.get());
444 void InFlightBackendIO::ReadData(EntryImpl
* entry
, int index
, int offset
,
445 net::IOBuffer
* buf
, int buf_len
,
446 const net::CompletionCallback
& callback
) {
447 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
448 operation
->ReadData(entry
, index
, offset
, buf
, buf_len
);
449 PostOperation(operation
.get());
452 void InFlightBackendIO::WriteData(EntryImpl
* entry
, int index
, int offset
,
453 net::IOBuffer
* buf
, int buf_len
,
455 const net::CompletionCallback
& callback
) {
456 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
457 operation
->WriteData(entry
, index
, offset
, buf
, buf_len
, truncate
);
458 PostOperation(operation
.get());
461 void InFlightBackendIO::ReadSparseData(
462 EntryImpl
* entry
, int64 offset
, net::IOBuffer
* buf
, int buf_len
,
463 const net::CompletionCallback
& callback
) {
464 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
465 operation
->ReadSparseData(entry
, offset
, buf
, buf_len
);
466 PostOperation(operation
.get());
469 void InFlightBackendIO::WriteSparseData(
470 EntryImpl
* entry
, int64 offset
, net::IOBuffer
* buf
, int buf_len
,
471 const net::CompletionCallback
& callback
) {
472 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
473 operation
->WriteSparseData(entry
, offset
, buf
, buf_len
);
474 PostOperation(operation
.get());
477 void InFlightBackendIO::GetAvailableRange(
478 EntryImpl
* entry
, int64 offset
, int len
, int64
* start
,
479 const net::CompletionCallback
& callback
) {
480 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
481 operation
->GetAvailableRange(entry
, offset
, len
, start
);
482 PostOperation(operation
.get());
485 void InFlightBackendIO::CancelSparseIO(EntryImpl
* entry
) {
486 scoped_refptr
<BackendIO
> operation(
487 new BackendIO(this, backend_
, net::CompletionCallback()));
488 operation
->CancelSparseIO(entry
);
489 PostOperation(operation
.get());
492 void InFlightBackendIO::ReadyForSparseIO(
493 EntryImpl
* entry
, const net::CompletionCallback
& callback
) {
494 scoped_refptr
<BackendIO
> operation(new BackendIO(this, backend_
, callback
));
495 operation
->ReadyForSparseIO(entry
);
496 PostOperation(operation
.get());
499 void InFlightBackendIO::WaitForPendingIO() {
500 InFlightIO::WaitForPendingIO();
503 void InFlightBackendIO::OnOperationComplete(BackgroundIO
* operation
,
505 BackendIO
* op
= static_cast<BackendIO
*>(operation
);
508 if (!op
->callback().is_null() && (!cancel
|| op
->IsEntryOperation()))
509 op
->callback().Run(op
->result());
512 void InFlightBackendIO::PostOperation(BackendIO
* operation
) {
513 background_thread_
->PostTask(FROM_HERE
,
514 base::Bind(&BackendIO::ExecuteOperation
, operation
));
515 OnOperationPosted(operation
);
518 base::WeakPtr
<InFlightBackendIO
> InFlightBackendIO::GetWeakPtr() {
519 return ptr_factory_
.GetWeakPtr();