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