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 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. 26 void BackendIO::ExecuteOperation() { 27 if (IsEntryOperation()) 28 return ExecuteEntryOperation(); 29 30 ExecuteBackendOperation(); 31 } 32 33 // Runs on the background thread. 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 41 bool BackendIO::IsEntryOperation() { 42 return operation_ > OP_MAX_BACKEND; 43 } 44 45 // Runs on the background thread. 46 void BackendIO::ReferenceEntry() { 47 entry_->AddRef(); 48 } 49 50 base::TimeDelta BackendIO::ElapsedTime() const { 51 return base::TimeTicks::Now() - start_time_; 52 } 53 54 void BackendIO::Init() { 55 operation_ = OP_INIT; 56 } 57 58 void BackendIO::OpenEntry(const std::string& key, Entry** entry) { 59 operation_ = OP_OPEN; 60 key_ = key; 61 entry_ptr_ = entry; 62 } 63 64 void BackendIO::CreateEntry(const std::string& key, Entry** entry) { 65 operation_ = OP_CREATE; 66 key_ = key; 67 entry_ptr_ = entry; 68 } 69 70 void BackendIO::DoomEntry(const std::string& key) { 71 operation_ = OP_DOOM; 72 key_ = key; 73 } 74 75 void BackendIO::DoomAllEntries() { 76 operation_ = OP_DOOM_ALL; 77 } 78 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 86 void BackendIO::DoomEntriesSince(const base::Time initial_time) { 87 operation_ = OP_DOOM_SINCE; 88 initial_time_ = initial_time; 89 } 90 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 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 103 void BackendIO::EndEnumeration(void* iterator) { 104 operation_ = OP_END_ENUMERATION; 105 iter_ = iterator; 106 } 107 108 void BackendIO::CloseEntryImpl(EntryImpl* entry) { 109 operation_ = OP_CLOSE_ENTRY; 110 entry_ = entry; 111 } 112 113 void BackendIO::DoomEntryImpl(EntryImpl* entry) { 114 operation_ = OP_DOOM_ENTRY; 115 entry_ = entry; 116 } 117 118 void BackendIO::FlushQueue() { 119 operation_ = OP_FLUSH_QUEUE; 120 } 121 122 void BackendIO::RunTask(Task* task) { 123 operation_ = OP_RUN_TASK; 124 task_ = task; 125 } 126 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 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 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 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 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 175 void BackendIO::CancelSparseIO(EntryImpl* entry) { 176 operation_ = OP_CANCEL_IO; 177 entry_ = entry; 178 } 179 180 void BackendIO::ReadyForSparseIO(EntryImpl* entry) { 181 operation_ = OP_IS_READY; 182 entry_ = entry; 183 } 184 185 BackendIO::~BackendIO() {} 186 187 // Runs on the background thread. 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. 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 284 InFlightBackendIO::InFlightBackendIO(BackendImpl* backend, 285 base::MessageLoopProxy* background_thread) 286 : backend_(backend), 287 background_thread_(background_thread) { 288 } 289 290 InFlightBackendIO::~InFlightBackendIO() { 291 } 292 293 void InFlightBackendIO::Init(CompletionCallback* callback) { 294 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback)); 295 operation->Init(); 296 PostOperation(operation); 297 } 298 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 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 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 320 void InFlightBackendIO::DoomAllEntries(CompletionCallback* callback) { 321 scoped_refptr<BackendIO> operation(new BackendIO(this, backend_, callback)); 322 operation->DoomAllEntries(); 323 PostOperation(operation); 324 } 325 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 439 void InFlightBackendIO::WaitForPendingIO() { 440 InFlightIO::WaitForPendingIO(); 441 } 442 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 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