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