OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |