diff options
Diffstat (limited to 'net/tools/dump_cache/simple_cache_dumper.cc')
-rw-r--r-- | net/tools/dump_cache/simple_cache_dumper.cc | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/net/tools/dump_cache/simple_cache_dumper.cc b/net/tools/dump_cache/simple_cache_dumper.cc new file mode 100644 index 0000000..73c3cd0 --- /dev/null +++ b/net/tools/dump_cache/simple_cache_dumper.cc @@ -0,0 +1,268 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/tools/dump_cache/simple_cache_dumper.h" + +#include "base/at_exit.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "base/message_loop_proxy.h" +#include "base/threading/thread.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/disk_cache/disk_cache.h" +#include "net/tools/dump_cache/cache_dumper.h" + +namespace net { + +SimpleCacheDumper::SimpleCacheDumper(FilePath input_path, FilePath output_path) + : state_(STATE_NONE), + input_path_(input_path), + output_path_(output_path), + cache_(NULL), + writer_(new DiskDumper(output_path)), + cache_thread_(new base::Thread("CacheThead")), + iter_(NULL), + src_entry_(NULL), + dst_entry_(NULL), + io_callback_(base::Bind(&SimpleCacheDumper::OnIOComplete, + base::Unretained(this))), + rv_(0) { +} + +SimpleCacheDumper::~SimpleCacheDumper() { + delete(cache_); +} + +int SimpleCacheDumper::Run() { + MessageLoopForIO main_message_loop; + + LOG(INFO) << "Reading cache from: " << input_path_.value(); + LOG(INFO) << "Writing cache to: " << output_path_.value(); + + if (!cache_thread_->StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))) { + LOG(ERROR) << "Unable to start thread"; + return ERR_UNEXPECTED; + } + state_ = STATE_CREATE_CACHE; + int rv = DoLoop(OK); + if (rv == ERR_IO_PENDING) { + main_message_loop.Run(); + return rv_; + } + return rv; +} + +int SimpleCacheDumper::DoLoop(int rv) { + do { + State state = state_; + state_ = STATE_NONE; + switch (state) { + case STATE_CREATE_CACHE: + CHECK_EQ(OK, rv); + rv = DoCreateCache(); + break; + case STATE_CREATE_CACHE_COMPLETE: + rv = DoCreateCacheComplete(rv); + break; + case STATE_OPEN_ENTRY: + CHECK_EQ(OK, rv); + rv = DoOpenEntry(); + break; + case STATE_OPEN_ENTRY_COMPLETE: + rv = DoOpenEntryComplete(rv); + break; + case STATE_CREATE_ENTRY: + CHECK_EQ(OK, rv); + rv = DoCreateEntry(); + break; + case STATE_CREATE_ENTRY_COMPLETE: + rv = DoCreateEntryComplete(rv); + break; + case STATE_READ_HEADERS: + CHECK_EQ(OK, rv); + rv = DoReadHeaders(); + break; + case STATE_READ_HEADERS_COMPLETE: + rv = DoReadHeadersComplete(rv); + break; + case STATE_WRITE_HEADERS: + CHECK_EQ(OK, rv); + rv = DoWriteHeaders(); + break; + case STATE_WRITE_HEADERS_COMPLETE: + rv = DoWriteHeadersComplete(rv); + break; + case STATE_READ_BODY: + CHECK_EQ(OK, rv); + rv = DoReadBody(); + break; + case STATE_READ_BODY_COMPLETE: + rv = DoReadBodyComplete(rv); + break; + case STATE_WRITE_BODY: + CHECK_EQ(OK, rv); + rv = DoWriteBody(); + break; + case STATE_WRITE_BODY_COMPLETE: + rv = DoWriteBodyComplete(rv); + break; + default: + NOTREACHED() << "state_: " << state_; + break; + } + } while (state_ != STATE_NONE && rv != ERR_IO_PENDING); + return rv; +} + +int SimpleCacheDumper::DoCreateCache() { + DCHECK(!cache_); + state_ = STATE_CREATE_CACHE_COMPLETE; + return disk_cache::CreateCacheBackend( + DISK_CACHE, input_path_, 0, false, + cache_thread_->message_loop_proxy(), + NULL, &cache_, io_callback_); +} + +int SimpleCacheDumper::DoCreateCacheComplete(int rv) { + if (rv < 0) + return rv; + + reinterpret_cast<disk_cache::BackendImpl*>(cache_)->SetUpgradeMode(); + reinterpret_cast<disk_cache::BackendImpl*>(cache_)->SetFlags( + disk_cache::kNoRandom); + + state_ = STATE_OPEN_ENTRY; + return OK; +} + +int SimpleCacheDumper::DoOpenEntry() { + DCHECK(!dst_entry_); + DCHECK(!src_entry_); + state_ = STATE_OPEN_ENTRY_COMPLETE; + return cache_->OpenNextEntry(&iter_, &src_entry_, io_callback_); +} + +int SimpleCacheDumper::DoOpenEntryComplete(int rv) { + // ERR_FAILED indicates iteration finished. + if (rv == ERR_FAILED) { + cache_->EndEnumeration(&iter_); + return OK; + } + + if (rv < 0) + return rv; + + state_ = STATE_CREATE_ENTRY; + return OK; +} + +int SimpleCacheDumper::DoCreateEntry() { + DCHECK(!dst_entry_); + state_ = STATE_CREATE_ENTRY_COMPLETE; + + return writer_->CreateEntry(src_entry_->GetKey(), &dst_entry_, + io_callback_); +} + +int SimpleCacheDumper::DoCreateEntryComplete(int rv) { + if (rv < 0) + return rv; + + state_ = STATE_READ_HEADERS; + return OK; +} + +int SimpleCacheDumper::DoReadHeaders() { + state_ = STATE_READ_HEADERS_COMPLETE; + int32 size = src_entry_->GetDataSize(0); + buf_ = new IOBufferWithSize(size); + return src_entry_->ReadData(0, 0, buf_, size, io_callback_); +} + +int SimpleCacheDumper::DoReadHeadersComplete(int rv) { + if (rv < 0) + return rv; + + state_ = STATE_WRITE_HEADERS; + return OK; +} + +int SimpleCacheDumper::DoWriteHeaders() { + int rv = writer_->WriteEntry(dst_entry_, 0, 0, buf_, buf_->size(), + io_callback_); + if (rv == 0) + return ERR_FAILED; + + state_ = STATE_WRITE_HEADERS_COMPLETE; + return OK; +} + +int SimpleCacheDumper::DoWriteHeadersComplete(int rv) { + if (rv < 0) + return rv; + + state_ = STATE_READ_BODY; + return OK; +} + +int SimpleCacheDumper::DoReadBody() { + state_ = STATE_READ_BODY_COMPLETE; + int32 size = src_entry_->GetDataSize(1); + // If the body is empty, we can neither read nor write it, so + // just move to the next. + if (size <= 0) { + state_ = STATE_WRITE_BODY_COMPLETE; + return OK; + } + buf_ = new IOBufferWithSize(size); + return src_entry_->ReadData(1, 0, buf_, size, io_callback_); +} + +int SimpleCacheDumper::DoReadBodyComplete(int rv) { + if (rv < 0) + return rv; + + state_ = STATE_WRITE_BODY; + return OK; +} + +int SimpleCacheDumper::DoWriteBody() { + int rv = writer_->WriteEntry(dst_entry_, 1, 0, buf_, buf_->size(), + io_callback_); + if (rv == 0) + return ERR_FAILED; + + state_ = STATE_WRITE_BODY_COMPLETE; + return OK; +} + +int SimpleCacheDumper::DoWriteBodyComplete(int rv) { + if (rv < 0) + return rv; + + src_entry_->Close(); + writer_->CloseEntry(dst_entry_, base::Time::Now(), base::Time::Now()); + src_entry_ = NULL; + dst_entry_ = NULL; + + state_ = STATE_OPEN_ENTRY; + return OK; +} + +void SimpleCacheDumper::OnIOComplete(int rv) { + rv = DoLoop(rv); + + if (rv != ERR_IO_PENDING) { + rv_ = rv; + delete cache_; + cache_ = NULL; + MessageLoop::current()->Quit(); + } +} + +} // namespace net |