• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 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.
4 
5 #include "net/disk_cache/in_flight_backend_io.h"
6 
7 #include "base/compiler_specific.h"
8 #include "base/logging.h"
9 #include "net/base/net_errors.h"
10 #include "net/disk_cache/backend_impl.h"
11 #include "net/disk_cache/entry_impl.h"
12 #include "net/disk_cache/histogram_macros.h"
13 
14 namespace disk_cache {
15 
BackendIO(InFlightIO * controller,BackendImpl * backend,net::CompletionCallback * callback)16 BackendIO::BackendIO(InFlightIO* controller, BackendImpl* backend,
17                      net::CompletionCallback* callback)
18     : BackgroundIO(controller), backend_(backend), callback_(callback),
19       operation_(OP_NONE),
20       ALLOW_THIS_IN_INITIALIZER_LIST(
21           my_callback_(this, &BackendIO::OnIOComplete)) {
22   start_time_ = base::TimeTicks::Now();
23 }
24 
25 // Runs on the background thread.
ExecuteOperation()26 void BackendIO::ExecuteOperation() {
27   if (IsEntryOperation())
28     return ExecuteEntryOperation();
29 
30   ExecuteBackendOperation();
31 }
32 
33 // Runs on the background thread.
OnIOComplete(int result)34 void BackendIO::OnIOComplete(int result) {
35   DCHECK(IsEntryOperation());
36   DCHECK_NE(result, net::ERR_IO_PENDING);
37   result_ = result;
38   controller_->OnIOComplete(this);
39 }
40 
IsEntryOperation()41 bool BackendIO::IsEntryOperation() {
42   return operation_ > OP_MAX_BACKEND;
43 }
44 
45 // Runs on the background thread.
ReferenceEntry()46 void BackendIO::ReferenceEntry() {
47   entry_->AddRef();
48 }
49 
ElapsedTime() const50 base::TimeDelta BackendIO::ElapsedTime() const {
51   return base::TimeTicks::Now() - start_time_;
52 }
53 
Init()54 void BackendIO::Init() {
55   operation_ = OP_INIT;
56 }
57 
OpenEntry(const std::string & key,Entry ** entry)58 void BackendIO::OpenEntry(const std::string& key, Entry** entry) {
59   operation_ = OP_OPEN;
60   key_ = key;
61   entry_ptr_ = entry;
62 }
63 
CreateEntry(const std::string & key,Entry ** entry)64 void BackendIO::CreateEntry(const std::string& key, Entry** entry) {
65   operation_ = OP_CREATE;
66   key_ = key;
67   entry_ptr_ = entry;
68 }
69 
DoomEntry(const std::string & key)70 void BackendIO::DoomEntry(const std::string& key) {
71   operation_ = OP_DOOM;
72   key_ = key;
73 }
74 
DoomAllEntries()75 void BackendIO::DoomAllEntries() {
76   operation_ = OP_DOOM_ALL;
77 }
78 
DoomEntriesBetween(const base::Time initial_time,const base::Time end_time)79 void BackendIO::DoomEntriesBetween(const base::Time initial_time,
80                                    const base::Time end_time) {
81   operation_ = OP_DOOM_BETWEEN;
82   initial_time_ = initial_time;
83   end_time_ = end_time;
84 }
85 
DoomEntriesSince(const base::Time initial_time)86 void BackendIO::DoomEntriesSince(const base::Time initial_time) {
87   operation_ = OP_DOOM_SINCE;
88   initial_time_ = initial_time;
89 }
90 
OpenNextEntry(void ** iter,Entry ** next_entry)91 void BackendIO::OpenNextEntry(void** iter, Entry** next_entry) {
92   operation_ = OP_OPEN_NEXT;
93   iter_ptr_ = iter;
94   entry_ptr_ = next_entry;
95 }
96 
OpenPrevEntry(void ** iter,Entry ** prev_entry)97 void BackendIO::OpenPrevEntry(void** iter, Entry** prev_entry) {
98   operation_ = OP_OPEN_PREV;
99   iter_ptr_ = iter;
100   entry_ptr_ = prev_entry;
101 }
102 
EndEnumeration(void * iterator)103 void BackendIO::EndEnumeration(void* iterator) {
104   operation_ = OP_END_ENUMERATION;
105   iter_ = iterator;
106 }
107 
CloseEntryImpl(EntryImpl * entry)108 void BackendIO::CloseEntryImpl(EntryImpl* entry) {
109   operation_ = OP_CLOSE_ENTRY;
110   entry_ = entry;
111 }
112 
DoomEntryImpl(EntryImpl * entry)113 void BackendIO::DoomEntryImpl(EntryImpl* entry) {
114   operation_ = OP_DOOM_ENTRY;
115   entry_ = entry;
116 }
117 
FlushQueue()118 void BackendIO::FlushQueue() {
119   operation_ = OP_FLUSH_QUEUE;
120 }
121 
RunTask(Task * task)122 void BackendIO::RunTask(Task* task) {
123   operation_ = OP_RUN_TASK;
124   task_ = task;
125 }
126 
ReadData(EntryImpl * entry,int index,int offset,net::IOBuffer * buf,int buf_len)127 void BackendIO::ReadData(EntryImpl* entry, int index, int offset,
128                          net::IOBuffer* buf, int buf_len) {
129   operation_ = OP_READ;
130   entry_ = entry;
131   index_ = index;
132   offset_ = offset;
133   buf_ = buf;
134   buf_len_ = buf_len;
135 }
136 
WriteData(EntryImpl * entry,int index,int offset,net::IOBuffer * buf,int buf_len,bool truncate)137 void BackendIO::WriteData(EntryImpl* entry, int index, int offset,
138                           net::IOBuffer* buf, int buf_len, bool truncate) {
139   operation_ = OP_WRITE;
140   entry_ = entry;
141   index_ = index;
142   offset_ = offset;
143   buf_ = buf;
144   buf_len_ = buf_len;
145   truncate_ = truncate;
146 }
147 
ReadSparseData(EntryImpl * entry,int64 offset,net::IOBuffer * buf,int buf_len)148 void BackendIO::ReadSparseData(EntryImpl* entry, int64 offset,
149                                net::IOBuffer* buf, int buf_len) {
150   operation_ = OP_READ_SPARSE;
151   entry_ = entry;
152   offset64_ = offset;
153   buf_ = buf;
154   buf_len_ = buf_len;
155 }
156 
WriteSparseData(EntryImpl * entry,int64 offset,net::IOBuffer * buf,int buf_len)157 void BackendIO::WriteSparseData(EntryImpl* entry, int64 offset,
158                                 net::IOBuffer* buf, int buf_len) {
159   operation_ = OP_WRITE_SPARSE;
160   entry_ = entry;
161   offset64_ = offset;
162   buf_ = buf;
163   buf_len_ = buf_len;
164 }
165 
GetAvailableRange(EntryImpl * entry,int64 offset,int len,int64 * start)166 void BackendIO::GetAvailableRange(EntryImpl* entry, int64 offset, int len,
167                                   int64* start) {
168   operation_ = OP_GET_RANGE;
169   entry_ = entry;
170   offset64_ = offset;
171   buf_len_ = len;
172   start_ = start;
173 }
174 
CancelSparseIO(EntryImpl * entry)175 void BackendIO::CancelSparseIO(EntryImpl* entry) {
176   operation_ = OP_CANCEL_IO;
177   entry_ = entry;
178 }
179 
ReadyForSparseIO(EntryImpl * entry)180 void BackendIO::ReadyForSparseIO(EntryImpl* entry) {
181   operation_ = OP_IS_READY;
182   entry_ = entry;
183 }
184 
~BackendIO()185 BackendIO::~BackendIO() {}
186 
187 // Runs on the background thread.
ExecuteBackendOperation()188 void BackendIO::ExecuteBackendOperation() {
189   switch (operation_) {
190     case OP_INIT:
191       result_ = backend_->SyncInit();
192       break;
193     case OP_OPEN:
194       result_ = backend_->SyncOpenEntry(key_, entry_ptr_);
195       break;
196     case OP_CREATE:
197       result_ = backend_->SyncCreateEntry(key_, entry_ptr_);
198       break;
199     case OP_DOOM:
200       result_ = backend_->SyncDoomEntry(key_);
201       break;
202     case OP_DOOM_ALL:
203       result_ = backend_->SyncDoomAllEntries();
204       break;
205     case OP_DOOM_BETWEEN:
206       result_ = backend_->SyncDoomEntriesBetween(initial_time_, end_time_);
207       break;
208     case OP_DOOM_SINCE:
209       result_ = backend_->SyncDoomEntriesSince(initial_time_);
210       break;
211     case OP_OPEN_NEXT:
212       result_ = backend_->SyncOpenNextEntry(iter_ptr_, entry_ptr_);
213       break;
214     case OP_OPEN_PREV:
215       result_ = backend_->SyncOpenPrevEntry(iter_ptr_, entry_ptr_);
216       break;
217     case OP_END_ENUMERATION:
218       backend_->SyncEndEnumeration(iter_);
219       result_ = net::OK;
220       break;
221     case OP_CLOSE_ENTRY:
222       entry_->Release();
223       result_ = net::OK;
224       break;
225     case OP_DOOM_ENTRY:
226       entry_->DoomImpl();
227       result_ = net::OK;
228       break;
229     case OP_FLUSH_QUEUE:
230       result_ = net::OK;
231       break;
232     case OP_RUN_TASK:
233       task_->Run();
234       delete task_;
235       result_ = net::OK;
236       break;
237     default:
238       NOTREACHED() << "Invalid Operation";
239       result_ = net::ERR_UNEXPECTED;
240   }
241   DCHECK_NE(net::ERR_IO_PENDING, result_);
242   controller_->OnIOComplete(this);
243 }
244 
245 // Runs on the background thread.
ExecuteEntryOperation()246 void BackendIO::ExecuteEntryOperation() {
247   switch (operation_) {
248     case OP_READ:
249       result_ = entry_->ReadDataImpl(index_, offset_, buf_, buf_len_,
250                                      &my_callback_);
251       break;
252     case OP_WRITE:
253       result_ = entry_->WriteDataImpl(index_, offset_, buf_, buf_len_,
254                                       &my_callback_, truncate_);
255       break;
256     case OP_READ_SPARSE:
257       result_ = entry_->ReadSparseDataImpl(offset64_, buf_, buf_len_,
258                                            &my_callback_);
259       break;
260     case OP_WRITE_SPARSE:
261       result_ = entry_->WriteSparseDataImpl(offset64_, buf_, buf_len_,
262                                             &my_callback_);
263       break;
264     case OP_GET_RANGE:
265       result_ = entry_->GetAvailableRangeImpl(offset64_, buf_len_, start_);
266       break;
267     case OP_CANCEL_IO:
268       entry_->CancelSparseIOImpl();
269       result_ = net::OK;
270       break;
271     case OP_IS_READY:
272       result_ = entry_->ReadyForSparseIOImpl(&my_callback_);
273       break;
274     default:
275       NOTREACHED() << "Invalid Operation";
276       result_ = net::ERR_UNEXPECTED;
277   }
278   if (result_ != net::ERR_IO_PENDING)
279     controller_->OnIOComplete(this);
280 }
281 
282 // ---------------------------------------------------------------------------
283 
InFlightBackendIO(BackendImpl * backend,base::MessageLoopProxy * background_thread)284 InFlightBackendIO::InFlightBackendIO(BackendImpl* backend,
285                     base::MessageLoopProxy* background_thread)
286     : backend_(backend),
287       background_thread_(background_thread) {
288 }
289 
~InFlightBackendIO()290 InFlightBackendIO::~InFlightBackendIO() {
291 }
292 
Init(CompletionCallback * callback)293 void InFlightBackendIO::Init(CompletionCallback* callback) {
294   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
295   operation->Init();
296   PostOperation(operation);
297 }
298 
OpenEntry(const std::string & key,Entry ** entry,CompletionCallback * callback)299 void InFlightBackendIO::OpenEntry(const std::string& key, Entry** entry,
300                                   CompletionCallback* callback) {
301   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
302   operation->OpenEntry(key, entry);
303   PostOperation(operation);
304 }
305 
CreateEntry(const std::string & key,Entry ** entry,CompletionCallback * callback)306 void InFlightBackendIO::CreateEntry(const std::string& key, Entry** entry,
307                                     CompletionCallback* callback) {
308   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
309   operation->CreateEntry(key, entry);
310   PostOperation(operation);
311 }
312 
DoomEntry(const std::string & key,CompletionCallback * callback)313 void InFlightBackendIO::DoomEntry(const std::string& key,
314                                   CompletionCallback* callback) {
315   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
316   operation->DoomEntry(key);
317   PostOperation(operation);
318 }
319 
DoomAllEntries(CompletionCallback * callback)320 void InFlightBackendIO::DoomAllEntries(CompletionCallback* callback) {
321   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
322   operation->DoomAllEntries();
323   PostOperation(operation);
324 }
325 
DoomEntriesBetween(const base::Time initial_time,const base::Time end_time,CompletionCallback * callback)326 void InFlightBackendIO::DoomEntriesBetween(const base::Time initial_time,
327                         const base::Time end_time,
328                         CompletionCallback* callback) {
329   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
330   operation->DoomEntriesBetween(initial_time, end_time);
331   PostOperation(operation);
332 }
333 
DoomEntriesSince(const base::Time initial_time,CompletionCallback * callback)334 void InFlightBackendIO::DoomEntriesSince(const base::Time initial_time,
335                                          CompletionCallback* callback) {
336   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
337   operation->DoomEntriesSince(initial_time);
338   PostOperation(operation);
339 }
340 
OpenNextEntry(void ** iter,Entry ** next_entry,CompletionCallback * callback)341 void InFlightBackendIO::OpenNextEntry(void** iter, Entry** next_entry,
342                                       CompletionCallback* callback) {
343   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
344   operation->OpenNextEntry(iter, next_entry);
345   PostOperation(operation);
346 }
347 
OpenPrevEntry(void ** iter,Entry ** prev_entry,CompletionCallback * callback)348 void InFlightBackendIO::OpenPrevEntry(void** iter, Entry** prev_entry,
349                                       CompletionCallback* callback) {
350   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
351   operation->OpenPrevEntry(iter, prev_entry);
352   PostOperation(operation);
353 }
354 
EndEnumeration(void * iterator)355 void InFlightBackendIO::EndEnumeration(void* iterator) {
356   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, NULL));
357   operation->EndEnumeration(iterator);
358   PostOperation(operation);
359 }
360 
CloseEntryImpl(EntryImpl * entry)361 void InFlightBackendIO::CloseEntryImpl(EntryImpl* entry) {
362   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, NULL));
363   operation->CloseEntryImpl(entry);
364   PostOperation(operation);
365 }
366 
DoomEntryImpl(EntryImpl * entry)367 void InFlightBackendIO::DoomEntryImpl(EntryImpl* entry) {
368   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, NULL));
369   operation->DoomEntryImpl(entry);
370   PostOperation(operation);
371 }
372 
FlushQueue(net::CompletionCallback * callback)373 void InFlightBackendIO::FlushQueue(net::CompletionCallback* callback) {
374   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
375   operation->FlushQueue();
376   PostOperation(operation);
377 }
378 
RunTask(Task * task,net::CompletionCallback * callback)379 void InFlightBackendIO::RunTask(Task* task, net::CompletionCallback* callback) {
380   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
381   operation->RunTask(task);
382   PostOperation(operation);
383 }
384 
ReadData(EntryImpl * entry,int index,int offset,net::IOBuffer * buf,int buf_len,CompletionCallback * callback)385 void InFlightBackendIO::ReadData(EntryImpl* entry, int index, int offset,
386                                  net::IOBuffer* buf, int buf_len,
387                                  CompletionCallback* callback) {
388   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
389   operation->ReadData(entry, index, offset, buf, buf_len);
390   PostOperation(operation);
391 }
392 
WriteData(EntryImpl * entry,int index,int offset,net::IOBuffer * buf,int buf_len,bool truncate,CompletionCallback * callback)393 void InFlightBackendIO::WriteData(EntryImpl* entry, int index, int offset,
394                                   net::IOBuffer* buf, int buf_len,
395                                   bool truncate,
396                                   CompletionCallback* callback) {
397   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
398   operation->WriteData(entry, index, offset, buf, buf_len, truncate);
399   PostOperation(operation);
400 }
401 
ReadSparseData(EntryImpl * entry,int64 offset,net::IOBuffer * buf,int buf_len,CompletionCallback * callback)402 void InFlightBackendIO::ReadSparseData(EntryImpl* entry, int64 offset,
403                                        net::IOBuffer* buf, int buf_len,
404                                        CompletionCallback* callback) {
405   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
406   operation->ReadSparseData(entry, offset, buf, buf_len);
407   PostOperation(operation);
408 }
409 
WriteSparseData(EntryImpl * entry,int64 offset,net::IOBuffer * buf,int buf_len,CompletionCallback * callback)410 void InFlightBackendIO::WriteSparseData(EntryImpl* entry, int64 offset,
411                                         net::IOBuffer* buf, int buf_len,
412                                         CompletionCallback* callback) {
413   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
414   operation->WriteSparseData(entry, offset, buf, buf_len);
415   PostOperation(operation);
416 }
417 
GetAvailableRange(EntryImpl * entry,int64 offset,int len,int64 * start,CompletionCallback * callback)418 void InFlightBackendIO::GetAvailableRange(EntryImpl* entry, int64 offset,
419                                           int len, int64* start,
420                                           CompletionCallback* callback) {
421   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
422   operation->GetAvailableRange(entry, offset, len, start);
423   PostOperation(operation);
424 }
425 
CancelSparseIO(EntryImpl * entry)426 void InFlightBackendIO::CancelSparseIO(EntryImpl* entry) {
427   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, NULL));
428   operation->CancelSparseIO(entry);
429   PostOperation(operation);
430 }
431 
ReadyForSparseIO(EntryImpl * entry,CompletionCallback * callback)432 void InFlightBackendIO::ReadyForSparseIO(EntryImpl* entry,
433                                          CompletionCallback* callback) {
434   scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback));
435   operation->ReadyForSparseIO(entry);
436   PostOperation(operation);
437 }
438 
WaitForPendingIO()439 void InFlightBackendIO::WaitForPendingIO() {
440   InFlightIO::WaitForPendingIO();
441 }
442 
OnOperationComplete(BackgroundIO * operation,bool cancel)443 void InFlightBackendIO::OnOperationComplete(BackgroundIO* operation,
444                                             bool cancel) {
445   BackendIO* op = static_cast<BackendIO*>(operation);
446 
447   if (op->IsEntryOperation()) {
448     CACHE_UMA(TIMES, "TotalIOTime", 0, op->ElapsedTime());
449   }
450 
451   if (op->callback() && (!cancel || op->IsEntryOperation()))
452     op->callback()->Run(op->result());
453 }
454 
PostOperation(BackendIO * operation)455 void InFlightBackendIO::PostOperation(BackendIO* operation) {
456   background_thread_->PostTask(FROM_HERE,
457       NewRunnableMethod(operation, &BackendIO::ExecuteOperation));
458   OnOperationPosted(operation);
459 }
460 
461 }  // namespace
462