1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef NET_DISK_CACHE_IN_FLIGHT_BACKEND_IO_H_ 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define NET_DISK_CACHE_IN_FLIGHT_BACKEND_IO_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <list> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop_proxy.h" 13ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen#include "base/time.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/completion_callback.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/io_buffer.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/disk_cache/in_flight_io.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace disk_cache { 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BackendImpl; 21ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsenclass Entry; 22ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsenclass EntryImpl; 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class represents a single asynchronous disk cache IO operation while it 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is being bounced between threads. 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BackendIO : public BackgroundIO { 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BackendIO(InFlightIO* controller, BackendImpl* backend, 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Runs the actual operation on the background thread. 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ExecuteOperation(); 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback implementation. 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnIOComplete(int result); 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if this operation is directed to an entry (vs. the backend). 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool IsEntryOperation(); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback() { return callback_; } 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Grabs an extra reference of entry_. 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void ReferenceEntry(); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Returns the time that has passed since the operation was created. 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::TimeDelta ElapsedTime() const; 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The operations we proxy: 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Init(); 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OpenEntry(const std::string& key, Entry** entry); 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CreateEntry(const std::string& key, Entry** entry); 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomEntry(const std::string& key); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomAllEntries(); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomEntriesBetween(const base::Time initial_time, 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const base::Time end_time); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomEntriesSince(const base::Time initial_time); 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OpenNextEntry(void** iter, Entry** next_entry); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OpenPrevEntry(void** iter, Entry** prev_entry); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void EndEnumeration(void* iterator); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CloseEntryImpl(EntryImpl* entry); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomEntryImpl(EntryImpl* entry); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void FlushQueue(); // Dummy operation. 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void RunTask(Task* task); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ReadData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len); 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void WriteData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len, bool truncate); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ReadSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf, 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void WriteSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf, 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetAvailableRange(EntryImpl* entry, int64 offset, int len, int64* start); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CancelSparseIO(EntryImpl* entry); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ReadyForSparseIO(EntryImpl* entry); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // There are two types of operations to proxy: regular backend operations are 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // executed sequentially (queued by the message loop). On the other hand, 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // operations targeted to a given entry can be long lived and support multiple 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // simultaneous users (multiple reads or writes to the same entry), and they 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // are subject to throttling, so we keep an explicit queue. 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum Operation { 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_NONE = 0, 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_INIT, 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_OPEN, 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_CREATE, 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_DOOM, 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_DOOM_ALL, 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_DOOM_BETWEEN, 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_DOOM_SINCE, 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_OPEN_NEXT, 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_OPEN_PREV, 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_END_ENUMERATION, 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_CLOSE_ENTRY, 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_DOOM_ENTRY, 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_FLUSH_QUEUE, 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OP_RUN_TASK, 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_MAX_BACKEND, 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_READ, 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_WRITE, 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_READ_SPARSE, 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_WRITE_SPARSE, 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_GET_RANGE, 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_CANCEL_IO, 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OP_IS_READY 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ~BackendIO(); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ExecuteBackendOperation(); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ExecuteEntryOperation(); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BackendImpl* backend_; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback_; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Operation operation_; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallbackImpl<BackendIO> my_callback_; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The arguments of all the operations we proxy: 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string key_; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Entry** entry_ptr_; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time initial_time_; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time end_time_; 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void** iter_ptr_; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* iter_; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EntryImpl* entry_; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index_; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int offset_; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<net::IOBuffer> buf_; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len_; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool truncate_; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 offset64_; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64* start_; 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::TimeTicks start_time_; 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Task* task_; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(BackendIO); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The specialized controller that keeps track of current operations. 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass InFlightBackendIO : public InFlightIO { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InFlightBackendIO(BackendImpl* backend, 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::MessageLoopProxy* background_thread); 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ~InFlightBackendIO(); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The operations we proxy: 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Init(net::CompletionCallback* callback); 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OpenEntry(const std::string& key, Entry** entry, 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CreateEntry(const std::string& key, Entry** entry, 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomEntry(const std::string& key, net::CompletionCallback* callback); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomAllEntries(net::CompletionCallback* callback); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomEntriesBetween(const base::Time initial_time, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const base::Time end_time, 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomEntriesSince(const base::Time initial_time, 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OpenNextEntry(void** iter, Entry** next_entry, 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OpenPrevEntry(void** iter, Entry** prev_entry, 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void EndEnumeration(void* iterator); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CloseEntryImpl(EntryImpl* entry); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoomEntryImpl(EntryImpl* entry); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void FlushQueue(net::CompletionCallback* callback); 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void RunTask(Task* task, net::CompletionCallback* callback); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ReadData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len, net::CompletionCallback* callback); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void WriteData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len, bool truncate, net::CompletionCallback* callback); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ReadSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf, 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len, net::CompletionCallback* callback); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void WriteSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf, 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len, net::CompletionCallback* callback); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetAvailableRange(EntryImpl* entry, int64 offset, int len, int64* start, 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CancelSparseIO(EntryImpl* entry); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ReadyForSparseIO(EntryImpl* entry, net::CompletionCallback* callback); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Blocks until all operations are cancelled or completed. 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void WaitForPendingIO(); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<base::MessageLoopProxy> background_thread() { 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return background_thread_; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if the current thread is the background thread. 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool BackgroundIsCurrentThread() { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return background_thread_->BelongsToCurrentThread(); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnOperationComplete(BackgroundIO* operation, bool cancel); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void PostOperation(BackendIO* operation); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BackendImpl* backend_; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<base::MessageLoopProxy> background_thread_; 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(InFlightBackendIO); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace disk_cache 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // NET_DISK_CACHE_IN_FLIGHT_BACKEND_IO_H_ 208