Index: net/tools/dump_cache/upgrade.cc |
=================================================================== |
--- net/tools/dump_cache/upgrade.cc (revision 0) |
+++ net/tools/dump_cache/upgrade.cc (revision 0) |
@@ -0,0 +1,791 @@ |
+// Copyright (c) 2008 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "base/string_util.h" |
+#include "net/disk_cache/backend_impl.h" |
+#include "net/disk_cache/entry_impl.h" |
+ |
+namespace { |
+ |
+const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\dump_cache_"; |
+const int kChannelSize = 64 * 1024; |
+const int kNumStreams = 2; |
+ |
+// Simple macro to print out formatted debug messages. It is similar to a DLOG |
+// except that it doesn't include a header. |
+#ifdef NDEBUG |
+#define DEBUGMSG(...) {} |
+#else |
+#define DEBUGMSG(...) { printf(__VA_ARGS__); } |
+#endif |
+ |
+HANDLE OpenServer(const std::wstring pipe_number) { |
+ std::wstring pipe_name(kPipePrefix); |
+ pipe_name.append(pipe_number); |
+ return CreateFile(pipe_name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, |
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); |
+} |
+ |
+// This is the basic message to use between the two processes. It is intended |
+// to transmit a single action (like "get the key name for entry xx"), with up |
+// to 5 32-bit arguments and 4 64-bit arguments. After this structure, the rest |
+// of the message has |buffer_bytes| of length with the actual data. |
+struct Message { |
+ int32 command; |
+ int32 result; |
+ int32 buffer_bytes; |
+ int32 arg1; |
+ int32 arg2; |
+ int32 arg3; |
+ int32 arg4; |
+ int32 arg5; |
+ int64 long_arg1; |
+ int64 long_arg2; |
+ int64 long_arg3; |
+ int64 long_arg4; |
+ Message() { |
+ memset(this, 0, sizeof(*this)); |
+ } |
+ Message& operator= (const Message& other) { |
+ memcpy(this, &other, sizeof(*this)); |
+ return *this; |
+ } |
+}; |
+ |
+const int kBufferSize = kChannelSize - sizeof(Message); |
+struct IoBuffer { |
+ Message msg; |
+ char buffer[kBufferSize]; |
+}; |
+COMPILE_ASSERT(sizeof(IoBuffer) == kChannelSize, invalid_io_buffer); |
+ |
+ |
+// The list of commands. |
+// Currently, there is support for working ONLY with one entry at a time. |
+enum { |
+ // Get the entry from list |arg1| that follows |long_arg1|. |
+ // The result is placed on |long_arg1| (closes the previous one). |
+ GET_NEXT_ENTRY = 1, |
+ // Get the entry from list |arg1| that precedes |long_arg1|. |
+ // The result is placed on |long_arg1| (closes the previous one). |
+ GET_PREV_ENTRY, |
+ // Closes the entry |long_arg1|. |
+ CLOSE_ENTRY, |
+ // Get the key of the entry |long_arg1|. |
+ GET_KEY, |
+ // Get last used (long_arg2) and last modified (long_arg3) times for the |
+ // entry at |long_arg1|. |
+ GET_USE_TIMES, |
+ // Returns on |arg2| the data size in bytes if the stream |arg1| of entry at |
+ // |long_arg1|. |
+ GET_DATA_SIZE, |
+ // Returns |arg2| bytes of the stream |arg1| for the entry at |long_arg1|, |
+ // starting at offset |arg3|. |
+ READ_DATA, |
+ // End processing requests. |
+ QUIT |
+}; |
+ |
+// The list of return codes. |
+enum { |
+ RESULT_OK = 0, |
+ RESULT_UNKNOWN_COMMAND, |
+ RESULT_INVALID_PARAMETER, |
+ RESULT_NAME_OVERFLOW |
+}; |
+ |
+// ----------------------------------------------------------------------- |
+ |
+class BaseSM : public MessageLoopForIO::IOHandler { |
+ public: |
+ BaseSM(disk_cache::BackendImpl* cache, HANDLE channel); |
+ virtual ~BaseSM(); |
+ |
+ protected: |
+ bool SendMsg(const Message& msg); |
+ bool ReceiveMsg(); |
+ bool ConnectChannel(); |
+ bool IsPending(); |
+ |
+ MessageLoopForIO::IOContext in_context_; |
+ MessageLoopForIO::IOContext out_context_; |
+ disk_cache::BackendImpl* cache_; |
+ disk_cache::EntryImpl* entry_; |
+ HANDLE channel_; |
+ int state_; |
+ int pending_count_; |
+ scoped_array<char> in_buffer_; |
+ scoped_array<char> out_buffer_; |
+ IoBuffer* input_; |
+ IoBuffer* output_; |
+ DISALLOW_COPY_AND_ASSIGN(BaseSM); |
+}; |
+ |
+BaseSM::BaseSM(disk_cache::BackendImpl* cache, HANDLE channel) |
+ : cache_(cache), entry_(NULL), channel_(channel), state_(0), |
+ pending_count_(0) { |
+ in_buffer_.reset(new char[kChannelSize]); |
+ out_buffer_.reset(new char[kChannelSize]); |
+ input_ = reinterpret_cast<IoBuffer*>(in_buffer_.get()); |
+ output_ = reinterpret_cast<IoBuffer*>(out_buffer_.get()); |
+ |
+ memset(&in_context_, 0, sizeof(in_context_)); |
+ memset(&out_context_, 0, sizeof(out_context_)); |
+ in_context_.handler = this; |
+ out_context_.handler = this; |
+ MessageLoopForIO::current()->RegisterIOHandler(channel_, this); |
+} |
+ |
+BaseSM::~BaseSM() { |
+ if (entry_) |
+ entry_->Close(); |
+} |
+ |
+bool BaseSM::SendMsg(const Message& msg) { |
+ // Only one command will be in-flight at a time. Let's start the Read IO here |
+ // when we know that it will be pending. |
+ if (!ReceiveMsg()) |
+ return false; |
+ |
+ output_->msg = msg; |
+ DWORD written; |
+ if (!WriteFile(channel_, output_, sizeof(msg) + msg.buffer_bytes, &written, |
+ &out_context_.overlapped)) { |
+ if (ERROR_IO_PENDING != GetLastError()) |
+ return false; |
+ } |
+ pending_count_++; |
+ return true; |
+} |
+ |
+bool BaseSM::ReceiveMsg() { |
+ DWORD read; |
+ if (!ReadFile(channel_, input_, kChannelSize, &read, |
+ &in_context_.overlapped)) { |
+ if (ERROR_IO_PENDING != GetLastError()) |
+ return false; |
+ } |
+ pending_count_++; |
+ return true; |
+} |
+ |
+bool BaseSM::ConnectChannel() { |
+ if (!ConnectNamedPipe(channel_, &in_context_.overlapped)) { |
+ DWORD error = GetLastError(); |
+ if (ERROR_PIPE_CONNECTED == error) |
+ return true; |
+ // By returning true in case of a generic error, we allow the operation to |
+ // fail while sending the first message. |
+ if (ERROR_IO_PENDING != error) |
+ return true; |
+ } |
+ pending_count_++; |
+ return false; |
+} |
+ |
+bool BaseSM::IsPending() { |
+ return pending_count_ != 0; |
+} |
+ |
+// ----------------------------------------------------------------------- |
+ |
+class MasterSM : public BaseSM { |
+ public: |
+ MasterSM(disk_cache::BackendImpl* cache, HANDLE channel) |
+ : BaseSM(cache, channel) {} |
+ virtual ~MasterSM() {} |
+ |
+ bool DoInit(); |
+ virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
+ DWORD bytes_transfered, DWORD error); |
+ |
+ private: |
+ enum { |
+ MASTER_INITIAL = 0, |
+ MASTER_CONNECT, |
+ MASTER_GET_ENTRY, |
+ MASTER_GET_NEXT_ENTRY, |
+ MASTER_GET_KEY, |
+ MASTER_GET_USE_TIMES, |
+ MASTER_GET_DATA_SIZE, |
+ MASTER_READ_DATA, |
+ MASTER_END |
+ }; |
+ |
+ void SendGetPrevEntry(); |
+ void DoGetEntry(); |
+ void DoGetKey(int bytes_read); |
+ void DoGetUseTimes(); |
+ void SendGetDataSize(); |
+ void DoGetDataSize(); |
+ void CloseEntry(); |
+ void SendReadData(); |
+ void DoReadData(int bytes_read); |
+ void SendQuit(); |
+ void DoEnd(); |
+ void Fail(); |
+ |
+ base::Time last_used_; |
+ base::Time last_modified_; |
+ int64 remote_entry_; |
+ int stream_; |
+ int bytes_remaining_; |
+ int offset_; |
+ int copied_entries_; |
+}; |
+ |
+void MasterSM::OnIOCompleted(MessageLoopForIO::IOContext* context, |
+ DWORD bytes_transfered, DWORD error) { |
+ pending_count_--; |
+ if (context == &out_context_) { |
+ if (!error) |
+ return; |
+ return Fail(); |
+ } |
+ |
+ int bytes_read = static_cast<int>(bytes_transfered); |
+ if (bytes_read < sizeof(Message) && state_ != MASTER_END && |
+ state_ != MASTER_CONNECT) { |
+ printf("Communication breakdown\n"); |
+ return Fail(); |
+ } |
+ |
+ switch (state_) { |
+ case MASTER_CONNECT: |
+ SendGetPrevEntry(); |
+ break; |
+ case MASTER_GET_ENTRY: |
+ DoGetEntry(); |
+ break; |
+ case MASTER_GET_KEY: |
+ DoGetKey(bytes_read); |
+ break; |
+ case MASTER_GET_USE_TIMES: |
+ DoGetUseTimes(); |
+ break; |
+ case MASTER_GET_DATA_SIZE: |
+ DoGetDataSize(); |
+ break; |
+ case MASTER_READ_DATA: |
+ DoReadData(bytes_read); |
+ break; |
+ case MASTER_END: |
+ if (!IsPending()) |
+ DoEnd(); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+bool MasterSM::DoInit() { |
+ DEBUGMSG("Master DoInit\n"); |
+ DCHECK(state_ == MASTER_INITIAL); |
+ |
+ copied_entries_ = 0; |
+ remote_entry_ = 0; |
+ |
+ if (ConnectChannel()) { |
+ SendGetPrevEntry(); |
+ // If we don't have pending operations we couldn't connect. |
+ return IsPending(); |
+ } |
+ |
+ state_ = MASTER_CONNECT; |
+ return true; |
+} |
+ |
+void MasterSM::SendGetPrevEntry() { |
+ DEBUGMSG("Master SendGetPrevEntry\n"); |
+ state_ = MASTER_GET_ENTRY; |
+ Message msg; |
+ msg.command = GET_PREV_ENTRY; |
+ msg.long_arg1 = remote_entry_; |
+ SendMsg(msg); |
+} |
+ |
+void MasterSM::DoGetEntry() { |
+ DEBUGMSG("Master DoGetEntry\n"); |
+ DCHECK(state_ == MASTER_GET_ENTRY); |
+ DCHECK(input_->msg.command == GET_PREV_ENTRY); |
+ if (input_->msg.result != RESULT_OK) |
+ return Fail(); |
+ |
+ if (!input_->msg.long_arg1) { |
+ printf("Done: %d entries copied over.\n", copied_entries_); |
+ return SendQuit(); |
+ } |
+ remote_entry_ = input_->msg.long_arg1; |
+ state_ = MASTER_GET_KEY; |
+ Message msg; |
+ msg.command = GET_KEY; |
+ msg.long_arg1 = remote_entry_; |
+ SendMsg(msg); |
+} |
+ |
+void MasterSM::DoGetKey(int bytes_read) { |
+ DEBUGMSG("Master DoGetKey\n"); |
+ DCHECK(state_ == MASTER_GET_KEY); |
+ DCHECK(input_->msg.command == GET_KEY); |
+ if (input_->msg.result == RESULT_NAME_OVERFLOW) |
+ // The key is too long. Just move on. |
+ return SendGetPrevEntry(); |
+ |
+ if (input_->msg.result != RESULT_OK) |
+ return Fail(); |
+ |
+ std::string key(input_->buffer); |
+ DCHECK(key.size() == input_->msg.buffer_bytes - 1); |
+ if (!cache_->CreateEntry(key, reinterpret_cast<disk_cache::Entry**>(&entry_))) |
+ return Fail(); |
+ |
+ if (key.size() < 60) { |
+ DEBUGMSG("Entry \"%s\" created\n", key.c_str()); |
+ } else { |
+ DEBUGMSG("Entry (long name) created\n", key.c_str()); |
+ } |
+ state_ = MASTER_GET_USE_TIMES; |
+ Message msg; |
+ msg.command = GET_USE_TIMES; |
+ msg.long_arg1 = remote_entry_; |
+ SendMsg(msg); |
+} |
+ |
+void MasterSM::DoGetUseTimes() { |
+ DEBUGMSG("Master DoGetUseTimes\n"); |
+ DCHECK(state_ == MASTER_GET_USE_TIMES); |
+ DCHECK(input_->msg.command == GET_USE_TIMES); |
+ if (input_->msg.result != RESULT_OK) |
+ return Fail(); |
+ |
+ last_used_ = base::Time::FromInternalValue(input_->msg.long_arg2); |
+ last_modified_ = base::Time::FromInternalValue(input_->msg.long_arg3); |
+ stream_ = 0; |
+ SendGetDataSize(); |
+} |
+ |
+void MasterSM::SendGetDataSize() { |
+ DEBUGMSG("Master SendGetDataSize (%d)\n", stream_); |
+ state_ = MASTER_GET_DATA_SIZE; |
+ Message msg; |
+ msg.command = GET_DATA_SIZE; |
+ msg.arg1 = stream_; |
+ msg.long_arg1 = remote_entry_; |
+ SendMsg(msg); |
+} |
+ |
+void MasterSM::DoGetDataSize() { |
+ DEBUGMSG("Master DoGetDataSize: %d\n", input_->msg.arg2); |
+ DCHECK(state_ == MASTER_GET_DATA_SIZE); |
+ DCHECK(input_->msg.command == GET_DATA_SIZE); |
+ if (input_->msg.result == RESULT_INVALID_PARAMETER) |
+ // No more streams, move to the next entry. |
+ return CloseEntry(); |
+ |
+ if (input_->msg.result != RESULT_OK) |
+ return Fail(); |
+ |
+ bytes_remaining_ = input_->msg.arg2; |
+ offset_ = 0; |
+ SendReadData(); |
+} |
+ |
+void MasterSM::CloseEntry() { |
+ DEBUGMSG("Master CloseEntry\n"); |
+ printf("%c\r", copied_entries_ % 2 ? 'x' : '+'); |
+ entry_->SetTimes(last_used_, last_modified_); |
+ entry_->Close(); |
+ entry_ = NULL; |
+ copied_entries_++; |
+ SendGetPrevEntry(); |
+} |
+ |
+void MasterSM::SendReadData() { |
+ int read_size = std::min(bytes_remaining_, kBufferSize); |
+ DEBUGMSG("Master SendReadData (%d): %d bytes at %d\n", stream_, read_size, |
+ offset_); |
+ if (bytes_remaining_ <= 0) { |
+ stream_++; |
+ if (stream_ >= kNumStreams) |
+ return CloseEntry(); |
+ return SendGetDataSize(); |
+ } |
+ |
+ state_ = MASTER_READ_DATA; |
+ Message msg; |
+ msg.command = READ_DATA; |
+ msg.arg1 = stream_; |
+ msg.arg2 = read_size; |
+ msg.arg3 = offset_; |
+ msg.long_arg1 = remote_entry_; |
+ SendMsg(msg); |
+} |
+ |
+void MasterSM::DoReadData(int bytes_read) { |
+ DEBUGMSG("Master DoReadData: %d bytes\n", input_->msg.buffer_bytes); |
+ DCHECK(state_ == MASTER_READ_DATA); |
+ DCHECK(input_->msg.command == READ_DATA); |
+ if (input_->msg.result != RESULT_OK) |
+ return Fail(); |
+ |
+ int read_size = input_->msg.buffer_bytes; |
+ if (read_size != entry_->WriteData(stream_, offset_, input_->buffer, |
+ read_size, NULL, false)) |
+ return Fail(); |
+ |
+ offset_ += read_size; |
+ bytes_remaining_ -= read_size; |
+ // Read some more. |
+ SendReadData(); |
+} |
+ |
+void MasterSM::SendQuit() { |
+ DEBUGMSG("Master SendQuit\n"); |
+ state_ = MASTER_END; |
+ Message msg; |
+ msg.command = QUIT; |
+ SendMsg(msg); |
+ if (!IsPending()) |
+ DoEnd(); |
+} |
+ |
+void MasterSM::DoEnd() { |
+ DEBUGMSG("Master DoEnd\n"); |
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+} |
+ |
+void MasterSM::Fail() { |
+ DEBUGMSG("Master Fail\n"); |
+ printf("Unexpected failure\n"); |
+ SendQuit(); |
+} |
+ |
+// ----------------------------------------------------------------------- |
+ |
+class SlaveSM : public BaseSM { |
+ public: |
+ SlaveSM(disk_cache::BackendImpl* cache, HANDLE channel) |
+ : BaseSM(cache, channel), iterator_(NULL) {} |
+ virtual ~SlaveSM(); |
+ |
+ bool DoInit(); |
+ virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, |
+ DWORD bytes_transfered, DWORD error); |
+ |
+ private: |
+ enum { |
+ SLAVE_INITIAL = 0, |
+ SLAVE_WAITING, |
+ SLAVE_END |
+ }; |
+ |
+ void DoGetNextEntry(); |
+ void DoGetPrevEntry(); |
+ int32 GetEntryFromList(); |
+ void DoCloseEntry(); |
+ void DoGetKey(); |
+ void DoGetUseTimes(); |
+ void DoGetDataSize(); |
+ void DoReadData(); |
+ void DoEnd(); |
+ void Fail(); |
+ |
+ void* iterator_; |
+}; |
+ |
+SlaveSM::~SlaveSM() { |
+ if (iterator_) |
+ cache_->EndEnumeration(&iterator_); |
+} |
+ |
+void SlaveSM::OnIOCompleted(MessageLoopForIO::IOContext* context, |
+ DWORD bytes_transfered, DWORD error) { |
+ pending_count_--; |
+ if (state_ == SLAVE_END) { |
+ if (IsPending()) |
+ return; |
+ return DoEnd(); |
+ } |
+ |
+ if (context == &out_context_) { |
+ if (!error) |
+ return; |
+ return Fail(); |
+ } |
+ |
+ int bytes_read = static_cast<int>(bytes_transfered); |
+ if (bytes_read < sizeof(Message)) { |
+ printf("Communication breakdown\n"); |
+ return Fail(); |
+ } |
+ DCHECK(state_ == SLAVE_WAITING); |
+ |
+ switch (input_->msg.command) { |
+ case GET_NEXT_ENTRY: |
+ DoGetNextEntry(); |
+ break; |
+ case GET_PREV_ENTRY: |
+ DoGetPrevEntry(); |
+ break; |
+ case CLOSE_ENTRY: |
+ DoCloseEntry(); |
+ break; |
+ case GET_KEY: |
+ DoGetKey(); |
+ break; |
+ case GET_USE_TIMES: |
+ DoGetUseTimes(); |
+ break; |
+ case GET_DATA_SIZE: |
+ DoGetDataSize(); |
+ break; |
+ case READ_DATA: |
+ DoReadData(); |
+ break; |
+ case QUIT: |
+ DoEnd(); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+bool SlaveSM::DoInit() { |
+ DEBUGMSG("\t\t\tSlave DoInit\n"); |
+ DCHECK(state_ == SLAVE_INITIAL); |
+ state_ = SLAVE_WAITING; |
+ return ReceiveMsg(); |
+} |
+ |
+void SlaveSM::DoGetNextEntry() { |
+ DEBUGMSG("\t\t\tSlave DoGetNextEntry\n"); |
+ Message msg; |
+ msg.command = GET_NEXT_ENTRY; |
+ |
+ if (input_->msg.arg1) { |
+ // We only support one list. |
+ msg.result = RESULT_UNKNOWN_COMMAND; |
+ } else { |
+ msg.result = GetEntryFromList(); |
+ msg.long_arg1 = reinterpret_cast<int64>(entry_); |
+ } |
+ SendMsg(msg); |
+} |
+ |
+void SlaveSM::DoGetPrevEntry() { |
+ DEBUGMSG("\t\t\tSlave DoGetPrevEntry\n"); |
+ Message msg; |
+ msg.command = GET_PREV_ENTRY; |
+ |
+ if (input_->msg.arg1) { |
+ // We only support one list. |
+ msg.result = RESULT_UNKNOWN_COMMAND; |
+ } else { |
+ msg.result = GetEntryFromList(); |
+ msg.long_arg1 = reinterpret_cast<int64>(entry_); |
+ } |
+ SendMsg(msg); |
+} |
+ |
+// Move to the next or previous entry on the list. |
+int32 SlaveSM::GetEntryFromList() { |
+ DEBUGMSG("\t\t\tSlave GetEntryFromList\n"); |
+ if (input_->msg.long_arg1 != reinterpret_cast<int64>(entry_)) |
+ return RESULT_INVALID_PARAMETER; |
+ |
+ // We know that the current iteration is valid. |
+ if (entry_) |
+ entry_->Close(); |
+ |
+ bool ret; |
+ if (input_->msg.command == GET_NEXT_ENTRY) { |
+ ret = cache_->OpenNextEntry(&iterator_, |
+ reinterpret_cast<disk_cache::Entry**>(&entry_)); |
+ } else { |
+ DCHECK(input_->msg.command == GET_PREV_ENTRY); |
+ ret = cache_->OpenPrevEntry(&iterator_, |
+ reinterpret_cast<disk_cache::Entry**>(&entry_)); |
+ } |
+ |
+ if (!ret) |
+ entry_ = NULL; |
+ |
+ if (!entry_) |
+ DEBUGMSG("\t\t\tSlave end of list\n"); |
+ |
+ return RESULT_OK; |
+} |
+ |
+void SlaveSM::DoCloseEntry() { |
+ DEBUGMSG("\t\t\tSlave DoCloseEntry\n"); |
+ Message msg; |
+ msg.command = GET_KEY; |
+ |
+ if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_)) { |
+ msg.result = RESULT_INVALID_PARAMETER; |
+ } else { |
+ entry_->Close(); |
+ entry_ = NULL; |
+ cache_->EndEnumeration(&iterator_); |
+ msg.result = RESULT_OK; |
+ } |
+ SendMsg(msg); |
+} |
+ |
+void SlaveSM::DoGetKey() { |
+ DEBUGMSG("\t\t\tSlave DoGetKey\n"); |
+ Message msg; |
+ msg.command = GET_KEY; |
+ |
+ if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_)) { |
+ msg.result = RESULT_INVALID_PARAMETER; |
+ } else { |
+ std::string key = entry_->GetKey(); |
+ msg.buffer_bytes = std::min(key.size() + 1, |
+ static_cast<size_t>(kBufferSize)); |
+ memcpy(output_->buffer, key.c_str(), msg.buffer_bytes); |
+ if (msg.buffer_bytes != key.size() + 1) { |
+ // We don't support moving this entry. Just tell the master. |
+ msg.result = RESULT_NAME_OVERFLOW; |
+ } else { |
+ msg.result = RESULT_OK; |
+ } |
+ } |
+ SendMsg(msg); |
+} |
+ |
+void SlaveSM::DoGetUseTimes() { |
+ DEBUGMSG("\t\t\tSlave DoGetUseTimes\n"); |
+ Message msg; |
+ msg.command = GET_USE_TIMES; |
+ |
+ if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_)) { |
+ msg.result = RESULT_INVALID_PARAMETER; |
+ } else { |
+ msg.long_arg2 = entry_->GetLastUsed().ToInternalValue(); |
+ msg.long_arg3 = entry_->GetLastModified().ToInternalValue(); |
+ msg.result = RESULT_OK; |
+ } |
+ SendMsg(msg); |
+} |
+ |
+void SlaveSM::DoGetDataSize() { |
+ DEBUGMSG("\t\t\tSlave DoGetDataSize\n"); |
+ Message msg; |
+ msg.command = GET_DATA_SIZE; |
+ |
+ int stream = input_->msg.arg1; |
+ if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_) || |
+ stream < 0 || stream >= kNumStreams) { |
+ msg.result = RESULT_INVALID_PARAMETER; |
+ } else { |
+ msg.arg1 = stream; |
+ msg.arg2 = entry_->GetDataSize(stream); |
+ msg.result = RESULT_OK; |
+ } |
+ SendMsg(msg); |
+} |
+ |
+void SlaveSM::DoReadData() { |
+ DEBUGMSG("\t\t\tSlave DoReadData\n"); |
+ Message msg; |
+ msg.command = READ_DATA; |
+ |
+ int stream = input_->msg.arg1; |
+ int size = input_->msg.arg2; |
+ if (!entry_ || input_->msg.long_arg1 != reinterpret_cast<int64>(entry_) || |
+ stream < 0 || stream > 1 || size > kBufferSize) { |
+ msg.result = RESULT_INVALID_PARAMETER; |
+ } else { |
+ int ret = entry_->ReadData(stream, input_->msg.arg3, output_->buffer, size, |
+ NULL); |
+ |
+ msg.buffer_bytes = (ret < 0) ? 0 : ret; |
+ msg.result = RESULT_OK; |
+ } |
+ SendMsg(msg); |
+} |
+ |
+void SlaveSM::DoEnd() { |
+ DEBUGMSG("\t\t\tSlave DoEnd\n"); |
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
+} |
+ |
+void SlaveSM::Fail() { |
+ DEBUGMSG("\t\t\tSlave Fail\n"); |
+ printf("Unexpected failure\n"); |
+ state_ = SLAVE_END; |
+ if (IsPending()) { |
+ CancelIo(channel_); |
+ } else { |
+ DoEnd(); |
+ } |
+} |
+ |
+} // namespace. |
+ |
+// ----------------------------------------------------------------------- |
+ |
+HANDLE CreateServer(std::wstring* pipe_number) { |
+ std::wstring pipe_name(kPipePrefix); |
+ srand(static_cast<int>(base::Time::Now().ToInternalValue())); |
+ *pipe_number = IntToWString(rand()); |
+ pipe_name.append(*pipe_number); |
+ |
+ DWORD mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | |
+ FILE_FLAG_OVERLAPPED; |
+ |
+ return CreateNamedPipe(pipe_name.c_str(), mode, 0, 1, kChannelSize, |
+ kChannelSize, 0, NULL); |
+} |
+ |
+// This is the controller process for an upgrade operation. |
+int Upgrade(const std::wstring output_path, HANDLE pipe) { |
+ MessageLoop loop(MessageLoop::TYPE_IO); |
+ disk_cache::BackendImpl cache(output_path); |
+ if (!cache.Init()) { |
+ printf("Unable to initialize new files\n"); |
+ return -1; |
+ } |
+ |
+ MasterSM master(&cache, pipe); |
+ if (!master.DoInit()) { |
+ printf("Unable to talk with the helper\n"); |
+ return -1; |
+ } |
+ |
+ loop.Run(); |
+ return 0; |
+} |
+ |
+// This process will only execute commands from the controller. |
+int RunSlave(const std::wstring input_path, const std::wstring pipe_number) { |
+ MessageLoop loop(MessageLoop::TYPE_IO); |
+ |
+ ScopedHandle pipe(OpenServer(pipe_number)); |
+ if (!pipe.IsValid()) { |
+ printf("Unable to open the server pipe\n"); |
+ return -1; |
+ } |
+ |
+ disk_cache::BackendImpl cache(input_path); |
+ if (!cache.Init()) { |
+ printf("Unable to open cache files\n"); |
+ return -1; |
+ } |
+ cache.SetUpgradeMode(); |
+ |
+ SlaveSM slave(&cache, pipe); |
+ if (!slave.DoInit()) { |
+ printf("Unable to talk with the main process\n"); |
+ return -1; |
+ } |
+ |
+ loop.Run(); |
+ return 0; |
+} |
Property changes on: net\tools\dump_cache\upgrade.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |