1// Copyright (c) 2009-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_SPARSE_CONTROL_H_
6#define NET_DISK_CACHE_SPARSE_CONTROL_H_
7#pragma once
8
9#include <string>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/compiler_specific.h"
14#include "net/base/completion_callback.h"
15#include "net/disk_cache/bitmap.h"
16#include "net/disk_cache/disk_format.h"
17
18namespace net {
19class IOBuffer;
20class DrainableIOBuffer;
21}
22
23namespace disk_cache {
24
25class Entry;
26class EntryImpl;
27
28// This class provides support for the sparse capabilities of the disk cache.
29// Basically, sparse IO is directed from EntryImpl to this class, and we split
30// the operation into multiple small pieces, sending each one to the
31// appropriate entry. An instance of this class is asociated with each entry
32// used directly for sparse operations (the entry passed in to the constructor).
33class SparseControl {
34 public:
35  // The operation to perform.
36  enum SparseOperation {
37    kNoOperation,
38    kReadOperation,
39    kWriteOperation,
40    kGetRangeOperation
41  };
42
43  explicit SparseControl(EntryImpl* entry);
44  ~SparseControl();
45
46  // Initializes the object for the current entry. If this entry already stores
47  // sparse data, or can be used to do it, it updates the relevant information
48  // on disk and returns net::OK. Otherwise it returns a net error code.
49  int Init();
50
51  // Performs a quick test to see if the entry is sparse or not, without
52  // generating disk IO (so the answer provided is only a best effort).
53  bool CouldBeSparse() const;
54
55  // Performs an actual sparse read or write operation for this entry. |op| is
56  // the operation to perform, |offset| is the desired sparse offset, |buf| and
57  // |buf_len| specify the actual data to use and |callback| is the callback
58  // to use for asynchronous operations. See the description of the Read /
59  // WriteSparseData for details about the arguments. The return value is the
60  // number of bytes read or written, or a net error code.
61  int StartIO(SparseOperation op, int64 offset, net::IOBuffer* buf,
62              int buf_len, net::CompletionCallback* callback);
63
64  // Implements Entry::GetAvailableRange().
65  int GetAvailableRange(int64 offset, int len, int64* start);
66
67  // Cancels the current sparse operation (if any).
68  void CancelIO();
69
70  // Returns OK if the entry can be used for new IO or ERR_IO_PENDING if we are
71  // busy. If the entry is busy, we'll invoke the callback when we are ready
72  // again. See disk_cache::Entry::ReadyToUse() for more info.
73  int ReadyToUse(net::CompletionCallback* completion_callback);
74
75  // Deletes the children entries of |entry|.
76  static void DeleteChildren(EntryImpl* entry);
77
78 private:
79  // Creates a new sparse entry or opens an aready created entry from disk.
80  // These methods just read / write the required info from disk for the current
81  // entry, and verify that everything is correct. The return value is a net
82  // error code.
83  int CreateSparseEntry();
84  int OpenSparseEntry(int data_len);
85
86  // Opens and closes a child entry. A child entry is a regular EntryImpl object
87  // with a key derived from the key of the resource to store and the range
88  // stored by that child.
89  bool OpenChild();
90  void CloseChild();
91  std::string GenerateChildKey();
92
93  // Deletes the current child and continues the current operation (open).
94  bool KillChildAndContinue(const std::string& key, bool fatal);
95
96  // Continues the current operation (open) without a current child.
97  bool ContinueWithoutChild(const std::string& key);
98
99  // Returns true if the required child is tracked by the parent entry, i.e. it
100  // was already created.
101  bool ChildPresent();
102
103  // Sets the bit for the current child to the provided |value|. In other words,
104  // starts or stops tracking this child.
105  void SetChildBit(bool value);
106
107  // Writes to disk the tracking information for this entry.
108  void WriteSparseData();
109
110  // Verify that the range to be accessed for the current child is appropriate.
111  // Returns false if an error is detected or there is no need to perform the
112  // current IO operation (for instance if the required range is not stored by
113  // the child).
114  bool VerifyRange();
115
116  // Updates the contents bitmap for the current range, based on the result of
117  // the current operation.
118  void UpdateRange(int result);
119
120  // Returns the number of bytes stored at |block_index|, if its allocation-bit
121  // is off (because it is not completely filled).
122  int PartialBlockLength(int block_index) const;
123
124  // Initializes the sparse info for the current child.
125  void InitChildData();
126
127  // Iterates through all the children needed to complete the current operation.
128  void DoChildrenIO();
129
130  // Performs a single operation with the current child. Returns true when we
131  // should move on to the next child and false when we should interrupt our
132  // work.
133  bool DoChildIO();
134
135  // Performs the required work for GetAvailableRange for one child.
136  int DoGetAvailableRange();
137
138  // Performs the required work after a single IO operations finishes.
139  void DoChildIOCompleted(int result);
140
141  // Invoked by the callback of asynchronous operations.
142  void OnChildIOCompleted(int result);
143
144  // Reports to the user that we are done.
145  void DoUserCallback();
146  void DoAbortCallbacks();
147
148  EntryImpl* entry_;  // The sparse entry.
149  EntryImpl* child_;  // The current child entry.
150  SparseOperation operation_;
151  bool pending_;  // True if any child IO operation returned pending.
152  bool finished_;
153  bool init_;
154  bool range_found_;  // True if GetAvailableRange found something.
155  bool abort_;  // True if we should abort the current operation ASAP.
156
157  SparseHeader sparse_header_;  // Data about the children of entry_.
158  Bitmap children_map_;  // The actual bitmap of children.
159  SparseData child_data_;  // Parent and allocation map of child_.
160  Bitmap child_map_;  // The allocation map as a bitmap.
161
162  net::CompletionCallbackImpl<SparseControl> child_callback_;
163  net::CompletionCallback* user_callback_;
164  std::vector<net::CompletionCallback*> abort_callbacks_;
165  int64 offset_;  // Current sparse offset.
166  scoped_refptr<net::DrainableIOBuffer> user_buf_;
167  int buf_len_;  // Bytes to read or write.
168  int child_offset_;  // Offset to use for the current child.
169  int child_len_;  // Bytes to read or write for this child.
170  int result_;
171
172  DISALLOW_COPY_AND_ASSIGN(SparseControl);
173};
174
175}  // namespace disk_cache
176
177#endif  // NET_DISK_CACHE_SPARSE_CONTROL_H_
178