[email protected] | b90d7e80 | 2011-01-09 16:32:20 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | cfaa1f2 | 2009-10-12 17:14:59 | [diff] [blame] | 5 | #include "base/file_path.h" |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 6 | #include "base/logging.h" |
[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame^] | 7 | #include "base/memory/scoped_ptr.h" |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 8 | #include "base/message_loop.h" |
[email protected] | c9c07779 | 2010-08-03 14:39:42 | [diff] [blame] | 9 | #include "base/string_number_conversions.h" |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 10 | #include "base/string_util.h" |
[email protected] | 34b9963 | 2011-01-01 01:01:06 | [diff] [blame] | 11 | #include "base/threading/thread.h" |
[email protected] | b90d7e80 | 2011-01-09 16:32:20 | [diff] [blame] | 12 | #include "base/win/scoped_handle.h" |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 13 | #include "googleurl/src/gurl.h" |
[email protected] | 74a85ce | 2009-02-12 00:03:19 | [diff] [blame] | 14 | #include "net/base/io_buffer.h" |
[email protected] | ad74a59 | 2011-01-21 18:40:55 | [diff] [blame] | 15 | #include "net/base/net_errors.h" |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 16 | #include "net/base/test_completion_callback.h" |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 17 | #include "net/disk_cache/backend_impl.h" |
| 18 | #include "net/disk_cache/entry_impl.h" |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 19 | #include "net/http/http_cache.h" |
| 20 | #include "net/http/http_response_headers.h" |
| 21 | #include "net/http/http_response_info.h" |
| 22 | #include "net/tools/dump_cache/cache_dumper.h" |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 23 | |
| 24 | namespace { |
| 25 | |
| 26 | const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\dump_cache_"; |
| 27 | const int kChannelSize = 64 * 1024; |
[email protected] | 62cdf1e | 2008-12-04 23:03:33 | [diff] [blame] | 28 | const int kNumStreams = 4; |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 29 | |
| 30 | // Simple macro to print out formatted debug messages. It is similar to a DLOG |
| 31 | // except that it doesn't include a header. |
| 32 | #ifdef NDEBUG |
| 33 | #define DEBUGMSG(...) {} |
| 34 | #else |
| 35 | #define DEBUGMSG(...) { printf(__VA_ARGS__); } |
| 36 | #endif |
| 37 | |
[email protected] | d149ce8 | 2009-07-01 23:57:02 | [diff] [blame] | 38 | HANDLE OpenServer(const std::wstring& pipe_number) { |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 39 | std::wstring pipe_name(kPipePrefix); |
| 40 | pipe_name.append(pipe_number); |
| 41 | return CreateFile(pipe_name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, |
| 42 | OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); |
| 43 | } |
| 44 | |
| 45 | // This is the basic message to use between the two processes. It is intended |
| 46 | // to transmit a single action (like "get the key name for entry xx"), with up |
| 47 | // to 5 32-bit arguments and 4 64-bit arguments. After this structure, the rest |
| 48 | // of the message has |buffer_bytes| of length with the actual data. |
| 49 | struct Message { |
| 50 | int32 command; |
| 51 | int32 result; |
| 52 | int32 buffer_bytes; |
| 53 | int32 arg1; |
| 54 | int32 arg2; |
| 55 | int32 arg3; |
| 56 | int32 arg4; |
| 57 | int32 arg5; |
| 58 | int64 long_arg1; |
| 59 | int64 long_arg2; |
| 60 | int64 long_arg3; |
| 61 | int64 long_arg4; |
| 62 | Message() { |
| 63 | memset(this, 0, sizeof(*this)); |
| 64 | } |
| 65 | Message& operator= (const Message& other) { |
| 66 | memcpy(this, &other, sizeof(*this)); |
| 67 | return *this; |
| 68 | } |
| 69 | }; |
| 70 | |
| 71 | const int kBufferSize = kChannelSize - sizeof(Message); |
| 72 | struct IoBuffer { |
| 73 | Message msg; |
| 74 | char buffer[kBufferSize]; |
| 75 | }; |
| 76 | COMPILE_ASSERT(sizeof(IoBuffer) == kChannelSize, invalid_io_buffer); |
| 77 | |
| 78 | |
| 79 | // The list of commands. |
| 80 | // Currently, there is support for working ONLY with one entry at a time. |
| 81 | enum { |
| 82 | // Get the entry from list |arg1| that follows |long_arg1|. |
| 83 | // The result is placed on |long_arg1| (closes the previous one). |
| 84 | GET_NEXT_ENTRY = 1, |
| 85 | // Get the entry from list |arg1| that precedes |long_arg1|. |
| 86 | // The result is placed on |long_arg1| (closes the previous one). |
| 87 | GET_PREV_ENTRY, |
| 88 | // Closes the entry |long_arg1|. |
| 89 | CLOSE_ENTRY, |
| 90 | // Get the key of the entry |long_arg1|. |
| 91 | GET_KEY, |
| 92 | // Get last used (long_arg2) and last modified (long_arg3) times for the |
| 93 | // entry at |long_arg1|. |
| 94 | GET_USE_TIMES, |
| 95 | // Returns on |arg2| the data size in bytes if the stream |arg1| of entry at |
| 96 | // |long_arg1|. |
| 97 | GET_DATA_SIZE, |
| 98 | // Returns |arg2| bytes of the stream |arg1| for the entry at |long_arg1|, |
| 99 | // starting at offset |arg3|. |
| 100 | READ_DATA, |
| 101 | // End processing requests. |
| 102 | QUIT |
| 103 | }; |
| 104 | |
| 105 | // The list of return codes. |
| 106 | enum { |
| 107 | RESULT_OK = 0, |
| 108 | RESULT_UNKNOWN_COMMAND, |
| 109 | RESULT_INVALID_PARAMETER, |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 110 | RESULT_NAME_OVERFLOW, |
| 111 | RESULT_PENDING // This error code is NOT expected by the master process. |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 112 | }; |
| 113 | |
| 114 | // ----------------------------------------------------------------------- |
| 115 | |
| 116 | class BaseSM : public MessageLoopForIO::IOHandler { |
| 117 | public: |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 118 | explicit BaseSM(HANDLE channel); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 119 | virtual ~BaseSM(); |
| 120 | |
| 121 | protected: |
| 122 | bool SendMsg(const Message& msg); |
| 123 | bool ReceiveMsg(); |
| 124 | bool ConnectChannel(); |
| 125 | bool IsPending(); |
| 126 | |
| 127 | MessageLoopForIO::IOContext in_context_; |
| 128 | MessageLoopForIO::IOContext out_context_; |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 129 | disk_cache::EntryImpl* entry_; |
| 130 | HANDLE channel_; |
| 131 | int state_; |
| 132 | int pending_count_; |
| 133 | scoped_array<char> in_buffer_; |
| 134 | scoped_array<char> out_buffer_; |
| 135 | IoBuffer* input_; |
| 136 | IoBuffer* output_; |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 137 | base::Thread cache_thread_; |
| 138 | |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 139 | DISALLOW_COPY_AND_ASSIGN(BaseSM); |
| 140 | }; |
| 141 | |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 142 | BaseSM::BaseSM(HANDLE channel) |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 143 | : entry_(NULL), channel_(channel), state_(0), pending_count_(0), |
| 144 | cache_thread_("cache") { |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 145 | in_buffer_.reset(new char[kChannelSize]); |
| 146 | out_buffer_.reset(new char[kChannelSize]); |
| 147 | input_ = reinterpret_cast<IoBuffer*>(in_buffer_.get()); |
| 148 | output_ = reinterpret_cast<IoBuffer*>(out_buffer_.get()); |
| 149 | |
| 150 | memset(&in_context_, 0, sizeof(in_context_)); |
| 151 | memset(&out_context_, 0, sizeof(out_context_)); |
| 152 | in_context_.handler = this; |
| 153 | out_context_.handler = this; |
| 154 | MessageLoopForIO::current()->RegisterIOHandler(channel_, this); |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 155 | CHECK(cache_thread_.StartWithOptions( |
| 156 | base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 157 | } |
| 158 | |
| 159 | BaseSM::~BaseSM() { |
| 160 | if (entry_) |
| 161 | entry_->Close(); |
| 162 | } |
| 163 | |
| 164 | bool BaseSM::SendMsg(const Message& msg) { |
| 165 | // Only one command will be in-flight at a time. Let's start the Read IO here |
| 166 | // when we know that it will be pending. |
| 167 | if (!ReceiveMsg()) |
| 168 | return false; |
| 169 | |
| 170 | output_->msg = msg; |
| 171 | DWORD written; |
| 172 | if (!WriteFile(channel_, output_, sizeof(msg) + msg.buffer_bytes, &written, |
| 173 | &out_context_.overlapped)) { |
| 174 | if (ERROR_IO_PENDING != GetLastError()) |
| 175 | return false; |
| 176 | } |
| 177 | pending_count_++; |
| 178 | return true; |
| 179 | } |
| 180 | |
| 181 | bool BaseSM::ReceiveMsg() { |
| 182 | DWORD read; |
| 183 | if (!ReadFile(channel_, input_, kChannelSize, &read, |
| 184 | &in_context_.overlapped)) { |
| 185 | if (ERROR_IO_PENDING != GetLastError()) |
| 186 | return false; |
| 187 | } |
| 188 | pending_count_++; |
| 189 | return true; |
| 190 | } |
| 191 | |
| 192 | bool BaseSM::ConnectChannel() { |
| 193 | if (!ConnectNamedPipe(channel_, &in_context_.overlapped)) { |
| 194 | DWORD error = GetLastError(); |
| 195 | if (ERROR_PIPE_CONNECTED == error) |
| 196 | return true; |
| 197 | // By returning true in case of a generic error, we allow the operation to |
| 198 | // fail while sending the first message. |
| 199 | if (ERROR_IO_PENDING != error) |
| 200 | return true; |
| 201 | } |
| 202 | pending_count_++; |
| 203 | return false; |
| 204 | } |
| 205 | |
| 206 | bool BaseSM::IsPending() { |
| 207 | return pending_count_ != 0; |
| 208 | } |
| 209 | |
| 210 | // ----------------------------------------------------------------------- |
| 211 | |
| 212 | class MasterSM : public BaseSM { |
| 213 | public: |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 214 | MasterSM(const std::wstring& path, HANDLE channel, bool dump_to_disk) |
| 215 | : BaseSM(channel), path_(path), dump_to_disk_(dump_to_disk), |
| 216 | ALLOW_THIS_IN_INITIALIZER_LIST( |
[email protected] | 3f73cd31 | 2010-06-17 21:59:39 | [diff] [blame] | 217 | create_callback_(this, &MasterSM::DoCreateEntryComplete)), |
| 218 | ALLOW_THIS_IN_INITIALIZER_LIST( |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 219 | write_callback_(this, &MasterSM::DoReadDataComplete)) { |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 220 | } |
| 221 | virtual ~MasterSM() { |
| 222 | delete writer_; |
| 223 | } |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 224 | |
| 225 | bool DoInit(); |
| 226 | virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
| 227 | DWORD bytes_transfered, DWORD error); |
| 228 | |
| 229 | private: |
| 230 | enum { |
| 231 | MASTER_INITIAL = 0, |
| 232 | MASTER_CONNECT, |
| 233 | MASTER_GET_ENTRY, |
| 234 | MASTER_GET_NEXT_ENTRY, |
| 235 | MASTER_GET_KEY, |
| 236 | MASTER_GET_USE_TIMES, |
| 237 | MASTER_GET_DATA_SIZE, |
| 238 | MASTER_READ_DATA, |
| 239 | MASTER_END |
| 240 | }; |
| 241 | |
| 242 | void SendGetPrevEntry(); |
| 243 | void DoGetEntry(); |
| 244 | void DoGetKey(int bytes_read); |
[email protected] | 3f73cd31 | 2010-06-17 21:59:39 | [diff] [blame] | 245 | void DoCreateEntryComplete(int result); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 246 | void DoGetUseTimes(); |
| 247 | void SendGetDataSize(); |
| 248 | void DoGetDataSize(); |
| 249 | void CloseEntry(); |
| 250 | void SendReadData(); |
| 251 | void DoReadData(int bytes_read); |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 252 | void DoReadDataComplete(int ret); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 253 | void SendQuit(); |
| 254 | void DoEnd(); |
| 255 | void Fail(); |
| 256 | |
| 257 | base::Time last_used_; |
| 258 | base::Time last_modified_; |
| 259 | int64 remote_entry_; |
| 260 | int stream_; |
| 261 | int bytes_remaining_; |
| 262 | int offset_; |
| 263 | int copied_entries_; |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 264 | int read_size_; |
| 265 | scoped_ptr<disk_cache::Backend> cache_; |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 266 | CacheDumpWriter* writer_; |
| 267 | const std::wstring& path_; |
| 268 | bool dump_to_disk_; |
[email protected] | 3f73cd31 | 2010-06-17 21:59:39 | [diff] [blame] | 269 | net::CompletionCallbackImpl<MasterSM> create_callback_; |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 270 | net::CompletionCallbackImpl<MasterSM> write_callback_; |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 271 | }; |
| 272 | |
| 273 | void MasterSM::OnIOCompleted(MessageLoopForIO::IOContext* context, |
| 274 | DWORD bytes_transfered, DWORD error) { |
| 275 | pending_count_--; |
| 276 | if (context == &out_context_) { |
| 277 | if (!error) |
| 278 | return; |
| 279 | return Fail(); |
| 280 | } |
| 281 | |
| 282 | int bytes_read = static_cast<int>(bytes_transfered); |
| 283 | if (bytes_read < sizeof(Message) && state_ != MASTER_END && |
| 284 | state_ != MASTER_CONNECT) { |
| 285 | printf("Communication breakdown\n"); |
| 286 | return Fail(); |
| 287 | } |
| 288 | |
| 289 | switch (state_) { |
| 290 | case MASTER_CONNECT: |
| 291 | SendGetPrevEntry(); |
| 292 | break; |
| 293 | case MASTER_GET_ENTRY: |
| 294 | DoGetEntry(); |
| 295 | break; |
| 296 | case MASTER_GET_KEY: |
| 297 | DoGetKey(bytes_read); |
| 298 | break; |
| 299 | case MASTER_GET_USE_TIMES: |
| 300 | DoGetUseTimes(); |
| 301 | break; |
| 302 | case MASTER_GET_DATA_SIZE: |
| 303 | DoGetDataSize(); |
| 304 | break; |
| 305 | case MASTER_READ_DATA: |
| 306 | DoReadData(bytes_read); |
| 307 | break; |
| 308 | case MASTER_END: |
| 309 | if (!IsPending()) |
| 310 | DoEnd(); |
| 311 | break; |
| 312 | default: |
| 313 | NOTREACHED(); |
| 314 | break; |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | bool MasterSM::DoInit() { |
| 319 | DEBUGMSG("Master DoInit\n"); |
| 320 | DCHECK(state_ == MASTER_INITIAL); |
| 321 | |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 322 | if (dump_to_disk_) { |
| 323 | writer_ = new DiskDumper(path_); |
| 324 | } else { |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 325 | disk_cache::Backend* cache; |
| 326 | TestCompletionCallback cb; |
| 327 | int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, |
| 328 | FilePath::FromWStringHack(path_), 0, |
| 329 | false, |
| 330 | cache_thread_.message_loop_proxy(), |
[email protected] | f6f1bebc | 2011-01-07 03:04:54 | [diff] [blame] | 331 | NULL, &cache, &cb); |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 332 | if (cb.GetResult(rv) != net::OK) { |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 333 | printf("Unable to initialize new files\n"); |
| 334 | return false; |
| 335 | } |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 336 | cache_.reset(cache); |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 337 | writer_ = new CacheDumper(cache_.get()); |
| 338 | } |
| 339 | if (!writer_) |
| 340 | return false; |
| 341 | |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 342 | copied_entries_ = 0; |
| 343 | remote_entry_ = 0; |
| 344 | |
| 345 | if (ConnectChannel()) { |
| 346 | SendGetPrevEntry(); |
| 347 | // If we don't have pending operations we couldn't connect. |
| 348 | return IsPending(); |
| 349 | } |
| 350 | |
| 351 | state_ = MASTER_CONNECT; |
| 352 | return true; |
| 353 | } |
| 354 | |
| 355 | void MasterSM::SendGetPrevEntry() { |
| 356 | DEBUGMSG("Master SendGetPrevEntry\n"); |
| 357 | state_ = MASTER_GET_ENTRY; |
| 358 | Message msg; |
| 359 | msg.command = GET_PREV_ENTRY; |
| 360 | msg.long_arg1 = remote_entry_; |
| 361 | SendMsg(msg); |
| 362 | } |
| 363 | |
| 364 | void MasterSM::DoGetEntry() { |
| 365 | DEBUGMSG("Master DoGetEntry\n"); |
| 366 | DCHECK(state_ == MASTER_GET_ENTRY); |
| 367 | DCHECK(input_->msg.command == GET_PREV_ENTRY); |
| 368 | if (input_->msg.result != RESULT_OK) |
| 369 | return Fail(); |
| 370 | |
| 371 | if (!input_->msg.long_arg1) { |
| 372 | printf("Done: %d entries copied over.\n", copied_entries_); |
| 373 | return SendQuit(); |
| 374 | } |
| 375 | remote_entry_ = input_->msg.long_arg1; |
| 376 | state_ = MASTER_GET_KEY; |
| 377 | Message msg; |
| 378 | msg.command = GET_KEY; |
| 379 | msg.long_arg1 = remote_entry_; |
| 380 | SendMsg(msg); |
| 381 | } |
| 382 | |
| 383 | void MasterSM::DoGetKey(int bytes_read) { |
| 384 | DEBUGMSG("Master DoGetKey\n"); |
| 385 | DCHECK(state_ == MASTER_GET_KEY); |
| 386 | DCHECK(input_->msg.command == GET_KEY); |
[email protected] | 8333732 | 2008-12-03 23:55:52 | [diff] [blame] | 387 | if (input_->msg.result == RESULT_NAME_OVERFLOW) { |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 388 | // The key is too long. Just move on. |
[email protected] | 8333732 | 2008-12-03 23:55:52 | [diff] [blame] | 389 | printf("Skipping entry (name too long)\n"); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 390 | return SendGetPrevEntry(); |
[email protected] | 8333732 | 2008-12-03 23:55:52 | [diff] [blame] | 391 | } |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 392 | |
| 393 | if (input_->msg.result != RESULT_OK) |
| 394 | return Fail(); |
| 395 | |
| 396 | std::string key(input_->buffer); |
[email protected] | f55bd486 | 2010-05-27 15:38:07 | [diff] [blame] | 397 | DCHECK(key.size() == static_cast<size_t>(input_->msg.buffer_bytes - 1)); |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 398 | |
[email protected] | 3f73cd31 | 2010-06-17 21:59:39 | [diff] [blame] | 399 | int rv = writer_->CreateEntry(key, |
| 400 | reinterpret_cast<disk_cache::Entry**>(&entry_), |
| 401 | &create_callback_); |
| 402 | |
| 403 | if (rv != net::ERR_IO_PENDING) |
| 404 | DoCreateEntryComplete(rv); |
| 405 | } |
| 406 | |
| 407 | void MasterSM::DoCreateEntryComplete(int result) { |
| 408 | std::string key(input_->buffer); |
| 409 | if (result != net::OK) { |
[email protected] | f55bd486 | 2010-05-27 15:38:07 | [diff] [blame] | 410 | printf("Skipping entry \"%s\": %d\n", key.c_str(), GetLastError()); |
[email protected] | 8333732 | 2008-12-03 23:55:52 | [diff] [blame] | 411 | return SendGetPrevEntry(); |
| 412 | } |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 413 | |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 414 | if (key.size() >= 64) { |
| 415 | key[60] = '.'; |
| 416 | key[61] = '.'; |
| 417 | key[62] = '.'; |
| 418 | key[63] = '\0'; |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 419 | } |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 420 | DEBUGMSG("Entry \"%s\" created\n", key.c_str()); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 421 | state_ = MASTER_GET_USE_TIMES; |
| 422 | Message msg; |
| 423 | msg.command = GET_USE_TIMES; |
| 424 | msg.long_arg1 = remote_entry_; |
| 425 | SendMsg(msg); |
| 426 | } |
| 427 | |
| 428 | void MasterSM::DoGetUseTimes() { |
| 429 | DEBUGMSG("Master DoGetUseTimes\n"); |
| 430 | DCHECK(state_ == MASTER_GET_USE_TIMES); |
| 431 | DCHECK(input_->msg.command == GET_USE_TIMES); |
| 432 | if (input_->msg.result != RESULT_OK) |
| 433 | return Fail(); |
| 434 | |
| 435 | last_used_ = base::Time::FromInternalValue(input_->msg.long_arg2); |
| 436 | last_modified_ = base::Time::FromInternalValue(input_->msg.long_arg3); |
| 437 | stream_ = 0; |
| 438 | SendGetDataSize(); |
| 439 | } |
| 440 | |
| 441 | void MasterSM::SendGetDataSize() { |
| 442 | DEBUGMSG("Master SendGetDataSize (%d)\n", stream_); |
| 443 | state_ = MASTER_GET_DATA_SIZE; |
| 444 | Message msg; |
| 445 | msg.command = GET_DATA_SIZE; |
| 446 | msg.arg1 = stream_; |
| 447 | msg.long_arg1 = remote_entry_; |
| 448 | SendMsg(msg); |
| 449 | } |
| 450 | |
| 451 | void MasterSM::DoGetDataSize() { |
| 452 | DEBUGMSG("Master DoGetDataSize: %d\n", input_->msg.arg2); |
| 453 | DCHECK(state_ == MASTER_GET_DATA_SIZE); |
| 454 | DCHECK(input_->msg.command == GET_DATA_SIZE); |
| 455 | if (input_->msg.result == RESULT_INVALID_PARAMETER) |
| 456 | // No more streams, move to the next entry. |
| 457 | return CloseEntry(); |
| 458 | |
| 459 | if (input_->msg.result != RESULT_OK) |
| 460 | return Fail(); |
| 461 | |
| 462 | bytes_remaining_ = input_->msg.arg2; |
| 463 | offset_ = 0; |
| 464 | SendReadData(); |
| 465 | } |
| 466 | |
| 467 | void MasterSM::CloseEntry() { |
| 468 | DEBUGMSG("Master CloseEntry\n"); |
| 469 | printf("%c\r", copied_entries_ % 2 ? 'x' : '+'); |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 470 | writer_->CloseEntry(entry_, last_used_, last_modified_); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 471 | entry_ = NULL; |
| 472 | copied_entries_++; |
| 473 | SendGetPrevEntry(); |
| 474 | } |
| 475 | |
| 476 | void MasterSM::SendReadData() { |
| 477 | int read_size = std::min(bytes_remaining_, kBufferSize); |
| 478 | DEBUGMSG("Master SendReadData (%d): %d bytes at %d\n", stream_, read_size, |
| 479 | offset_); |
| 480 | if (bytes_remaining_ <= 0) { |
| 481 | stream_++; |
| 482 | if (stream_ >= kNumStreams) |
| 483 | return CloseEntry(); |
| 484 | return SendGetDataSize(); |
| 485 | } |
| 486 | |
| 487 | state_ = MASTER_READ_DATA; |
| 488 | Message msg; |
| 489 | msg.command = READ_DATA; |
| 490 | msg.arg1 = stream_; |
| 491 | msg.arg2 = read_size; |
| 492 | msg.arg3 = offset_; |
| 493 | msg.long_arg1 = remote_entry_; |
| 494 | SendMsg(msg); |
| 495 | } |
| 496 | |
| 497 | void MasterSM::DoReadData(int bytes_read) { |
| 498 | DEBUGMSG("Master DoReadData: %d bytes\n", input_->msg.buffer_bytes); |
| 499 | DCHECK(state_ == MASTER_READ_DATA); |
| 500 | DCHECK(input_->msg.command == READ_DATA); |
| 501 | if (input_->msg.result != RESULT_OK) |
| 502 | return Fail(); |
| 503 | |
| 504 | int read_size = input_->msg.buffer_bytes; |
[email protected] | 8333732 | 2008-12-03 23:55:52 | [diff] [blame] | 505 | if (!read_size) { |
| 506 | printf("Read failed, entry \"%s\" truncated!\n", entry_->GetKey().c_str()); |
| 507 | bytes_remaining_ = 0; |
| 508 | return SendReadData(); |
| 509 | } |
| 510 | |
[email protected] | 74a85ce | 2009-02-12 00:03:19 | [diff] [blame] | 511 | scoped_refptr<net::WrappedIOBuffer> buf = |
| 512 | new net::WrappedIOBuffer(input_->buffer); |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 513 | int rv = writer_->WriteEntry(entry_, stream_, offset_, buf, read_size, |
| 514 | &write_callback_); |
| 515 | if (rv == net::ERR_IO_PENDING) { |
| 516 | // We'll continue in DoReadDataComplete. |
| 517 | read_size_ = read_size; |
| 518 | return; |
| 519 | } |
| 520 | |
| 521 | if (rv <= 0) |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 522 | return Fail(); |
| 523 | |
| 524 | offset_ += read_size; |
| 525 | bytes_remaining_ -= read_size; |
| 526 | // Read some more. |
| 527 | SendReadData(); |
| 528 | } |
| 529 | |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 530 | void MasterSM::DoReadDataComplete(int ret) { |
| 531 | if (ret != read_size_) |
| 532 | return Fail(); |
| 533 | |
| 534 | offset_ += ret; |
| 535 | bytes_remaining_ -= ret; |
| 536 | // Read some more. |
| 537 | SendReadData(); |
| 538 | } |
| 539 | |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 540 | void MasterSM::SendQuit() { |
| 541 | DEBUGMSG("Master SendQuit\n"); |
| 542 | state_ = MASTER_END; |
| 543 | Message msg; |
| 544 | msg.command = QUIT; |
| 545 | SendMsg(msg); |
| 546 | if (!IsPending()) |
| 547 | DoEnd(); |
| 548 | } |
| 549 | |
| 550 | void MasterSM::DoEnd() { |
| 551 | DEBUGMSG("Master DoEnd\n"); |
| 552 | MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 553 | } |
| 554 | |
| 555 | void MasterSM::Fail() { |
| 556 | DEBUGMSG("Master Fail\n"); |
| 557 | printf("Unexpected failure\n"); |
| 558 | SendQuit(); |
| 559 | } |
| 560 | |
| 561 | // ----------------------------------------------------------------------- |
| 562 | |
| 563 | class SlaveSM : public BaseSM { |
| 564 | public: |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 565 | SlaveSM(const std::wstring& path, HANDLE channel); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 566 | virtual ~SlaveSM(); |
| 567 | |
| 568 | bool DoInit(); |
| 569 | virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
| 570 | DWORD bytes_transfered, DWORD error); |
| 571 | |
| 572 | private: |
| 573 | enum { |
| 574 | SLAVE_INITIAL = 0, |
| 575 | SLAVE_WAITING, |
| 576 | SLAVE_END |
| 577 | }; |
| 578 | |
| 579 | void DoGetNextEntry(); |
| 580 | void DoGetPrevEntry(); |
| 581 | int32 GetEntryFromList(); |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 582 | void DoGetEntryComplete(int result); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 583 | void DoCloseEntry(); |
| 584 | void DoGetKey(); |
| 585 | void DoGetUseTimes(); |
| 586 | void DoGetDataSize(); |
| 587 | void DoReadData(); |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 588 | void DoReadDataComplete(int ret); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 589 | void DoEnd(); |
| 590 | void Fail(); |
| 591 | |
| 592 | void* iterator_; |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 593 | Message msg_; // Used for DoReadDataComplete and DoGetEntryComplete. |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 594 | |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 595 | net::CompletionCallbackImpl<SlaveSM> read_callback_; |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 596 | net::CompletionCallbackImpl<SlaveSM> next_callback_; |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 597 | scoped_ptr<disk_cache::BackendImpl> cache_; |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 598 | }; |
| 599 | |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 600 | SlaveSM::SlaveSM(const std::wstring& path, HANDLE channel) |
| 601 | : BaseSM(channel), iterator_(NULL), |
| 602 | ALLOW_THIS_IN_INITIALIZER_LIST( |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 603 | read_callback_(this, &SlaveSM::DoReadDataComplete)), |
| 604 | ALLOW_THIS_IN_INITIALIZER_LIST( |
| 605 | next_callback_(this, &SlaveSM::DoGetEntryComplete)) { |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 606 | disk_cache::Backend* cache; |
| 607 | TestCompletionCallback cb; |
| 608 | int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, |
| 609 | FilePath::FromWStringHack(path), 0, |
| 610 | false, |
| 611 | cache_thread_.message_loop_proxy(), |
[email protected] | f6f1bebc | 2011-01-07 03:04:54 | [diff] [blame] | 612 | NULL, &cache, &cb); |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 613 | if (cb.GetResult(rv) != net::OK) { |
| 614 | printf("Unable to open cache files\n"); |
| 615 | return; |
| 616 | } |
| 617 | cache_.reset(reinterpret_cast<disk_cache::BackendImpl*>(cache)); |
| 618 | cache_->SetUpgradeMode(); |
| 619 | } |
| 620 | |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 621 | SlaveSM::~SlaveSM() { |
| 622 | if (iterator_) |
| 623 | cache_->EndEnumeration(&iterator_); |
| 624 | } |
| 625 | |
| 626 | void SlaveSM::OnIOCompleted(MessageLoopForIO::IOContext* context, |
| 627 | DWORD bytes_transfered, DWORD error) { |
| 628 | pending_count_--; |
| 629 | if (state_ == SLAVE_END) { |
| 630 | if (IsPending()) |
| 631 | return; |
| 632 | return DoEnd(); |
| 633 | } |
| 634 | |
| 635 | if (context == &out_context_) { |
| 636 | if (!error) |
| 637 | return; |
| 638 | return Fail(); |
| 639 | } |
| 640 | |
| 641 | int bytes_read = static_cast<int>(bytes_transfered); |
| 642 | if (bytes_read < sizeof(Message)) { |
| 643 | printf("Communication breakdown\n"); |
| 644 | return Fail(); |
| 645 | } |
| 646 | DCHECK(state_ == SLAVE_WAITING); |
| 647 | |
| 648 | switch (input_->msg.command) { |
| 649 | case GET_NEXT_ENTRY: |
| 650 | DoGetNextEntry(); |
| 651 | break; |
| 652 | case GET_PREV_ENTRY: |
| 653 | DoGetPrevEntry(); |
| 654 | break; |
| 655 | case CLOSE_ENTRY: |
| 656 | DoCloseEntry(); |
| 657 | break; |
| 658 | case GET_KEY: |
| 659 | DoGetKey(); |
| 660 | break; |
| 661 | case GET_USE_TIMES: |
| 662 | DoGetUseTimes(); |
| 663 | break; |
| 664 | case GET_DATA_SIZE: |
| 665 | DoGetDataSize(); |
| 666 | break; |
| 667 | case READ_DATA: |
| 668 | DoReadData(); |
| 669 | break; |
| 670 | case QUIT: |
| 671 | DoEnd(); |
| 672 | break; |
| 673 | default: |
| 674 | NOTREACHED(); |
| 675 | break; |
| 676 | } |
| 677 | } |
| 678 | |
| 679 | bool SlaveSM::DoInit() { |
| 680 | DEBUGMSG("\t\t\tSlave DoInit\n"); |
| 681 | DCHECK(state_ == SLAVE_INITIAL); |
| 682 | state_ = SLAVE_WAITING; |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 683 | if (!cache_.get()) |
| 684 | return false; |
| 685 | |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 686 | return ReceiveMsg(); |
| 687 | } |
| 688 | |
| 689 | void SlaveSM::DoGetNextEntry() { |
| 690 | DEBUGMSG("\t\t\tSlave DoGetNextEntry\n"); |
| 691 | Message msg; |
| 692 | msg.command = GET_NEXT_ENTRY; |
| 693 | |
| 694 | if (input_->msg.arg1) { |
| 695 | // We only support one list. |
| 696 | msg.result = RESULT_UNKNOWN_COMMAND; |
| 697 | } else { |
| 698 | msg.result = GetEntryFromList(); |
| 699 | msg.long_arg1 = reinterpret_cast<int64>(entry_); |
| 700 | } |
| 701 | SendMsg(msg); |
| 702 | } |
| 703 | |
| 704 | void SlaveSM::DoGetPrevEntry() { |
| 705 | DEBUGMSG("\t\t\tSlave DoGetPrevEntry\n"); |
| 706 | Message msg; |
| 707 | msg.command = GET_PREV_ENTRY; |
| 708 | |
| 709 | if (input_->msg.arg1) { |
| 710 | // We only support one list. |
| 711 | msg.result = RESULT_UNKNOWN_COMMAND; |
| 712 | } else { |
| 713 | msg.result = GetEntryFromList(); |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 714 | if (msg.result == RESULT_PENDING) { |
| 715 | // We are not done yet. |
| 716 | msg_ = msg; |
| 717 | return; |
| 718 | } |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 719 | msg.long_arg1 = reinterpret_cast<int64>(entry_); |
| 720 | } |
| 721 | SendMsg(msg); |
| 722 | } |
| 723 | |
| 724 | // Move to the next or previous entry on the list. |
| 725 | int32 SlaveSM::GetEntryFromList() { |
| 726 | DEBUGMSG("\t\t\tSlave GetEntryFromList\n"); |
| 727 | if (input_->msg.long_arg1 != reinterpret_cast<int64>(entry_)) |
| 728 | return RESULT_INVALID_PARAMETER; |
| 729 | |
| 730 | // We know that the current iteration is valid. |
| 731 | if (entry_) |
| 732 | entry_->Close(); |
| 733 | |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 734 | int rv; |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 735 | if (input_->msg.command == GET_NEXT_ENTRY) { |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 736 | rv = cache_->OpenNextEntry(&iterator_, |
| 737 | reinterpret_cast<disk_cache::Entry**>(&entry_), |
| 738 | &next_callback_); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 739 | } else { |
| 740 | DCHECK(input_->msg.command == GET_PREV_ENTRY); |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 741 | rv = cache_->OpenPrevEntry(&iterator_, |
| 742 | reinterpret_cast<disk_cache::Entry**>(&entry_), |
| 743 | &next_callback_); |
| 744 | } |
| 745 | DCHECK_EQ(net::ERR_IO_PENDING, rv); |
| 746 | return RESULT_PENDING; |
| 747 | } |
| 748 | |
| 749 | void SlaveSM::DoGetEntryComplete(int result) { |
| 750 | DEBUGMSG("\t\t\tSlave DoGetEntryComplete\n"); |
| 751 | if (result != net::OK) { |
| 752 | entry_ = NULL; |
| 753 | DEBUGMSG("\t\t\tSlave end of list\n"); |
[email protected] | a899ee8 | 2010-07-08 17:32:14 | [diff] [blame] | 754 | } |
[email protected] | a899ee8 | 2010-07-08 17:32:14 | [diff] [blame] | 755 | |
[email protected] | fb2622f | 2010-07-13 18:00:56 | [diff] [blame] | 756 | msg_.result = RESULT_OK; |
| 757 | msg_.long_arg1 = reinterpret_cast<int64>(entry_); |
| 758 | SendMsg(msg_); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 759 | } |
| 760 | |
| 761 | void SlaveSM::DoCloseEntry() { |
| 762 | DEBUGMSG("\t\t\tSlave DoCloseEntry\n"); |
| 763 | Message msg; |
| 764 | msg.command = GET_KEY; |
| 765 | |
| 766 | if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_)) { |
| 767 | msg.result = RESULT_INVALID_PARAMETER; |
| 768 | } else { |
| 769 | entry_->Close(); |
| 770 | entry_ = NULL; |
| 771 | cache_->EndEnumeration(&iterator_); |
| 772 | msg.result = RESULT_OK; |
| 773 | } |
| 774 | SendMsg(msg); |
| 775 | } |
| 776 | |
| 777 | void SlaveSM::DoGetKey() { |
| 778 | DEBUGMSG("\t\t\tSlave DoGetKey\n"); |
| 779 | Message msg; |
| 780 | msg.command = GET_KEY; |
| 781 | |
| 782 | if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_)) { |
| 783 | msg.result = RESULT_INVALID_PARAMETER; |
| 784 | } else { |
| 785 | std::string key = entry_->GetKey(); |
| 786 | msg.buffer_bytes = std::min(key.size() + 1, |
| 787 | static_cast<size_t>(kBufferSize)); |
| 788 | memcpy(output_->buffer, key.c_str(), msg.buffer_bytes); |
[email protected] | f55bd486 | 2010-05-27 15:38:07 | [diff] [blame] | 789 | if (msg.buffer_bytes != static_cast<int32>(key.size() + 1)) { |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 790 | // We don't support moving this entry. Just tell the master. |
| 791 | msg.result = RESULT_NAME_OVERFLOW; |
| 792 | } else { |
| 793 | msg.result = RESULT_OK; |
| 794 | } |
| 795 | } |
| 796 | SendMsg(msg); |
| 797 | } |
| 798 | |
| 799 | void SlaveSM::DoGetUseTimes() { |
| 800 | DEBUGMSG("\t\t\tSlave DoGetUseTimes\n"); |
| 801 | Message msg; |
| 802 | msg.command = GET_USE_TIMES; |
| 803 | |
| 804 | if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_)) { |
| 805 | msg.result = RESULT_INVALID_PARAMETER; |
| 806 | } else { |
| 807 | msg.long_arg2 = entry_->GetLastUsed().ToInternalValue(); |
| 808 | msg.long_arg3 = entry_->GetLastModified().ToInternalValue(); |
| 809 | msg.result = RESULT_OK; |
| 810 | } |
| 811 | SendMsg(msg); |
| 812 | } |
| 813 | |
| 814 | void SlaveSM::DoGetDataSize() { |
| 815 | DEBUGMSG("\t\t\tSlave DoGetDataSize\n"); |
| 816 | Message msg; |
| 817 | msg.command = GET_DATA_SIZE; |
| 818 | |
| 819 | int stream = input_->msg.arg1; |
| 820 | if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_) || |
| 821 | stream < 0 || stream >= kNumStreams) { |
| 822 | msg.result = RESULT_INVALID_PARAMETER; |
| 823 | } else { |
| 824 | msg.arg1 = stream; |
| 825 | msg.arg2 = entry_->GetDataSize(stream); |
| 826 | msg.result = RESULT_OK; |
| 827 | } |
| 828 | SendMsg(msg); |
| 829 | } |
| 830 | |
| 831 | void SlaveSM::DoReadData() { |
| 832 | DEBUGMSG("\t\t\tSlave DoReadData\n"); |
| 833 | Message msg; |
| 834 | msg.command = READ_DATA; |
| 835 | |
| 836 | int stream = input_->msg.arg1; |
| 837 | int size = input_->msg.arg2; |
| 838 | if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_) || |
| 839 | stream < 0 || stream > 1 || size > kBufferSize) { |
| 840 | msg.result = RESULT_INVALID_PARAMETER; |
| 841 | } else { |
[email protected] | 74a85ce | 2009-02-12 00:03:19 | [diff] [blame] | 842 | scoped_refptr<net::WrappedIOBuffer> buf = |
| 843 | new net::WrappedIOBuffer(output_->buffer); |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 844 | int ret = entry_->ReadData(stream, input_->msg.arg3, buf, size, |
| 845 | &read_callback_); |
| 846 | if (ret == net::ERR_IO_PENDING) { |
| 847 | // Save the message so we can continue were we left. |
| 848 | msg_ = msg; |
| 849 | return; |
| 850 | } |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 851 | |
| 852 | msg.buffer_bytes = (ret < 0) ? 0 : ret; |
| 853 | msg.result = RESULT_OK; |
| 854 | } |
| 855 | SendMsg(msg); |
| 856 | } |
| 857 | |
[email protected] | ec44a9a | 2010-06-15 19:31:51 | [diff] [blame] | 858 | void SlaveSM::DoReadDataComplete(int ret) { |
| 859 | DEBUGMSG("\t\t\tSlave DoReadDataComplete\n"); |
| 860 | DCHECK_EQ(READ_DATA, msg_.command); |
| 861 | msg_.buffer_bytes = (ret < 0) ? 0 : ret; |
| 862 | msg_.result = RESULT_OK; |
| 863 | SendMsg(msg_); |
| 864 | } |
| 865 | |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 866 | void SlaveSM::DoEnd() { |
| 867 | DEBUGMSG("\t\t\tSlave DoEnd\n"); |
| 868 | MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 869 | } |
| 870 | |
| 871 | void SlaveSM::Fail() { |
| 872 | DEBUGMSG("\t\t\tSlave Fail\n"); |
| 873 | printf("Unexpected failure\n"); |
| 874 | state_ = SLAVE_END; |
| 875 | if (IsPending()) { |
| 876 | CancelIo(channel_); |
| 877 | } else { |
| 878 | DoEnd(); |
| 879 | } |
| 880 | } |
| 881 | |
| 882 | } // namespace. |
| 883 | |
| 884 | // ----------------------------------------------------------------------- |
| 885 | |
| 886 | HANDLE CreateServer(std::wstring* pipe_number) { |
| 887 | std::wstring pipe_name(kPipePrefix); |
| 888 | srand(static_cast<int>(base::Time::Now().ToInternalValue())); |
[email protected] | c9c07779 | 2010-08-03 14:39:42 | [diff] [blame] | 889 | *pipe_number = base::IntToString16(rand()); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 890 | pipe_name.append(*pipe_number); |
| 891 | |
| 892 | DWORD mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | |
| 893 | FILE_FLAG_OVERLAPPED; |
| 894 | |
| 895 | return CreateNamedPipe(pipe_name.c_str(), mode, 0, 1, kChannelSize, |
| 896 | kChannelSize, 0, NULL); |
| 897 | } |
| 898 | |
| 899 | // This is the controller process for an upgrade operation. |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 900 | int CopyCache(const std::wstring& output_path, HANDLE pipe, bool copy_to_text) { |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 901 | MessageLoop loop(MessageLoop::TYPE_IO); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 902 | |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 903 | MasterSM master(output_path, pipe, copy_to_text); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 904 | if (!master.DoInit()) { |
| 905 | printf("Unable to talk with the helper\n"); |
| 906 | return -1; |
| 907 | } |
| 908 | |
| 909 | loop.Run(); |
| 910 | return 0; |
| 911 | } |
| 912 | |
| 913 | // This process will only execute commands from the controller. |
[email protected] | d149ce8 | 2009-07-01 23:57:02 | [diff] [blame] | 914 | int RunSlave(const std::wstring& input_path, const std::wstring& pipe_number) { |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 915 | MessageLoop loop(MessageLoop::TYPE_IO); |
| 916 | |
[email protected] | b90d7e80 | 2011-01-09 16:32:20 | [diff] [blame] | 917 | base::win::ScopedHandle pipe(OpenServer(pipe_number)); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 918 | if (!pipe.IsValid()) { |
| 919 | printf("Unable to open the server pipe\n"); |
| 920 | return -1; |
| 921 | } |
| 922 | |
[email protected] | c44344e | 2009-09-02 22:05:50 | [diff] [blame] | 923 | SlaveSM slave(input_path, pipe); |
[email protected] | 07c3f84 | 2008-12-02 19:14:29 | [diff] [blame] | 924 | if (!slave.DoInit()) { |
| 925 | printf("Unable to talk with the main process\n"); |
| 926 | return -1; |
| 927 | } |
| 928 | |
| 929 | loop.Run(); |
| 930 | return 0; |
| 931 | } |