Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: net/disk_cache/sparse_control.cc

Issue 126179: Disk cache: First pass to add support for sparse entries.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/disk_cache/sparse_control.h ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 #include "net/disk_cache/sparse_control.h"
6
7 #include "base/logging.h"
8 #include "base/string_util.h"
9 #include "base/time.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
12 #include "net/disk_cache/backend_impl.h"
13 #include "net/disk_cache/entry_impl.h"
14
15 using base::Time;
16
17 namespace {
18
19 // Stream of the sparse data index.
20 const int kSparseIndex = 2;
21
22 // Stream of the sparse data.
23 const int kSparseData = 1;
24
25 }
26
27 namespace disk_cache {
28
29 SparseControl::~SparseControl() {
30 if (child_)
31 CloseChild();
32 if (init_)
33 WriteSparseData();
34 }
35
36 int SparseControl::Init() {
37 DCHECK(!init_);
38
39 // We should not have sparse data for the exposed entry.
40 if (entry_->GetDataSize(kSparseData))
41 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
42
43 // Now see if there is something where we store our data.
44 int rv = net::OK;
45 int data_len = entry_->GetDataSize(kSparseIndex);
46 if (!data_len) {
47 rv = CreateSparseEntry();
48 } else {
49 rv = OpenSparseEntry(data_len);
50 }
51
52 if (rv == net::OK)
53 init_ = true;
54 return rv;
55 }
56
57 int SparseControl::StartIO(SparseOperation op, int64 offset, net::IOBuffer* buf,
58 int buf_len, net::CompletionCallback* callback) {
59 DCHECK(init_);
60 // We don't support simultaneous IO for sparse data.
61 if (operation_ != kNoOperation)
62 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
63
64 if (offset < 0 || buf_len < 0)
65 return net::ERR_INVALID_ARGUMENT;
66
67 // We only support up to 64 GB.
68 if (offset + buf_len >= 0x1000000000LL)
69 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
70
71 DCHECK(!user_buf_);
72 DCHECK(!user_callback_);
73
74 // Copy the operation parameters.
75 operation_ = op;
76 offset_ = offset;
77 user_buf_ = new net::ReusedIOBuffer(buf, buf_len);
78 buf_len_ = buf_len;
79
80 result_ = 0;
81 pending_ = false;
82 finished_ = false;
83 user_callback_ = callback;
84
85 DoChildrenIO();
86
87 if (!pending_) {
88 // Everything was done synchronously.
89 operation_ = kNoOperation;
90 user_buf_ = NULL;
91 user_callback_ = NULL;
92 return result_;
93 }
94
95 return net::ERR_IO_PENDING;
96 }
97
98 int SparseControl::GetAvailableRange(int64 offset, int len, int64* start) {
99 DCHECK(init_);
100 NOTIMPLEMENTED();
101 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
102 }
103
104 // We are going to start using this entry to store sparse data, so we have to
105 // initialize our control info.
106 int SparseControl::CreateSparseEntry() {
107 // TODO(rvargas): Set/check a flag in EntryStore.
108
109 memset(&sparse_header_, 0, sizeof(sparse_header_));
110 sparse_header_.signature = Time::Now().ToInternalValue();
111 sparse_header_.magic = kIndexMagic;
112 sparse_header_.parent_key_len = entry_->GetKey().size();
113 children_map_.Resize(kNumSparseBits, true);
114
115 // Save the header. The bitmap is saved in the destructor.
116 scoped_refptr<net::IOBuffer> buf =
117 new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_));
118
119 int rv = entry_->WriteData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL,
120 false);
121 if (rv != sizeof(sparse_header_)) {
122 DLOG(ERROR) << "Unable to save sparse_header_";
123 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
124 }
125 return net::OK;
126 }
127
128 // We are opening an entry from disk. Make sure that our control data is there.
129 int SparseControl::OpenSparseEntry(int data_len) {
130 if (data_len < static_cast<int>(sizeof(SparseData)))
131 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
132
133 if (entry_->GetDataSize(kSparseData))
134 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
135
136 // TODO(rvargas): Set/check a flag in EntryStore.
137
138 // Dont't go over board with the bitmap. 8 KB gives us offsets up to 64 GB.
139 int map_len = data_len - sizeof(sparse_header_);
140 if (map_len > 8 * 1024 || map_len % 4)
141 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
142
143 scoped_refptr<net::IOBuffer> buf =
144 new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_));
145
146 // Read header.
147 int rv = entry_->ReadData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL);
148 if (rv != static_cast<int>(sizeof(sparse_header_)))
149 return net::ERR_CACHE_READ_FAILURE;
150
151 // The real validation should be performed by the caller. This is just to
152 // double check.
153 if (sparse_header_.magic != kIndexMagic ||
154 sparse_header_.parent_key_len !=
155 static_cast<int>(entry_->GetKey().size()))
156 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
157
158 // Read the actual bitmap.
159 buf = new net::IOBuffer(map_len);
160 rv = entry_->ReadData(kSparseIndex, sizeof(sparse_header_), buf, map_len,
161 NULL);
162 if (rv != map_len)
163 return net::ERR_CACHE_READ_FAILURE;
164
165 // Grow the bitmap to the current size and copy the bits.
166 children_map_.Resize(map_len * 8, false);
167 children_map_.SetMap(reinterpret_cast<uint32*>(buf->data()), map_len);
168 return net::OK;
169 }
170
171 bool SparseControl::OpenChild() {
172 DCHECK_GE(result_, 0);
173
174 std::string key = GenerateChildKey();
175 if (child_) {
176 // Keep using the same child or open another one?.
177 if (key == child_->GetKey())
178 return true;
179 CloseChild();
180 }
181
182 // Se if we are tracking this child.
183 bool child_present = ChildPresent();
184 if (kReadOperation == operation_ && !child_present)
185 return false;
186
187 if (!child_present || !entry_->backend_->OpenEntry(key, &child_)) {
188 if (!entry_->backend_->CreateEntry(key, &child_)) {
189 child_ = NULL;
190 result_ = net::ERR_CACHE_READ_FAILURE;
191 return false;
192 }
193 // Write signature.
194 InitChildData();
195 return true;
196 }
197
198 // TODO(rvargas): Set/check a flag in EntryStore.
199
200 scoped_refptr<net::WrappedIOBuffer> buf =
201 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_));
202
203 // Read signature.
204 int rv = child_->ReadData(kSparseIndex, 0, buf, sizeof(child_data_), NULL);
205 if (rv != sizeof(child_data_)) {
206 result_ = net::ERR_CACHE_READ_FAILURE;
207 return false;
208 }
209
210 // TODO(rvargas): Proper error handling and check magic etc.
211 if (child_data_.header.signature != sparse_header_.signature) {
212 result_ = net::ERR_CACHE_READ_FAILURE;
213 return false;
214 }
215
216 return true;
217 }
218
219 void SparseControl::CloseChild() {
220 scoped_refptr<net::WrappedIOBuffer> buf =
221 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_));
222
223 // Save the allocation bitmap before closing the child entry.
224 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_),
225 NULL, false);
226 if (rv != sizeof(child_data_))
227 DLOG(ERROR) << "Failed to save child data";
228 child_->Close();
229 child_ = NULL;
230 }
231
232 // If this entry is called entry_name, child entreies will be named something
233 // like Range_entry_name:XXX:YYY where XXX is the entry signature and YYY is the
234 // number of the particular child.
235 std::string SparseControl::GenerateChildKey() {
236 return StringPrintf("Range_%s:%llx:%llx", entry_->GetKey().c_str(),
237 sparse_header_.signature, offset_ >> 20);
238 }
239
240 bool SparseControl::ChildPresent() {
241 int child_bit = static_cast<int>(offset_ >> 20);
242 if (children_map_.Size() < child_bit)
243 return false;
244
245 return children_map_.Get(child_bit);
246 }
247
248 void SparseControl::SetChildBit() {
249 int child_bit = static_cast<int>(offset_ >> 20);
250
251 // We may have to increase the bitmap of child entries.
252 if (children_map_.Size() <= child_bit)
253 children_map_.Resize(Bitmap::RequiredArraySize(child_bit + 1) * 32, true);
254
255 children_map_.Set(child_bit, true);
256 }
257
258 void SparseControl::WriteSparseData() {
259 scoped_refptr<net::IOBuffer> buf = new net::WrappedIOBuffer(
260 reinterpret_cast<const char*>(children_map_.GetMap()));
261
262 int len = children_map_.ArraySize() * 4;
263 int rv = entry_->WriteData(kSparseIndex, sizeof(sparse_header_), buf, len,
264 NULL, false);
265 if (rv != len) {
266 DLOG(ERROR) << "Unable to save sparse map";
267 }
268 }
269
270 bool SparseControl::VerifyRange() {
271 DCHECK_GE(result_, 0);
272
273 child_offset_ = static_cast<int>(offset_) & 0xfffff;
274 child_len_ = std::min(buf_len_, 0x100000 - child_offset_);
275
276 // We can write to anywhere in this child.
277 if (operation_ != kReadOperation)
278 return true;
279
280 // Check that there are no holes in this range.
281 int last_bit = (child_offset_ + child_len_ + 1023) >> 10;
282 int start = child_offset_ >> 10;
283 if (child_map_.FindNextBit(&start, last_bit, false)) {
284 // Something is not here.
285 if (start == child_offset_ >> 10)
286 return false;
287
288 // We have the first part.
289 // TODO(rvargas): Avoid coming back here again after the actual read.
290 child_len_ = (start << 10) - child_offset_;
291 }
292 return true;
293 }
294
295 void SparseControl::UpdateRange(int result) {
296 if (result <= 0 || operation_ != kWriteOperation)
297 return;
298
299 // Write the bitmap.
300 int last_bit = (child_offset_ + result + 1023) >> 10;
301 child_map_.SetRange(child_offset_ >> 10, last_bit, true);
302
303 // TODO(rvargas): Keep track of partial writes so that we don't consider the
304 // whole block to be present.
305 }
306
307 void SparseControl::InitChildData() {
308 memset(&child_data_, 0, sizeof(child_data_));
309 child_data_.header = sparse_header_;
310
311 scoped_refptr<net::WrappedIOBuffer> buf =
312 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_));
313
314 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_),
315 NULL, false);
316 if (rv != sizeof(child_data_))
317 DLOG(ERROR) << "Failed to save child data";
318 SetChildBit();
319 }
320
321 void SparseControl::DoChildrenIO() {
322 while (DoChildIO()) continue;
323
324 if (pending_ && finished_)
325 DoUserCallback();
326 }
327
328 bool SparseControl::DoChildIO() {
329 finished_ = true;
330 if (!buf_len_ || result_ < 0)
331 return false;
332
333 if (!OpenChild())
334 return false;
335
336 if (!VerifyRange())
337 return false;
338
339 // We have more work to do. Let's not trigger a callback to the caller.
340 finished_ = false;
341 net::CompletionCallback* callback = user_callback_ ? &child_callback_ : NULL;
342
343 int rv;
344 if (kReadOperation == operation_) {
345 rv = child_->ReadData(kSparseData, child_offset_, user_buf_, child_len_,
346 callback);
347 } else {
348 DCHECK(kWriteOperation == operation_);
349 rv = child_->WriteData(kSparseData, child_offset_, user_buf_, child_len_,
350 callback, false);
351 }
352
353 if (rv == net::ERR_IO_PENDING) {
354 if (!pending_) {
355 pending_ = true;
356 // The child will protect himself against closing the entry while IO is in
357 // progress. However, this entry can still be closed, and that would not
358 // be a good thing for us, so we increase the refcount until we're
359 // finished doing sparse stuff.
360 entry_->AddRef();
361 }
362 return false;
363 }
364
365 DoChildIOCompleted(rv);
366 return true;
367 }
368
369 void SparseControl::DoChildIOCompleted(int result) {
370 if (result < 0) {
371 // We fail the whole operation if we encounter an error.
372 result_ = result;
373 return;
374 }
375
376 UpdateRange(result);
377
378 result_ += result;
379 offset_ += result;
380 buf_len_ -= result;
381
382 // We'll be reusing the user provided buffer for the next chunk.
383 if (buf_len_)
384 user_buf_->SetOffset(result_);
385 }
386
387 void SparseControl::OnChildIOCompleted(int result) {
388 DCHECK_NE(net::ERR_IO_PENDING, result);
389 DoChildIOCompleted(result);
390
391 // We are running a callback from the message loop. It's time to restart what
392 // we were doing before.
393 DoChildrenIO();
394 }
395
396 void SparseControl::DoUserCallback() {
397 DCHECK(user_callback_);
398 net::CompletionCallback* c = user_callback_;
399 user_callback_ = NULL;
400 user_buf_ = NULL;
401 pending_ = false;
402 operation_ = kNoOperation;
403 entry_->Release(); // Don't touch object after this line.
404 c->Run(result_);
405 }
406
407 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/sparse_control.h ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698