blob: a8a86eb9ffc55fb22fa90a1a99ae7ed434f2dc33 [file] [log] [blame]
// Copyright (c) 2011 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_
#pragma once
#include <list>
#include <string>
#include "base/message_loop_proxy.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/disk_cache/entry_impl.h"
#include "net/disk_cache/in_flight_io.h"
namespace disk_cache {
class BackendImpl;
// 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,
net::CompletionCallback* callback);
// Runs the actual operation on the background thread.
void ExecuteOperation();
// Callback implementation.
void OnIOComplete(int result);
// Returns true if this operation is directed to an entry (vs. the backend).
bool IsEntryOperation();
net::CompletionCallback* callback() { return callback_; }
// Grabs an extra reference of entry_.
void ReferenceEntry();
// Returns the time that has passed since the operation was created.
base::TimeDelta ElapsedTime() const;
// 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(Task* 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();
void ExecuteBackendOperation();
void ExecuteEntryOperation();
BackendImpl* backend_;
net::CompletionCallback* callback_;
Operation operation_;
net::CompletionCallbackImpl<BackendIO> my_callback_;
// 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<net::IOBuffer> buf_;
int buf_len_;
bool truncate_;
int64 offset64_;
int64* start_;
base::TimeTicks start_time_;
Task* 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();
// The operations we proxy:
void Init(net::CompletionCallback* callback);
void OpenEntry(const std::string& key, Entry** entry,
net::CompletionCallback* callback);
void CreateEntry(const std::string& key, Entry** entry,
net::CompletionCallback* callback);
void DoomEntry(const std::string& key, net::CompletionCallback* callback);
void DoomAllEntries(net::CompletionCallback* callback);
void DoomEntriesBetween(const base::Time initial_time,
const base::Time end_time,
net::CompletionCallback* callback);
void DoomEntriesSince(const base::Time initial_time,
net::CompletionCallback* callback);
void OpenNextEntry(void** iter, Entry** next_entry,
net::CompletionCallback* callback);
void OpenPrevEntry(void** iter, Entry** prev_entry,
net::CompletionCallback* callback);
void EndEnumeration(void* iterator);
void OnExternalCacheHit(const std::string& key);
void CloseEntryImpl(EntryImpl* entry);
void DoomEntryImpl(EntryImpl* entry);
void FlushQueue(net::CompletionCallback* callback);
void RunTask(Task* task, net::CompletionCallback* callback);
void ReadData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf,
int buf_len, net::CompletionCallback* callback);
void WriteData(EntryImpl* entry, int index, int offset, net::IOBuffer* buf,
int buf_len, bool truncate, net::CompletionCallback* callback);
void ReadSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf,
int buf_len, net::CompletionCallback* callback);
void WriteSparseData(EntryImpl* entry, int64 offset, net::IOBuffer* buf,
int buf_len, net::CompletionCallback* callback);
void GetAvailableRange(EntryImpl* entry, int64 offset, int len, int64* start,
net::CompletionCallback* callback);
void CancelSparseIO(EntryImpl* entry);
void ReadyForSparseIO(EntryImpl* entry, net::CompletionCallback* callback);
// Blocks until all operations are cancelled or completed.
void WaitForPendingIO();
scoped_refptr<base::MessageLoopProxy> background_thread() {
return background_thread_;
}
// Returns true if the current thread is the background thread.
bool BackgroundIsCurrentThread() {
return background_thread_->BelongsToCurrentThread();
}
protected:
virtual void OnOperationComplete(BackgroundIO* operation, bool cancel);
private:
void PostOperation(BackendIO* operation);
BackendImpl* backend_;
scoped_refptr<base::MessageLoopProxy> background_thread_;
DISALLOW_COPY_AND_ASSIGN(InFlightBackendIO);
};
} // namespace disk_cache
#endif // NET_DISK_CACHE_IN_FLIGHT_BACKEND_IO_H_