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

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

Issue 149306: Disk cache: Add explicit support for eviction / deletion... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 5 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') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/disk_cache/sparse_control.h" 5 #include "net/disk_cache/sparse_control.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/message_loop.h"
8 #include "base/string_util.h" 9 #include "base/string_util.h"
9 #include "base/time.h" 10 #include "base/time.h"
10 #include "net/base/io_buffer.h" 11 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h" 12 #include "net/base/net_errors.h"
12 #include "net/disk_cache/backend_impl.h" 13 #include "net/disk_cache/backend_impl.h"
13 #include "net/disk_cache/entry_impl.h" 14 #include "net/disk_cache/entry_impl.h"
15 #include "net/disk_cache/file.h"
14 16
15 using base::Time; 17 using base::Time;
16 18
17 namespace { 19 namespace {
18 20
19 // Stream of the sparse data index. 21 // Stream of the sparse data index.
20 const int kSparseIndex = 2; 22 const int kSparseIndex = 2;
21 23
22 // Stream of the sparse data. 24 // Stream of the sparse data.
23 const int kSparseData = 1; 25 const int kSparseData = 1;
24 26
27 // We can have up to 64k children.
28 const int kMaxMapSize = 8 * 1024;
29
30 // Returns the name of of a child entry given the base_name and signature of the
31 // parent and the child_id.
32 // If the entry is called entry_name, child entries will be named something
33 // like Range_entry_name:XXX:YYY where XXX is the entry signature and YYY is the
34 // number of the particular child.
35 std::string GenerateChildName(const std::string& base_name, int64 signature,
36 int64 child_id) {
37 return StringPrintf("Range_%s:%llx:%llx", base_name.c_str(), signature,
38 child_id);
39 }
40
41 // This class deletes the children of a sparse entry.
42 class ChildrenDeleter
43 : public base::RefCounted<ChildrenDeleter>,
44 public disk_cache::FileIOCallback {
45 public:
46 ChildrenDeleter(disk_cache::BackendImpl* backend, const std::string& name)
47 : backend_(backend), name_(name) {}
48
49 virtual void OnFileIOComplete(int bytes_copied);
50
51 // Two ways of deleting the children: if we have the children map, use Start()
52 // directly, otherwise pass the data address to ReadData().
53 void Start(char* buffer, int len);
54 void ReadData(disk_cache::Addr address, int len);
55
56 private:
57 void DeleteChildren();
58
59 disk_cache::BackendImpl* backend_;
60 std::string name_;
61 disk_cache::Bitmap children_map_;
62 int64 signature_;
63 scoped_array<char> buffer_;
64 DISALLOW_EVIL_CONSTRUCTORS(ChildrenDeleter);
65 };
66
67 // This is the callback of the file operation.
68 void ChildrenDeleter::OnFileIOComplete(int bytes_copied) {
69 char* buffer = buffer_.release();
70 Start(buffer, bytes_copied);
71 }
72
73 void ChildrenDeleter::Start(char* buffer, int len) {
74 buffer_.reset(buffer);
75 if (len < static_cast<int>(sizeof(disk_cache::SparseData)))
76 return Release();
77
78 // Just copy the information from |buffer|, delete |buffer| and start deleting
79 // the child entries.
80 disk_cache::SparseData* data =
81 reinterpret_cast<disk_cache::SparseData*>(buffer);
82 signature_ = data->header.signature;
83
84 int num_bits = (len - sizeof(disk_cache::SparseHeader)) * 8;
85 children_map_.Resize(num_bits, false);
86 children_map_.SetMap(data->bitmap, num_bits / 32);
87 buffer_.reset();
88
89 DeleteChildren();
90 }
91
92 void ChildrenDeleter::ReadData(disk_cache::Addr address, int len) {
93 DCHECK(address.is_block_file());
94 disk_cache::File* file(backend_->File(address));
95 if (!file)
96 return Release();
97
98 size_t file_offset = address.start_block() * address.BlockSize() +
99 disk_cache::kBlockHeaderSize;
100
101 buffer_.reset(new char[len]);
102 bool completed;
103 if (!file->Read(buffer_.get(), len, file_offset, this, &completed))
104 return Release();
105
106 if (completed)
107 OnFileIOComplete(len);
108
109 // And wait until OnFileIOComplete gets called.
110 }
111
112 void ChildrenDeleter::DeleteChildren() {
113 int child_id = 0;
114 if (!children_map_.FindNextSetBit(&child_id)) {
115 // We are done. Just delete this object.
116 return Release();
117 }
118 std::string child_name = GenerateChildName(name_, signature_, child_id);
119 backend_->DoomEntry(child_name);
120 children_map_.Set(child_id, false);
121
122 // Post a task to delete the next child.
123 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
124 this, &ChildrenDeleter::DeleteChildren));
125 }
126
25 } 127 }
26 128
27 namespace disk_cache { 129 namespace disk_cache {
28 130
29 SparseControl::~SparseControl() { 131 SparseControl::~SparseControl() {
30 if (child_) 132 if (child_)
31 CloseChild(); 133 CloseChild();
32 if (init_) 134 if (init_)
33 WriteSparseData(); 135 WriteSparseData();
34 } 136 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 if (range_found_) { 213 if (range_found_) {
112 *start = offset_; 214 *start = offset_;
113 return result; 215 return result;
114 } 216 }
115 217
116 // This is a failure. We want to return a valid start value in any case. 218 // This is a failure. We want to return a valid start value in any case.
117 *start = offset; 219 *start = offset;
118 return result < 0 ? result : 0; // Don't mask error codes to the caller. 220 return result < 0 ? result : 0; // Don't mask error codes to the caller.
119 } 221 }
120 222
223 // Static
224 void SparseControl::DeleteChildren(EntryImpl* entry) {
225 DCHECK(entry->GetEntryFlags() & PARENT_ENTRY);
226 int data_len = entry->GetDataSize(kSparseIndex);
227 if (data_len < static_cast<int>(sizeof(SparseData)) ||
228 entry->GetDataSize(kSparseData))
229 return;
230
231 int map_len = data_len - sizeof(SparseHeader);
232 if (map_len > kMaxMapSize || map_len % 4)
233 return;
234
235 char* buffer;
236 Addr address;
237 entry->GetData(kSparseIndex, &buffer, &address);
238 if (!buffer && !address.is_initialized())
239 return;
240
241 ChildrenDeleter* deleter = new ChildrenDeleter(entry->backend_,
242 entry->GetKey());
243 // The object will self destruct when finished.
244 deleter->AddRef();
245
246 if (buffer) {
247 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
248 deleter, &ChildrenDeleter::Start, buffer, data_len));
249 } else {
250 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
251 deleter, &ChildrenDeleter::ReadData, address, data_len));
252 }
253 }
254
121 // We are going to start using this entry to store sparse data, so we have to 255 // We are going to start using this entry to store sparse data, so we have to
122 // initialize our control info. 256 // initialize our control info.
123 int SparseControl::CreateSparseEntry() { 257 int SparseControl::CreateSparseEntry() {
124 // TODO(rvargas): Set/check a flag in EntryStore. 258 if (CHILD_ENTRY & entry_->GetEntryFlags())
259 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
125 260
126 memset(&sparse_header_, 0, sizeof(sparse_header_)); 261 memset(&sparse_header_, 0, sizeof(sparse_header_));
127 sparse_header_.signature = Time::Now().ToInternalValue(); 262 sparse_header_.signature = Time::Now().ToInternalValue();
128 sparse_header_.magic = kIndexMagic; 263 sparse_header_.magic = kIndexMagic;
129 sparse_header_.parent_key_len = entry_->GetKey().size(); 264 sparse_header_.parent_key_len = entry_->GetKey().size();
130 children_map_.Resize(kNumSparseBits, true); 265 children_map_.Resize(kNumSparseBits, true);
131 266
132 // Save the header. The bitmap is saved in the destructor. 267 // Save the header. The bitmap is saved in the destructor.
133 scoped_refptr<net::IOBuffer> buf = 268 scoped_refptr<net::IOBuffer> buf =
134 new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_)); 269 new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_));
135 270
136 int rv = entry_->WriteData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL, 271 int rv = entry_->WriteData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL,
137 false); 272 false);
138 if (rv != sizeof(sparse_header_)) { 273 if (rv != sizeof(sparse_header_)) {
139 DLOG(ERROR) << "Unable to save sparse_header_"; 274 DLOG(ERROR) << "Unable to save sparse_header_";
140 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 275 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
141 } 276 }
277
278 entry_->SetEntryFlags(PARENT_ENTRY);
142 return net::OK; 279 return net::OK;
143 } 280 }
144 281
145 // We are opening an entry from disk. Make sure that our control data is there. 282 // We are opening an entry from disk. Make sure that our control data is there.
146 int SparseControl::OpenSparseEntry(int data_len) { 283 int SparseControl::OpenSparseEntry(int data_len) {
147 if (data_len < static_cast<int>(sizeof(SparseData))) 284 if (data_len < static_cast<int>(sizeof(SparseData)))
148 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 285 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
149 286
150 if (entry_->GetDataSize(kSparseData)) 287 if (entry_->GetDataSize(kSparseData))
151 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 288 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
152 289
153 // TODO(rvargas): Set/check a flag in EntryStore. 290 if (!(PARENT_ENTRY & entry_->GetEntryFlags()))
291 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
154 292
155 // Dont't go over board with the bitmap. 8 KB gives us offsets up to 64 GB. 293 // Dont't go over board with the bitmap. 8 KB gives us offsets up to 64 GB.
156 int map_len = data_len - sizeof(sparse_header_); 294 int map_len = data_len - sizeof(sparse_header_);
157 if (map_len > 8 * 1024 || map_len % 4) 295 if (map_len > kMaxMapSize || map_len % 4)
158 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 296 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
159 297
160 scoped_refptr<net::IOBuffer> buf = 298 scoped_refptr<net::IOBuffer> buf =
161 new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_)); 299 new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_));
162 300
163 // Read header. 301 // Read header.
164 int rv = entry_->ReadData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL); 302 int rv = entry_->ReadData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL);
165 if (rv != static_cast<int>(sizeof(sparse_header_))) 303 if (rv != static_cast<int>(sizeof(sparse_header_)))
166 return net::ERR_CACHE_READ_FAILURE; 304 return net::ERR_CACHE_READ_FAILURE;
167 305
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 if (!entry_->backend_->CreateEntry(key, &child_)) { 347 if (!entry_->backend_->CreateEntry(key, &child_)) {
210 child_ = NULL; 348 child_ = NULL;
211 result_ = net::ERR_CACHE_READ_FAILURE; 349 result_ = net::ERR_CACHE_READ_FAILURE;
212 return false; 350 return false;
213 } 351 }
214 // Write signature. 352 // Write signature.
215 InitChildData(); 353 InitChildData();
216 return true; 354 return true;
217 } 355 }
218 356
219 // TODO(rvargas): Set/check a flag in EntryStore. 357 EntryImpl* child = static_cast<EntryImpl*>(child_);
358 if (!(CHILD_ENTRY & child->GetEntryFlags())) {
359 result_ = net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
360 return false;
361 }
220 362
221 scoped_refptr<net::WrappedIOBuffer> buf = 363 scoped_refptr<net::WrappedIOBuffer> buf =
222 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)); 364 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_));
223 365
224 // Read signature. 366 // Read signature.
225 int rv = child_->ReadData(kSparseIndex, 0, buf, sizeof(child_data_), NULL); 367 int rv = child_->ReadData(kSparseIndex, 0, buf, sizeof(child_data_), NULL);
226 if (rv != sizeof(child_data_)) { 368 if (rv != sizeof(child_data_)) {
227 result_ = net::ERR_CACHE_READ_FAILURE; 369 result_ = net::ERR_CACHE_READ_FAILURE;
228 return false; 370 return false;
229 } 371 }
(...skipping 13 matching lines...) Expand all
243 385
244 // Save the allocation bitmap before closing the child entry. 386 // Save the allocation bitmap before closing the child entry.
245 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_), 387 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_),
246 NULL, false); 388 NULL, false);
247 if (rv != sizeof(child_data_)) 389 if (rv != sizeof(child_data_))
248 DLOG(ERROR) << "Failed to save child data"; 390 DLOG(ERROR) << "Failed to save child data";
249 child_->Close(); 391 child_->Close();
250 child_ = NULL; 392 child_ = NULL;
251 } 393 }
252 394
253 // If this entry is called entry_name, child entreies will be named something
254 // like Range_entry_name:XXX:YYY where XXX is the entry signature and YYY is the
255 // number of the particular child.
256 std::string SparseControl::GenerateChildKey() { 395 std::string SparseControl::GenerateChildKey() {
257 return StringPrintf("Range_%s:%llx:%llx", entry_->GetKey().c_str(), 396 return GenerateChildName(entry_->GetKey(), sparse_header_.signature,
258 sparse_header_.signature, offset_ >> 20); 397 offset_ >> 20);
259 } 398 }
260 399
261 bool SparseControl::ChildPresent() { 400 bool SparseControl::ChildPresent() {
262 int child_bit = static_cast<int>(offset_ >> 20); 401 int child_bit = static_cast<int>(offset_ >> 20);
263 if (children_map_.Size() < child_bit) 402 if (children_map_.Size() <= child_bit)
264 return false; 403 return false;
265 404
266 return children_map_.Get(child_bit); 405 return children_map_.Get(child_bit);
267 } 406 }
268 407
269 void SparseControl::SetChildBit() { 408 void SparseControl::SetChildBit() {
270 int child_bit = static_cast<int>(offset_ >> 20); 409 int child_bit = static_cast<int>(offset_ >> 20);
271 410
272 // We may have to increase the bitmap of child entries. 411 // We may have to increase the bitmap of child entries.
273 if (children_map_.Size() <= child_bit) 412 if (children_map_.Size() <= child_bit)
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 458
320 // Write the bitmap. 459 // Write the bitmap.
321 int last_bit = (child_offset_ + result + 1023) >> 10; 460 int last_bit = (child_offset_ + result + 1023) >> 10;
322 child_map_.SetRange(child_offset_ >> 10, last_bit, true); 461 child_map_.SetRange(child_offset_ >> 10, last_bit, true);
323 462
324 // TODO(rvargas): Keep track of partial writes so that we don't consider the 463 // TODO(rvargas): Keep track of partial writes so that we don't consider the
325 // whole block to be present. 464 // whole block to be present.
326 } 465 }
327 466
328 void SparseControl::InitChildData() { 467 void SparseControl::InitChildData() {
468 // We know the real type of child_.
469 EntryImpl* child = static_cast<EntryImpl*>(child_);
470 child->SetEntryFlags(CHILD_ENTRY);
471
329 memset(&child_data_, 0, sizeof(child_data_)); 472 memset(&child_data_, 0, sizeof(child_data_));
330 child_data_.header = sparse_header_; 473 child_data_.header = sparse_header_;
331 474
332 scoped_refptr<net::WrappedIOBuffer> buf = 475 scoped_refptr<net::WrappedIOBuffer> buf =
333 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)); 476 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_));
334 477
335 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_), 478 int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_),
336 NULL, false); 479 NULL, false);
337 if (rv != sizeof(child_data_)) 480 if (rv != sizeof(child_data_))
338 DLOG(ERROR) << "Failed to save child data"; 481 DLOG(ERROR) << "Failed to save child data";
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 net::CompletionCallback* c = user_callback_; 601 net::CompletionCallback* c = user_callback_;
459 user_callback_ = NULL; 602 user_callback_ = NULL;
460 user_buf_ = NULL; 603 user_buf_ = NULL;
461 pending_ = false; 604 pending_ = false;
462 operation_ = kNoOperation; 605 operation_ = kNoOperation;
463 entry_->Release(); // Don't touch object after this line. 606 entry_->Release(); // Don't touch object after this line.
464 c->Run(result_); 607 c->Run(result_);
465 } 608 }
466 609
467 } // namespace disk_cache 610 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/sparse_control.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698