Index: net/tools/dump_cache/simple_cache_dumper.cc |
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 0000000000000000000000000000000000000000..73c3cd0d1047679d03049bafbe02738534941a36 |
--- /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 |