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/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"
22 SimpleCacheDumper::SimpleCacheDumper(base::FilePath input_path
,
23 base::FilePath output_path
)
25 input_path_(input_path
),
26 output_path_(output_path
),
27 writer_(new DiskDumper(output_path
)),
28 cache_thread_(new base::Thread("CacheThead")),
31 io_callback_(base::Bind(&SimpleCacheDumper::OnIOComplete
,
32 base::Unretained(this))),
36 SimpleCacheDumper::~SimpleCacheDumper() {
39 int SimpleCacheDumper::Run() {
40 base::MessageLoopForIO main_message_loop
;
42 LOG(INFO
) << "Reading cache from: " << input_path_
.value();
43 LOG(INFO
) << "Writing cache to: " << output_path_
.value();
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
;
50 state_
= STATE_CREATE_CACHE
;
52 if (rv
== ERR_IO_PENDING
) {
53 main_message_loop
.Run();
59 int SimpleCacheDumper::DoLoop(int rv
) {
64 case STATE_CREATE_CACHE
:
68 case STATE_CREATE_CACHE_COMPLETE
:
69 rv
= DoCreateCacheComplete(rv
);
71 case STATE_OPEN_ENTRY
:
75 case STATE_OPEN_ENTRY_COMPLETE
:
76 rv
= DoOpenEntryComplete(rv
);
78 case STATE_CREATE_ENTRY
:
82 case STATE_CREATE_ENTRY_COMPLETE
:
83 rv
= DoCreateEntryComplete(rv
);
85 case STATE_READ_HEADERS
:
89 case STATE_READ_HEADERS_COMPLETE
:
90 rv
= DoReadHeadersComplete(rv
);
92 case STATE_WRITE_HEADERS
:
94 rv
= DoWriteHeaders();
96 case STATE_WRITE_HEADERS_COMPLETE
:
97 rv
= DoWriteHeadersComplete(rv
);
103 case STATE_READ_BODY_COMPLETE
:
104 rv
= DoReadBodyComplete(rv
);
106 case STATE_WRITE_BODY
:
110 case STATE_WRITE_BODY_COMPLETE
:
111 rv
= DoWriteBodyComplete(rv
);
114 NOTREACHED() << "state_: " << state_
;
117 } while (state_
!= STATE_NONE
&& rv
!= ERR_IO_PENDING
);
121 int SimpleCacheDumper::DoCreateCache() {
123 state_
= STATE_CREATE_CACHE_COMPLETE
;
124 return disk_cache::CreateCacheBackend(
126 CACHE_BACKEND_DEFAULT
,
130 cache_thread_
->message_loop_proxy().get(),
136 int SimpleCacheDumper::DoCreateCacheComplete(int rv
) {
140 reinterpret_cast<disk_cache::BackendImpl
*>(cache_
.get())->SetUpgradeMode();
141 reinterpret_cast<disk_cache::BackendImpl
*>(cache_
.get())->SetFlags(
142 disk_cache::kNoRandom
);
144 state_
= STATE_OPEN_ENTRY
;
148 int SimpleCacheDumper::DoOpenEntry() {
151 state_
= STATE_OPEN_ENTRY_COMPLETE
;
153 iter_
= cache_
->CreateIterator();
154 return iter_
->OpenNextEntry(&src_entry_
, io_callback_
);
157 int SimpleCacheDumper::DoOpenEntryComplete(int rv
) {
158 // ERR_FAILED indicates iteration finished.
159 if (rv
== ERR_FAILED
)
165 state_
= STATE_CREATE_ENTRY
;
169 int SimpleCacheDumper::DoCreateEntry() {
171 state_
= STATE_CREATE_ENTRY_COMPLETE
;
173 return writer_
->CreateEntry(src_entry_
->GetKey(), &dst_entry_
,
177 int SimpleCacheDumper::DoCreateEntryComplete(int rv
) {
181 state_
= STATE_READ_HEADERS
;
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_
);
192 int SimpleCacheDumper::DoReadHeadersComplete(int rv
) {
196 state_
= STATE_WRITE_HEADERS
;
200 int SimpleCacheDumper::DoWriteHeaders() {
201 int rv
= writer_
->WriteEntry(
202 dst_entry_
, 0, 0, buf_
.get(), buf_
->size(), io_callback_
);
206 state_
= STATE_WRITE_HEADERS_COMPLETE
;
210 int SimpleCacheDumper::DoWriteHeadersComplete(int rv
) {
214 state_
= STATE_READ_BODY
;
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.
224 state_
= STATE_WRITE_BODY_COMPLETE
;
227 buf_
= new IOBufferWithSize(size
);
228 return src_entry_
->ReadData(1, 0, buf_
.get(), size
, io_callback_
);
231 int SimpleCacheDumper::DoReadBodyComplete(int rv
) {
235 state_
= STATE_WRITE_BODY
;
239 int SimpleCacheDumper::DoWriteBody() {
240 int rv
= writer_
->WriteEntry(
241 dst_entry_
, 1, 0, buf_
.get(), buf_
->size(), io_callback_
);
245 state_
= STATE_WRITE_BODY_COMPLETE
;
249 int SimpleCacheDumper::DoWriteBodyComplete(int rv
) {
254 writer_
->CloseEntry(dst_entry_
, base::Time::Now(), base::Time::Now());
258 state_
= STATE_OPEN_ENTRY
;
262 void SimpleCacheDumper::OnIOComplete(int rv
) {
265 if (rv
!= ERR_IO_PENDING
) {
268 base::MessageLoop::current()->Quit();