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

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

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

Powered by Google App Engine
This is Rietveld 408576698