Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: net/tools/cachetool/cachetool.cc

Issue 2114933002: cachetool: Implement batch mode to speed-up cache processing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698