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

Side by Side Diff: net/http/disk_based_cert_cache.cc

Issue 361513003: Improving and adding an in-memory MRU cache to DiskBasedCertCache. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@DBCC_Implement
Patch Set: Added tests, and fixed issues with last patch. Created 6 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
OLDNEW
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 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 "net/http/disk_based_cert_cache.h" 5 #include "net/http/disk_based_cert_cache.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
11 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
12 #include "base/stl_util.h" 12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "net/base/io_buffer.h" 14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
16 #include "net/disk_cache/disk_cache.h" 16 #include "net/disk_cache/disk_cache.h"
17 17
18 namespace net { 18 namespace net {
19 19
20 namespace { 20 namespace {
21 21
22 // TODO(brandonsalmon): change this number to improve performance.
23 const int kMemoryCacheMaxSize = 30;
Ryan Sleevi 2014/07/02 21:49:58 size_t
24
22 // Used to obtain a unique cache key for a certificate in the form of 25 // Used to obtain a unique cache key for a certificate in the form of
23 // "cert:<hash>". 26 // "cert:<hash>".
24 std::string GetCacheKeyToCert(const X509Certificate::OSCertHandle cert_handle) { 27 std::string GetCacheKeyToCert(const X509Certificate::OSCertHandle cert_handle) {
25 SHA1HashValue fingerprint = 28 SHA1HashValue fingerprint =
26 X509Certificate::CalculateFingerprint(cert_handle); 29 X509Certificate::CalculateFingerprint(cert_handle);
27 30
28 return "cert:" + 31 return "cert:" +
29 base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); 32 base::HexEncode(fingerprint.data, arraysize(fingerprint.data));
30 } 33 }
31 34
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 std::vector<SetCallback> user_callbacks_; 104 std::vector<SetCallback> user_callbacks_;
102 CompletionCallback io_callback_; 105 CompletionCallback io_callback_;
103 }; 106 };
104 107
105 DiskBasedCertCache::WriteWorker::WriteWorker( 108 DiskBasedCertCache::WriteWorker::WriteWorker(
106 disk_cache::Backend* backend, 109 disk_cache::Backend* backend,
107 const std::string& key, 110 const std::string& key,
108 X509Certificate::OSCertHandle cert_handle, 111 X509Certificate::OSCertHandle cert_handle,
109 const base::Closure& cleanup_callback) 112 const base::Closure& cleanup_callback)
110 : backend_(backend), 113 : backend_(backend),
111 cert_handle_(cert_handle), 114 cert_handle_(cert_handle),
wtc 2014/07/02 20:51:49 I wonder if we should dup the cert_handle here, an
Ryan Sleevi 2014/07/02 21:49:58 Oof. Missed this. Yes, we should.
112 key_(key), 115 key_(key),
113 canceled_(false), 116 canceled_(false),
114 entry_(NULL), 117 entry_(NULL),
115 state_(STATE_NONE), 118 state_(STATE_NONE),
116 io_buf_len_(0), 119 io_buf_len_(0),
117 cleanup_callback_(cleanup_callback), 120 cleanup_callback_(cleanup_callback),
118 io_callback_( 121 io_callback_(
119 base::Bind(&WriteWorker::OnIOComplete, base::Unretained(this))) { 122 base::Bind(&WriteWorker::OnIOComplete, base::Unretained(this))) {
120 } 123 }
121 124
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 state_ = STATE_WRITE; 202 state_ = STATE_WRITE;
200 return OK; 203 return OK;
201 } 204 }
202 205
203 int DiskBasedCertCache::WriteWorker::DoOpen() { 206 int DiskBasedCertCache::WriteWorker::DoOpen() {
204 state_ = STATE_OPEN_COMPLETE; 207 state_ = STATE_OPEN_COMPLETE;
205 return backend_->OpenEntry(key_, &entry_, io_callback_); 208 return backend_->OpenEntry(key_, &entry_, io_callback_);
206 } 209 }
207 210
208 int DiskBasedCertCache::WriteWorker::DoOpenComplete(int rv) { 211 int DiskBasedCertCache::WriteWorker::DoOpenComplete(int rv) {
209 if (rv < 0) { 212 if (rv < 0)
210 state_ = STATE_NONE;
211 return rv; 213 return rv;
212 } 214
213 state_ = STATE_WRITE; 215 state_ = STATE_WRITE;
214 return OK; 216 return OK;
215 } 217 }
216 218
217 int DiskBasedCertCache::WriteWorker::DoWrite() { 219 int DiskBasedCertCache::WriteWorker::DoWrite() {
218 std::string write_data; 220 std::string write_data;
219 bool encoded = X509Certificate::GetDEREncoded(cert_handle_, &write_data); 221 bool encoded = X509Certificate::GetDEREncoded(cert_handle_, &write_data);
220 222
221 if (!encoded) { 223 if (!encoded)
222 state_ = STATE_NONE;
223 return ERR_FAILED; 224 return ERR_FAILED;
224 }
225 225
226 buffer_ = new IOBuffer(write_data.size()); 226 buffer_ = new IOBuffer(write_data.size());
227 io_buf_len_ = write_data.size(); 227 io_buf_len_ = write_data.size();
228 memcpy(buffer_->data(), write_data.data(), io_buf_len_); 228 memcpy(buffer_->data(), write_data.data(), io_buf_len_);
229 229
230 state_ = STATE_WRITE_COMPLETE; 230 state_ = STATE_WRITE_COMPLETE;
231 231
232 return entry_->WriteData(0 /* index */, 232 return entry_->WriteData(0 /* index */,
233 0 /* offset */, 233 0 /* offset */,
234 buffer_, 234 buffer_,
235 write_data.size(), 235 write_data.size(),
236 io_callback_, 236 io_callback_,
237 true /* truncate */); 237 true /* truncate */);
238 } 238 }
239 239
240 int DiskBasedCertCache::WriteWorker::DoWriteComplete(int rv) { 240 int DiskBasedCertCache::WriteWorker::DoWriteComplete(int rv) {
241 state_ = STATE_NONE;
242 if (rv < io_buf_len_) 241 if (rv < io_buf_len_)
243 return ERR_FAILED; 242 return ERR_FAILED;
244 243
245 return OK; 244 return OK;
246 } 245 }
247 246
248 void DiskBasedCertCache::WriteWorker::RunCallbacks(int rv) { 247 void DiskBasedCertCache::WriteWorker::RunCallbacks(int rv) {
249 std::string key; 248 std::string key;
250 if (rv >= 0) 249 if (rv >= 0)
251 key = key_; 250 key = key_;
(...skipping 10 matching lines...) Expand all
262 cleanup_callback_.Run(); 261 cleanup_callback_.Run();
263 cleanup_callback_.Reset(); 262 cleanup_callback_.Reset();
264 RunCallbacks(rv); 263 RunCallbacks(rv);
265 delete this; 264 delete this;
266 } 265 }
267 266
268 void DiskBasedCertCache::WriteWorker::Cancel() { 267 void DiskBasedCertCache::WriteWorker::Cancel() {
269 canceled_ = true; 268 canceled_ = true;
270 } 269 }
271 270
272 DiskBasedCertCache::WriteWorker::~WriteWorker() { 271 DiskBasedCertCache::WriteWorker::~WriteWorker() {
wtc 2014/07/02 20:51:49 Define the destructor right after the constructor.
273 if (entry_) 272 if (entry_)
274 entry_->Close(); 273 entry_->Close();
275 } 274 }
276 275
277 // ReadWorkers represent pending Get jobs in the DiskBasedCertCache. Each 276 // ReadWorkers represent pending Get jobs in the DiskBasedCertCache. Each
278 // certificate requested to be retrieved from the cache is assigned a ReadWorker 277 // certificate requested to be retrieved from the cache is assigned a ReadWorker
279 // on a one-to-one basis. The same |key| should not have multiple ReadWorkers 278 // on a one-to-one basis. The same |key| should not have multiple ReadWorkers
280 // at the same time; instead, call AddCallback to add a user_callback_ to 279 // at the same time; instead, call AddCallback to add a user_callback_ to
281 // the the existing ReadWorker. 280 // the the existing ReadWorker.
282 class DiskBasedCertCache::ReadWorker { 281 class DiskBasedCertCache::ReadWorker {
283 public: 282 public:
284 // |backend| is the backend to read |certificate| from, using 283 // |backend| is the backend to read |certificate| from, using
285 // |key| as the key for the disk_cache::Entry. 284 // |key| as the key for the disk_cache::Entry.
286 // |cleanup_callback| is called to clean up this ReadWorker, 285 // |cleanup_callback| is called to clean up this ReadWorker,
287 // regardless of success or failure. 286 // regardless of success or failure.
288 ReadWorker(disk_cache::Backend* backend, 287 ReadWorker(disk_cache::Backend* backend,
289 const std::string& key, 288 const std::string& key,
290 const base::Closure& cleanup_callback); 289 const GetCallback& cleanup_callback);
291 290
292 ~ReadWorker(); 291 ~ReadWorker();
293 292
294 // Reads the given certificate from the cache. On completion, will invoke all 293 // Reads the given certificate from the cache. On completion, will invoke all
295 // user callbacks. 294 // user callbacks.
296 void Start(); 295 void Start();
297 296
298 // Adds a callback to the set of callbacks to be run when this 297 // Adds a callback to the set of callbacks to be run when this
299 // ReadWorker finishes processing. 298 // ReadWorker finishes processing.
300 void AddCallback(const GetCallback& user_callback); 299 void AddCallback(const GetCallback& user_callback);
(...skipping 27 matching lines...) Expand all
328 X509Certificate::OSCertHandle cert_handle_; 327 X509Certificate::OSCertHandle cert_handle_;
329 std::string key_; 328 std::string key_;
330 bool canceled_; 329 bool canceled_;
331 330
332 disk_cache::Entry* entry_; 331 disk_cache::Entry* entry_;
333 332
334 State state_; 333 State state_;
335 scoped_refptr<IOBuffer> buffer_; 334 scoped_refptr<IOBuffer> buffer_;
336 int io_buf_len_; 335 int io_buf_len_;
337 336
338 base::Closure cleanup_callback_; 337 GetCallback cleanup_callback_;
339 std::vector<GetCallback> user_callbacks_; 338 std::vector<GetCallback> user_callbacks_;
340 CompletionCallback io_callback_; 339 CompletionCallback io_callback_;
341 }; 340 };
342 341
343 DiskBasedCertCache::ReadWorker::ReadWorker( 342 DiskBasedCertCache::ReadWorker::ReadWorker(disk_cache::Backend* backend,
344 disk_cache::Backend* backend, 343 const std::string& key,
345 const std::string& key, 344 const GetCallback& cleanup_callback)
346 const base::Closure& cleanup_callback)
347 : backend_(backend), 345 : backend_(backend),
348 cert_handle_(NULL), 346 cert_handle_(NULL),
349 key_(key), 347 key_(key),
350 canceled_(false), 348 canceled_(false),
351 entry_(NULL), 349 entry_(NULL),
352 state_(STATE_NONE), 350 state_(STATE_NONE),
353 io_buf_len_(0), 351 io_buf_len_(0),
354 cleanup_callback_(cleanup_callback), 352 cleanup_callback_(cleanup_callback),
355 io_callback_( 353 io_callback_(
356 base::Bind(&ReadWorker::OnIOComplete, base::Unretained(this))) { 354 base::Bind(&ReadWorker::OnIOComplete, base::Unretained(this))) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 409
412 return rv; 410 return rv;
413 } 411 }
414 412
415 int DiskBasedCertCache::ReadWorker::DoOpen() { 413 int DiskBasedCertCache::ReadWorker::DoOpen() {
416 state_ = STATE_OPEN_COMPLETE; 414 state_ = STATE_OPEN_COMPLETE;
417 return backend_->OpenEntry(key_, &entry_, io_callback_); 415 return backend_->OpenEntry(key_, &entry_, io_callback_);
418 } 416 }
419 417
420 int DiskBasedCertCache::ReadWorker::DoOpenComplete(int rv) { 418 int DiskBasedCertCache::ReadWorker::DoOpenComplete(int rv) {
421 if (rv < 0) { 419 if (rv < 0)
422 state_ = STATE_NONE;
423 return rv; 420 return rv;
424 } 421
425 state_ = STATE_READ; 422 state_ = STATE_READ;
426 return OK; 423 return OK;
427 } 424 }
428 425
429 int DiskBasedCertCache::ReadWorker::DoRead() { 426 int DiskBasedCertCache::ReadWorker::DoRead() {
430 state_ = STATE_READ_COMPLETE; 427 state_ = STATE_READ_COMPLETE;
431 io_buf_len_ = entry_->GetDataSize(0 /* index */); 428 io_buf_len_ = entry_->GetDataSize(0 /* index */);
432 buffer_ = new IOBuffer(io_buf_len_); 429 buffer_ = new IOBuffer(io_buf_len_);
433 return entry_->ReadData( 430 return entry_->ReadData(
434 0 /* index */, 0 /* offset */, buffer_, io_buf_len_, io_callback_); 431 0 /* index */, 0 /* offset */, buffer_, io_buf_len_, io_callback_);
435 } 432 }
436 433
437 int DiskBasedCertCache::ReadWorker::DoReadComplete(int rv) { 434 int DiskBasedCertCache::ReadWorker::DoReadComplete(int rv) {
438 state_ = STATE_NONE;
439 if (rv < io_buf_len_) 435 if (rv < io_buf_len_)
440 return ERR_FAILED; 436 return ERR_FAILED;
441 437
442 cert_handle_ = X509Certificate::CreateOSCertHandleFromBytes(buffer_->data(), 438 cert_handle_ = X509Certificate::CreateOSCertHandleFromBytes(buffer_->data(),
443 io_buf_len_); 439 io_buf_len_);
444 if (!cert_handle_) 440 if (!cert_handle_)
445 return ERR_FAILED; 441 return ERR_FAILED;
446 442
447 return OK; 443 return OK;
448 } 444 }
449 445
450 void DiskBasedCertCache::ReadWorker::RunCallbacks() { 446 void DiskBasedCertCache::ReadWorker::RunCallbacks() {
451 for (std::vector<GetCallback>::const_iterator it = user_callbacks_.begin(); 447 for (std::vector<GetCallback>::const_iterator it = user_callbacks_.begin();
452 it != user_callbacks_.end(); 448 it != user_callbacks_.end();
453 ++it) { 449 ++it) {
454 it->Run(cert_handle_); 450 it->Run(cert_handle_);
455 } 451 }
456 user_callbacks_.clear(); 452 user_callbacks_.clear();
457 } 453 }
458 454
459 void DiskBasedCertCache::ReadWorker::Finish(int rv) { 455 void DiskBasedCertCache::ReadWorker::Finish(int rv) {
460 cleanup_callback_.Run(); 456 cleanup_callback_.Run(cert_handle_);
461 cleanup_callback_.Reset(); 457 cleanup_callback_.Reset();
462 RunCallbacks(); 458 RunCallbacks();
463 delete this; 459 delete this;
464 } 460 }
465 461
466 void DiskBasedCertCache::ReadWorker::Cancel() { 462 void DiskBasedCertCache::ReadWorker::Cancel() {
467 canceled_ = true; 463 canceled_ = true;
468 } 464 }
469 465
470 DiskBasedCertCache::ReadWorker::~ReadWorker() { 466 DiskBasedCertCache::ReadWorker::~ReadWorker() {
wtc 2014/07/02 20:51:50 Define the destructor right after the constructor.
471 if (entry_) 467 if (entry_)
472 entry_->Close(); 468 entry_->Close();
473 if (cert_handle_) 469 if (cert_handle_)
474 X509Certificate::FreeOSCertHandle(cert_handle_); 470 X509Certificate::FreeOSCertHandle(cert_handle_);
475 } 471 }
476 472
477 DiskBasedCertCache::DiskBasedCertCache(disk_cache::Backend* backend) 473 DiskBasedCertCache::DiskBasedCertCache(disk_cache::Backend* backend)
478 : backend_(backend), weak_factory_(this) { 474 : backend_(backend),
475 mru_cert_cache_(kMemoryCacheMaxSize),
476 mem_cache_hits_(0),
477 mem_cache_misses_(0),
478 weak_factory_(this) {
479 DCHECK(backend_); 479 DCHECK(backend_);
480 } 480 }
481 481
482 DiskBasedCertCache::~DiskBasedCertCache() { 482 DiskBasedCertCache::~DiskBasedCertCache() {
483 for (WriteWorkerMap::iterator it = write_worker_map_.begin(); 483 for (WriteWorkerMap::iterator it = write_worker_map_.begin();
484 it != write_worker_map_.end(); 484 it != write_worker_map_.end();
485 ++it) { 485 ++it) {
486 it->second->Cancel(); 486 it->second->Cancel();
487 } 487 }
488 for (ReadWorkerMap::iterator it = read_worker_map_.begin(); 488 for (ReadWorkerMap::iterator it = read_worker_map_.begin();
489 it != read_worker_map_.end(); 489 it != read_worker_map_.end();
490 ++it) { 490 ++it) {
491 it->second->Cancel(); 491 it->second->Cancel();
492 } 492 }
493 } 493 }
494 494
495 void DiskBasedCertCache::Get(const std::string& key, const GetCallback& cb) { 495 void DiskBasedCertCache::Get(const std::string& key, const GetCallback& cb) {
496 DCHECK(!key.empty()); 496 DCHECK(!key.empty());
497 497
498 // If the handle is already in the MRU cache, just return that (via callback).
499 // Note, this will also bring the cert_handle to the front
wtc 2014/07/02 20:51:50 Nit: this line break is too short.
500 // of the recency list in the MRU cache.
501 MRUCertCache::iterator mru_it = mru_cert_cache_.Get(key);
502 if (mru_it != mru_cert_cache_.end()) {
503 ++mem_cache_hits_;
504 cb.Run(mru_it->second);
505 return;
rvargas (doing something else) 2014/07/02 22:14:38 You may want to tell the backend about this: backe
506 }
507 ++mem_cache_misses_;
508
498 ReadWorkerMap::iterator it = read_worker_map_.find(key); 509 ReadWorkerMap::iterator it = read_worker_map_.find(key);
499 510
500 if (it == read_worker_map_.end()) { 511 if (it == read_worker_map_.end()) {
501 ReadWorker* worker = 512 ReadWorker* worker =
502 new ReadWorker(backend_, 513 new ReadWorker(backend_,
503 key, 514 key,
504 base::Bind(&DiskBasedCertCache::FinishedReadOperation, 515 base::Bind(&DiskBasedCertCache::FinishedReadOperation,
505 weak_factory_.GetWeakPtr(), 516 weak_factory_.GetWeakPtr(),
506 key)); 517 key));
507 read_worker_map_[key] = worker; 518 read_worker_map_[key] = worker;
508 worker->AddCallback(cb); 519 worker->AddCallback(cb);
509 worker->Start(); 520 worker->Start();
510 } else { 521 } else {
511 it->second->AddCallback(cb); 522 it->second->AddCallback(cb);
512 } 523 }
513 } 524 }
514 525
515 void DiskBasedCertCache::Set(const X509Certificate::OSCertHandle cert_handle, 526 void DiskBasedCertCache::Set(const X509Certificate::OSCertHandle cert_handle,
516 const SetCallback& cb) { 527 const SetCallback& cb) {
517 DCHECK(!cb.is_null()); 528 DCHECK(!cb.is_null());
518 DCHECK(cert_handle); 529 DCHECK(cert_handle);
519 std::string key = GetCacheKeyToCert(cert_handle); 530 std::string key = GetCacheKeyToCert(cert_handle);
520 531
532 // If |cert_handle| already exists in the MRU cache, there is no need to
533 // re-write it to the disk cache. This will also bring |cert_handle|
534 // to the front of the recency list in the MRU cache.
535 if (mru_cert_cache_.Get(key) != mru_cert_cache_.end()) {
536 ++mem_cache_hits_;
537 cb.Run(key);
538 return;
539 }
540 ++mem_cache_misses_;
wtc 2014/07/02 20:51:50 IMPORTANT: We should think about whether Set() sho
Ryan Sleevi 2014/07/02 21:49:58 Yes. I think we only want Get to be satisfied by
541
521 WriteWorkerMap::iterator it = write_worker_map_.find(key); 542 WriteWorkerMap::iterator it = write_worker_map_.find(key);
522 543
523 if (it == write_worker_map_.end()) { 544 if (it == write_worker_map_.end()) {
524 WriteWorker* worker = 545 WriteWorker* worker =
525 new WriteWorker(backend_, 546 new WriteWorker(backend_,
526 key, 547 key,
527 cert_handle, 548 cert_handle,
528 base::Bind(&DiskBasedCertCache::FinishedWriteOperation, 549 base::Bind(&DiskBasedCertCache::FinishedWriteOperation,
529 weak_factory_.GetWeakPtr(), 550 weak_factory_.GetWeakPtr(),
530 key)); 551 key,
552 cert_handle));
531 write_worker_map_[key] = worker; 553 write_worker_map_[key] = worker;
532 worker->AddCallback(cb); 554 worker->AddCallback(cb);
533 worker->Start(); 555 worker->Start();
534 } else { 556 } else {
535 it->second->AddCallback(cb); 557 it->second->AddCallback(cb);
536 } 558 }
537 } 559 }
538 560
539 void DiskBasedCertCache::FinishedWriteOperation(const std::string& key) { 561 void DiskBasedCertCache::FinishedWriteOperation(
562 const std::string& key,
563 X509Certificate::OSCertHandle cert_handle) {
540 write_worker_map_.erase(key); 564 write_worker_map_.erase(key);
565 if (key != std::string())
wtc 2014/07/02 20:51:49 Test !key.empty().
566 mru_cert_cache_.Put(key, X509Certificate::DupOSCertHandle(cert_handle));
541 } 567 }
542 568
543 void DiskBasedCertCache::FinishedReadOperation(const std::string& key) { 569 void DiskBasedCertCache::FinishedReadOperation(
570 const std::string& key,
571 X509Certificate::OSCertHandle cert_handle) {
572 if (cert_handle)
573 mru_cert_cache_.Put(key, X509Certificate::DupOSCertHandle(cert_handle));
544 read_worker_map_.erase(key); 574 read_worker_map_.erase(key);
545 } 575 }
546 576
547 } // namespace net 577 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698