OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <iostream> | 5 #include <iostream> |
6 #include <memory> | 6 #include <memory> |
7 | 7 |
8 #include "base/at_exit.h" | 8 #include "base/at_exit.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" |
12 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
13 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
14 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
15 #include "net/base/io_buffer.h" | 16 #include "net/base/io_buffer.h" |
16 #include "net/base/test_completion_callback.h" | 17 #include "net/base/test_completion_callback.h" |
17 #include "net/disk_cache/disk_cache.h" | 18 #include "net/disk_cache/disk_cache.h" |
18 #include "net/http/http_cache.h" | 19 #include "net/http/http_cache.h" |
19 #include "net/http/http_response_headers.h" | 20 #include "net/http/http_response_headers.h" |
20 #include "net/http/http_util.h" | 21 #include "net/http/http_util.h" |
21 | 22 |
22 using disk_cache::Backend; | 23 using disk_cache::Backend; |
23 using disk_cache::Entry; | 24 using disk_cache::Entry; |
24 | 25 |
25 namespace { | 26 namespace { |
26 | 27 |
27 int kResponseInfoIndex = 0; | 28 constexpr int kResponseInfoIndex = 0; |
28 | 29 |
29 // Get the cache's size. | 30 const char* const kCommandNames[] = { |
30 bool GetSize(Backend* cache_backend) { | 31 "stop", "get_size", "list_keys", "get_stream_for_key", |
| 32 "delete_stream", "delete_key", "update_raw_headers", |
| 33 }; |
| 34 |
| 35 // Prints the command line help. |
| 36 void PrintHelp() { |
| 37 std::cout << "cachetool <cache_path> <cache_backend_type> <subcommand> " |
| 38 << std::endl |
| 39 << std::endl; |
| 40 std::cout << "Available cache backend types: simple, blockfile" << std::endl; |
| 41 std::cout << "Available subcommands:" << std::endl; |
| 42 std::cout << " batch: Starts cachetool to process serialized commands " |
| 43 << "passed down by the standard input and return commands output " |
| 44 << "in the stdout until the stop command is received." << std::endl; |
| 45 std::cout << " delete_key <key>: Delete key from cache." << std::endl; |
| 46 std::cout << " delete_stream <key> <index>: Delete a particular stream of a" |
| 47 << " given key." << std::endl; |
| 48 std::cout << " get_size: Calculate the total size of the cache in bytes." |
| 49 << std::endl; |
| 50 std::cout << " get_stream <key> <index>: Print a particular stream for a" |
| 51 << " given key." << std::endl; |
| 52 std::cout << " list_keys: List all keys in the cache." << std::endl; |
| 53 std::cout << " update_raw_headers <key>: Update stdin as the key's raw " |
| 54 << "response headers." << std::endl; |
| 55 std::cout << " stop: Verify that the cache can be opened and return, " |
| 56 << "confirming the cache exists and is of the right type." |
| 57 << std::endl; |
| 58 std::cout << "Expected values of <index> are:" << std::endl; |
| 59 std::cout << " 0 (HTTP response headers)" << std::endl; |
| 60 std::cout << " 1 (transport encoded content)" << std::endl; |
| 61 std::cout << " 2 (compiled content)" << std::endl; |
| 62 } |
| 63 |
| 64 // Generic command input/output. |
| 65 class CommandMarshal { |
| 66 public: |
| 67 CommandMarshal(Backend* cache_backend) |
| 68 : command_failed_(false), cache_backend_(cache_backend){}; |
| 69 virtual ~CommandMarshal(){}; |
| 70 |
| 71 // Reads the next command's name to execute. |
| 72 virtual std::string ReadCommandName() = 0; |
| 73 |
| 74 // Reads the next parameter as an integer. |
| 75 virtual int ReadInt() = 0; |
| 76 |
| 77 // Reads the next parameter as stream index. |
| 78 int ReadStreamIndex() { |
| 79 if (has_failed()) |
| 80 return -1; |
| 81 int index = ReadInt(); |
| 82 if (index < 0 || index > 2) { |
| 83 ReturnFailure("Invalid stream index."); |
| 84 return -1; |
| 85 } |
| 86 return index; |
| 87 } |
| 88 |
| 89 // Reads the next parameter as an string. |
| 90 virtual std::string ReadString() = 0; |
| 91 |
| 92 // Reads the next parameter from stdin as string. |
| 93 virtual std::string ReadBufferedString() = 0; |
| 94 |
| 95 // Communicates back an integer. |
| 96 virtual void ReturnInt(int integer) = 0; |
| 97 |
| 98 // Communicates back a string. |
| 99 virtual void ReturnString(const std::string& string) = 0; |
| 100 |
| 101 // Communicates back a buffer. |
| 102 virtual void ReturnBuffer(net::GrowableIOBuffer* buffer) = 0; |
| 103 |
| 104 // Communicates back command failure. |
| 105 virtual void ReturnFailure(const std::string& error_msg) = 0; |
| 106 |
| 107 // Communicates back command success. |
| 108 virtual void ReturnSuccess() { DCHECK(!command_failed_); }; |
| 109 |
| 110 // Returns whether the command has failed. |
| 111 inline bool has_failed() { return command_failed_; } |
| 112 |
| 113 // Returns the opened cache backend. |
| 114 Backend* cache_backend() { return cache_backend_; } |
| 115 |
| 116 protected: |
| 117 bool command_failed_; |
| 118 Backend* const cache_backend_; |
| 119 }; |
| 120 |
| 121 // Command line input/output that is user readable. |
| 122 class ProgramArgumentCommandMarshal final : public CommandMarshal { |
| 123 public: |
| 124 ProgramArgumentCommandMarshal(Backend* cache_backend, |
| 125 base::CommandLine::StringVector args) |
| 126 : CommandMarshal(cache_backend), command_line_args_(args), args_id_(0) {} |
| 127 |
| 128 // Implements CommandMarshal. |
| 129 std::string ReadCommandName() override { |
| 130 if (args_id_ == 0) |
| 131 return ReadString(); |
| 132 else if (args_id_ == command_line_args_.size()) |
| 133 return "stop"; |
| 134 else if (!has_failed()) |
| 135 ReturnFailure("Command line arguments to long."); |
| 136 return ""; |
| 137 } |
| 138 |
| 139 // Implements CommandMarshal. |
| 140 int ReadInt() override { |
| 141 std::string interger_str = ReadString(); |
| 142 int interger = -1; |
| 143 if (!base::StringToInt(interger_str, &interger)) { |
| 144 ReturnFailure("Couldn't parse integer."); |
| 145 return 0; |
| 146 } |
| 147 return interger; |
| 148 } |
| 149 |
| 150 // Implements CommandMarshal. |
| 151 std::string ReadString() override { |
| 152 if (args_id_ < command_line_args_.size()) |
| 153 return command_line_args_[args_id_++]; |
| 154 if (!has_failed()) |
| 155 ReturnFailure("Command line arguments to short."); |
| 156 return ""; |
| 157 } |
| 158 |
| 159 // Implements CommandMarshal. |
| 160 std::string ReadBufferedString() override { |
| 161 std::ostringstream raw_headers_stream; |
| 162 for (std::string line; std::getline(std::cin, line);) |
| 163 raw_headers_stream << line << std::endl; |
| 164 return raw_headers_stream.str(); |
| 165 } |
| 166 |
| 167 // Implements CommandMarshal. |
| 168 void ReturnInt(int integer) override { |
| 169 DCHECK(!has_failed()); |
| 170 std::cout << integer << std::endl; |
| 171 } |
| 172 |
| 173 // Implements CommandMarshal. |
| 174 void ReturnString(const std::string& string) override { |
| 175 DCHECK(!has_failed()); |
| 176 std::cout << string << std::endl; |
| 177 } |
| 178 |
| 179 // Implements CommandMarshal. |
| 180 void ReturnBuffer(net::GrowableIOBuffer* buffer) override { |
| 181 DCHECK(!has_failed()); |
| 182 std::cout.write(buffer->data(), buffer->offset()); |
| 183 } |
| 184 |
| 185 // Implements CommandMarshal. |
| 186 void ReturnFailure(const std::string& error_msg) override { |
| 187 DCHECK(!has_failed()); |
| 188 std::cerr << error_msg << std::endl; |
| 189 command_failed_ = true; |
| 190 } |
| 191 |
| 192 private: |
| 193 const base::CommandLine::StringVector command_line_args_; |
| 194 size_t args_id_; |
| 195 }; |
| 196 |
| 197 // Online command input/output that receives pickled commands from stdin and |
| 198 // returns their results back in stdout. Send the stop command to properly exit |
| 199 // cachetool's main loop. |
| 200 class StreamCommandMarshal final : public CommandMarshal { |
| 201 public: |
| 202 StreamCommandMarshal(Backend* cache_backend) |
| 203 : CommandMarshal(cache_backend) {} |
| 204 |
| 205 // Implements CommandMarshal. |
| 206 std::string ReadCommandName() override { |
| 207 if (has_failed()) |
| 208 return ""; |
| 209 std::cout.flush(); |
| 210 size_t command_id = static_cast<size_t>(std::cin.get()); |
| 211 if (command_id >= arraysize(kCommandNames)) { |
| 212 ReturnFailure("Unknown command."); |
| 213 return ""; |
| 214 } |
| 215 return kCommandNames[command_id]; |
| 216 } |
| 217 |
| 218 // Implements CommandMarshal. |
| 219 int ReadInt() override { |
| 220 if (has_failed()) |
| 221 return -1; |
| 222 int integer = -1; |
| 223 std::cin.read(reinterpret_cast<char*>(&integer), sizeof(integer)); |
| 224 return integer; |
| 225 } |
| 226 |
| 227 // Implements CommandMarshal. |
| 228 std::string ReadString() override { |
| 229 if (has_failed()) |
| 230 return ""; |
| 231 int string_size = ReadInt(); |
| 232 if (string_size <= 0) { |
| 233 if (string_size < 0) |
| 234 ReturnFailure("Size of string is negative."); |
| 235 return ""; |
| 236 } |
| 237 std::vector<char> tmp_buffer(string_size + 1); |
| 238 std::cin.read(&tmp_buffer[0], string_size); |
| 239 tmp_buffer[string_size] = 0; |
| 240 return std::string(&tmp_buffer[0], string_size); |
| 241 } |
| 242 |
| 243 // Implements CommandMarshal. |
| 244 std::string ReadBufferedString() override { return ReadString(); } |
| 245 |
| 246 // Implements CommandMarshal. |
| 247 void ReturnInt(int integer) override { |
| 248 DCHECK(!command_failed_); |
| 249 std::cout.write(reinterpret_cast<char*>(&integer), sizeof(integer)); |
| 250 } |
| 251 |
| 252 // Implements CommandMarshal. |
| 253 void ReturnString(const std::string& string) override { |
| 254 ReturnInt(string.size()); |
| 255 std::cout.write(string.c_str(), string.size()); |
| 256 } |
| 257 |
| 258 // Implements CommandMarshal. |
| 259 void ReturnBuffer(net::GrowableIOBuffer* buffer) override { |
| 260 ReturnInt(buffer->offset()); |
| 261 std::cout.write(buffer->StartOfBuffer(), buffer->offset()); |
| 262 } |
| 263 |
| 264 // Implements CommandMarshal. |
| 265 void ReturnFailure(const std::string& error_msg) override { |
| 266 ReturnString(error_msg); |
| 267 command_failed_ = true; |
| 268 } |
| 269 |
| 270 // Implements CommandMarshal. |
| 271 void ReturnSuccess() override { ReturnInt(0); } |
| 272 }; |
| 273 |
| 274 // Gets the cache's size. |
| 275 void GetSize(CommandMarshal* command_marshal) { |
31 net::TestCompletionCallback cb; | 276 net::TestCompletionCallback cb; |
32 int rv = cache_backend->CalculateSizeOfAllEntries(cb.callback()); | 277 int rv = command_marshal->cache_backend()->CalculateSizeOfAllEntries( |
| 278 cb.callback()); |
33 rv = cb.GetResult(rv); | 279 rv = cb.GetResult(rv); |
34 if (rv < 0) { | 280 if (rv < 0) |
35 std::cerr << "Couldn't get cache size." << std::endl; | 281 return command_marshal->ReturnFailure("Couldn't get cache size."); |
36 return false; | 282 command_marshal->ReturnSuccess(); |
37 } | 283 command_marshal->ReturnInt(rv); |
38 std::cout << rv << std::endl; | |
39 return true; | |
40 } | 284 } |
41 | 285 |
42 // Print all of a cache's keys to stdout. | 286 // Prints all of a cache's keys to stdout. |
43 bool ListKeys(Backend* cache_backend) { | 287 bool ListKeys(CommandMarshal* command_marshal) { |
44 std::unique_ptr<Backend::Iterator> entry_iterator = | 288 std::unique_ptr<Backend::Iterator> entry_iterator = |
45 cache_backend->CreateIterator(); | 289 command_marshal->cache_backend()->CreateIterator(); |
46 Entry* entry = nullptr; | 290 Entry* entry = nullptr; |
47 net::TestCompletionCallback cb; | 291 net::TestCompletionCallback cb; |
48 int rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); | 292 int rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); |
| 293 command_marshal->ReturnSuccess(); |
49 while (cb.GetResult(rv) == net::OK) { | 294 while (cb.GetResult(rv) == net::OK) { |
50 std::string url = entry->GetKey(); | 295 std::string url = entry->GetKey(); |
51 std::cout << url << std::endl; | 296 command_marshal->ReturnString(url); |
52 entry->Close(); | 297 entry->Close(); |
53 entry = nullptr; | 298 entry = nullptr; |
54 rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); | 299 rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); |
55 } | 300 } |
| 301 command_marshal->ReturnString(""); |
56 return true; | 302 return true; |
57 } | 303 } |
58 | 304 |
59 // Get a key's stream to a buffer. | 305 // Gets a key's stream to a buffer. |
60 scoped_refptr<net::GrowableIOBuffer> GetStreamForKeyBuffer( | 306 scoped_refptr<net::GrowableIOBuffer> GetStreamForKeyBuffer( |
61 Backend* cache_backend, | 307 CommandMarshal* command_marshal, |
62 const std::string& key, | 308 const std::string& key, |
63 int index) { | 309 int index) { |
| 310 DCHECK(!command_marshal->has_failed()); |
64 Entry* cache_entry; | 311 Entry* cache_entry; |
65 net::TestCompletionCallback cb; | 312 net::TestCompletionCallback cb; |
66 int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); | 313 int rv = command_marshal->cache_backend()->OpenEntry(key, &cache_entry, |
| 314 cb.callback()); |
67 if (cb.GetResult(rv) != net::OK) { | 315 if (cb.GetResult(rv) != net::OK) { |
68 std::cerr << "Couldn't find key's entry." << std::endl; | 316 command_marshal->ReturnFailure("Couldn't find key's entry."); |
69 return nullptr; | 317 return nullptr; |
70 } | 318 } |
71 | 319 |
72 const int kInitBufferSize = 8192; | 320 const int kInitBufferSize = 8192; |
73 scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer()); | 321 scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer()); |
74 buffer->SetCapacity(kInitBufferSize); | 322 buffer->SetCapacity(kInitBufferSize); |
75 while (true) { | 323 while (true) { |
76 rv = cache_entry->ReadData(index, buffer->offset(), buffer.get(), | 324 rv = cache_entry->ReadData(index, buffer->offset(), buffer.get(), |
77 buffer->capacity() - buffer->offset(), | 325 buffer->capacity() - buffer->offset(), |
78 cb.callback()); | 326 cb.callback()); |
79 rv = cb.GetResult(rv); | 327 rv = cb.GetResult(rv); |
80 if (rv < 0) { | 328 if (rv < 0) { |
81 cache_entry->Close(); | 329 cache_entry->Close(); |
82 std::cerr << "Stream read error." << std::endl; | 330 command_marshal->ReturnFailure("Stream read error."); |
83 return nullptr; | 331 return nullptr; |
84 } | 332 } |
85 buffer->set_offset(buffer->offset() + rv); | 333 buffer->set_offset(buffer->offset() + rv); |
86 if (rv == 0) | 334 if (rv == 0) |
87 break; | 335 break; |
88 buffer->SetCapacity(buffer->offset() * 2); | 336 buffer->SetCapacity(buffer->offset() * 2); |
89 } | 337 } |
90 cache_entry->Close(); | 338 cache_entry->Close(); |
91 return buffer; | 339 return buffer; |
92 } | 340 } |
93 | 341 |
94 // Print a key's stream to stdout. | 342 // Prints a key's stream to stdout. |
95 bool GetStreamForKey(Backend* cache_backend, | 343 void GetStreamForKey(CommandMarshal* command_marshal) { |
96 const std::string& key, | 344 std::string key = command_marshal->ReadString(); |
97 int index) { | 345 int index = command_marshal->ReadInt(); |
| 346 if (command_marshal->has_failed()) |
| 347 return; |
98 scoped_refptr<net::GrowableIOBuffer> buffer( | 348 scoped_refptr<net::GrowableIOBuffer> buffer( |
99 GetStreamForKeyBuffer(cache_backend, key, index)); | 349 GetStreamForKeyBuffer(command_marshal, key, index)); |
100 if (!buffer) | 350 if (command_marshal->has_failed()) |
101 return false; | 351 return; |
102 if (index == kResponseInfoIndex) { | 352 if (index == kResponseInfoIndex) { |
103 net::HttpResponseInfo response_info; | 353 net::HttpResponseInfo response_info; |
104 bool truncated_response_info = false; | 354 bool truncated_response_info = false; |
105 net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), | 355 net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), |
106 &response_info, &truncated_response_info); | 356 &response_info, &truncated_response_info); |
107 if (truncated_response_info) { | 357 if (truncated_response_info) |
108 std::cerr << "Truncated HTTP response." << std::endl; | 358 return command_marshal->ReturnFailure("Truncated HTTP response."); |
109 return false; | 359 command_marshal->ReturnSuccess(); |
110 } | 360 command_marshal->ReturnString( |
111 std::cout << net::HttpUtil::ConvertHeadersBackToHTTPResponse( | 361 net::HttpUtil::ConvertHeadersBackToHTTPResponse( |
112 response_info.headers->raw_headers()); | 362 response_info.headers->raw_headers())); |
113 } else { | 363 } else { |
114 std::cout.write(buffer->StartOfBuffer(), buffer->offset()); | 364 command_marshal->ReturnSuccess(); |
| 365 command_marshal->ReturnBuffer(buffer.get()); |
115 } | 366 } |
116 return true; | |
117 } | 367 } |
118 | 368 |
119 // Set stdin as the key's raw response headers. | 369 // Sets stdin as the key's raw response headers. |
120 bool UpdateRawResponseHeaders(Backend* cache_backend, const std::string& key) { | 370 void UpdateRawResponseHeaders(CommandMarshal* command_marshal) { |
| 371 std::string key = command_marshal->ReadString(); |
| 372 std::string raw_headers = command_marshal->ReadBufferedString(); |
| 373 if (command_marshal->has_failed()) |
| 374 return; |
121 scoped_refptr<net::GrowableIOBuffer> buffer( | 375 scoped_refptr<net::GrowableIOBuffer> buffer( |
122 GetStreamForKeyBuffer(cache_backend, key, kResponseInfoIndex)); | 376 GetStreamForKeyBuffer(command_marshal, key, kResponseInfoIndex)); |
123 if (!buffer) | 377 if (command_marshal->has_failed()) |
124 return false; | 378 return; |
125 net::HttpResponseInfo response_info; | 379 net::HttpResponseInfo response_info; |
126 bool truncated_response_info = false; | 380 bool truncated_response_info = false; |
127 net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), | 381 net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), |
128 &response_info, &truncated_response_info); | 382 &response_info, &truncated_response_info); |
129 if (truncated_response_info) { | 383 if (truncated_response_info) |
130 std::cerr << "Truncated HTTP response." << std::endl; | 384 return command_marshal->ReturnFailure("Truncated HTTP response."); |
131 return false; | 385 |
132 } | 386 response_info.headers = new net::HttpResponseHeaders(raw_headers); |
133 std::ostringstream raw_headers_stream; | |
134 for (std::string line; std::getline(std::cin, line);) | |
135 raw_headers_stream << line << std::endl; | |
136 response_info.headers = | |
137 new net::HttpResponseHeaders(raw_headers_stream.str()); | |
138 scoped_refptr<net::PickledIOBuffer> data(new net::PickledIOBuffer()); | 387 scoped_refptr<net::PickledIOBuffer> data(new net::PickledIOBuffer()); |
139 response_info.Persist(data->pickle(), false, false); | 388 response_info.Persist(data->pickle(), false, false); |
140 data->Done(); | 389 data->Done(); |
141 Entry* cache_entry; | 390 Entry* cache_entry; |
142 net::TestCompletionCallback cb; | 391 net::TestCompletionCallback cb; |
143 int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); | 392 int rv = command_marshal->cache_backend()->OpenEntry(key, &cache_entry, |
| 393 cb.callback()); |
144 CHECK(cb.GetResult(rv) == net::OK); | 394 CHECK(cb.GetResult(rv) == net::OK); |
145 int data_len = data->pickle()->size(); | 395 int data_len = data->pickle()->size(); |
146 rv = cache_entry->WriteData(kResponseInfoIndex, 0, data.get(), data_len, | 396 rv = cache_entry->WriteData(kResponseInfoIndex, 0, data.get(), data_len, |
147 cb.callback(), true); | 397 cb.callback(), true); |
148 if (cb.GetResult(rv) != data_len) { | 398 if (cb.GetResult(rv) != data_len) |
149 std::cerr << "Couldn't write headers." << std::endl; | 399 return command_marshal->ReturnFailure("Couldn't write headers."); |
150 return false; | 400 command_marshal->ReturnSuccess(); |
151 } | |
152 cache_entry->Close(); | 401 cache_entry->Close(); |
153 return true; | |
154 } | 402 } |
155 | 403 |
156 // Delete a specified key stream from the cache. | 404 // Deletes a specified key stream from the cache. |
157 bool DeleteStreamForKey(Backend* cache_backend, | 405 void DeleteStreamForKey(CommandMarshal* command_marshal) { |
158 const std::string& key, | 406 std::string key = command_marshal->ReadString(); |
159 int index) { | 407 int index = command_marshal->ReadInt(); |
| 408 if (command_marshal->has_failed()) |
| 409 return; |
160 Entry* cache_entry; | 410 Entry* cache_entry; |
161 net::TestCompletionCallback cb; | 411 net::TestCompletionCallback cb; |
162 int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); | 412 int rv = command_marshal->cache_backend()->OpenEntry(key, &cache_entry, |
163 if (cb.GetResult(rv) != net::OK) { | 413 cb.callback()); |
164 std::cerr << "Couldn't find key's entry." << std::endl; | 414 if (cb.GetResult(rv) != net::OK) |
165 return false; | 415 return command_marshal->ReturnFailure("Couldn't find key's entry."); |
166 } | |
167 | 416 |
168 scoped_refptr<net::StringIOBuffer> buffer(new net::StringIOBuffer("")); | 417 scoped_refptr<net::StringIOBuffer> buffer(new net::StringIOBuffer("")); |
169 rv = cache_entry->WriteData(index, 0, buffer.get(), 0, cb.callback(), true); | 418 rv = cache_entry->WriteData(index, 0, buffer.get(), 0, cb.callback(), true); |
170 if (cb.GetResult(rv) != 0) { | 419 if (cb.GetResult(rv) != net::OK) |
171 std::cerr << "Couldn't delete key stream." << std::endl; | 420 return command_marshal->ReturnFailure("Couldn't delete key stream."); |
172 return false; | 421 command_marshal->ReturnSuccess(); |
173 } | |
174 cache_entry->Close(); | 422 cache_entry->Close(); |
175 return true; | |
176 } | 423 } |
177 | 424 |
178 // Delete a specified key from the cache. | 425 // Deletes a specified key from the cache. |
179 bool DeleteKey(Backend* cache_backend, const std::string& key) { | 426 void DeleteKey(CommandMarshal* command_marshal) { |
| 427 std::string key = command_marshal->ReadString(); |
| 428 if (command_marshal->has_failed()) |
| 429 return; |
180 net::TestCompletionCallback cb; | 430 net::TestCompletionCallback cb; |
181 int rv = cache_backend->DoomEntry(key, cb.callback()); | 431 int rv = command_marshal->cache_backend()->DoomEntry(key, cb.callback()); |
182 if (cb.GetResult(rv) != net::OK) { | 432 if (cb.GetResult(rv) != net::OK) |
183 std::cerr << "Couldn't delete key." << std::endl; | 433 command_marshal->ReturnFailure("Couldn't delete key."); |
184 return false; | 434 else |
185 } | 435 command_marshal->ReturnSuccess(); |
186 return true; | |
187 } | 436 } |
188 | 437 |
189 // Parse stream index from command line argument string. | 438 // Executes all command from the |command_marshal|. |
190 int ParseStreamIndex(const std::string& index_arg) { | 439 bool ExecuteCommands(CommandMarshal* command_marshal) { |
191 int index = -1; | 440 while (!command_marshal->has_failed()) { |
192 if (!base::StringToInt(index_arg, &index)) { | 441 std::string subcommand(command_marshal->ReadCommandName()); |
193 std::cerr << "<index> must be an integer." << std::endl; | 442 if (command_marshal->has_failed()) |
194 return -1; | 443 break; |
195 } else if (index < 0 || index > 2) { | 444 if (subcommand == "stop") { |
196 std::cerr << "Invalid stream index." << std::endl; | 445 command_marshal->ReturnSuccess(); |
197 return -1; | 446 return true; |
| 447 } else if (subcommand == "batch") { |
| 448 StreamCommandMarshal stream_command_marshal( |
| 449 command_marshal->cache_backend()); |
| 450 return ExecuteCommands(&stream_command_marshal); |
| 451 } else if (subcommand == "delete_key") { |
| 452 DeleteKey(command_marshal); |
| 453 } else if (subcommand == "delete_stream") { |
| 454 DeleteStreamForKey(command_marshal); |
| 455 } else if (subcommand == "get_size") { |
| 456 GetSize(command_marshal); |
| 457 } else if (subcommand == "get_stream") { |
| 458 GetStreamForKey(command_marshal); |
| 459 } else if (subcommand == "list_keys") { |
| 460 ListKeys(command_marshal); |
| 461 } else if (subcommand == "update_raw_headers") { |
| 462 UpdateRawResponseHeaders(command_marshal); |
| 463 } else { |
| 464 // The wrong subcommand is originated from the command line. |
| 465 command_marshal->ReturnFailure("Unknown command."); |
| 466 PrintHelp(); |
| 467 } |
198 } | 468 } |
199 return index; | 469 return false; |
200 } | |
201 | |
202 // Print the command line help. | |
203 void PrintHelp() { | |
204 std::cout << "cachetool <cache_path> <cache_backend_type> <subcommand> ..." | |
205 << std::endl | |
206 << std::endl; | |
207 std::cout << "Available cache backend types: simple, blockfile" << std::endl; | |
208 std::cout << "Available subcommands:" << std::endl; | |
209 std::cout << " delete_key <key>: Delete key from cache." << std::endl; | |
210 std::cout << " delete_stream <key> <index>: Delete a particular stream of a" | |
211 << " given key." << std::endl; | |
212 std::cout << " get_size: Calculate the total size of the cache in bytes." | |
213 << std::endl; | |
214 std::cout << " get_stream <key> <index>: Print a particular stream for a" | |
215 << " given key." << std::endl; | |
216 std::cout << " list_keys: List all keys in the cache." << std::endl; | |
217 std::cout << " update_raw_headers <key>: Update stdin as the key's raw " | |
218 << "response headers." << std::endl; | |
219 std::cout << " validate: Verify that the cache can be opened and return, " | |
220 << "confirming the cache exists and is of the right type." | |
221 << std::endl; | |
222 std::cout << "Expected values of <index> are:" << std::endl; | |
223 std::cout << " 0 (HTTP response headers)" << std::endl; | |
224 std::cout << " 1 (transport encoded content)" << std::endl; | |
225 std::cout << " 2 (compiled content)" << std::endl; | |
226 } | 470 } |
227 | 471 |
228 } // namespace | 472 } // namespace |
229 | 473 |
230 int main(int argc, char* argv[]) { | 474 int main(int argc, char* argv[]) { |
231 base::AtExitManager at_exit_manager; | 475 base::AtExitManager at_exit_manager; |
232 base::MessageLoopForIO message_loop; | 476 base::MessageLoopForIO message_loop; |
233 base::CommandLine::Init(argc, argv); | 477 base::CommandLine::Init(argc, argv); |
234 const base::CommandLine& command_line = | 478 const base::CommandLine& command_line = |
235 *base::CommandLine::ForCurrentProcess(); | 479 *base::CommandLine::ForCurrentProcess(); |
236 | 480 |
237 base::CommandLine::StringVector args = command_line.GetArgs(); | 481 base::CommandLine::StringVector args = command_line.GetArgs(); |
238 if (args.size() < 3U) { | 482 if (args.size() < 3U) { |
239 PrintHelp(); | 483 PrintHelp(); |
240 return 1; | 484 return 1; |
241 } | 485 } |
242 | 486 |
243 base::FilePath cache_path(args[0]); | 487 base::FilePath cache_path(args[0]); |
244 std::string cache_backend_type(args[1]); | 488 std::string cache_backend_type(args[1]); |
245 std::string subcommand(args[2]); | |
246 | 489 |
247 net::BackendType backend_type; | 490 net::BackendType backend_type; |
248 if (cache_backend_type == "simple") { | 491 if (cache_backend_type == "simple") { |
249 backend_type = net::CACHE_BACKEND_SIMPLE; | 492 backend_type = net::CACHE_BACKEND_SIMPLE; |
250 } else if (cache_backend_type == "blockfile") { | 493 } else if (cache_backend_type == "blockfile") { |
251 backend_type = net::CACHE_BACKEND_BLOCKFILE; | 494 backend_type = net::CACHE_BACKEND_BLOCKFILE; |
252 } else { | 495 } else { |
253 std::cerr << "Unknown cache type." << std::endl; | 496 std::cerr << "Unknown cache type." << std::endl; |
254 PrintHelp(); | 497 PrintHelp(); |
255 return 1; | 498 return 1; |
256 } | 499 } |
257 | 500 |
258 std::unique_ptr<Backend> cache_backend; | 501 std::unique_ptr<Backend> cache_backend; |
259 net::TestCompletionCallback cb; | 502 net::TestCompletionCallback cb; |
260 int rv = disk_cache::CreateCacheBackend( | 503 int rv = disk_cache::CreateCacheBackend( |
261 net::DISK_CACHE, backend_type, cache_path, INT_MAX, false, | 504 net::DISK_CACHE, backend_type, cache_path, INT_MAX, false, |
262 message_loop.task_runner(), nullptr, &cache_backend, cb.callback()); | 505 message_loop.task_runner(), nullptr, &cache_backend, cb.callback()); |
263 if (cb.GetResult(rv) != net::OK) { | 506 if (cb.GetResult(rv) != net::OK) { |
264 std::cerr << "Invalid cache." << std::endl; | 507 std::cerr << "Invalid cache." << std::endl; |
265 return 1; | 508 return 1; |
266 } | 509 } |
267 | 510 |
268 bool successful_command; | 511 ProgramArgumentCommandMarshal program_argument_marshal( |
269 if (subcommand == "delete_key" && args.size() == 4) { | 512 cache_backend.get(), |
270 successful_command = DeleteKey(cache_backend.get(), args[3]); | 513 base::CommandLine::StringVector(args.begin() + 2, args.end())); |
271 } else if (subcommand == "delete_stream" && args.size() == 5) { | 514 bool successful_commands = ExecuteCommands(&program_argument_marshal); |
272 int index = ParseStreamIndex(args[4]); | 515 |
273 if (index < 0) | |
274 return 1; | |
275 successful_command = | |
276 DeleteStreamForKey(cache_backend.get(), args[3], index); | |
277 } else if (subcommand == "get_size" && args.size() == 3) { | |
278 successful_command = GetSize(cache_backend.get()); | |
279 } else if (subcommand == "get_stream" && args.size() == 5) { | |
280 int index = ParseStreamIndex(args[4]); | |
281 if (index < 0) | |
282 return 1; | |
283 successful_command = GetStreamForKey(cache_backend.get(), args[3], index); | |
284 } else if (subcommand == "list_keys" && args.size() == 3) { | |
285 successful_command = ListKeys(cache_backend.get()); | |
286 } else if (subcommand == "update_raw_headers" && args.size() == 4) { | |
287 successful_command = UpdateRawResponseHeaders(cache_backend.get(), args[3]); | |
288 } else if (subcommand == "validate" && args.size() == 3) { | |
289 successful_command = true; | |
290 } else { | |
291 successful_command = false; | |
292 PrintHelp(); | |
293 } | |
294 base::RunLoop().RunUntilIdle(); | 516 base::RunLoop().RunUntilIdle(); |
295 cache_backend = nullptr; | 517 cache_backend = nullptr; |
296 base::RunLoop().RunUntilIdle(); | 518 base::RunLoop().RunUntilIdle(); |
297 return !successful_command; | 519 return !successful_commands; |
298 } | 520 } |
OLD | NEW |