| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "net/tools/dump_cache/simple_cache_dumper.h" | |
| 6 | |
| 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" | |
| 20 | |
| 21 namespace net { | |
| 22 | |
| 23 SimpleCacheDumper::SimpleCacheDumper(base::FilePath input_path, | |
| 24 base::FilePath output_path) | |
| 25 : state_(STATE_NONE), | |
| 26 input_path_(input_path), | |
| 27 output_path_(output_path), | |
| 28 writer_(new DiskDumper(output_path)), | |
| 29 cache_thread_(new base::Thread("CacheThead")), | |
| 30 src_entry_(NULL), | |
| 31 dst_entry_(NULL), | |
| 32 io_callback_(base::Bind(&SimpleCacheDumper::OnIOComplete, | |
| 33 base::Unretained(this))), | |
| 34 rv_(0) { | |
| 35 } | |
| 36 | |
| 37 SimpleCacheDumper::~SimpleCacheDumper() { | |
| 38 } | |
| 39 | |
| 40 int SimpleCacheDumper::Run() { | |
| 41 base::MessageLoopForIO main_message_loop; | |
| 42 | |
| 43 LOG(INFO) << "Reading cache from: " << input_path_.value(); | |
| 44 LOG(INFO) << "Writing cache to: " << output_path_.value(); | |
| 45 | |
| 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; | |
| 50 } | |
| 51 state_ = STATE_CREATE_CACHE; | |
| 52 int rv = DoLoop(OK); | |
| 53 if (rv == ERR_IO_PENDING) { | |
| 54 main_message_loop.Run(); | |
| 55 return rv_; | |
| 56 } | |
| 57 return rv; | |
| 58 } | |
| 59 | |
| 60 int SimpleCacheDumper::DoLoop(int rv) { | |
| 61 do { | |
| 62 State state = state_; | |
| 63 state_ = STATE_NONE; | |
| 64 switch (state) { | |
| 65 case STATE_CREATE_CACHE: | |
| 66 CHECK_EQ(OK, rv); | |
| 67 rv = DoCreateCache(); | |
| 68 break; | |
| 69 case STATE_CREATE_CACHE_COMPLETE: | |
| 70 rv = DoCreateCacheComplete(rv); | |
| 71 break; | |
| 72 case STATE_OPEN_ENTRY: | |
| 73 CHECK_EQ(OK, rv); | |
| 74 rv = DoOpenEntry(); | |
| 75 break; | |
| 76 case STATE_OPEN_ENTRY_COMPLETE: | |
| 77 rv = DoOpenEntryComplete(rv); | |
| 78 break; | |
| 79 case STATE_CREATE_ENTRY: | |
| 80 CHECK_EQ(OK, rv); | |
| 81 rv = DoCreateEntry(); | |
| 82 break; | |
| 83 case STATE_CREATE_ENTRY_COMPLETE: | |
| 84 rv = DoCreateEntryComplete(rv); | |
| 85 break; | |
| 86 case STATE_READ_HEADERS: | |
| 87 CHECK_EQ(OK, rv); | |
| 88 rv = DoReadHeaders(); | |
| 89 break; | |
| 90 case STATE_READ_HEADERS_COMPLETE: | |
| 91 rv = DoReadHeadersComplete(rv); | |
| 92 break; | |
| 93 case STATE_WRITE_HEADERS: | |
| 94 CHECK_EQ(OK, rv); | |
| 95 rv = DoWriteHeaders(); | |
| 96 break; | |
| 97 case STATE_WRITE_HEADERS_COMPLETE: | |
| 98 rv = DoWriteHeadersComplete(rv); | |
| 99 break; | |
| 100 case STATE_READ_BODY: | |
| 101 CHECK_EQ(OK, rv); | |
| 102 rv = DoReadBody(); | |
| 103 break; | |
| 104 case STATE_READ_BODY_COMPLETE: | |
| 105 rv = DoReadBodyComplete(rv); | |
| 106 break; | |
| 107 case STATE_WRITE_BODY: | |
| 108 CHECK_EQ(OK, rv); | |
| 109 rv = DoWriteBody(); | |
| 110 break; | |
| 111 case STATE_WRITE_BODY_COMPLETE: | |
| 112 rv = DoWriteBodyComplete(rv); | |
| 113 break; | |
| 114 default: | |
| 115 NOTREACHED() << "state_: " << state_; | |
| 116 break; | |
| 117 } | |
| 118 } while (state_ != STATE_NONE && rv != ERR_IO_PENDING); | |
| 119 return rv; | |
| 120 } | |
| 121 | |
| 122 int SimpleCacheDumper::DoCreateCache() { | |
| 123 DCHECK(!cache_); | |
| 124 state_ = STATE_CREATE_CACHE_COMPLETE; | |
| 125 return disk_cache::CreateCacheBackend( | |
| 126 DISK_CACHE, | |
| 127 CACHE_BACKEND_DEFAULT, | |
| 128 input_path_, | |
| 129 0, | |
| 130 false, | |
| 131 cache_thread_->message_loop_proxy().get(), | |
| 132 NULL, | |
| 133 &cache_, | |
| 134 io_callback_); | |
| 135 } | |
| 136 | |
| 137 int SimpleCacheDumper::DoCreateCacheComplete(int rv) { | |
| 138 if (rv < 0) | |
| 139 return rv; | |
| 140 | |
| 141 reinterpret_cast<disk_cache::BackendImpl*>(cache_.get())->SetUpgradeMode(); | |
| 142 reinterpret_cast<disk_cache::BackendImpl*>(cache_.get())->SetFlags( | |
| 143 disk_cache::kNoRandom); | |
| 144 | |
| 145 state_ = STATE_OPEN_ENTRY; | |
| 146 return OK; | |
| 147 } | |
| 148 | |
| 149 int SimpleCacheDumper::DoOpenEntry() { | |
| 150 DCHECK(!dst_entry_); | |
| 151 DCHECK(!src_entry_); | |
| 152 state_ = STATE_OPEN_ENTRY_COMPLETE; | |
| 153 if (!iter_) | |
| 154 iter_ = cache_->CreateIterator(); | |
| 155 return iter_->OpenNextEntry(&src_entry_, io_callback_); | |
| 156 } | |
| 157 | |
| 158 int SimpleCacheDumper::DoOpenEntryComplete(int rv) { | |
| 159 // ERR_FAILED indicates iteration finished. | |
| 160 if (rv == ERR_FAILED) | |
| 161 return OK; | |
| 162 | |
| 163 if (rv < 0) | |
| 164 return rv; | |
| 165 | |
| 166 state_ = STATE_CREATE_ENTRY; | |
| 167 return OK; | |
| 168 } | |
| 169 | |
| 170 int SimpleCacheDumper::DoCreateEntry() { | |
| 171 DCHECK(!dst_entry_); | |
| 172 state_ = STATE_CREATE_ENTRY_COMPLETE; | |
| 173 | |
| 174 return writer_->CreateEntry(src_entry_->GetKey(), &dst_entry_, | |
| 175 io_callback_); | |
| 176 } | |
| 177 | |
| 178 int SimpleCacheDumper::DoCreateEntryComplete(int rv) { | |
| 179 if (rv < 0) | |
| 180 return rv; | |
| 181 | |
| 182 state_ = STATE_READ_HEADERS; | |
| 183 return OK; | |
| 184 } | |
| 185 | |
| 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_); | |
| 191 } | |
| 192 | |
| 193 int SimpleCacheDumper::DoReadHeadersComplete(int rv) { | |
| 194 if (rv < 0) | |
| 195 return rv; | |
| 196 | |
| 197 state_ = STATE_WRITE_HEADERS; | |
| 198 return OK; | |
| 199 } | |
| 200 | |
| 201 int SimpleCacheDumper::DoWriteHeaders() { | |
| 202 int rv = writer_->WriteEntry( | |
| 203 dst_entry_, 0, 0, buf_.get(), buf_->size(), io_callback_); | |
| 204 if (rv == 0) | |
| 205 return ERR_FAILED; | |
| 206 | |
| 207 state_ = STATE_WRITE_HEADERS_COMPLETE; | |
| 208 return OK; | |
| 209 } | |
| 210 | |
| 211 int SimpleCacheDumper::DoWriteHeadersComplete(int rv) { | |
| 212 if (rv < 0) | |
| 213 return rv; | |
| 214 | |
| 215 state_ = STATE_READ_BODY; | |
| 216 return OK; | |
| 217 } | |
| 218 | |
| 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. | |
| 224 if (size <= 0) { | |
| 225 state_ = STATE_WRITE_BODY_COMPLETE; | |
| 226 return OK; | |
| 227 } | |
| 228 buf_ = new IOBufferWithSize(size); | |
| 229 return src_entry_->ReadData(1, 0, buf_.get(), size, io_callback_); | |
| 230 } | |
| 231 | |
| 232 int SimpleCacheDumper::DoReadBodyComplete(int rv) { | |
| 233 if (rv < 0) | |
| 234 return rv; | |
| 235 | |
| 236 state_ = STATE_WRITE_BODY; | |
| 237 return OK; | |
| 238 } | |
| 239 | |
| 240 int SimpleCacheDumper::DoWriteBody() { | |
| 241 int rv = writer_->WriteEntry( | |
| 242 dst_entry_, 1, 0, buf_.get(), buf_->size(), io_callback_); | |
| 243 if (rv == 0) | |
| 244 return ERR_FAILED; | |
| 245 | |
| 246 state_ = STATE_WRITE_BODY_COMPLETE; | |
| 247 return OK; | |
| 248 } | |
| 249 | |
| 250 int SimpleCacheDumper::DoWriteBodyComplete(int rv) { | |
| 251 if (rv < 0) | |
| 252 return rv; | |
| 253 | |
| 254 src_entry_->Close(); | |
| 255 writer_->CloseEntry(dst_entry_, base::Time::Now(), base::Time::Now()); | |
| 256 src_entry_ = NULL; | |
| 257 dst_entry_ = NULL; | |
| 258 | |
| 259 state_ = STATE_OPEN_ENTRY; | |
| 260 return OK; | |
| 261 } | |
| 262 | |
| 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")); | |
| 268 | |
| 269 rv = DoLoop(rv); | |
| 270 | |
| 271 if (rv != ERR_IO_PENDING) { | |
| 272 rv_ = rv; | |
| 273 cache_.reset(); | |
| 274 base::MessageLoop::current()->Quit(); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 } // namespace net | |
| OLD | NEW |