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