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.
5 #include "net/tools/dump_cache/simple_cache_dumper.h"
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.h"
12 #include "base/message_loop_proxy.h"
13 #include "base/threading/thread.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
16 #include "net/disk_cache/disk_cache.h"
17 #include "net/tools/dump_cache/cache_dumper.h"
21 SimpleCacheDumper::SimpleCacheDumper(base::FilePath input_path
,
22 base::FilePath output_path
)
24 input_path_(input_path
),
25 output_path_(output_path
),
27 writer_(new DiskDumper(output_path
)),
28 cache_thread_(new base::Thread("CacheThead")),
32 io_callback_(base::Bind(&SimpleCacheDumper::OnIOComplete
,
33 base::Unretained(this))),
37 SimpleCacheDumper::~SimpleCacheDumper() {
41 int SimpleCacheDumper::Run() {
42 MessageLoopForIO main_message_loop
;
44 LOG(INFO
) << "Reading cache from: " << input_path_
.value();
45 LOG(INFO
) << "Writing cache to: " << output_path_
.value();
47 if (!cache_thread_
->StartWithOptions(
48 base::Thread::Options(MessageLoop::TYPE_IO
, 0))) {
49 LOG(ERROR
) << "Unable to start thread";
50 return ERR_UNEXPECTED
;
52 state_
= STATE_CREATE_CACHE
;
54 if (rv
== ERR_IO_PENDING
) {
55 main_message_loop
.Run();
61 int SimpleCacheDumper::DoLoop(int rv
) {
66 case STATE_CREATE_CACHE
:
70 case STATE_CREATE_CACHE_COMPLETE
:
71 rv
= DoCreateCacheComplete(rv
);
73 case STATE_OPEN_ENTRY
:
77 case STATE_OPEN_ENTRY_COMPLETE
:
78 rv
= DoOpenEntryComplete(rv
);
80 case STATE_CREATE_ENTRY
:
84 case STATE_CREATE_ENTRY_COMPLETE
:
85 rv
= DoCreateEntryComplete(rv
);
87 case STATE_READ_HEADERS
:
91 case STATE_READ_HEADERS_COMPLETE
:
92 rv
= DoReadHeadersComplete(rv
);
94 case STATE_WRITE_HEADERS
:
96 rv
= DoWriteHeaders();
98 case STATE_WRITE_HEADERS_COMPLETE
:
99 rv
= DoWriteHeadersComplete(rv
);
101 case STATE_READ_BODY
:
105 case STATE_READ_BODY_COMPLETE
:
106 rv
= DoReadBodyComplete(rv
);
108 case STATE_WRITE_BODY
:
112 case STATE_WRITE_BODY_COMPLETE
:
113 rv
= DoWriteBodyComplete(rv
);
116 NOTREACHED() << "state_: " << state_
;
119 } while (state_
!= STATE_NONE
&& rv
!= ERR_IO_PENDING
);
123 int SimpleCacheDumper::DoCreateCache() {
125 state_
= STATE_CREATE_CACHE_COMPLETE
;
126 return disk_cache::CreateCacheBackend(
127 DISK_CACHE
, input_path_
, 0, false,
128 cache_thread_
->message_loop_proxy(),
129 NULL
, &cache_
, io_callback_
);
132 int SimpleCacheDumper::DoCreateCacheComplete(int rv
) {
136 reinterpret_cast<disk_cache::BackendImpl
*>(cache_
)->SetUpgradeMode();
137 reinterpret_cast<disk_cache::BackendImpl
*>(cache_
)->SetFlags(
138 disk_cache::kNoRandom
);
140 state_
= STATE_OPEN_ENTRY
;
144 int SimpleCacheDumper::DoOpenEntry() {
147 state_
= STATE_OPEN_ENTRY_COMPLETE
;
148 return cache_
->OpenNextEntry(&iter_
, &src_entry_
, io_callback_
);
151 int SimpleCacheDumper::DoOpenEntryComplete(int rv
) {
152 // ERR_FAILED indicates iteration finished.
153 if (rv
== ERR_FAILED
) {
154 cache_
->EndEnumeration(&iter_
);
161 state_
= STATE_CREATE_ENTRY
;
165 int SimpleCacheDumper::DoCreateEntry() {
167 state_
= STATE_CREATE_ENTRY_COMPLETE
;
169 return writer_
->CreateEntry(src_entry_
->GetKey(), &dst_entry_
,
173 int SimpleCacheDumper::DoCreateEntryComplete(int rv
) {
177 state_
= STATE_READ_HEADERS
;
181 int SimpleCacheDumper::DoReadHeaders() {
182 state_
= STATE_READ_HEADERS_COMPLETE
;
183 int32 size
= src_entry_
->GetDataSize(0);
184 buf_
= new IOBufferWithSize(size
);
185 return src_entry_
->ReadData(0, 0, buf_
, size
, io_callback_
);
188 int SimpleCacheDumper::DoReadHeadersComplete(int rv
) {
192 state_
= STATE_WRITE_HEADERS
;
196 int SimpleCacheDumper::DoWriteHeaders() {
197 int rv
= writer_
->WriteEntry(dst_entry_
, 0, 0, buf_
, buf_
->size(),
202 state_
= STATE_WRITE_HEADERS_COMPLETE
;
206 int SimpleCacheDumper::DoWriteHeadersComplete(int rv
) {
210 state_
= STATE_READ_BODY
;
214 int SimpleCacheDumper::DoReadBody() {
215 state_
= STATE_READ_BODY_COMPLETE
;
216 int32 size
= src_entry_
->GetDataSize(1);
217 // If the body is empty, we can neither read nor write it, so
218 // just move to the next.
220 state_
= STATE_WRITE_BODY_COMPLETE
;
223 buf_
= new IOBufferWithSize(size
);
224 return src_entry_
->ReadData(1, 0, buf_
, size
, io_callback_
);
227 int SimpleCacheDumper::DoReadBodyComplete(int rv
) {
231 state_
= STATE_WRITE_BODY
;
235 int SimpleCacheDumper::DoWriteBody() {
236 int rv
= writer_
->WriteEntry(dst_entry_
, 1, 0, buf_
, buf_
->size(),
241 state_
= STATE_WRITE_BODY_COMPLETE
;
245 int SimpleCacheDumper::DoWriteBodyComplete(int rv
) {
250 writer_
->CloseEntry(dst_entry_
, base::Time::Now(), base::Time::Now());
254 state_
= STATE_OPEN_ENTRY
;
258 void SimpleCacheDumper::OnIOComplete(int rv
) {
261 if (rv
!= ERR_IO_PENDING
) {
265 MessageLoop::current()->Quit();