OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/file_path.h" | 5 #include "base/file_path.h" |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/scoped_ptr.h" | 8 #include "base/scoped_ptr.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/thread.h" |
10 #include "googleurl/src/gurl.h" | 11 #include "googleurl/src/gurl.h" |
11 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
| 13 #include "net/base/test_completion_callback.h" |
12 #include "net/disk_cache/backend_impl.h" | 14 #include "net/disk_cache/backend_impl.h" |
13 #include "net/disk_cache/entry_impl.h" | 15 #include "net/disk_cache/entry_impl.h" |
14 #include "net/http/http_cache.h" | 16 #include "net/http/http_cache.h" |
15 #include "net/http/http_response_headers.h" | 17 #include "net/http/http_response_headers.h" |
16 #include "net/http/http_response_info.h" | 18 #include "net/http/http_response_info.h" |
17 #include "net/tools/dump_cache/cache_dumper.h" | 19 #include "net/tools/dump_cache/cache_dumper.h" |
18 | 20 |
19 namespace { | 21 namespace { |
20 | 22 |
21 const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\dump_cache_"; | 23 const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\dump_cache_"; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 RESULT_OK = 0, | 104 RESULT_OK = 0, |
103 RESULT_UNKNOWN_COMMAND, | 105 RESULT_UNKNOWN_COMMAND, |
104 RESULT_INVALID_PARAMETER, | 106 RESULT_INVALID_PARAMETER, |
105 RESULT_NAME_OVERFLOW | 107 RESULT_NAME_OVERFLOW |
106 }; | 108 }; |
107 | 109 |
108 // ----------------------------------------------------------------------- | 110 // ----------------------------------------------------------------------- |
109 | 111 |
110 class BaseSM : public MessageLoopForIO::IOHandler { | 112 class BaseSM : public MessageLoopForIO::IOHandler { |
111 public: | 113 public: |
112 BaseSM(HANDLE channel); | 114 explicit BaseSM(HANDLE channel); |
113 virtual ~BaseSM(); | 115 virtual ~BaseSM(); |
114 | 116 |
115 protected: | 117 protected: |
116 bool SendMsg(const Message& msg); | 118 bool SendMsg(const Message& msg); |
117 bool ReceiveMsg(); | 119 bool ReceiveMsg(); |
118 bool ConnectChannel(); | 120 bool ConnectChannel(); |
119 bool IsPending(); | 121 bool IsPending(); |
120 | 122 |
121 MessageLoopForIO::IOContext in_context_; | 123 MessageLoopForIO::IOContext in_context_; |
122 MessageLoopForIO::IOContext out_context_; | 124 MessageLoopForIO::IOContext out_context_; |
123 disk_cache::EntryImpl* entry_; | 125 disk_cache::EntryImpl* entry_; |
124 HANDLE channel_; | 126 HANDLE channel_; |
125 int state_; | 127 int state_; |
126 int pending_count_; | 128 int pending_count_; |
127 scoped_array<char> in_buffer_; | 129 scoped_array<char> in_buffer_; |
128 scoped_array<char> out_buffer_; | 130 scoped_array<char> out_buffer_; |
129 IoBuffer* input_; | 131 IoBuffer* input_; |
130 IoBuffer* output_; | 132 IoBuffer* output_; |
| 133 base::Thread cache_thread_; |
| 134 |
131 DISALLOW_COPY_AND_ASSIGN(BaseSM); | 135 DISALLOW_COPY_AND_ASSIGN(BaseSM); |
132 }; | 136 }; |
133 | 137 |
134 BaseSM::BaseSM(HANDLE channel) | 138 BaseSM::BaseSM(HANDLE channel) |
135 : entry_(NULL), channel_(channel), state_(0), pending_count_(0) { | 139 : entry_(NULL), channel_(channel), state_(0), pending_count_(0), |
| 140 cache_thread_("cache") { |
136 in_buffer_.reset(new char[kChannelSize]); | 141 in_buffer_.reset(new char[kChannelSize]); |
137 out_buffer_.reset(new char[kChannelSize]); | 142 out_buffer_.reset(new char[kChannelSize]); |
138 input_ = reinterpret_cast<IoBuffer*>(in_buffer_.get()); | 143 input_ = reinterpret_cast<IoBuffer*>(in_buffer_.get()); |
139 output_ = reinterpret_cast<IoBuffer*>(out_buffer_.get()); | 144 output_ = reinterpret_cast<IoBuffer*>(out_buffer_.get()); |
140 | 145 |
141 memset(&in_context_, 0, sizeof(in_context_)); | 146 memset(&in_context_, 0, sizeof(in_context_)); |
142 memset(&out_context_, 0, sizeof(out_context_)); | 147 memset(&out_context_, 0, sizeof(out_context_)); |
143 in_context_.handler = this; | 148 in_context_.handler = this; |
144 out_context_.handler = this; | 149 out_context_.handler = this; |
145 MessageLoopForIO::current()->RegisterIOHandler(channel_, this); | 150 MessageLoopForIO::current()->RegisterIOHandler(channel_, this); |
| 151 CHECK(cache_thread_.StartWithOptions( |
| 152 base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
146 } | 153 } |
147 | 154 |
148 BaseSM::~BaseSM() { | 155 BaseSM::~BaseSM() { |
149 if (entry_) | 156 if (entry_) |
150 entry_->Close(); | 157 entry_->Close(); |
151 } | 158 } |
152 | 159 |
153 bool BaseSM::SendMsg(const Message& msg) { | 160 bool BaseSM::SendMsg(const Message& msg) { |
154 // Only one command will be in-flight at a time. Let's start the Read IO here | 161 // Only one command will be in-flight at a time. Let's start the Read IO here |
155 // when we know that it will be pending. | 162 // when we know that it will be pending. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 } | 200 } |
194 | 201 |
195 bool BaseSM::IsPending() { | 202 bool BaseSM::IsPending() { |
196 return pending_count_ != 0; | 203 return pending_count_ != 0; |
197 } | 204 } |
198 | 205 |
199 // ----------------------------------------------------------------------- | 206 // ----------------------------------------------------------------------- |
200 | 207 |
201 class MasterSM : public BaseSM { | 208 class MasterSM : public BaseSM { |
202 public: | 209 public: |
203 MasterSM(const std::wstring& path, HANDLE channel, bool dump_to_disk) | 210 MasterSM(const std::wstring& path, HANDLE channel, bool dump_to_disk) |
204 : BaseSM(channel), path_(path), dump_to_disk_(dump_to_disk) { | 211 : BaseSM(channel), path_(path), dump_to_disk_(dump_to_disk), |
| 212 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 213 write_callback_(this, &MasterSM::DoReadDataComplete)) { |
205 } | 214 } |
206 virtual ~MasterSM() { | 215 virtual ~MasterSM() { |
207 delete writer_; | 216 delete writer_; |
208 } | 217 } |
209 | 218 |
210 bool DoInit(); | 219 bool DoInit(); |
211 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, | 220 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
212 DWORD bytes_transfered, DWORD error); | 221 DWORD bytes_transfered, DWORD error); |
213 | 222 |
214 private: | 223 private: |
(...skipping 11 matching lines...) Expand all Loading... |
226 | 235 |
227 void SendGetPrevEntry(); | 236 void SendGetPrevEntry(); |
228 void DoGetEntry(); | 237 void DoGetEntry(); |
229 void DoGetKey(int bytes_read); | 238 void DoGetKey(int bytes_read); |
230 void DoGetUseTimes(); | 239 void DoGetUseTimes(); |
231 void SendGetDataSize(); | 240 void SendGetDataSize(); |
232 void DoGetDataSize(); | 241 void DoGetDataSize(); |
233 void CloseEntry(); | 242 void CloseEntry(); |
234 void SendReadData(); | 243 void SendReadData(); |
235 void DoReadData(int bytes_read); | 244 void DoReadData(int bytes_read); |
| 245 void DoReadDataComplete(int ret); |
236 void SendQuit(); | 246 void SendQuit(); |
237 void DoEnd(); | 247 void DoEnd(); |
238 void Fail(); | 248 void Fail(); |
239 | 249 |
240 base::Time last_used_; | 250 base::Time last_used_; |
241 base::Time last_modified_; | 251 base::Time last_modified_; |
242 int64 remote_entry_; | 252 int64 remote_entry_; |
243 int stream_; | 253 int stream_; |
244 int bytes_remaining_; | 254 int bytes_remaining_; |
245 int offset_; | 255 int offset_; |
246 int copied_entries_; | 256 int copied_entries_; |
247 scoped_ptr<disk_cache::BackendImpl> cache_; | 257 int read_size_; |
| 258 scoped_ptr<disk_cache::Backend> cache_; |
248 CacheDumpWriter* writer_; | 259 CacheDumpWriter* writer_; |
249 const std::wstring& path_; | 260 const std::wstring& path_; |
250 bool dump_to_disk_; | 261 bool dump_to_disk_; |
| 262 net::CompletionCallbackImpl<MasterSM> write_callback_; |
251 }; | 263 }; |
252 | 264 |
253 void MasterSM::OnIOCompleted(MessageLoopForIO::IOContext* context, | 265 void MasterSM::OnIOCompleted(MessageLoopForIO::IOContext* context, |
254 DWORD bytes_transfered, DWORD error) { | 266 DWORD bytes_transfered, DWORD error) { |
255 pending_count_--; | 267 pending_count_--; |
256 if (context == &out_context_) { | 268 if (context == &out_context_) { |
257 if (!error) | 269 if (!error) |
258 return; | 270 return; |
259 return Fail(); | 271 return Fail(); |
260 } | 272 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 } | 307 } |
296 } | 308 } |
297 | 309 |
298 bool MasterSM::DoInit() { | 310 bool MasterSM::DoInit() { |
299 DEBUGMSG("Master DoInit\n"); | 311 DEBUGMSG("Master DoInit\n"); |
300 DCHECK(state_ == MASTER_INITIAL); | 312 DCHECK(state_ == MASTER_INITIAL); |
301 | 313 |
302 if (dump_to_disk_) { | 314 if (dump_to_disk_) { |
303 writer_ = new DiskDumper(path_); | 315 writer_ = new DiskDumper(path_); |
304 } else { | 316 } else { |
305 cache_.reset(new disk_cache::BackendImpl(FilePath::FromWStringHack(path_))); | 317 disk_cache::Backend* cache; |
306 if (!cache_->Init()) { | 318 TestCompletionCallback cb; |
| 319 int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, |
| 320 FilePath::FromWStringHack(path_), 0, |
| 321 false, |
| 322 cache_thread_.message_loop_proxy(), |
| 323 &cache, &cb); |
| 324 if (cb.GetResult(rv) != net::OK) { |
307 printf("Unable to initialize new files\n"); | 325 printf("Unable to initialize new files\n"); |
308 return false; | 326 return false; |
309 } | 327 } |
| 328 cache_.reset(cache); |
310 writer_ = new CacheDumper(cache_.get()); | 329 writer_ = new CacheDumper(cache_.get()); |
311 } | 330 } |
312 if (!writer_) | 331 if (!writer_) |
313 return false; | 332 return false; |
314 | 333 |
315 copied_entries_ = 0; | 334 copied_entries_ = 0; |
316 remote_entry_ = 0; | 335 remote_entry_ = 0; |
317 | 336 |
318 if (ConnectChannel()) { | 337 if (ConnectChannel()) { |
319 SendGetPrevEntry(); | 338 SendGetPrevEntry(); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 | 486 |
468 int read_size = input_->msg.buffer_bytes; | 487 int read_size = input_->msg.buffer_bytes; |
469 if (!read_size) { | 488 if (!read_size) { |
470 printf("Read failed, entry \"%s\" truncated!\n", entry_->GetKey().c_str()); | 489 printf("Read failed, entry \"%s\" truncated!\n", entry_->GetKey().c_str()); |
471 bytes_remaining_ = 0; | 490 bytes_remaining_ = 0; |
472 return SendReadData(); | 491 return SendReadData(); |
473 } | 492 } |
474 | 493 |
475 scoped_refptr<net::WrappedIOBuffer> buf = | 494 scoped_refptr<net::WrappedIOBuffer> buf = |
476 new net::WrappedIOBuffer(input_->buffer); | 495 new net::WrappedIOBuffer(input_->buffer); |
477 if (!writer_->WriteEntry(entry_, stream_, offset_, buf, read_size)) | 496 int rv = writer_->WriteEntry(entry_, stream_, offset_, buf, read_size, |
| 497 &write_callback_); |
| 498 if (rv == net::ERR_IO_PENDING) { |
| 499 // We'll continue in DoReadDataComplete. |
| 500 read_size_ = read_size; |
| 501 return; |
| 502 } |
| 503 |
| 504 if (rv <= 0) |
478 return Fail(); | 505 return Fail(); |
479 | 506 |
480 offset_ += read_size; | 507 offset_ += read_size; |
481 bytes_remaining_ -= read_size; | 508 bytes_remaining_ -= read_size; |
482 // Read some more. | 509 // Read some more. |
483 SendReadData(); | 510 SendReadData(); |
484 } | 511 } |
485 | 512 |
| 513 void MasterSM::DoReadDataComplete(int ret) { |
| 514 if (ret != read_size_) |
| 515 return Fail(); |
| 516 |
| 517 offset_ += ret; |
| 518 bytes_remaining_ -= ret; |
| 519 // Read some more. |
| 520 SendReadData(); |
| 521 } |
| 522 |
486 void MasterSM::SendQuit() { | 523 void MasterSM::SendQuit() { |
487 DEBUGMSG("Master SendQuit\n"); | 524 DEBUGMSG("Master SendQuit\n"); |
488 state_ = MASTER_END; | 525 state_ = MASTER_END; |
489 Message msg; | 526 Message msg; |
490 msg.command = QUIT; | 527 msg.command = QUIT; |
491 SendMsg(msg); | 528 SendMsg(msg); |
492 if (!IsPending()) | 529 if (!IsPending()) |
493 DoEnd(); | 530 DoEnd(); |
494 } | 531 } |
495 | 532 |
496 void MasterSM::DoEnd() { | 533 void MasterSM::DoEnd() { |
497 DEBUGMSG("Master DoEnd\n"); | 534 DEBUGMSG("Master DoEnd\n"); |
498 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); | 535 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
499 } | 536 } |
500 | 537 |
501 void MasterSM::Fail() { | 538 void MasterSM::Fail() { |
502 DEBUGMSG("Master Fail\n"); | 539 DEBUGMSG("Master Fail\n"); |
503 printf("Unexpected failure\n"); | 540 printf("Unexpected failure\n"); |
504 SendQuit(); | 541 SendQuit(); |
505 } | 542 } |
506 | 543 |
507 // ----------------------------------------------------------------------- | 544 // ----------------------------------------------------------------------- |
508 | 545 |
509 class SlaveSM : public BaseSM { | 546 class SlaveSM : public BaseSM { |
510 public: | 547 public: |
511 SlaveSM(const std::wstring& path, HANDLE channel) | 548 SlaveSM(const std::wstring& path, HANDLE channel); |
512 : BaseSM(channel), iterator_(NULL) { | |
513 cache_.reset(new disk_cache::BackendImpl(FilePath::FromWStringHack(path))); | |
514 if (!cache_->Init()) { | |
515 printf("Unable to open cache files\n"); | |
516 return; | |
517 } | |
518 cache_->SetUpgradeMode(); | |
519 } | |
520 virtual ~SlaveSM(); | 549 virtual ~SlaveSM(); |
521 | 550 |
522 bool DoInit(); | 551 bool DoInit(); |
523 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, | 552 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
524 DWORD bytes_transfered, DWORD error); | 553 DWORD bytes_transfered, DWORD error); |
525 | 554 |
526 private: | 555 private: |
527 enum { | 556 enum { |
528 SLAVE_INITIAL = 0, | 557 SLAVE_INITIAL = 0, |
529 SLAVE_WAITING, | 558 SLAVE_WAITING, |
530 SLAVE_END | 559 SLAVE_END |
531 }; | 560 }; |
532 | 561 |
533 void DoGetNextEntry(); | 562 void DoGetNextEntry(); |
534 void DoGetPrevEntry(); | 563 void DoGetPrevEntry(); |
535 int32 GetEntryFromList(); | 564 int32 GetEntryFromList(); |
536 void DoCloseEntry(); | 565 void DoCloseEntry(); |
537 void DoGetKey(); | 566 void DoGetKey(); |
538 void DoGetUseTimes(); | 567 void DoGetUseTimes(); |
539 void DoGetDataSize(); | 568 void DoGetDataSize(); |
540 void DoReadData(); | 569 void DoReadData(); |
| 570 void DoReadDataComplete(int ret); |
541 void DoEnd(); | 571 void DoEnd(); |
542 void Fail(); | 572 void Fail(); |
543 | 573 |
544 void* iterator_; | 574 void* iterator_; |
| 575 Message msg_; // Only used for DoReadDataComplete. |
545 | 576 |
| 577 net::CompletionCallbackImpl<SlaveSM> read_callback_; |
546 scoped_ptr<disk_cache::BackendImpl> cache_; | 578 scoped_ptr<disk_cache::BackendImpl> cache_; |
547 }; | 579 }; |
548 | 580 |
| 581 SlaveSM::SlaveSM(const std::wstring& path, HANDLE channel) |
| 582 : BaseSM(channel), iterator_(NULL), |
| 583 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 584 read_callback_(this, &SlaveSM::DoReadDataComplete)) { |
| 585 disk_cache::Backend* cache; |
| 586 TestCompletionCallback cb; |
| 587 int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, |
| 588 FilePath::FromWStringHack(path), 0, |
| 589 false, |
| 590 cache_thread_.message_loop_proxy(), |
| 591 &cache, &cb); |
| 592 if (cb.GetResult(rv) != net::OK) { |
| 593 printf("Unable to open cache files\n"); |
| 594 return; |
| 595 } |
| 596 cache_.reset(reinterpret_cast<disk_cache::BackendImpl*>(cache)); |
| 597 cache_->SetUpgradeMode(); |
| 598 } |
| 599 |
549 SlaveSM::~SlaveSM() { | 600 SlaveSM::~SlaveSM() { |
550 if (iterator_) | 601 if (iterator_) |
551 cache_->EndEnumeration(&iterator_); | 602 cache_->EndEnumeration(&iterator_); |
552 } | 603 } |
553 | 604 |
554 void SlaveSM::OnIOCompleted(MessageLoopForIO::IOContext* context, | 605 void SlaveSM::OnIOCompleted(MessageLoopForIO::IOContext* context, |
555 DWORD bytes_transfered, DWORD error) { | 606 DWORD bytes_transfered, DWORD error) { |
556 pending_count_--; | 607 pending_count_--; |
557 if (state_ == SLAVE_END) { | 608 if (state_ == SLAVE_END) { |
558 if (IsPending()) | 609 if (IsPending()) |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 msg.command = READ_DATA; | 797 msg.command = READ_DATA; |
747 | 798 |
748 int stream = input_->msg.arg1; | 799 int stream = input_->msg.arg1; |
749 int size = input_->msg.arg2; | 800 int size = input_->msg.arg2; |
750 if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_) || | 801 if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_) || |
751 stream < 0 || stream > 1 || size > kBufferSize) { | 802 stream < 0 || stream > 1 || size > kBufferSize) { |
752 msg.result = RESULT_INVALID_PARAMETER; | 803 msg.result = RESULT_INVALID_PARAMETER; |
753 } else { | 804 } else { |
754 scoped_refptr<net::WrappedIOBuffer> buf = | 805 scoped_refptr<net::WrappedIOBuffer> buf = |
755 new net::WrappedIOBuffer(output_->buffer); | 806 new net::WrappedIOBuffer(output_->buffer); |
756 int ret = entry_->ReadData(stream, input_->msg.arg3, buf, size, NULL); | 807 int ret = entry_->ReadData(stream, input_->msg.arg3, buf, size, |
| 808 &read_callback_); |
| 809 if (ret == net::ERR_IO_PENDING) { |
| 810 // Save the message so we can continue were we left. |
| 811 msg_ = msg; |
| 812 return; |
| 813 } |
757 | 814 |
758 msg.buffer_bytes = (ret < 0) ? 0 : ret; | 815 msg.buffer_bytes = (ret < 0) ? 0 : ret; |
759 msg.result = RESULT_OK; | 816 msg.result = RESULT_OK; |
760 } | 817 } |
761 SendMsg(msg); | 818 SendMsg(msg); |
762 } | 819 } |
763 | 820 |
| 821 void SlaveSM::DoReadDataComplete(int ret) { |
| 822 DEBUGMSG("\t\t\tSlave DoReadDataComplete\n"); |
| 823 DCHECK_EQ(READ_DATA, msg_.command); |
| 824 msg_.buffer_bytes = (ret < 0) ? 0 : ret; |
| 825 msg_.result = RESULT_OK; |
| 826 SendMsg(msg_); |
| 827 } |
| 828 |
764 void SlaveSM::DoEnd() { | 829 void SlaveSM::DoEnd() { |
765 DEBUGMSG("\t\t\tSlave DoEnd\n"); | 830 DEBUGMSG("\t\t\tSlave DoEnd\n"); |
766 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); | 831 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
767 } | 832 } |
768 | 833 |
769 void SlaveSM::Fail() { | 834 void SlaveSM::Fail() { |
770 DEBUGMSG("\t\t\tSlave Fail\n"); | 835 DEBUGMSG("\t\t\tSlave Fail\n"); |
771 printf("Unexpected failure\n"); | 836 printf("Unexpected failure\n"); |
772 state_ = SLAVE_END; | 837 state_ = SLAVE_END; |
773 if (IsPending()) { | 838 if (IsPending()) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 | 885 |
821 SlaveSM slave(input_path, pipe); | 886 SlaveSM slave(input_path, pipe); |
822 if (!slave.DoInit()) { | 887 if (!slave.DoInit()) { |
823 printf("Unable to talk with the main process\n"); | 888 printf("Unable to talk with the main process\n"); |
824 return -1; | 889 return -1; |
825 } | 890 } |
826 | 891 |
827 loop.Run(); | 892 loop.Run(); |
828 return 0; | 893 return 0; |
829 } | 894 } |
OLD | NEW |