Home | History | Annotate | Download | only in dump_cache
      1 // Copyright (c) 2012 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/tools/dump_cache/simple_cache_dumper.h"
      6 
      7 #include "base/at_exit.h"
      8 #include "base/command_line.h"
      9 #include "base/logging.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/message_loop/message_loop_proxy.h"
     13 #include "base/threading/thread.h"
     14 #include "net/base/cache_type.h"
     15 #include "net/base/io_buffer.h"
     16 #include "net/base/net_errors.h"
     17 #include "net/disk_cache/disk_cache.h"
     18 #include "net/tools/dump_cache/cache_dumper.h"
     19 
     20 namespace net {
     21 
     22 SimpleCacheDumper::SimpleCacheDumper(base::FilePath input_path,
     23                                      base::FilePath output_path)
     24     : state_(STATE_NONE),
     25       input_path_(input_path),
     26       output_path_(output_path),
     27       writer_(new DiskDumper(output_path)),
     28       cache_thread_(new base::Thread("CacheThead")),
     29       src_entry_(NULL),
     30       dst_entry_(NULL),
     31       io_callback_(base::Bind(&SimpleCacheDumper::OnIOComplete,
     32                               base::Unretained(this))),
     33       rv_(0) {
     34 }
     35 
     36 SimpleCacheDumper::~SimpleCacheDumper() {
     37 }
     38 
     39 int SimpleCacheDumper::Run() {
     40   base::MessageLoopForIO main_message_loop;
     41 
     42   LOG(INFO) << "Reading cache from: " << input_path_.value();
     43   LOG(INFO) << "Writing cache to: " << output_path_.value();
     44 
     45   if (!cache_thread_->StartWithOptions(
     46           base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) {
     47     LOG(ERROR) << "Unable to start thread";
     48     return ERR_UNEXPECTED;
     49   }
     50   state_ = STATE_CREATE_CACHE;
     51   int rv = DoLoop(OK);
     52   if (rv == ERR_IO_PENDING) {
     53     main_message_loop.Run();
     54     return rv_;
     55   }
     56   return rv;
     57 }
     58 
     59 int SimpleCacheDumper::DoLoop(int rv) {
     60   do {
     61     State state = state_;
     62     state_ = STATE_NONE;
     63     switch (state) {
     64       case STATE_CREATE_CACHE:
     65         CHECK_EQ(OK, rv);
     66         rv = DoCreateCache();
     67         break;
     68       case STATE_CREATE_CACHE_COMPLETE:
     69         rv = DoCreateCacheComplete(rv);
     70         break;
     71       case STATE_OPEN_ENTRY:
     72         CHECK_EQ(OK, rv);
     73         rv = DoOpenEntry();
     74         break;
     75       case STATE_OPEN_ENTRY_COMPLETE:
     76         rv = DoOpenEntryComplete(rv);
     77         break;
     78       case STATE_CREATE_ENTRY:
     79         CHECK_EQ(OK, rv);
     80         rv = DoCreateEntry();
     81         break;
     82       case STATE_CREATE_ENTRY_COMPLETE:
     83         rv = DoCreateEntryComplete(rv);
     84         break;
     85       case STATE_READ_HEADERS:
     86         CHECK_EQ(OK, rv);
     87         rv = DoReadHeaders();
     88         break;
     89       case STATE_READ_HEADERS_COMPLETE:
     90         rv = DoReadHeadersComplete(rv);
     91         break;
     92       case STATE_WRITE_HEADERS:
     93         CHECK_EQ(OK, rv);
     94         rv = DoWriteHeaders();
     95         break;
     96       case STATE_WRITE_HEADERS_COMPLETE:
     97         rv = DoWriteHeadersComplete(rv);
     98         break;
     99       case STATE_READ_BODY:
    100         CHECK_EQ(OK, rv);
    101         rv = DoReadBody();
    102         break;
    103       case STATE_READ_BODY_COMPLETE:
    104         rv = DoReadBodyComplete(rv);
    105         break;
    106       case STATE_WRITE_BODY:
    107         CHECK_EQ(OK, rv);
    108         rv = DoWriteBody();
    109         break;
    110       case STATE_WRITE_BODY_COMPLETE:
    111         rv = DoWriteBodyComplete(rv);
    112         break;
    113       default:
    114         NOTREACHED() << "state_: " << state_;
    115         break;
    116     }
    117   } while (state_ != STATE_NONE && rv != ERR_IO_PENDING);
    118   return rv;
    119 }
    120 
    121 int SimpleCacheDumper::DoCreateCache() {
    122   DCHECK(!cache_);
    123   state_ = STATE_CREATE_CACHE_COMPLETE;
    124   return disk_cache::CreateCacheBackend(
    125       DISK_CACHE,
    126       CACHE_BACKEND_DEFAULT,
    127       input_path_,
    128       0,
    129       false,
    130       cache_thread_->message_loop_proxy().get(),
    131       NULL,
    132       &cache_,
    133       io_callback_);
    134 }
    135 
    136 int SimpleCacheDumper::DoCreateCacheComplete(int rv) {
    137   if (rv < 0)
    138     return rv;
    139 
    140   reinterpret_cast<disk_cache::BackendImpl*>(cache_.get())->SetUpgradeMode();
    141   reinterpret_cast<disk_cache::BackendImpl*>(cache_.get())->SetFlags(
    142       disk_cache::kNoRandom);
    143 
    144   state_ = STATE_OPEN_ENTRY;
    145   return OK;
    146 }
    147 
    148 int SimpleCacheDumper::DoOpenEntry() {
    149   DCHECK(!dst_entry_);
    150   DCHECK(!src_entry_);
    151   state_ = STATE_OPEN_ENTRY_COMPLETE;
    152   if (!iter_)
    153     iter_ = cache_->CreateIterator();
    154   return iter_->OpenNextEntry(&src_entry_, io_callback_);
    155 }
    156 
    157 int SimpleCacheDumper::DoOpenEntryComplete(int rv) {
    158   // ERR_FAILED indicates iteration finished.
    159   if (rv == ERR_FAILED)
    160     return OK;
    161 
    162   if (rv < 0)
    163     return rv;
    164 
    165   state_ = STATE_CREATE_ENTRY;
    166   return OK;
    167 }
    168 
    169 int SimpleCacheDumper::DoCreateEntry() {
    170   DCHECK(!dst_entry_);
    171   state_ = STATE_CREATE_ENTRY_COMPLETE;
    172 
    173   return writer_->CreateEntry(src_entry_->GetKey(), &dst_entry_,
    174                               io_callback_);
    175 }
    176 
    177 int SimpleCacheDumper::DoCreateEntryComplete(int rv) {
    178   if (rv < 0)
    179     return rv;
    180 
    181   state_ = STATE_READ_HEADERS;
    182   return OK;
    183 }
    184 
    185 int SimpleCacheDumper::DoReadHeaders() {
    186   state_ = STATE_READ_HEADERS_COMPLETE;
    187   int32 size = src_entry_->GetDataSize(0);
    188   buf_ = new IOBufferWithSize(size);
    189   return src_entry_->ReadData(0, 0, buf_.get(), size, io_callback_);
    190 }
    191 
    192 int SimpleCacheDumper::DoReadHeadersComplete(int rv) {
    193   if (rv < 0)
    194     return rv;
    195 
    196   state_ = STATE_WRITE_HEADERS;
    197   return OK;
    198 }
    199 
    200 int SimpleCacheDumper::DoWriteHeaders() {
    201   int rv = writer_->WriteEntry(
    202       dst_entry_, 0, 0, buf_.get(), buf_->size(), io_callback_);
    203   if (rv == 0)
    204     return ERR_FAILED;
    205 
    206   state_ = STATE_WRITE_HEADERS_COMPLETE;
    207   return OK;
    208 }
    209 
    210 int SimpleCacheDumper::DoWriteHeadersComplete(int rv) {
    211   if (rv < 0)
    212     return rv;
    213 
    214   state_ = STATE_READ_BODY;
    215   return OK;
    216 }
    217 
    218 int SimpleCacheDumper::DoReadBody() {
    219   state_ = STATE_READ_BODY_COMPLETE;
    220   int32 size = src_entry_->GetDataSize(1);
    221   // If the body is empty, we can neither read nor write it, so
    222   // just move to the next.
    223   if (size <= 0) {
    224     state_ = STATE_WRITE_BODY_COMPLETE;
    225     return OK;
    226   }
    227   buf_ = new IOBufferWithSize(size);
    228   return src_entry_->ReadData(1, 0, buf_.get(), size, io_callback_);
    229 }
    230 
    231 int SimpleCacheDumper::DoReadBodyComplete(int rv) {
    232   if (rv < 0)
    233     return rv;
    234 
    235   state_ = STATE_WRITE_BODY;
    236   return OK;
    237 }
    238 
    239 int SimpleCacheDumper::DoWriteBody() {
    240   int rv = writer_->WriteEntry(
    241       dst_entry_, 1, 0, buf_.get(), buf_->size(), io_callback_);
    242   if (rv == 0)
    243     return ERR_FAILED;
    244 
    245   state_ = STATE_WRITE_BODY_COMPLETE;
    246   return OK;
    247 }
    248 
    249 int SimpleCacheDumper::DoWriteBodyComplete(int rv) {
    250   if (rv < 0)
    251     return rv;
    252 
    253   src_entry_->Close();
    254   writer_->CloseEntry(dst_entry_, base::Time::Now(), base::Time::Now());
    255   src_entry_ = NULL;
    256   dst_entry_ = NULL;
    257 
    258   state_ = STATE_OPEN_ENTRY;
    259   return OK;
    260 }
    261 
    262 void SimpleCacheDumper::OnIOComplete(int rv) {
    263   rv = DoLoop(rv);
    264 
    265   if (rv != ERR_IO_PENDING) {
    266     rv_ = rv;
    267     cache_.reset();
    268     base::MessageLoop::current()->Quit();
    269   }
    270 }
    271 
    272 }  // namespace net
    273