Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: net/tools/dump_cache/upgrade.cc

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

Powered by Google App Engine
This is Rietveld 408576698