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

Side by Side Diff: chrome/browser/chromeos/drive/resource_metadata_storage.cc

Issue 54223003: drive: Recover cache entries from trashed DB to filter out non-dirty cache files (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/chromeos/drive/resource_metadata_storage.h" 5 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 23 matching lines...) Expand all
34 }; 34 };
35 35
36 // The name of the DB which stores the metadata. 36 // The name of the DB which stores the metadata.
37 const base::FilePath::CharType kResourceMapDBName[] = 37 const base::FilePath::CharType kResourceMapDBName[] =
38 FILE_PATH_LITERAL("resource_metadata_resource_map.db"); 38 FILE_PATH_LITERAL("resource_metadata_resource_map.db");
39 39
40 // The name of the DB which couldn't be opened, but is preserved just in case. 40 // The name of the DB which couldn't be opened, but is preserved just in case.
41 const base::FilePath::CharType kPreservedResourceMapDBName[] = 41 const base::FilePath::CharType kPreservedResourceMapDBName[] =
42 FILE_PATH_LITERAL("resource_metadata_preserved_resource_map.db"); 42 FILE_PATH_LITERAL("resource_metadata_preserved_resource_map.db");
43 43
44 // The name of the DB which couldn't be opened, and was replaced with a new one.
45 const base::FilePath::CharType kTrashedResourceMapDBName[] =
46 FILE_PATH_LITERAL("resource_metadata_trashed_resource_map.db");
47
44 // Meant to be a character which never happen to be in real IDs. 48 // Meant to be a character which never happen to be in real IDs.
45 const char kDBKeyDelimeter = '\0'; 49 const char kDBKeyDelimeter = '\0';
46 50
47 // String used as a suffix of a key for a cache entry. 51 // String used as a suffix of a key for a cache entry.
48 const char kCacheEntryKeySuffix[] = "CACHE"; 52 const char kCacheEntryKeySuffix[] = "CACHE";
49 53
50 // String used as a prefix of a key for a resource-ID-to-local-ID entry. 54 // String used as a prefix of a key for a resource-ID-to-local-ID entry.
51 const char kIdEntryKeyPrefix[] = "ID"; 55 const char kIdEntryKeyPrefix[] = "ID";
52 56
53 // Returns a string to be used as the key for the header. 57 // Returns a string to be used as the key for the header.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 return DB_INIT_IO_ERROR; 134 return DB_INIT_IO_ERROR;
131 return DB_INIT_FAILED; 135 return DB_INIT_FAILED;
132 } 136 }
133 137
134 ResourceMetadataHeader GetDefaultHeaderEntry() { 138 ResourceMetadataHeader GetDefaultHeaderEntry() {
135 ResourceMetadataHeader header; 139 ResourceMetadataHeader header;
136 header.set_version(ResourceMetadataStorage::kDBVersion); 140 header.set_version(ResourceMetadataStorage::kDBVersion);
137 return header; 141 return header;
138 } 142 }
139 143
144 bool MoveIfPossible(const base::FilePath& from, const base::FilePath& to) {
145 return !base::PathExists(from) || base::Move(from, to);
146 }
147
140 } // namespace 148 } // namespace
141 149
142 ResourceMetadataStorage::Iterator::Iterator(scoped_ptr<leveldb::Iterator> it) 150 ResourceMetadataStorage::Iterator::Iterator(scoped_ptr<leveldb::Iterator> it)
143 : it_(it.Pass()) { 151 : it_(it.Pass()) {
144 base::ThreadRestrictions::AssertIOAllowed(); 152 base::ThreadRestrictions::AssertIOAllowed();
145 DCHECK(it_); 153 DCHECK(it_);
146 154
147 // Skip the header entry. 155 // Skip the header entry.
148 // Note: The header entry comes before all other entries because its key 156 // Note: The header entry comes before all other entries because its key
149 // starts with kDBKeyDelimeter. (i.e. '\0') 157 // starts with kDBKeyDelimeter. (i.e. '\0')
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 375
368 bool ResourceMetadataStorage::Initialize() { 376 bool ResourceMetadataStorage::Initialize() {
369 base::ThreadRestrictions::AssertIOAllowed(); 377 base::ThreadRestrictions::AssertIOAllowed();
370 378
371 resource_map_.reset(); 379 resource_map_.reset();
372 380
373 const base::FilePath resource_map_path = 381 const base::FilePath resource_map_path =
374 directory_path_.Append(kResourceMapDBName); 382 directory_path_.Append(kResourceMapDBName);
375 const base::FilePath preserved_resource_map_path = 383 const base::FilePath preserved_resource_map_path =
376 directory_path_.Append(kPreservedResourceMapDBName); 384 directory_path_.Append(kPreservedResourceMapDBName);
385 const base::FilePath trashed_resource_map_path =
386 directory_path_.Append(kTrashedResourceMapDBName);
387
388 // Discard unneeded DBs.
389 if (!base::DeleteFile(preserved_resource_map_path, true /* recursive */) ||
390 !base::DeleteFile(trashed_resource_map_path, true /* recursive */)) {
391 LOG(ERROR) << "Failed to remove unneeded DBs.";
392 return false;
393 }
377 394
378 // Try to open the existing DB. 395 // Try to open the existing DB.
379 leveldb::DB* db = NULL; 396 leveldb::DB* db = NULL;
380 leveldb::Options options; 397 leveldb::Options options;
381 options.max_open_files = 0; // Use minimum. 398 options.max_open_files = 0; // Use minimum.
382 options.create_if_missing = false; 399 options.create_if_missing = false;
383 400
384 DBInitStatus open_existing_result = DB_INIT_NOT_FOUND; 401 DBInitStatus open_existing_result = DB_INIT_NOT_FOUND;
385 leveldb::Status status; 402 leveldb::Status status;
386 if (base::PathExists(resource_map_path)) { 403 if (base::PathExists(resource_map_path)) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 open_existing_result, 435 open_existing_result,
419 DB_INIT_MAX_VALUE); 436 DB_INIT_MAX_VALUE);
420 437
421 DBInitStatus init_result = DB_INIT_SUCCESS; 438 DBInitStatus init_result = DB_INIT_SUCCESS;
422 439
423 // Failed to open the existing DB, create new DB. 440 // Failed to open the existing DB, create new DB.
424 if (!resource_map_) { 441 if (!resource_map_) {
425 // Move the existing DB to the preservation path. The moved old DB is 442 // Move the existing DB to the preservation path. The moved old DB is
426 // deleted once the new DB creation succeeds, or is restored later in 443 // deleted once the new DB creation succeeds, or is restored later in
427 // UpgradeOldDB() when the creation fails. 444 // UpgradeOldDB() when the creation fails.
428 if (base::PathExists(resource_map_path) && 445 MoveIfPossible(resource_map_path, preserved_resource_map_path);
429 base::DeleteFile(preserved_resource_map_path, true /* recursive */))
430 base::Move(resource_map_path, preserved_resource_map_path);
431 446
432 // Create DB. 447 // Create DB.
433 options.max_open_files = 0; // Use minimum. 448 options.max_open_files = 0; // Use minimum.
434 options.create_if_missing = true; 449 options.create_if_missing = true;
435 options.error_if_exists = true; 450 options.error_if_exists = true;
436 451
437 status = leveldb::DB::Open(options, resource_map_path.AsUTF8Unsafe(), &db); 452 status = leveldb::DB::Open(options, resource_map_path.AsUTF8Unsafe(), &db);
438 if (status.ok()) { 453 if (status.ok()) {
439 resource_map_.reset(db); 454 resource_map_.reset(db);
440 455
441 if (!PutHeader(GetDefaultHeaderEntry()) || // Set up header. 456 if (!PutHeader(GetDefaultHeaderEntry()) || // Set up header.
442 !base::DeleteFile(preserved_resource_map_path, 457 !MoveIfPossible(preserved_resource_map_path, // Trash the old DB.
443 true /* recursive */)) { // Remove the old DB. 458 trashed_resource_map_path)) {
444 init_result = DB_INIT_FAILED; 459 init_result = DB_INIT_FAILED;
445 resource_map_.reset(); 460 resource_map_.reset();
446 } 461 }
447 } else { 462 } else {
448 LOG(ERROR) << "Failed to create resource map DB: " << status.ToString(); 463 LOG(ERROR) << "Failed to create resource map DB: " << status.ToString();
449 init_result = LevelDBStatusToDBInitStatus(status); 464 init_result = LevelDBStatusToDBInitStatus(status);
450 } 465 }
451 } 466 }
452 467
453 UMA_HISTOGRAM_ENUMERATION("Drive.MetadataDBInitResult", 468 UMA_HISTOGRAM_ENUMERATION("Drive.MetadataDBInitResult",
454 init_result, 469 init_result,
455 DB_INIT_MAX_VALUE); 470 DB_INIT_MAX_VALUE);
456 return resource_map_; 471 return resource_map_;
457 } 472 }
458 473
474 void ResourceMetadataStorage::RecoverCacheEntriesFromTrashedResourceMap(
475 std::map<std::string, FileCacheEntry>* out_entries) {
476 const base::FilePath trashed_resource_map_path =
477 directory_path_.Append(kTrashedResourceMapDBName);
478
479 if (!base::PathExists(trashed_resource_map_path))
480 return;
481
482 leveldb::Options options;
483 options.max_open_files = 0; // Use minimum.
484 options.create_if_missing = false;
485
486 // Trashed DB may be broken, repair it first.
487 leveldb::Status status;
488 status = leveldb::RepairDB(trashed_resource_map_path.AsUTF8Unsafe(), options);
489 if (!status.ok()) {
490 LOG(ERROR) << "Failed to repair trashed DB: " << status.ToString();
491 return;
492 }
493
494 // Open it.
495 leveldb::DB* db = NULL;
496 status = leveldb::DB::Open(options, trashed_resource_map_path.AsUTF8Unsafe(),
497 &db);
498 if (!status.ok()) {
499 LOG(ERROR) << "Failed to open trashed DB: " << status.ToString();
500 return;
501 }
502 scoped_ptr<leveldb::DB> resource_map(db);
503
504 // Check DB version.
505 std::string serialized_header;
506 ResourceMetadataHeader header;
507 if (!resource_map->Get(leveldb::ReadOptions(),
508 leveldb::Slice(GetHeaderDBKey()),
509 &serialized_header).ok() ||
510 !header.ParseFromString(serialized_header) ||
511 header.version() != kDBVersion) {
512 LOG(ERROR) << "Incompatible DB version: " << header.version();
513 return;
514 }
515
516 // Collect cache entries.
517 scoped_ptr<leveldb::Iterator> it(
518 resource_map->NewIterator(leveldb::ReadOptions()));
519 for (it->SeekToFirst(); it->Valid(); it->Next()) {
520 if (IsCacheEntryKey(it->key())) {
521 const std::string& id = GetIdFromCacheEntryKey(it->key());
522 FileCacheEntry cache_entry;
523 if (cache_entry.ParseFromArray(it->value().data(), it->value().size()))
524 (*out_entries)[id] = cache_entry;
525 }
526 }
527 }
528
459 bool ResourceMetadataStorage::SetLargestChangestamp( 529 bool ResourceMetadataStorage::SetLargestChangestamp(
460 int64 largest_changestamp) { 530 int64 largest_changestamp) {
461 base::ThreadRestrictions::AssertIOAllowed(); 531 base::ThreadRestrictions::AssertIOAllowed();
462 532
463 ResourceMetadataHeader header; 533 ResourceMetadataHeader header;
464 if (!GetHeader(&header)) { 534 if (!GetHeader(&header)) {
465 DLOG(ERROR) << "Failed to get the header."; 535 DLOG(ERROR) << "Failed to get the header.";
466 return false; 536 return false;
467 } 537 }
468 header.set_largest_changestamp(largest_changestamp); 538 header.set_largest_changestamp(largest_changestamp);
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 if (!it->status().ok() || num_child_entries != num_entries_with_parent) { 897 if (!it->status().ok() || num_child_entries != num_entries_with_parent) {
828 DLOG(ERROR) << "Error during checking resource map. status = " 898 DLOG(ERROR) << "Error during checking resource map. status = "
829 << it->status().ToString(); 899 << it->status().ToString();
830 return false; 900 return false;
831 } 901 }
832 return true; 902 return true;
833 } 903 }
834 904
835 } // namespace internal 905 } // namespace internal
836 } // namespace drive 906 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698