// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_DISK_CACHE_IN_FLIGHT_BACKEND_IO_H_ #define NET_DISK_CACHE_IN_FLIGHT_BACKEND_IO_H_ #include #include #include "base/message_loop_proxy.h" #include "base/time.h" #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/disk_cache/in_flight_io.h" namespace disk_cache { class BackendImpl; class Entry; class EntryImpl; // This class represents a single asynchronous disk cache IO operation while it // is being bounced between threads. class BackendIO : public BackgroundIO { public: BackendIO(InFlightIO* controller, BackendImpl* backend, const net::CompletionCallback& callback); // Runs the actual operation on the background thread. void ExecuteOperation(); // Callback implementation. void OnIOComplete(int result); // Called when we are finishing this operation. If |cancel| is true, the user // callback will not be invoked. void OnDone(bool cancel); // Returns true if this operation is directed to an entry (vs. the backend). bool IsEntryOperation(); net::CompletionCallback callback() const { return callback_; } // Grabs an extra reference of entry_. void ReferenceEntry(); // The operations we proxy: void Init(); void OpenEntry(const std::string& key, Entry** entry); void CreateEntry(const std::string& key, Entry** entry); void DoomEntry(const std::string& key); void DoomAllEntries(); void DoomEntriesBetween(const base::Time initial_time, const base::Time end_time); void DoomEntriesSince(const base::Time initial_time); void OpenNextEntry(void** iter, Entry** next_entry); void OpenPrevEntry(void** iter, Entry** prev_entry); void EndEnumeration(void* iterator); void OnExternalCacheHit(const std::string& key); void CloseEntryImpl(EntryImpl* entry); void DoomEntryImpl(EntryImpl* entry); void FlushQueue(); // Dummy operation. void RunTask(const base::Closure& task); void ReadData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, int buf_len); void WriteData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, int buf_len, bool truncate); void ReadSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf, int buf_len); void WriteSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf, int buf_len); void GetAvailableRange(EntryImpl* entry, int64 offset, int len, int64* start); void CancelSparseIO(EntryImpl* entry); void ReadyForSparseIO(EntryImpl* entry); private: // There are two types of operations to proxy: regular backend operations are // executed sequentially (queued by the message loop). On the other hand, // operations targeted to a given entry can be long lived and support multiple // simultaneous users (multiple reads or writes to the same entry), and they // are subject to throttling, so we keep an explicit queue. enum Operation { OP_NONE = 0, OP_INIT, OP_OPEN, OP_CREATE, OP_DOOM, OP_DOOM_ALL, OP_DOOM_BETWEEN, OP_DOOM_SINCE, OP_OPEN_NEXT, OP_OPEN_PREV, OP_END_ENUMERATION, OP_ON_EXTERNAL_CACHE_HIT, OP_CLOSE_ENTRY, OP_DOOM_ENTRY, OP_FLUSH_QUEUE, OP_RUN_TASK, OP_MAX_BACKEND, OP_READ, OP_WRITE, OP_READ_SPARSE, OP_WRITE_SPARSE, OP_GET_RANGE, OP_CANCEL_IO, OP_IS_READY }; virtual ~BackendIO(); // Returns true if this operation returns an entry. bool ReturnsEntry(); // Returns the time that has passed since the operation was created. base::TimeDelta ElapsedTime() const; void ExecuteBackendOperation(); void ExecuteEntryOperation(); BackendImpl* backend_; net::CompletionCallback callback_; Operation operation_; // The arguments of all the operations we proxy: std::string key_; Entry** entry_ptr_; base::Time initial_time_; base::Time end_time_; void** iter_ptr_; void* iter_; EntryImpl* entry_; int index_; int offset_; scoped_refptr buf_; int buf_len_; bool truncate_; int64 offset64_; int64* start_; base::TimeTicks start_time_; base::Closure task_; DISALLOW_COPY_AND_ASSIGN(BackendIO); }; // The specialized controller that keeps track of current operations. class InFlightBackendIO : public InFlightIO { public: InFlightBackendIO(BackendImpl* backend, base::MessageLoopProxy* background_thread); virtual ~InFlightBackendIO(); // Proxied operations. void Init(const net::CompletionCallback& callback); void OpenEntry(const std::string& key, Entry** entry, const net::CompletionCallback& callback); void CreateEntry(const std::string& key, Entry** entry, const net::CompletionCallback& callback); void DoomEntry(const std::string& key, const net::CompletionCallback& callback); void DoomAllEntries(const net::CompletionCallback& callback); void DoomEntriesBetween(const base::Time initial_time, const base::Time end_time, const net::CompletionCallback& callback); void DoomEntriesSince(const base::Time initial_time, const net::CompletionCallback& callback); void OpenNextEntry(void** iter, Entry** next_entry, const net::CompletionCallback& callback); void OpenPrevEntry(void** iter, Entry** prev_entry, const net::CompletionCallback& callback); void EndEnumeration(void* iterator); void OnExternalCacheHit(const std::string& key); void CloseEntryImpl(EntryImpl* entry); void DoomEntryImpl(EntryImpl* entry); void FlushQueue(const net::CompletionCallback& callback); void RunTask(const base::Closure& task, const net::CompletionCallback& callback); void ReadData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback); void WriteData( EntryImpl* entry, int index, int offset, net::IOBuffer* buf, int buf_len, bool truncate, const net::CompletionCallback& callback); void ReadSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback); void WriteSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback); void GetAvailableRange(EntryImpl* entry, int64 offset, int len, int64* start, const net::CompletionCallback& callback); void CancelSparseIO(EntryImpl* entry); void ReadyForSparseIO(EntryImpl* entry, const net::CompletionCallback& callback); // Blocks until all operations are cancelled or completed. void WaitForPendingIO(); scoped_refptr background_thread() { return background_thread_; } // Returns true if the current thread is the background thread. bool BackgroundIsCurrentThread() { return background_thread_->BelongsToCurrentThread(); } base::WeakPtr GetWeakPtr(); protected: virtual void OnOperationComplete(BackgroundIO* operation, bool cancel) OVERRIDE; private: void PostOperation(BackendIO* operation); BackendImpl* backend_; scoped_refptr background_thread_; base::WeakPtrFactory ptr_factory_; DISALLOW_COPY_AND_ASSIGN(InFlightBackendIO); }; } // namespace disk_cache #endif // NET_DISK_CACHE_IN_FLIGHT_BACKEND_IO_H_