1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/resource_metadata_storage.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/bind.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/file_util.h" 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/location.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/histogram.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/sequenced_task_runner.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/drive.pb.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/db.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace drive { 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace internal { 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Enum to describe DB initialization status. 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum DBInitStatus { 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_SUCCESS, 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_NOT_FOUND, 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_CORRUPTION, 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_IO_ERROR, 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_FAILED, 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_INCOMPATIBLE, 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_BROKEN, 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_MAX_VALUE, 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const base::FilePath::CharType kResourceMapDBName[] = 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FILE_PATH_LITERAL("resource_metadata_resource_map.db"); 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const base::FilePath::CharType kChildMapDBName[] = 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FILE_PATH_LITERAL("resource_metadata_child_map.db"); 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Meant to be a character which never happen to be in real resource IDs. 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kDBKeyDelimeter = '\0'; 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// String used as a suffix of a key for a cache entry. 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char kCacheEntryKeySuffix[] = "CACHE"; 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns a string to be used as the key for the header. 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GetHeaderDBKey() { 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string key; 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) key.push_back(kDBKeyDelimeter); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) key.append("HEADER"); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return key; 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns true if |key| is a key for a child entry. 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IsChildEntryKey(const leveldb::Slice& key) { 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return !key.empty() && key[key.size() - 1] == kDBKeyDelimeter; 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Returns a string to be used as a key for a cache entry. 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string GetCacheEntryKey(const std::string& resource_id) { 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string key(resource_id); 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch key.push_back(kDBKeyDelimeter); 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch key.append(kCacheEntryKeySuffix); 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return key; 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Returns true if |key| is a key for a cache entry. 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool IsCacheEntryKey(const leveldb::Slice& key) { 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // A cache entry key should end with |kDBKeyDelimeter + kCacheEntryKeySuffix|. 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const leveldb::Slice expected_suffix(kCacheEntryKeySuffix, 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch arraysize(kCacheEntryKeySuffix) - 1); 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (key.size() < 1 + expected_suffix.size() || 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch key[key.size() - expected_suffix.size() - 1] != kDBKeyDelimeter) 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const leveldb::Slice key_substring( 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch key.data() + key.size() - expected_suffix.size(), expected_suffix.size()); 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return key_substring.compare(expected_suffix) == 0; 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Converts leveldb::Status to DBInitStatus. 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DBInitStatus LevelDBStatusToDBInitStatus(const leveldb::Status status) { 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status.ok()) 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DB_INIT_SUCCESS; 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status.IsNotFound()) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DB_INIT_NOT_FOUND; 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status.IsCorruption()) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DB_INIT_CORRUPTION; 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status.IsIOError()) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DB_INIT_IO_ERROR; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DB_INIT_FAILED; 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)ResourceMetadataStorage::Iterator::Iterator(scoped_ptr<leveldb::Iterator> it) 97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) : it_(it.Pass()) { 98a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(it_); 100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Skip the header entry. 102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Note: The header entry comes before all other entries because its key 103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // starts with kDBKeyDelimeter. (i.e. '\0') 104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) it_->Seek(leveldb::Slice(GetHeaderDBKey())); 105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Advance(); 107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)ResourceMetadataStorage::Iterator::~Iterator() { 110a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ResourceMetadataStorage::Iterator::IsAtEnd() const { 114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return !it_->Valid(); 116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const ResourceEntry& ResourceMetadataStorage::Iterator::Get() const { 119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!IsAtEnd()); 121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return entry_; 122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 12458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochbool ResourceMetadataStorage::Iterator::GetCacheEntry( 12558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch FileCacheEntry* cache_entry) { 12658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch base::ThreadRestrictions::AssertIOAllowed(); 12758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch DCHECK(!IsAtEnd()); 12858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 12958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch // Try to seek to the cache entry. 13058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch std::string current_key = it_->key().ToString(); 13158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch std::string cache_entry_key = GetCacheEntryKey(current_key); 13258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch it_->Seek(leveldb::Slice(cache_entry_key)); 13358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 13458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch bool success = it_->Valid() && 13558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch it_->key().compare(cache_entry_key) == 0 && 13658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch cache_entry->ParseFromArray(it_->value().data(), it_->value().size()); 13758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 13858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch // Seek back to the original position. 13958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch it_->Seek(leveldb::Slice(current_key)); 14058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch DCHECK(!IsAtEnd()); 14158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch DCHECK_EQ(current_key, it_->key().ToString()); 14258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 14358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch return success; 14458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch} 14558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadataStorage::Iterator::Advance() { 147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!IsAtEnd()); 149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (it_->Next() ; it_->Valid(); it_->Next()) { 151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!IsChildEntryKey(it_->key()) && 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch !IsCacheEntryKey(it_->key()) && 153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) entry_.ParseFromArray(it_->value().data(), it_->value().size())) 154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ResourceMetadataStorage::Iterator::HasError() const { 159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return !it_->status().ok(); 161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochResourceMetadataStorage::CacheEntryIterator::CacheEntryIterator( 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<leveldb::Iterator> it) : it_(it.Pass()) { 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(it_); 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it_->SeekToFirst(); 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AdvanceInternal(); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochResourceMetadataStorage::CacheEntryIterator::~CacheEntryIterator() { 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ResourceMetadataStorage::CacheEntryIterator::IsAtEnd() const { 177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return !it_->Valid(); 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst std::string& ResourceMetadataStorage::CacheEntryIterator::GetID() const { 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!IsAtEnd()); 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return resource_id_; 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst FileCacheEntry& 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochResourceMetadataStorage::CacheEntryIterator::GetValue() const { 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!IsAtEnd()); 191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return entry_; 192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ResourceMetadataStorage::CacheEntryIterator::Advance() { 195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!IsAtEnd()); 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it_->Next(); 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AdvanceInternal(); 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ResourceMetadataStorage::CacheEntryIterator::HasError() const { 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return !it_->status().ok(); 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ResourceMetadataStorage::CacheEntryIterator::AdvanceInternal() { 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (; it_->Valid(); it_->Next()) { 209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Skip unparsable broken entries. 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(hashimoto): Broken entries should be cleaned up at some point. 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IsCacheEntryKey(it_->key()) && 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch entry_.ParseFromArray(it_->value().data(), it_->value().size())) { 213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Drop the suffix |kDBKeyDelimeter + kCacheEntryKeySuffix| from the key. 214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const size_t kSuffixLength = arraysize(kCacheEntryKeySuffix) - 1; 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int id_length = it_->key().size() - 1 - kSuffixLength; 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch resource_id_.assign(it_->key().data(), id_length); 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochResourceMetadataStorage::ResourceMetadataStorage( 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& directory_path, 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::SequencedTaskRunner* blocking_task_runner) 225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : directory_path_(directory_path), 226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch opened_existing_db_(false), 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch blocking_task_runner_(blocking_task_runner) { 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ResourceMetadataStorage::Destroy() { 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch blocking_task_runner_->PostTask( 232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FROM_HERE, 233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&ResourceMetadataStorage::DestroyOnBlockingPool, 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this))); 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadataStorage::Initialize() { 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove unused child map DB. 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath child_map_path = directory_path_.Append(kChildMapDBName); 2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(child_map_path, true /* recursive */); 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_.reset(); 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath resource_map_path = 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) directory_path_.Append(kResourceMapDBName); 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Try to open the existing DB. 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::DB* db = NULL; 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Options options; 2526bda25ffe15103e73b1811c624157f45962839deTorne (Richard Coles) options.max_open_files = 64; // Use minimum. 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options.create_if_missing = false; 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DBInitStatus open_existing_result = DB_INIT_NOT_FOUND; 2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (base::PathExists(resource_map_path)) { 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::Status status = 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::DB::Open(options, resource_map_path.AsUTF8Unsafe(), &db); 259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) open_existing_result = LevelDBStatusToDBInitStatus(status); 260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (open_existing_result == DB_INIT_SUCCESS) { 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_.reset(db); 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check the validity of existing DB. 266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResourceMetadataHeader header; 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!GetHeader(&header) || header.version() != kDBVersion) { 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) open_existing_result = DB_INIT_INCOMPATIBLE; 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(INFO) << "Reject incompatible DB."; 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (!CheckValidity()) { 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) open_existing_result = DB_INIT_BROKEN; 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Reject invalid DB."; 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (open_existing_result == DB_INIT_SUCCESS) 276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch opened_existing_db_ = true; 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_.reset(); 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Drive.MetadataDBOpenExistingResult", 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) open_existing_result, 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_MAX_VALUE); 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DBInitStatus init_result = DB_INIT_SUCCESS; 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Failed to open the existing DB, create new DB. 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!resource_map_) { 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_.reset(); 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Clean up the destination. 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const bool kRecursive = true; 2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(resource_map_path, kRecursive); 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create DB. 2966bda25ffe15103e73b1811c624157f45962839deTorne (Richard Coles) options.max_open_files = 64; // Use minimum. 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options.create_if_missing = true; 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::Status status = 300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) leveldb::DB::Open(options, resource_map_path.AsUTF8Unsafe(), &db); 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status.ok()) { 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_.reset(db); 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set up header. 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ResourceMetadataHeader header; 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) header.set_version(kDBVersion); 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!PutHeader(header)) { 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) init_result = DB_INIT_FAILED; 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_.reset(); 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Failed to create resource map DB: " << status.ToString(); 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) init_result = LevelDBStatusToDBInitStatus(status); 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Drive.MetadataDBInitResult", 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) init_result, 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DB_INIT_MAX_VALUE); 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return resource_map_; 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadataStorage::SetLargestChangestamp( 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int64 largest_changestamp) { 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResourceMetadataHeader header; 328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!GetHeader(&header)) { 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Failed to get the header."; 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch header.set_largest_changestamp(largest_changestamp); 333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return PutHeader(header); 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int64 ResourceMetadataStorage::GetLargestChangestamp() { 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResourceMetadataHeader header; 339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!GetHeader(&header)) { 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Failed to get the header."; 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 0; 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return header.largest_changestamp(); 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) { 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!entry.resource_id().empty()); 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string serialized_entry; 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!entry.SerializeToString(&serialized_entry)) { 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Failed to serialize the entry: " << entry.resource_id(); 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::WriteBatch batch; 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove from the old parent. 3597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ResourceEntry old_entry; 3607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (GetEntry(entry.resource_id(), &old_entry) && 3617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !old_entry.parent_resource_id().empty()) { 3627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) batch.Delete(GetChildEntryKey(old_entry.parent_resource_id(), 3637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) old_entry.base_name())); 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Add to the new parent. 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!entry.parent_resource_id().empty()) { 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) batch.Put(GetChildEntryKey(entry.parent_resource_id(), entry.base_name()), 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entry.resource_id()); 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Put the entry itself. 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) batch.Put(entry.resource_id(), serialized_entry); 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const leveldb::Status status = resource_map_->Write(leveldb::WriteOptions(), 376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &batch); 377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return status.ok(); 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool ResourceMetadataStorage::GetEntry(const std::string& resource_id, 3817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ResourceEntry* out_entry) { 382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!resource_id.empty()); 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string serialized_entry; 386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const leveldb::Status status = resource_map_->Get(leveldb::ReadOptions(), 387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Slice(resource_id), 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &serialized_entry); 3897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return status.ok() && out_entry->ParseFromString(serialized_entry); 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadataStorage::RemoveEntry(const std::string& resource_id) { 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!resource_id.empty()); 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ResourceEntry entry; 3977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!GetEntry(resource_id, &entry)) 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::WriteBatch batch; 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove from the parent. 4037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!entry.parent_resource_id().empty()) { 4047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) batch.Delete(GetChildEntryKey(entry.parent_resource_id(), 4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) entry.base_name())); 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove the entry itself. 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) batch.Delete(resource_id); 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const leveldb::Status status = resource_map_->Write(leveldb::WriteOptions(), 411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &batch); 412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return status.ok(); 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)scoped_ptr<ResourceMetadataStorage::Iterator> 416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)ResourceMetadataStorage::GetIterator() { 417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<leveldb::Iterator> it( 420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_->NewIterator(leveldb::ReadOptions())); 421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return make_scoped_ptr(new Iterator(it.Pass())); 422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string ResourceMetadataStorage::GetChild( 425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& parent_resource_id, 426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& child_name) { 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string child_resource_id; 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_->Get( 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::ReadOptions(), 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Slice(GetChildEntryKey(parent_resource_id, child_name)), 433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &child_resource_id); 434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return child_resource_id; 435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ResourceMetadataStorage::GetChildren(const std::string& parent_resource_id, 438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<std::string>* children) { 439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Iterate over all entries with keys starting with |parent_resource_id|. 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<leveldb::Iterator> it( 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) resource_map_->NewIterator(leveldb::ReadOptions())); 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (it->Seek(parent_resource_id); 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it->Valid() && it->key().starts_with(leveldb::Slice(parent_resource_id)); 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it->Next()) { 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (IsChildEntryKey(it->key())) 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) children->push_back(it->value().ToString()); 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(it->status().ok()); 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ResourceMetadataStorage::PutCacheEntry(const std::string& resource_id, 454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const FileCacheEntry& entry) { 455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!resource_id.empty()); 457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string serialized_entry; 459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!entry.SerializeToString(&serialized_entry)) { 460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DLOG(ERROR) << "Failed to serialize the entry."; 461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const leveldb::Status status = resource_map_->Put( 465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb::WriteOptions(), 466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb::Slice(GetCacheEntryKey(resource_id)), 467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb::Slice(serialized_entry)); 468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return status.ok(); 469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ResourceMetadataStorage::GetCacheEntry(const std::string& resource_id, 472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FileCacheEntry* out_entry) { 473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!resource_id.empty()); 475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string serialized_entry; 477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const leveldb::Status status = resource_map_->Get( 478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb::ReadOptions(), 479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb::Slice(GetCacheEntryKey(resource_id)), 480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &serialized_entry); 481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return status.ok() && out_entry->ParseFromString(serialized_entry); 482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ResourceMetadataStorage::RemoveCacheEntry(const std::string& resource_id) { 485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!resource_id.empty()); 487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const leveldb::Status status = resource_map_->Delete( 489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb::WriteOptions(), 490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch leveldb::Slice(GetCacheEntryKey(resource_id))); 491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return status.ok(); 492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<ResourceMetadataStorage::CacheEntryIterator> 495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochResourceMetadataStorage::GetCacheEntryIterator() { 496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<leveldb::Iterator> it( 499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch resource_map_->NewIterator(leveldb::ReadOptions())); 500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return make_scoped_ptr(new CacheEntryIterator(it.Pass())); 501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochResourceMetadataStorage::~ResourceMetadataStorage() { 504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ResourceMetadataStorage::DestroyOnBlockingPool() { 508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delete this; 509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string ResourceMetadataStorage::GetChildEntryKey( 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& parent_resource_id, 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& child_name) { 515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string key = parent_resource_id; 516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) key.push_back(kDBKeyDelimeter); 517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) key.append(child_name); 518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) key.push_back(kDBKeyDelimeter); 519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return key; 520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadataStorage::PutHeader( 523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ResourceMetadataHeader& header) { 524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string serialized_header; 527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!header.SerializeToString(&serialized_header)) { 528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Failed to serialize the header"; 529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const leveldb::Status status = resource_map_->Put( 533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::WriteOptions(), 534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Slice(GetHeaderDBKey()), 535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Slice(serialized_header)); 536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return status.ok(); 537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ResourceMetadataStorage::GetHeader(ResourceMetadataHeader* header) { 540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string serialized_header; 543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const leveldb::Status status = resource_map_->Get( 544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::ReadOptions(), 545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Slice(GetHeaderDBKey()), 546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &serialized_header); 547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return status.ok() && header->ParseFromString(serialized_header); 548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadataStorage::CheckValidity() { 551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::AssertIOAllowed(); 552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Perform read with checksums verification enalbed. 554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::ReadOptions options; 555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options.verify_checksums = true; 556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<leveldb::Iterator> it(resource_map_->NewIterator(options)); 558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it->SeekToFirst(); 559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // DB is organized like this: 561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // 562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // <key> : <value> 563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "\0HEADER" : ResourceMetadataHeader 564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "|ID of A|" : ResourceEntry for entry A. 565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "|ID of A|\0CACHE" : FileCacheEntry for entry A. 566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "|ID of A|\0|child name 1|\0" : ID of the 1st child entry of entry A. 567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "|ID of A|\0|child name 2|\0" : ID of the 2nd child entry of entry A. 568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // ... 569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "|ID of A|\0|child name n|\0" : ID of the nth child entry of entry A. 570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "|ID of B|" : ResourceEntry for entry B. 571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // "|ID of B|\0CACHE" : FileCacheEntry for entry B. 572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // ... 573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check the header. 575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ResourceMetadataHeader header; 576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!it->Valid() || 577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it->key() != GetHeaderDBKey() || // Header entry must come first. 578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !header.ParseFromArray(it->value().data(), it->value().size()) || 579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) header.version() != kDBVersion) { 580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Invalid header detected. version = " << header.version(); 581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Check all entries. 585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t num_entries_with_parent = 0; 586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t num_child_entries = 0; 587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ResourceEntry entry; 588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string serialized_parent_entry; 589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string child_resource_id; 590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (it->Next(); it->Valid(); it->Next()) { 591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Count child entries. 592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (IsChildEntryKey(it->key())) { 593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++num_child_entries; 594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) continue; 595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Ignore cache entries. 598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (IsCacheEntryKey(it->key())) 599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check if stored data is broken. 602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!entry.ParseFromArray(it->value().data(), it->value().size()) || 603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entry.resource_id() != it->key()) { 604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Broken entry detected"; 605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!entry.parent_resource_id().empty()) { 609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check if the parent entry is stored. 610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Status status = resource_map_->Get( 611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options, 612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Slice(entry.parent_resource_id()), 613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &serialized_parent_entry); 614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!status.ok()) { 615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Can't get parent entry. status = " << status.ToString(); 616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check if parent-child relationship is stored correctly. 620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) status = resource_map_->Get( 621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options, 622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) leveldb::Slice(GetChildEntryKey(entry.parent_resource_id(), 623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entry.base_name())), 624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &child_resource_id); 625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!status.ok() || child_resource_id != entry.resource_id()) { 626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Child map is broken. status = " << status.ToString(); 627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++num_entries_with_parent; 630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!it->status().ok() || num_child_entries != num_entries_with_parent) { 633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(ERROR) << "Error during checking resource map. status = " 634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << it->status().ToString(); 635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace internal 641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace drive 642