| OLD | NEW | 
| (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 | 
| OLD | NEW |