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/profiler/scoped_tracker.h"
14 #include "base/threading/thread.h"
15 #include "net/base/cache_type.h"
16 #include "net/base/io_buffer.h"
17 #include "net/base/net_errors.h"
18 #include "net/disk_cache/disk_cache.h"
19 #include "net/tools/dump_cache/cache_dumper.h"
23 SimpleCacheDumper::SimpleCacheDumper(base::FilePath input_path
,
24 base::FilePath output_path
)
26 input_path_(input_path
),
27 output_path_(output_path
),
28 writer_(new DiskDumper(output_path
)),
29 cache_thread_(new base::Thread("CacheThead")),
32 io_callback_(base::Bind(&SimpleCacheDumper::OnIOComplete
,
33 base::Unretained(this))),
37 SimpleCacheDumper::~SimpleCacheDumper() {
40 int SimpleCacheDumper::Run() {
41 base::MessageLoopForIO main_message_loop
;
43 LOG(INFO
) << "Reading cache from: " << input_path_
.value();
44 LOG(INFO
) << "Writing cache to: " << output_path_
.value();
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
;
51 state_
= STATE_CREATE_CACHE
;
53 if (rv
== ERR_IO_PENDING
) {
54 main_message_loop
.Run();
60 int SimpleCacheDumper::DoLoop(int rv
) {
65 case STATE_CREATE_CACHE
:
69 case STATE_CREATE_CACHE_COMPLETE
:
70 rv
= DoCreateCacheComplete(rv
);
72 case STATE_OPEN_ENTRY
:
76 case STATE_OPEN_ENTRY_COMPLETE
:
77 rv
= DoOpenEntryComplete(rv
);
79 case STATE_CREATE_ENTRY
:
83 case STATE_CREATE_ENTRY_COMPLETE
:
84 rv
= DoCreateEntryComplete(rv
);
86 case STATE_READ_HEADERS
:
90 case STATE_READ_HEADERS_COMPLETE
:
91 rv
= DoReadHeadersComplete(rv
);
93 case STATE_WRITE_HEADERS
:
95 rv
= DoWriteHeaders();
97 case STATE_WRITE_HEADERS_COMPLETE
:
98 rv
= DoWriteHeadersComplete(rv
);
100 case STATE_READ_BODY
:
104 case STATE_READ_BODY_COMPLETE
:
105 rv
= DoReadBodyComplete(rv
);
107 case STATE_WRITE_BODY
:
111 case STATE_WRITE_BODY_COMPLETE
:
112 rv
= DoWriteBodyComplete(rv
);
115 NOTREACHED() << "state_: " << state_
;
118 } while (state_
!= STATE_NONE
&& rv
!= ERR_IO_PENDING
);
122 int SimpleCacheDumper::DoCreateCache() {
124 state_
= STATE_CREATE_CACHE_COMPLETE
;
125 return disk_cache::CreateCacheBackend(
127 CACHE_BACKEND_DEFAULT
,
131 cache_thread_
->message_loop_proxy().get(),
137 int SimpleCacheDumper::DoCreateCacheComplete(int rv
) {
141 reinterpret_cast<disk_cache::BackendImpl
*>(cache_
.get())->SetUpgradeMode();
142 reinterpret_cast<disk_cache::BackendImpl
*>(cache_
.get())->SetFlags(
143 disk_cache::kNoRandom
);
145 state_
= STATE_OPEN_ENTRY
;
149 int SimpleCacheDumper::DoOpenEntry() {
152 state_
= STATE_OPEN_ENTRY_COMPLETE
;
154 iter_
= cache_
->CreateIterator();
155 return iter_
->OpenNextEntry(&src_entry_
, io_callback_
);
158 int SimpleCacheDumper::DoOpenEntryComplete(int rv
) {
159 // ERR_FAILED indicates iteration finished.
160 if (rv
== ERR_FAILED
)
166 state_
= STATE_CREATE_ENTRY
;
170 int SimpleCacheDumper::DoCreateEntry() {
172 state_
= STATE_CREATE_ENTRY_COMPLETE
;
174 return writer_
->CreateEntry(src_entry_
->GetKey(), &dst_entry_
,
178 int SimpleCacheDumper::DoCreateEntryComplete(int rv
) {
182 state_
= STATE_READ_HEADERS
;
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_
);
193 int SimpleCacheDumper::DoReadHeadersComplete(int rv
) {
197 state_
= STATE_WRITE_HEADERS
;
201 int SimpleCacheDumper::DoWriteHeaders() {
202 int rv
= writer_
->WriteEntry(
203 dst_entry_
, 0, 0, buf_
.get(), buf_
->size(), io_callback_
);
207 state_
= STATE_WRITE_HEADERS_COMPLETE
;
211 int SimpleCacheDumper::DoWriteHeadersComplete(int rv
) {
215 state_
= STATE_READ_BODY
;
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.
225 state_
= STATE_WRITE_BODY_COMPLETE
;
228 buf_
= new IOBufferWithSize(size
);
229 return src_entry_
->ReadData(1, 0, buf_
.get(), size
, io_callback_
);
232 int SimpleCacheDumper::DoReadBodyComplete(int rv
) {
236 state_
= STATE_WRITE_BODY
;
240 int SimpleCacheDumper::DoWriteBody() {
241 int rv
= writer_
->WriteEntry(
242 dst_entry_
, 1, 0, buf_
.get(), buf_
->size(), io_callback_
);
246 state_
= STATE_WRITE_BODY_COMPLETE
;
250 int SimpleCacheDumper::DoWriteBodyComplete(int rv
) {
255 writer_
->CloseEntry(dst_entry_
, base::Time::Now(), base::Time::Now());
259 state_
= STATE_OPEN_ENTRY
;
263 void SimpleCacheDumper::OnIOComplete(int rv
) {
264 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
265 tracked_objects::ScopedTracker
tracking_profile(
266 FROM_HERE_WITH_EXPLICIT_FUNCTION(
267 "422516 SimpleCacheDumper::OnIOComplete"));
271 if (rv
!= ERR_IO_PENDING
) {
274 base::MessageLoop::current()->Quit();