Index: net/tools/dump_cache/upgrade.cc |
diff --git a/net/tools/dump_cache/upgrade.cc b/net/tools/dump_cache/upgrade.cc |
deleted file mode 100644 |
index 34bc174558677f8b75a4fe140e4ff57c77c9015c..0000000000000000000000000000000000000000 |
--- a/net/tools/dump_cache/upgrade.cc |
+++ /dev/null |
@@ -1,922 +0,0 @@ |
-// Copyright (c) 2012 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/bind.h" |
-#include "base/bind_helpers.h" |
-#include "base/file_path.h" |
-#include "base/logging.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/message_loop.h" |
-#include "base/string_number_conversions.h" |
-#include "base/string_util.h" |
-#include "base/threading/thread.h" |
-#include "base/win/scoped_handle.h" |
-#include "googleurl/src/gurl.h" |
-#include "net/base/io_buffer.h" |
-#include "net/base/net_errors.h" |
-#include "net/base/test_completion_callback.h" |
-#include "net/disk_cache/backend_impl.h" |
-#include "net/disk_cache/entry_impl.h" |
-#include "net/http/http_cache.h" |
-#include "net/http/http_response_headers.h" |
-#include "net/http/http_response_info.h" |
-#include "net/tools/dump_cache/cache_dumper.h" |
- |
-namespace { |
- |
-const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\dump_cache_"; |
-const int kChannelSize = 64 * 1024; |
-const int kNumStreams = 4; |
- |
-// 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, |
- RESULT_PENDING // This error code is NOT expected by the master process. |
-}; |
- |
-// ----------------------------------------------------------------------- |
- |
-class BaseSM : public MessageLoopForIO::IOHandler { |
- public: |
- explicit BaseSM(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::EntryImpl* entry_; |
- HANDLE channel_; |
- int state_; |
- int pending_count_; |
- scoped_array<char> in_buffer_; |
- scoped_array<char> out_buffer_; |
- IoBuffer* input_; |
- IoBuffer* output_; |
- base::Thread cache_thread_; |
- |
- DISALLOW_COPY_AND_ASSIGN(BaseSM); |
-}; |
- |
-BaseSM::BaseSM(HANDLE channel) |
- : entry_(NULL), channel_(channel), state_(0), pending_count_(0), |
- cache_thread_("cache") { |
- 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); |
- CHECK(cache_thread_.StartWithOptions( |
- base::Thread::Options(MessageLoop::TYPE_IO, 0))); |
-} |
- |
-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(const FilePath& path, HANDLE channel, bool dump_to_disk) |
- : BaseSM(channel), |
- path_(path), |
- dump_to_disk_(dump_to_disk) { |
- } |
- virtual ~MasterSM() { |
- delete writer_; |
- } |
- |
- 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 DoCreateEntryComplete(int result); |
- void DoGetUseTimes(); |
- void SendGetDataSize(); |
- void DoGetDataSize(); |
- void CloseEntry(); |
- void SendReadData(); |
- void DoReadData(int bytes_read); |
- void DoReadDataComplete(int ret); |
- 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_; |
- int read_size_; |
- scoped_ptr<disk_cache::Backend> cache_; |
- CacheDumpWriter* writer_; |
- const FilePath path_; |
- bool dump_to_disk_; |
-}; |
- |
-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); |
- |
- if (dump_to_disk_) { |
- writer_ = new DiskDumper(path_); |
- } else { |
- disk_cache::Backend* cache; |
- net::TestCompletionCallback cb; |
- int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path_, 0, false, |
- cache_thread_.message_loop_proxy(), |
- NULL, &cache, cb.callback()); |
- if (cb.GetResult(rv) != net::OK) { |
- printf("Unable to initialize new files\n"); |
- return false; |
- } |
- cache_.reset(cache); |
- writer_ = new CacheDumper(cache_.get()); |
- } |
- if (!writer_) |
- return false; |
- |
- 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. |
- printf("Skipping entry (name too long)\n"); |
- return SendGetPrevEntry(); |
- } |
- |
- if (input_->msg.result != RESULT_OK) |
- return Fail(); |
- |
- std::string key(input_->buffer); |
- DCHECK(key.size() == static_cast<size_t>(input_->msg.buffer_bytes - 1)); |
- |
- int rv = writer_->CreateEntry( |
- key, reinterpret_cast<disk_cache::Entry**>(&entry_), |
- base::Bind(&MasterSM::DoCreateEntryComplete, base::Unretained(this))); |
- |
- if (rv != net::ERR_IO_PENDING) |
- DoCreateEntryComplete(rv); |
-} |
- |
-void MasterSM::DoCreateEntryComplete(int result) { |
- std::string key(input_->buffer); |
- if (result != net::OK) { |
- printf("Skipping entry \"%s\": %d\n", key.c_str(), GetLastError()); |
- return SendGetPrevEntry(); |
- } |
- |
- if (key.size() >= 64) { |
- key[60] = '.'; |
- key[61] = '.'; |
- key[62] = '.'; |
- key[63] = '\0'; |
- } |
- DEBUGMSG("Entry \"%s\" 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' : '+'); |
- writer_->CloseEntry(entry_, last_used_, last_modified_); |
- 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) { |
- printf("Read failed, entry \"%s\" truncated!\n", entry_->GetKey().c_str()); |
- bytes_remaining_ = 0; |
- return SendReadData(); |
- } |
- |
- scoped_refptr<net::WrappedIOBuffer> buf = |
- new net::WrappedIOBuffer(input_->buffer); |
- int rv = writer_->WriteEntry( |
- entry_, stream_, offset_, buf, read_size, |
- base::Bind(&MasterSM::DoReadDataComplete, base::Unretained(this))); |
- if (rv == net::ERR_IO_PENDING) { |
- // We'll continue in DoReadDataComplete. |
- read_size_ = read_size; |
- return; |
- } |
- |
- if (rv <= 0) |
- return Fail(); |
- |
- offset_ += read_size; |
- bytes_remaining_ -= read_size; |
- // Read some more. |
- SendReadData(); |
-} |
- |
-void MasterSM::DoReadDataComplete(int ret) { |
- if (ret != read_size_) |
- return Fail(); |
- |
- offset_ += ret; |
- bytes_remaining_ -= ret; |
- // 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, MessageLoop::QuitClosure()); |
-} |
- |
-void MasterSM::Fail() { |
- DEBUGMSG("Master Fail\n"); |
- printf("Unexpected failure\n"); |
- SendQuit(); |
-} |
- |
-// ----------------------------------------------------------------------- |
- |
-class SlaveSM : public BaseSM { |
- public: |
- SlaveSM(const FilePath& path, HANDLE channel); |
- 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 DoGetEntryComplete(int result); |
- void DoCloseEntry(); |
- void DoGetKey(); |
- void DoGetUseTimes(); |
- void DoGetDataSize(); |
- void DoReadData(); |
- void DoReadDataComplete(int ret); |
- void DoEnd(); |
- void Fail(); |
- |
- void* iterator_; |
- Message msg_; // Used for DoReadDataComplete and DoGetEntryComplete. |
- |
- scoped_ptr<disk_cache::BackendImpl> cache_; |
-}; |
- |
-SlaveSM::SlaveSM(const FilePath& path, HANDLE channel) |
- : BaseSM(channel), iterator_(NULL) { |
- disk_cache::Backend* cache; |
- net::TestCompletionCallback cb; |
- int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false, |
- cache_thread_.message_loop_proxy(), |
- NULL, &cache, cb.callback()); |
- if (cb.GetResult(rv) != net::OK) { |
- printf("Unable to open cache files\n"); |
- return; |
- } |
- cache_.reset(reinterpret_cast<disk_cache::BackendImpl*>(cache)); |
- cache_->SetUpgradeMode(); |
-} |
- |
-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; |
- if (!cache_.get()) |
- return false; |
- |
- 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(); |
- if (msg.result == RESULT_PENDING) { |
- // We are not done yet. |
- msg_ = msg; |
- return; |
- } |
- 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(); |
- |
- int rv; |
- if (input_->msg.command == GET_NEXT_ENTRY) { |
- rv = cache_->OpenNextEntry( |
- &iterator_, reinterpret_cast<disk_cache::Entry**>(&entry_), |
- base::Bind(&SlaveSM::DoGetEntryComplete, base::Unretained(this))); |
- } else { |
- DCHECK(input_->msg.command == GET_PREV_ENTRY); |
- rv = cache_->OpenPrevEntry(&iterator_, |
- reinterpret_cast<disk_cache::Entry**>(&entry_), |
- base::Bind(&SlaveSM::DoGetEntryComplete, |
- base::Unretained(this))); |
- } |
- DCHECK_EQ(net::ERR_IO_PENDING, rv); |
- return RESULT_PENDING; |
-} |
- |
-void SlaveSM::DoGetEntryComplete(int result) { |
- DEBUGMSG("\t\t\tSlave DoGetEntryComplete\n"); |
- if (result != net::OK) { |
- entry_ = NULL; |
- DEBUGMSG("\t\t\tSlave end of list\n"); |
- } |
- |
- msg_.result = RESULT_OK; |
- msg_.long_arg1 = reinterpret_cast<int64>(entry_); |
- SendMsg(msg_); |
-} |
- |
-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 != static_cast<int32>(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 { |
- scoped_refptr<net::WrappedIOBuffer> buf = |
- new net::WrappedIOBuffer(output_->buffer); |
- int ret = entry_->ReadData(stream, input_->msg.arg3, buf, size, |
- base::Bind(&SlaveSM::DoReadDataComplete, |
- base::Unretained(this))); |
- if (ret == net::ERR_IO_PENDING) { |
- // Save the message so we can continue were we left. |
- msg_ = msg; |
- return; |
- } |
- |
- msg.buffer_bytes = (ret < 0) ? 0 : ret; |
- msg.result = RESULT_OK; |
- } |
- SendMsg(msg); |
-} |
- |
-void SlaveSM::DoReadDataComplete(int ret) { |
- DEBUGMSG("\t\t\tSlave DoReadDataComplete\n"); |
- DCHECK_EQ(READ_DATA, msg_.command); |
- 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, MessageLoop::QuitClosure()); |
-} |
- |
-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 = base::IntToString16(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 CopyCache(const FilePath& output_path, HANDLE pipe, bool copy_to_text) { |
- MessageLoop loop(MessageLoop::TYPE_IO); |
- |
- MasterSM master(output_path, pipe, copy_to_text); |
- 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 FilePath& input_path, const std::wstring& pipe_number) { |
- MessageLoop loop(MessageLoop::TYPE_IO); |
- |
- base::win::ScopedHandle pipe(OpenServer(pipe_number)); |
- if (!pipe.IsValid()) { |
- printf("Unable to open the server pipe\n"); |
- return -1; |
- } |
- |
- SlaveSM slave(input_path, pipe); |
- if (!slave.DoInit()) { |
- printf("Unable to talk with the main process\n"); |
- return -1; |
- } |
- |
- loop.Run(); |
- return 0; |
-} |