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