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 const int kResponseInfoIndex = 0; |
pasko
2016/07/05 15:13:30
constexpr is preferred now as of https://chromium-
gabadie
2016/07/06 09:25:53
Done.
| |
29 | |
30 const char* const kCommandNames[] = { | |
31 "stop", "get_size", "list_keys", "get_stream_for_key", | |
pasko
2016/07/05 15:13:30
any reason for these to be separated by multiple s
gabadie
2016/07/06 09:25:53
looks like `git cl format net` did it by itself...
pasko
2016/07/06 15:18:55
weird :) works for me then..
| |
32 "delete_stream", "delete_key", "update_raw_headers", | |
33 }; | |
34 | |
35 // Print the command line help. | |
pasko
2016/07/05 15:13:31
s/Print/Prints/
gabadie
2016/07/06 09:25:53
No, Gavin wanted in the previous reviews the comme
pasko
2016/07/06 15:18:55
Ack, this goes back to Gavin. Though I am not sure
| |
36 void PrintHelp() { | |
37 std::cout << "cachetool <cache_path> <cache_backend_type> <subcommand> ..." | |
pasko
2016/07/05 15:13:30
The '...' is slightly confusing, maybe should be:
gabadie
2016/07/06 09:25:53
No. the ... stands for sub-command specific parame
pasko
2016/07/06 15:18:55
Then the description is still incorrect. Subcomman
gabadie
2016/07/06 16:45:32
Done.
| |
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 << " delete_key <key>: Delete key from cache." << std::endl; | |
43 std::cout << " delete_stream <key> <index>: Delete a particular stream of a" | |
44 << " given key." << std::endl; | |
45 std::cout << " get_size: Calculate the total size of the cache in bytes." | |
46 << std::endl; | |
47 std::cout << " get_stream <key> <index>: Print a particular stream for a" | |
48 << " given key." << std::endl; | |
49 std::cout << " list_keys: List all keys in the cache." << std::endl; | |
50 std::cout << " online: Starts cachetool to process serialized commands " | |
pasko
2016/07/05 15:13:31
Making "online" a subcommand is somewhat confusing
gabadie
2016/07/06 09:25:53
Command line tool only have one subcommand. Either
pasko
2016/07/06 15:18:55
Ah, ok, thanks for explaining.
| |
51 << "passed down by the standard input and return commands output " | |
52 << "in the stdout until the stop command is received." << 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; | |
pasko
2016/07/05 15:13:31
there can be other things in stream 2, so we can s
gabadie
2016/07/06 09:25:53
Interesting, waiting for Gavin's opinion to change
| |
62 } | |
63 | |
64 // Generic command input/output. | |
65 class CachetoolIOBase { | |
pasko
2016/07/05 15:13:30
Ha, now I understand why you call it 'IO', basical
gabadie
2016/07/06 09:25:53
This is not for speed, but rather for reliability.
pasko
2016/07/06 15:18:55
Oh, that's actually a very good point, which I tot
gabadie
2016/07/06 16:45:32
Ok let's wait for Gavin's opinion. But your offlin
| |
66 public: | |
67 CachetoolIOBase(Backend* cache_backend) | |
68 : command_failed_(false), cache_backend_(cache_backend){}; | |
69 virtual ~CachetoolIOBase(){}; | |
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 // Communicate back an integer. | |
96 virtual void ReturnInt(int integer) = 0; | |
97 | |
98 // Communicate back a string. | |
99 virtual void ReturnString(const std::string& string) = 0; | |
100 | |
101 // Communicate back a buffer. | |
102 virtual void ReturnBuffer(net::GrowableIOBuffer* buffer) = 0; | |
103 | |
104 // Communicate back command failure. | |
105 virtual void ReturnFailure(const std::string& error_msg) = 0; | |
106 | |
107 // Communicate back command success. | |
108 virtual void ReturnSuccess() { DCHECK(!command_failed_); }; | |
109 | |
110 // Returns weather the command has failed. | |
pasko
2016/07/05 15:13:31
s/weather/whether/
gabadie
2016/07/06 09:25:53
Done.
| |
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 CommandLineIO final : public CachetoolIOBase { | |
123 public: | |
124 CommandLineIO(Backend* cache_backend, base::CommandLine::StringVector args) | |
125 : CachetoolIOBase(cache_backend), command_line_args_(args), args_id_(0) {} | |
126 | |
127 // Implements CachetoolIOBase. | |
128 std::string ReadCommandName() override { | |
129 if (args_id_ == 0) | |
130 return ReadString(); | |
131 else if (args_id_ == command_line_args_.size()) | |
132 return "stop"; | |
133 else if (!has_failed()) | |
134 ReturnFailure("Command line arguments to long."); | |
135 return ""; | |
136 } | |
137 | |
138 // Implements CachetoolIOBase. | |
139 int ReadInt() override { | |
140 std::string interger_str = ReadString(); | |
141 int interger = -1; | |
142 if (!base::StringToInt(interger_str, &interger)) { | |
143 ReturnFailure("Couldn't parse integer."); | |
144 return 0; | |
145 } | |
146 return interger; | |
147 } | |
148 | |
149 // Implements CachetoolIOBase. | |
150 std::string ReadString() override { | |
151 if (args_id_ < command_line_args_.size()) | |
152 return command_line_args_[args_id_++]; | |
153 if (!has_failed()) | |
154 ReturnFailure("Command line arguments to short."); | |
155 return ""; | |
156 } | |
157 | |
158 // Implements CachetoolIOBase. | |
159 std::string ReadBufferedString() override { | |
160 std::ostringstream raw_headers_stream; | |
161 for (std::string line; std::getline(std::cin, line);) | |
162 raw_headers_stream << line << std::endl; | |
163 return raw_headers_stream.str(); | |
164 } | |
165 | |
166 // Implements CachetoolIOBase. | |
167 void ReturnInt(int integer) override { | |
168 DCHECK(!has_failed()); | |
169 std::cout << integer << std::endl; | |
170 } | |
171 | |
172 // Implements CachetoolIOBase. | |
173 void ReturnString(const std::string& string) override { | |
174 DCHECK(!has_failed()); | |
175 std::cout << string << std::endl; | |
176 } | |
177 | |
178 // Implements CachetoolIOBase. | |
179 void ReturnBuffer(net::GrowableIOBuffer* buffer) override { | |
180 DCHECK(!has_failed()); | |
181 std::cout.write(buffer->data(), buffer->offset()); | |
182 } | |
183 | |
184 // Implements CachetoolIOBase. | |
185 void ReturnFailure(const std::string& error_msg) override { | |
186 DCHECK(!has_failed()); | |
187 std::cerr << error_msg << std::endl; | |
188 command_failed_ = true; | |
189 } | |
190 | |
191 private: | |
192 const base::CommandLine::StringVector command_line_args_; | |
193 size_t args_id_; | |
194 }; | |
195 | |
196 // Online command input/output that receives pickled commands from stdin and | |
197 // returns their results back in stdout. Send the stop command to properly exit | |
198 // cachetool's main loop. | |
199 class OnlineCommandIO final : public CachetoolIOBase { | |
200 public: | |
201 OnlineCommandIO(Backend* cache_backend) : CachetoolIOBase(cache_backend) {} | |
202 | |
203 // Implements CachetoolIOBase. | |
204 std::string ReadCommandName() override { | |
205 if (has_failed()) | |
206 return ""; | |
207 std::cout.flush(); | |
208 size_t command_id = static_cast<size_t>(std::cin.get()); | |
209 if (command_id >= arraysize(kCommandNames)) { | |
210 ReturnFailure("Unknown command."); | |
211 return ""; | |
212 } | |
213 return kCommandNames[command_id]; | |
214 } | |
215 | |
216 // Implements CachetoolIOBase. | |
217 int ReadInt() override { | |
218 if (has_failed()) | |
219 return -1; | |
220 int integer = -1; | |
221 std::cin.read(reinterpret_cast<char*>(&integer), sizeof(integer)); | |
pasko
2016/07/05 15:13:30
read 4 bytes? why?
why not std::cin >> integer?
gabadie
2016/07/06 09:25:53
Because binary protocol, not ascii protocol.
| |
222 return integer; | |
223 } | |
224 | |
225 // Implements CachetoolIOBase. | |
226 std::string ReadString() override { | |
227 if (has_failed()) | |
228 return ""; | |
229 int string_size = ReadInt(); | |
230 if (string_size <= 0) { | |
231 if (string_size < 0) | |
232 ReturnFailure("Size of string is negative."); | |
233 return ""; | |
234 } | |
235 std::vector<char> tmp_buffer(string_size + 1); | |
236 std::cin.read(&tmp_buffer[0], string_size); | |
237 tmp_buffer[string_size] = 0; | |
238 return std::string(&tmp_buffer[0], string_size); | |
239 } | |
240 | |
241 // Implements CachetoolIOBase. | |
242 std::string ReadBufferedString() override { return ReadString(); } | |
243 | |
244 // Implements CachetoolIOBase. | |
245 void ReturnInt(int integer) override { | |
246 DCHECK(!command_failed_); | |
247 std::cout.write(reinterpret_cast<char*>(&integer), sizeof(integer)); | |
248 } | |
249 | |
250 // Implements CachetoolIOBase. | |
251 void ReturnString(const std::string& string) override { | |
252 ReturnInt(string.size()); | |
253 std::cout.write(string.c_str(), string.size()); | |
254 } | |
255 | |
256 // Implements CachetoolIOBase. | |
257 void ReturnBuffer(net::GrowableIOBuffer* buffer) override { | |
258 ReturnInt(buffer->offset()); | |
259 std::cout.write(buffer->StartOfBuffer(), buffer->offset()); | |
260 } | |
261 | |
262 // Implements CachetoolIOBase. | |
263 void ReturnFailure(const std::string& error_msg) override { | |
264 ReturnString(error_msg); | |
265 command_failed_ = true; | |
266 } | |
267 | |
268 // Implements CachetoolIOBase. | |
269 void ReturnSuccess() override { ReturnInt(0); } | |
270 }; | |
28 | 271 |
29 // Get the cache's size. | 272 // Get the cache's size. |
30 bool GetSize(Backend* cache_backend) { | 273 void GetSize(CachetoolIOBase* cachetool_io) { |
31 net::TestCompletionCallback cb; | 274 net::TestCompletionCallback cb; |
32 int rv = cache_backend->CalculateSizeOfAllEntries(cb.callback()); | 275 int rv = |
276 cachetool_io->cache_backend()->CalculateSizeOfAllEntries(cb.callback()); | |
33 rv = cb.GetResult(rv); | 277 rv = cb.GetResult(rv); |
34 if (rv < 0) { | 278 if (rv < 0) |
35 std::cerr << "Couldn't get cache size." << std::endl; | 279 return cachetool_io->ReturnFailure("Couldn't get cache size."); |
36 return false; | 280 cachetool_io->ReturnSuccess(); |
37 } | 281 cachetool_io->ReturnInt(rv); |
38 std::cout << rv << std::endl; | |
39 return true; | |
40 } | 282 } |
41 | 283 |
42 // Print all of a cache's keys to stdout. | 284 // Print all of a cache's keys to stdout. |
43 bool ListKeys(Backend* cache_backend) { | 285 bool ListKeys(CachetoolIOBase* cachetool_io) { |
44 std::unique_ptr<Backend::Iterator> entry_iterator = | 286 std::unique_ptr<Backend::Iterator> entry_iterator = |
45 cache_backend->CreateIterator(); | 287 cachetool_io->cache_backend()->CreateIterator(); |
46 Entry* entry = nullptr; | 288 Entry* entry = nullptr; |
47 net::TestCompletionCallback cb; | 289 net::TestCompletionCallback cb; |
48 int rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); | 290 int rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); |
291 cachetool_io->ReturnSuccess(); | |
49 while (cb.GetResult(rv) == net::OK) { | 292 while (cb.GetResult(rv) == net::OK) { |
50 std::string url = entry->GetKey(); | 293 std::string url = entry->GetKey(); |
51 std::cout << url << std::endl; | 294 cachetool_io->ReturnString(url); |
52 entry->Close(); | 295 entry->Close(); |
53 entry = nullptr; | 296 entry = nullptr; |
54 rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); | 297 rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); |
55 } | 298 } |
299 cachetool_io->ReturnString(""); | |
56 return true; | 300 return true; |
57 } | 301 } |
58 | 302 |
59 // Get a key's stream to a buffer. | 303 // Get a key's stream to a buffer. |
60 scoped_refptr<net::GrowableIOBuffer> GetStreamForKeyBuffer( | 304 scoped_refptr<net::GrowableIOBuffer> GetStreamForKeyBuffer( |
61 Backend* cache_backend, | 305 CachetoolIOBase* cachetool_io, |
62 const std::string& key, | 306 const std::string& key, |
63 int index) { | 307 int index) { |
308 DCHECK(!cachetool_io->has_failed()); | |
64 Entry* cache_entry; | 309 Entry* cache_entry; |
65 net::TestCompletionCallback cb; | 310 net::TestCompletionCallback cb; |
66 int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); | 311 int rv = cachetool_io->cache_backend()->OpenEntry(key, &cache_entry, |
312 cb.callback()); | |
67 if (cb.GetResult(rv) != net::OK) { | 313 if (cb.GetResult(rv) != net::OK) { |
68 std::cerr << "Couldn't find key's entry." << std::endl; | 314 cachetool_io->ReturnFailure("Couldn't find key's entry."); |
69 return nullptr; | 315 return nullptr; |
70 } | 316 } |
71 | 317 |
72 const int kInitBufferSize = 8192; | 318 const int kInitBufferSize = 8192; |
73 scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer()); | 319 scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer()); |
74 buffer->SetCapacity(kInitBufferSize); | 320 buffer->SetCapacity(kInitBufferSize); |
75 while (true) { | 321 while (true) { |
76 rv = cache_entry->ReadData(index, buffer->offset(), buffer.get(), | 322 rv = cache_entry->ReadData(index, buffer->offset(), buffer.get(), |
77 buffer->capacity() - buffer->offset(), | 323 buffer->capacity() - buffer->offset(), |
78 cb.callback()); | 324 cb.callback()); |
79 rv = cb.GetResult(rv); | 325 rv = cb.GetResult(rv); |
80 if (rv < 0) { | 326 if (rv < 0) { |
81 cache_entry->Close(); | 327 cache_entry->Close(); |
82 std::cerr << "Stream read error." << std::endl; | 328 cachetool_io->ReturnFailure("Stream read error."); |
83 return nullptr; | 329 return nullptr; |
84 } | 330 } |
85 buffer->set_offset(buffer->offset() + rv); | 331 buffer->set_offset(buffer->offset() + rv); |
86 if (rv == 0) | 332 if (rv == 0) |
87 break; | 333 break; |
88 buffer->SetCapacity(buffer->offset() * 2); | 334 buffer->SetCapacity(buffer->offset() * 2); |
89 } | 335 } |
90 cache_entry->Close(); | 336 cache_entry->Close(); |
91 return buffer; | 337 return buffer; |
92 } | 338 } |
93 | 339 |
94 // Print a key's stream to stdout. | 340 // Print a key's stream to stdout. |
95 bool GetStreamForKey(Backend* cache_backend, | 341 void GetStreamForKey(CachetoolIOBase* cachetool_io) { |
96 const std::string& key, | 342 std::string key = cachetool_io->ReadString(); |
97 int index) { | 343 int index = cachetool_io->ReadInt(); |
344 if (cachetool_io->has_failed()) | |
345 return; | |
98 scoped_refptr<net::GrowableIOBuffer> buffer( | 346 scoped_refptr<net::GrowableIOBuffer> buffer( |
99 GetStreamForKeyBuffer(cache_backend, key, index)); | 347 GetStreamForKeyBuffer(cachetool_io, key, index)); |
100 if (!buffer) | 348 if (cachetool_io->has_failed()) |
101 return false; | 349 return; |
102 if (index == kResponseInfoIndex) { | 350 if (index == kResponseInfoIndex) { |
103 net::HttpResponseInfo response_info; | 351 net::HttpResponseInfo response_info; |
104 bool truncated_response_info = false; | 352 bool truncated_response_info = false; |
105 net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), | 353 net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), |
106 &response_info, &truncated_response_info); | 354 &response_info, &truncated_response_info); |
107 if (truncated_response_info) { | 355 if (truncated_response_info) |
108 std::cerr << "Truncated HTTP response." << std::endl; | 356 return cachetool_io->ReturnFailure("Truncated HTTP response."); |
109 return false; | 357 cachetool_io->ReturnSuccess(); |
110 } | 358 cachetool_io->ReturnString(net::HttpUtil::ConvertHeadersBackToHTTPResponse( |
111 std::cout << net::HttpUtil::ConvertHeadersBackToHTTPResponse( | 359 response_info.headers->raw_headers())); |
112 response_info.headers->raw_headers()); | |
113 } else { | 360 } else { |
114 std::cout.write(buffer->StartOfBuffer(), buffer->offset()); | 361 cachetool_io->ReturnSuccess(); |
362 cachetool_io->ReturnBuffer(buffer.get()); | |
115 } | 363 } |
116 return true; | |
117 } | 364 } |
118 | 365 |
119 // Set stdin as the key's raw response headers. | 366 // Set stdin as the key's raw response headers. |
120 bool UpdateRawResponseHeaders(Backend* cache_backend, const std::string& key) { | 367 void UpdateRawResponseHeaders(CachetoolIOBase* cachetool_io) { |
368 std::string key = cachetool_io->ReadString(); | |
369 std::string raw_headers = cachetool_io->ReadBufferedString(); | |
370 if (cachetool_io->has_failed()) | |
371 return; | |
121 scoped_refptr<net::GrowableIOBuffer> buffer( | 372 scoped_refptr<net::GrowableIOBuffer> buffer( |
122 GetStreamForKeyBuffer(cache_backend, key, kResponseInfoIndex)); | 373 GetStreamForKeyBuffer(cachetool_io, key, kResponseInfoIndex)); |
123 if (!buffer) | 374 if (cachetool_io->has_failed()) |
124 return false; | 375 return; |
125 net::HttpResponseInfo response_info; | 376 net::HttpResponseInfo response_info; |
126 bool truncated_response_info = false; | 377 bool truncated_response_info = false; |
127 net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), | 378 net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), |
128 &response_info, &truncated_response_info); | 379 &response_info, &truncated_response_info); |
129 if (truncated_response_info) { | 380 if (truncated_response_info) |
130 std::cerr << "Truncated HTTP response." << std::endl; | 381 return cachetool_io->ReturnFailure("Truncated HTTP response."); |
131 return false; | 382 |
132 } | 383 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()); | 384 scoped_refptr<net::PickledIOBuffer> data(new net::PickledIOBuffer()); |
139 response_info.Persist(data->pickle(), false, false); | 385 response_info.Persist(data->pickle(), false, false); |
140 data->Done(); | 386 data->Done(); |
141 Entry* cache_entry; | 387 Entry* cache_entry; |
142 net::TestCompletionCallback cb; | 388 net::TestCompletionCallback cb; |
143 int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); | 389 int rv = cachetool_io->cache_backend()->OpenEntry(key, &cache_entry, |
390 cb.callback()); | |
144 CHECK(cb.GetResult(rv) == net::OK); | 391 CHECK(cb.GetResult(rv) == net::OK); |
145 int data_len = data->pickle()->size(); | 392 int data_len = data->pickle()->size(); |
146 rv = cache_entry->WriteData(kResponseInfoIndex, 0, data.get(), data_len, | 393 rv = cache_entry->WriteData(kResponseInfoIndex, 0, data.get(), data_len, |
147 cb.callback(), true); | 394 cb.callback(), true); |
148 if (cb.GetResult(rv) != data_len) { | 395 if (cb.GetResult(rv) != data_len) |
149 std::cerr << "Couldn't write headers." << std::endl; | 396 return cachetool_io->ReturnFailure("Couldn't write headers."); |
150 return false; | 397 cachetool_io->ReturnSuccess(); |
151 } | |
152 cache_entry->Close(); | 398 cache_entry->Close(); |
153 return true; | |
154 } | 399 } |
155 | 400 |
156 // Delete a specified key stream from the cache. | 401 // Delete a specified key stream from the cache. |
157 bool DeleteStreamForKey(Backend* cache_backend, | 402 void DeleteStreamForKey(CachetoolIOBase* cachetool_io) { |
158 const std::string& key, | 403 std::string key = cachetool_io->ReadString(); |
159 int index) { | 404 int index = cachetool_io->ReadInt(); |
405 if (cachetool_io->has_failed()) | |
406 return; | |
160 Entry* cache_entry; | 407 Entry* cache_entry; |
161 net::TestCompletionCallback cb; | 408 net::TestCompletionCallback cb; |
162 int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); | 409 int rv = cachetool_io->cache_backend()->OpenEntry(key, &cache_entry, |
163 if (cb.GetResult(rv) != net::OK) { | 410 cb.callback()); |
164 std::cerr << "Couldn't find key's entry." << std::endl; | 411 if (cb.GetResult(rv) != net::OK) |
165 return false; | 412 return cachetool_io->ReturnFailure("Couldn't find key's entry."); |
166 } | |
167 | 413 |
168 scoped_refptr<net::StringIOBuffer> buffer(new net::StringIOBuffer("")); | 414 scoped_refptr<net::StringIOBuffer> buffer(new net::StringIOBuffer("")); |
169 rv = cache_entry->WriteData(index, 0, buffer.get(), 0, cb.callback(), true); | 415 rv = cache_entry->WriteData(index, 0, buffer.get(), 0, cb.callback(), true); |
170 if (cb.GetResult(rv) != 0) { | 416 if (cb.GetResult(rv) != net::OK) |
171 std::cerr << "Couldn't delete key stream." << std::endl; | 417 return cachetool_io->ReturnFailure("Couldn't delete key stream."); |
172 return false; | 418 cachetool_io->ReturnSuccess(); |
173 } | |
174 cache_entry->Close(); | 419 cache_entry->Close(); |
175 return true; | |
176 } | 420 } |
177 | 421 |
178 // Delete a specified key from the cache. | 422 // Delete a specified key from the cache. |
179 bool DeleteKey(Backend* cache_backend, const std::string& key) { | 423 void DeleteKey(CachetoolIOBase* cachetool_io) { |
424 std::string key = cachetool_io->ReadString(); | |
425 if (cachetool_io->has_failed()) | |
426 return; | |
180 net::TestCompletionCallback cb; | 427 net::TestCompletionCallback cb; |
181 int rv = cache_backend->DoomEntry(key, cb.callback()); | 428 int rv = cachetool_io->cache_backend()->DoomEntry(key, cb.callback()); |
182 if (cb.GetResult(rv) != net::OK) { | 429 if (cb.GetResult(rv) != net::OK) |
183 std::cerr << "Couldn't delete key." << std::endl; | 430 cachetool_io->ReturnFailure("Couldn't delete key."); |
184 return false; | 431 else |
185 } | 432 cachetool_io->ReturnSuccess(); |
186 return true; | |
187 } | 433 } |
188 | 434 |
189 // Parse stream index from command line argument string. | 435 // Execute all command from the |common_input|. |
pasko
2016/07/05 15:13:30
what is |common_input|?
gabadie
2016/07/06 09:25:53
Oups, variable renaming artifact.
| |
190 int ParseStreamIndex(const std::string& index_arg) { | 436 bool ExecuteCommands(CachetoolIOBase* cachetool_io) { |
191 int index = -1; | 437 while (!cachetool_io->has_failed()) { |
192 if (!base::StringToInt(index_arg, &index)) { | 438 std::string subcommand(cachetool_io->ReadCommandName()); |
193 std::cerr << "<index> must be an integer." << std::endl; | 439 if (cachetool_io->has_failed()) |
194 return -1; | 440 break; |
195 } else if (index < 0 || index > 2) { | 441 if (subcommand == "stop") { |
196 std::cerr << "Invalid stream index." << std::endl; | 442 cachetool_io->ReturnSuccess(); |
197 return -1; | 443 return true; |
444 } else if (subcommand == "online") { | |
445 OnlineCommandIO online_command_io(cachetool_io->cache_backend()); | |
446 return ExecuteCommands(&online_command_io); | |
447 } else if (subcommand == "delete_key") { | |
448 DeleteKey(cachetool_io); | |
449 } else if (subcommand == "delete_stream") { | |
450 DeleteStreamForKey(cachetool_io); | |
451 } else if (subcommand == "get_size") { | |
452 GetSize(cachetool_io); | |
453 } else if (subcommand == "get_stream") { | |
454 GetStreamForKey(cachetool_io); | |
455 } else if (subcommand == "list_keys") { | |
456 ListKeys(cachetool_io); | |
457 } else if (subcommand == "update_raw_headers") { | |
458 UpdateRawResponseHeaders(cachetool_io); | |
459 } else { | |
460 // The wrong subcommand is originated from the command line. | |
461 cachetool_io->ReturnFailure("Unknown command."); | |
462 PrintHelp(); | |
463 } | |
198 } | 464 } |
199 return index; | 465 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 } | 466 } |
227 | 467 |
228 } // namespace | 468 } // namespace |
229 | 469 |
230 int main(int argc, char* argv[]) { | 470 int main(int argc, char* argv[]) { |
231 base::AtExitManager at_exit_manager; | 471 base::AtExitManager at_exit_manager; |
232 base::MessageLoopForIO message_loop; | 472 base::MessageLoopForIO message_loop; |
233 base::CommandLine::Init(argc, argv); | 473 base::CommandLine::Init(argc, argv); |
234 const base::CommandLine& command_line = | 474 const base::CommandLine& command_line = |
235 *base::CommandLine::ForCurrentProcess(); | 475 *base::CommandLine::ForCurrentProcess(); |
236 | 476 |
237 base::CommandLine::StringVector args = command_line.GetArgs(); | 477 base::CommandLine::StringVector args = command_line.GetArgs(); |
238 if (args.size() < 3U) { | 478 if (args.size() < 3U) { |
239 PrintHelp(); | 479 PrintHelp(); |
240 return 1; | 480 return 1; |
241 } | 481 } |
242 | 482 |
243 base::FilePath cache_path(args[0]); | 483 base::FilePath cache_path(args[0]); |
244 std::string cache_backend_type(args[1]); | 484 std::string cache_backend_type(args[1]); |
245 std::string subcommand(args[2]); | |
246 | 485 |
247 net::BackendType backend_type; | 486 net::BackendType backend_type; |
248 if (cache_backend_type == "simple") { | 487 if (cache_backend_type == "simple") { |
249 backend_type = net::CACHE_BACKEND_SIMPLE; | 488 backend_type = net::CACHE_BACKEND_SIMPLE; |
250 } else if (cache_backend_type == "blockfile") { | 489 } else if (cache_backend_type == "blockfile") { |
251 backend_type = net::CACHE_BACKEND_BLOCKFILE; | 490 backend_type = net::CACHE_BACKEND_BLOCKFILE; |
252 } else { | 491 } else { |
253 std::cerr << "Unknown cache type." << std::endl; | 492 std::cerr << "Unknown cache type." << std::endl; |
254 PrintHelp(); | 493 PrintHelp(); |
255 return 1; | 494 return 1; |
256 } | 495 } |
257 | 496 |
258 std::unique_ptr<Backend> cache_backend; | 497 std::unique_ptr<Backend> cache_backend; |
259 net::TestCompletionCallback cb; | 498 net::TestCompletionCallback cb; |
260 int rv = disk_cache::CreateCacheBackend( | 499 int rv = disk_cache::CreateCacheBackend( |
261 net::DISK_CACHE, backend_type, cache_path, INT_MAX, false, | 500 net::DISK_CACHE, backend_type, cache_path, INT_MAX, false, |
262 message_loop.task_runner(), nullptr, &cache_backend, cb.callback()); | 501 message_loop.task_runner(), nullptr, &cache_backend, cb.callback()); |
263 if (cb.GetResult(rv) != net::OK) { | 502 if (cb.GetResult(rv) != net::OK) { |
264 std::cerr << "Invalid cache." << std::endl; | 503 std::cerr << "Invalid cache." << std::endl; |
265 return 1; | 504 return 1; |
266 } | 505 } |
267 | 506 |
268 bool successful_command; | 507 CommandLineIO command_line_io( |
269 if (subcommand == "delete_key" && args.size() == 4) { | 508 cache_backend.get(), |
270 successful_command = DeleteKey(cache_backend.get(), args[3]); | 509 base::CommandLine::StringVector(args.begin() + 2, args.end())); |
271 } else if (subcommand == "delete_stream" && args.size() == 5) { | 510 bool successful_commands = ExecuteCommands(&command_line_io); |
272 int index = ParseStreamIndex(args[4]); | 511 |
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(); | 512 base::RunLoop().RunUntilIdle(); |
295 cache_backend = nullptr; | 513 cache_backend = nullptr; |
296 base::RunLoop().RunUntilIdle(); | 514 base::RunLoop().RunUntilIdle(); |
297 return !successful_command; | 515 return !successful_commands; |
298 } | 516 } |
OLD | NEW |