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