drive: Stop checking free disk space in ResourceMetadata::Initialize

Instead, perform stricter error checks.

Stop calling EnoughDiskSpaceIsAvailableForDBOperation() in ResourceMetadata::Initialize().
To distinguish serious failures from not-found cases, change the return type of  ResourceMetadataStorage's methods to FileError.

BUG=319410
TEST=unit_tests

Review URL: https://codereview.chromium.org/265833003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269541 0039d316-1c4b-4281-b951-d872f2087c98
parent 761eea27
...@@ -74,7 +74,7 @@ bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const { ...@@ -74,7 +74,7 @@ bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const {
bool FileCache::GetCacheEntry(const std::string& id, FileCacheEntry* entry) { bool FileCache::GetCacheEntry(const std::string& id, FileCacheEntry* entry) {
DCHECK(entry); DCHECK(entry);
AssertOnSequencedWorkerPool(); AssertOnSequencedWorkerPool();
return storage_->GetCacheEntry(id, entry); return storage_->GetCacheEntry(id, entry) == FILE_ERROR_OK;
} }
scoped_ptr<FileCache::Iterator> FileCache::GetIterator() { scoped_ptr<FileCache::Iterator> FileCache::GetIterator() {
...@@ -102,7 +102,8 @@ bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { ...@@ -102,7 +102,8 @@ bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) {
!mounted_files_.count(it->GetID())) !mounted_files_.count(it->GetID()))
storage_->RemoveCacheEntry(it->GetID()); storage_->RemoveCacheEntry(it->GetID());
} }
DCHECK(!it->HasError()); if (it->HasError())
return false;
// Remove all files which have no corresponding cache entries. // Remove all files which have no corresponding cache entries.
base::FileEnumerator enumerator(cache_file_directory_, base::FileEnumerator enumerator(cache_file_directory_,
...@@ -112,8 +113,11 @@ bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { ...@@ -112,8 +113,11 @@ bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) {
for (base::FilePath current = enumerator.Next(); !current.empty(); for (base::FilePath current = enumerator.Next(); !current.empty();
current = enumerator.Next()) { current = enumerator.Next()) {
std::string id = GetIdFromPath(current); std::string id = GetIdFromPath(current);
if (!storage_->GetCacheEntry(id, &entry)) FileError error = storage_->GetCacheEntry(id, &entry);
if (error == FILE_ERROR_NOT_FOUND)
base::DeleteFile(current, false /* recursive */); base::DeleteFile(current, false /* recursive */);
else if (error != FILE_ERROR_OK)
return false;
} }
// Check the disk space again. // Check the disk space again.
...@@ -126,8 +130,10 @@ FileError FileCache::GetFile(const std::string& id, ...@@ -126,8 +130,10 @@ FileError FileCache::GetFile(const std::string& id,
DCHECK(cache_file_path); DCHECK(cache_file_path);
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
if (!storage_->GetCacheEntry(id, &cache_entry) || FileError error = storage_->GetCacheEntry(id, &cache_entry);
!cache_entry.is_present()) if (error != FILE_ERROR_OK)
return error;
if (!cache_entry.is_present())
return FILE_ERROR_NOT_FOUND; return FILE_ERROR_NOT_FOUND;
*cache_file_path = GetCacheFilePath(id); *cache_file_path = GetCacheFilePath(id);
...@@ -177,23 +183,25 @@ FileError FileCache::Store(const std::string& id, ...@@ -177,23 +183,25 @@ FileError FileCache::Store(const std::string& id,
// Now that file operations have completed, update metadata. // Now that file operations have completed, update metadata.
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
storage_->GetCacheEntry(id, &cache_entry); FileError error = storage_->GetCacheEntry(id, &cache_entry);
if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND)
return error;
cache_entry.set_md5(md5); cache_entry.set_md5(md5);
cache_entry.set_is_present(true); cache_entry.set_is_present(true);
if (md5.empty()) if (md5.empty())
cache_entry.set_is_dirty(true); cache_entry.set_is_dirty(true);
return storage_->PutCacheEntry(id, cache_entry) ? return storage_->PutCacheEntry(id, cache_entry);
FILE_ERROR_OK : FILE_ERROR_FAILED;
} }
FileError FileCache::Pin(const std::string& id) { FileError FileCache::Pin(const std::string& id) {
AssertOnSequencedWorkerPool(); AssertOnSequencedWorkerPool();
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
storage_->GetCacheEntry(id, &cache_entry); FileError error = storage_->GetCacheEntry(id, &cache_entry);
if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND)
return error;
cache_entry.set_is_pinned(true); cache_entry.set_is_pinned(true);
return storage_->PutCacheEntry(id, cache_entry) ? return storage_->PutCacheEntry(id, cache_entry);
FILE_ERROR_OK : FILE_ERROR_FAILED;
} }
FileError FileCache::Unpin(const std::string& id) { FileError FileCache::Unpin(const std::string& id) {
...@@ -201,18 +209,21 @@ FileError FileCache::Unpin(const std::string& id) { ...@@ -201,18 +209,21 @@ FileError FileCache::Unpin(const std::string& id) {
// Unpinning a file means its entry must exist in cache. // Unpinning a file means its entry must exist in cache.
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
if (!storage_->GetCacheEntry(id, &cache_entry)) FileError error = storage_->GetCacheEntry(id, &cache_entry);
return FILE_ERROR_NOT_FOUND; if (error != FILE_ERROR_OK)
return error;
// Now that file operations have completed, update metadata. // Now that file operations have completed, update metadata.
if (cache_entry.is_present()) { if (cache_entry.is_present()) {
cache_entry.set_is_pinned(false); cache_entry.set_is_pinned(false);
if (!storage_->PutCacheEntry(id, cache_entry)) error = storage_->PutCacheEntry(id, cache_entry);
return FILE_ERROR_FAILED; if (error != FILE_ERROR_OK)
return error;
} else { } else {
// Remove the existing entry if we are unpinning a non-present file. // Remove the existing entry if we are unpinning a non-present file.
if (!storage_->RemoveCacheEntry(id)) error = storage_->RemoveCacheEntry(id);
return FILE_ERROR_FAILED; if (error != FILE_ERROR_OK)
return error;
} }
// Now it's a chance to free up space if needed. // Now it's a chance to free up space if needed.
...@@ -228,8 +239,9 @@ FileError FileCache::MarkAsMounted(const std::string& id, ...@@ -228,8 +239,9 @@ FileError FileCache::MarkAsMounted(const std::string& id,
// Get cache entry associated with the id and md5 // Get cache entry associated with the id and md5
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
if (!storage_->GetCacheEntry(id, &cache_entry)) FileError error = storage_->GetCacheEntry(id, &cache_entry);
return FILE_ERROR_NOT_FOUND; if (error != FILE_ERROR_OK)
return error;
if (mounted_files_.count(id)) if (mounted_files_.count(id))
return FILE_ERROR_INVALID_OPERATION; return FILE_ERROR_INVALID_OPERATION;
...@@ -258,16 +270,19 @@ FileError FileCache::OpenForWrite( ...@@ -258,16 +270,19 @@ FileError FileCache::OpenForWrite(
// Marking a file dirty means its entry and actual file blob must exist in // Marking a file dirty means its entry and actual file blob must exist in
// cache. // cache.
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
if (!storage_->GetCacheEntry(id, &cache_entry) || FileError error = storage_->GetCacheEntry(id, &cache_entry);
!cache_entry.is_present()) { if (error != FILE_ERROR_OK)
return error;
if (!cache_entry.is_present()) {
LOG(WARNING) << "Can't mark dirty a file that wasn't cached: " << id; LOG(WARNING) << "Can't mark dirty a file that wasn't cached: " << id;
return FILE_ERROR_NOT_FOUND; return FILE_ERROR_NOT_FOUND;
} }
cache_entry.set_is_dirty(true); cache_entry.set_is_dirty(true);
cache_entry.clear_md5(); cache_entry.clear_md5();
if (!storage_->PutCacheEntry(id, cache_entry)) error = storage_->PutCacheEntry(id, cache_entry);
return FILE_ERROR_FAILED; if (error != FILE_ERROR_OK)
return error;
write_opened_files_[id]++; write_opened_files_[id]++;
file_closer->reset(new base::ScopedClosureRunner( file_closer->reset(new base::ScopedClosureRunner(
...@@ -291,8 +306,10 @@ FileError FileCache::UpdateMd5(const std::string& id) { ...@@ -291,8 +306,10 @@ FileError FileCache::UpdateMd5(const std::string& id) {
return FILE_ERROR_IN_USE; return FILE_ERROR_IN_USE;
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
if (!storage_->GetCacheEntry(id, &cache_entry) || FileError error = storage_->GetCacheEntry(id, &cache_entry);
!cache_entry.is_present()) if (error != FILE_ERROR_OK)
return error;
if (!cache_entry.is_present())
return FILE_ERROR_NOT_FOUND; return FILE_ERROR_NOT_FOUND;
const std::string& md5 = util::GetMd5Digest(GetCacheFilePath(id)); const std::string& md5 = util::GetMd5Digest(GetCacheFilePath(id));
...@@ -300,8 +317,7 @@ FileError FileCache::UpdateMd5(const std::string& id) { ...@@ -300,8 +317,7 @@ FileError FileCache::UpdateMd5(const std::string& id) {
return FILE_ERROR_NOT_FOUND; return FILE_ERROR_NOT_FOUND;
cache_entry.set_md5(md5); cache_entry.set_md5(md5);
return storage_->PutCacheEntry(id, cache_entry) ? return storage_->PutCacheEntry(id, cache_entry);
FILE_ERROR_OK : FILE_ERROR_FAILED;
} }
FileError FileCache::ClearDirty(const std::string& id) { FileError FileCache::ClearDirty(const std::string& id) {
...@@ -313,8 +329,10 @@ FileError FileCache::ClearDirty(const std::string& id) { ...@@ -313,8 +329,10 @@ FileError FileCache::ClearDirty(const std::string& id) {
// Clearing a dirty file means its entry and actual file blob must exist in // Clearing a dirty file means its entry and actual file blob must exist in
// cache. // cache.
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
if (!storage_->GetCacheEntry(id, &cache_entry) || FileError error = storage_->GetCacheEntry(id, &cache_entry);
!cache_entry.is_present()) { if (error != FILE_ERROR_OK)
return error;
if (!cache_entry.is_present()) {
LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: " LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: "
<< id; << id;
return FILE_ERROR_NOT_FOUND; return FILE_ERROR_NOT_FOUND;
...@@ -328,8 +346,7 @@ FileError FileCache::ClearDirty(const std::string& id) { ...@@ -328,8 +346,7 @@ FileError FileCache::ClearDirty(const std::string& id) {
} }
cache_entry.set_is_dirty(false); cache_entry.set_is_dirty(false);
return storage_->PutCacheEntry(id, cache_entry) ? return storage_->PutCacheEntry(id, cache_entry);
FILE_ERROR_OK : FILE_ERROR_FAILED;
} }
FileError FileCache::Remove(const std::string& id) { FileError FileCache::Remove(const std::string& id) {
...@@ -338,8 +355,11 @@ FileError FileCache::Remove(const std::string& id) { ...@@ -338,8 +355,11 @@ FileError FileCache::Remove(const std::string& id) {
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
// If entry doesn't exist, nothing to do. // If entry doesn't exist, nothing to do.
if (!storage_->GetCacheEntry(id, &cache_entry)) FileError error = storage_->GetCacheEntry(id, &cache_entry);
if (error == FILE_ERROR_NOT_FOUND)
return FILE_ERROR_OK; return FILE_ERROR_OK;
if (error != FILE_ERROR_OK)
return error;
// Cannot delete a mounted file. // Cannot delete a mounted file.
if (mounted_files_.count(id)) if (mounted_files_.count(id))
...@@ -351,7 +371,7 @@ FileError FileCache::Remove(const std::string& id) { ...@@ -351,7 +371,7 @@ FileError FileCache::Remove(const std::string& id) {
return FILE_ERROR_FAILED; return FILE_ERROR_FAILED;
// Now that all file operations have completed, remove from metadata. // Now that all file operations have completed, remove from metadata.
return storage_->RemoveCacheEntry(id) ? FILE_ERROR_OK : FILE_ERROR_FAILED; return storage_->RemoveCacheEntry(id);
} }
bool FileCache::ClearAll() { bool FileCache::ClearAll() {
...@@ -361,7 +381,7 @@ bool FileCache::ClearAll() { ...@@ -361,7 +381,7 @@ bool FileCache::ClearAll() {
scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
storage_->GetCacheEntryIterator(); storage_->GetCacheEntryIterator();
for (; !it->IsAtEnd(); it->Advance()) { for (; !it->IsAtEnd(); it->Advance()) {
if (!storage_->RemoveCacheEntry(it->GetID())) if (storage_->RemoveCacheEntry(it->GetID()) != FILE_ERROR_OK)
return false; return false;
} }
...@@ -390,10 +410,12 @@ bool FileCache::Initialize() { ...@@ -390,10 +410,12 @@ bool FileCache::Initialize() {
if (it->GetValue().is_dirty()) { if (it->GetValue().is_dirty()) {
FileCacheEntry new_entry(it->GetValue()); FileCacheEntry new_entry(it->GetValue());
new_entry.clear_md5(); new_entry.clear_md5();
if (!storage_->PutCacheEntry(it->GetID(), new_entry)) if (storage_->PutCacheEntry(it->GetID(), new_entry) != FILE_ERROR_OK)
return false; return false;
} }
} }
if (it->HasError())
return false;
if (!RenameCacheFilesToNewFormat()) if (!RenameCacheFilesToNewFormat())
return false; return false;
...@@ -429,10 +451,13 @@ bool FileCache::RecoverFilesFromCacheDirectory( ...@@ -429,10 +451,13 @@ bool FileCache::RecoverFilesFromCacheDirectory(
current = enumerator.Next()) { current = enumerator.Next()) {
const std::string& id = GetIdFromPath(current); const std::string& id = GetIdFromPath(current);
FileCacheEntry entry; FileCacheEntry entry;
if (storage_->GetCacheEntry(id, &entry)) { FileError error = storage_->GetCacheEntry(id, &entry);
if (error == FILE_ERROR_OK) {
// This file is managed by FileCache, no need to recover it. // This file is managed by FileCache, no need to recover it.
continue; continue;
} }
if (error != FILE_ERROR_NOT_FOUND)
return false;
// If a cache entry which is non-dirty and has matching MD5 is found in // If a cache entry which is non-dirty and has matching MD5 is found in
// |recovered_cache_entries|, it means the current file is already uploaded // |recovered_cache_entries|, it means the current file is already uploaded
...@@ -517,8 +542,9 @@ FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) { ...@@ -517,8 +542,9 @@ FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) {
// Get cache entry associated with the id and md5 // Get cache entry associated with the id and md5
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
if (!storage_->GetCacheEntry(id, &cache_entry)) FileError error = storage_->GetCacheEntry(id, &cache_entry);
return FILE_ERROR_NOT_FOUND; if (error != FILE_ERROR_OK)
return error;
std::set<std::string>::iterator it = mounted_files_.find(id); std::set<std::string>::iterator it = mounted_files_.find(id);
if (it == mounted_files_.end()) if (it == mounted_files_.end())
......
...@@ -38,13 +38,21 @@ std::string GetUniquifiedName(const std::string& name, int uniquifier) { ...@@ -38,13 +38,21 @@ std::string GetUniquifiedName(const std::string& name, int uniquifier) {
// Returns true when there is no entry with the specified name under the parent // Returns true when there is no entry with the specified name under the parent
// other than the specified entry. // other than the specified entry.
bool EntryCanUseName(ResourceMetadataStorage* storage, FileError EntryCanUseName(ResourceMetadataStorage* storage,
const std::string& parent_local_id, const std::string& parent_local_id,
const std::string& local_id, const std::string& local_id,
const std::string& base_name) { const std::string& base_name,
const std::string existing_entry_id = storage->GetChild(parent_local_id, bool* result) {
base_name); std::string existing_entry_id;
return existing_entry_id.empty() || existing_entry_id == local_id; FileError error = storage->GetChild(parent_local_id, base_name,
&existing_entry_id);
if (error == FILE_ERROR_OK)
*result = existing_entry_id == local_id;
else if (error == FILE_ERROR_NOT_FOUND)
*result = true;
else
return error;
return FILE_ERROR_OK;
} }
} // namespace } // namespace
...@@ -59,14 +67,7 @@ ResourceMetadata::ResourceMetadata( ...@@ -59,14 +67,7 @@ ResourceMetadata::ResourceMetadata(
FileError ResourceMetadata::Initialize() { FileError ResourceMetadata::Initialize() {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
return SetUpDefaultEntries();
if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
return FILE_ERROR_NO_LOCAL_SPACE;
if (!SetUpDefaultEntries())
return FILE_ERROR_FAILED;
return FILE_ERROR_OK;
} }
void ResourceMetadata::Destroy() { void ResourceMetadata::Destroy() {
...@@ -84,84 +85,112 @@ FileError ResourceMetadata::Reset() { ...@@ -84,84 +85,112 @@ FileError ResourceMetadata::Reset() {
if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path())) if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
return FILE_ERROR_NO_LOCAL_SPACE; return FILE_ERROR_NO_LOCAL_SPACE;
if (!storage_->SetLargestChangestamp(0)) FileError error = storage_->SetLargestChangestamp(0);
return FILE_ERROR_FAILED; if (error != FILE_ERROR_OK)
return error;
// Remove all root entries. // Remove all root entries.
scoped_ptr<Iterator> it = GetIterator(); scoped_ptr<Iterator> it = GetIterator();
for (; !it->IsAtEnd(); it->Advance()) { for (; !it->IsAtEnd(); it->Advance()) {
if (it->GetValue().parent_local_id().empty()) { if (it->GetValue().parent_local_id().empty()) {
if (!RemoveEntryRecursively(it->GetID())) error = RemoveEntryRecursively(it->GetID());
return FILE_ERROR_FAILED; if (error != FILE_ERROR_OK)
return error;
} }
} }
if (it->HasError()) if (it->HasError())
return FILE_ERROR_FAILED; return FILE_ERROR_FAILED;
if (!SetUpDefaultEntries()) return SetUpDefaultEntries();
return FILE_ERROR_FAILED;
return FILE_ERROR_OK;
} }
ResourceMetadata::~ResourceMetadata() { ResourceMetadata::~ResourceMetadata() {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
} }
bool ResourceMetadata::SetUpDefaultEntries() { FileError ResourceMetadata::SetUpDefaultEntries() {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
// Initialize "/drive", "/drive/other", "drive/trash" and "drive/root". // Initialize "/drive".
ResourceEntry entry; ResourceEntry entry;
if (!storage_->GetEntry(util::kDriveGrandRootLocalId, &entry)) { FileError error = storage_->GetEntry(util::kDriveGrandRootLocalId, &entry);
if (error == FILE_ERROR_NOT_FOUND) {
ResourceEntry root; ResourceEntry root;
root.mutable_file_info()->set_is_directory(true); root.mutable_file_info()->set_is_directory(true);
root.set_local_id(util::kDriveGrandRootLocalId); root.set_local_id(util::kDriveGrandRootLocalId);
root.set_title(util::kDriveGrandRootDirName); root.set_title(util::kDriveGrandRootDirName);
root.set_base_name(util::kDriveGrandRootDirName); root.set_base_name(util::kDriveGrandRootDirName);
if (!storage_->PutEntry(root)) error = storage_->PutEntry(root);
return false; if (error != FILE_ERROR_OK)
} else if (!entry.resource_id().empty()) { return error;
} else if (error == FILE_ERROR_OK) {
if (!entry.resource_id().empty()) {
// Old implementations used kDriveGrandRootLocalId as a resource ID. // Old implementations used kDriveGrandRootLocalId as a resource ID.
entry.clear_resource_id(); entry.clear_resource_id();
if (!storage_->PutEntry(entry)) error = storage_->PutEntry(entry);
return false; if (error != FILE_ERROR_OK)
return error;
} }
if (!storage_->GetEntry(util::kDriveOtherDirLocalId, &entry)) { } else {
return error;
}
// Initialize "/drive/other".
error = storage_->GetEntry(util::kDriveOtherDirLocalId, &entry);
if (error == FILE_ERROR_NOT_FOUND) {
ResourceEntry other_dir; ResourceEntry other_dir;
other_dir.mutable_file_info()->set_is_directory(true); other_dir.mutable_file_info()->set_is_directory(true);
other_dir.set_local_id(util::kDriveOtherDirLocalId); other_dir.set_local_id(util::kDriveOtherDirLocalId);
other_dir.set_parent_local_id(util::kDriveGrandRootLocalId); other_dir.set_parent_local_id(util::kDriveGrandRootLocalId);
other_dir.set_title(util::kDriveOtherDirName); other_dir.set_title(util::kDriveOtherDirName);
if (!PutEntryUnderDirectory(other_dir)) error = PutEntryUnderDirectory(other_dir);
return false; if (error != FILE_ERROR_OK)
} else if (!entry.resource_id().empty()) { return error;
} else if (error == FILE_ERROR_OK) {
if (!entry.resource_id().empty()) {
// Old implementations used kDriveOtherDirLocalId as a resource ID. // Old implementations used kDriveOtherDirLocalId as a resource ID.
entry.clear_resource_id(); entry.clear_resource_id();
if (!storage_->PutEntry(entry)) error = storage_->PutEntry(entry);
return false; if (error != FILE_ERROR_OK)
return error;
}
} else {
return error;
} }
if (!storage_->GetEntry(util::kDriveTrashDirLocalId, &entry)) {
// Initialize "drive/trash".
error = storage_->GetEntry(util::kDriveTrashDirLocalId, &entry);
if (error == FILE_ERROR_NOT_FOUND) {
ResourceEntry trash_dir; ResourceEntry trash_dir;
trash_dir.mutable_file_info()->set_is_directory(true); trash_dir.mutable_file_info()->set_is_directory(true);
trash_dir.set_local_id(util::kDriveTrashDirLocalId); trash_dir.set_local_id(util::kDriveTrashDirLocalId);
trash_dir.set_parent_local_id(util::kDriveGrandRootLocalId); trash_dir.set_parent_local_id(util::kDriveGrandRootLocalId);
trash_dir.set_title(util::kDriveTrashDirName); trash_dir.set_title(util::kDriveTrashDirName);
if (!PutEntryUnderDirectory(trash_dir)) error = PutEntryUnderDirectory(trash_dir);
return false; if (error != FILE_ERROR_OK)
return error;
} else if (error != FILE_ERROR_OK) {
return error;
} }
if (storage_->GetChild(util::kDriveGrandRootLocalId,
util::kDriveMyDriveRootDirName).empty()) { // Initialize "drive/root".
std::string child_id;
error = storage_->GetChild(
util::kDriveGrandRootLocalId, util::kDriveMyDriveRootDirName, &child_id);
if (error == FILE_ERROR_NOT_FOUND) {
ResourceEntry mydrive; ResourceEntry mydrive;
mydrive.mutable_file_info()->set_is_directory(true); mydrive.mutable_file_info()->set_is_directory(true);
mydrive.set_parent_local_id(util::kDriveGrandRootLocalId); mydrive.set_parent_local_id(util::kDriveGrandRootLocalId);
mydrive.set_title(util::kDriveMyDriveRootDirName); mydrive.set_title(util::kDriveMyDriveRootDirName);
std::string local_id; std::string local_id;
if (AddEntry(mydrive, &local_id) != FILE_ERROR_OK) error = AddEntry(mydrive, &local_id);
return false; if (error != FILE_ERROR_OK)
return error;
} else if (error != FILE_ERROR_OK) {
return error;
} }
return true; return FILE_ERROR_OK;
} }
void ResourceMetadata::DestroyOnBlockingPool() { void ResourceMetadata::DestroyOnBlockingPool() {
...@@ -171,7 +200,9 @@ void ResourceMetadata::DestroyOnBlockingPool() { ...@@ -171,7 +200,9 @@ void ResourceMetadata::DestroyOnBlockingPool() {
int64 ResourceMetadata::GetLargestChangestamp() { int64 ResourceMetadata::GetLargestChangestamp() {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
return storage_->GetLargestChangestamp(); int64 value = 0;
storage_->GetLargestChangestamp(&value);
return value;
} }
FileError ResourceMetadata::SetLargestChangestamp(int64 value) { FileError ResourceMetadata::SetLargestChangestamp(int64 value) {
...@@ -180,8 +211,7 @@ FileError ResourceMetadata::SetLargestChangestamp(int64 value) { ...@@ -180,8 +211,7 @@ FileError ResourceMetadata::SetLargestChangestamp(int64 value) {
if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path())) if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
return FILE_ERROR_NO_LOCAL_SPACE; return FILE_ERROR_NO_LOCAL_SPACE;
return storage_->SetLargestChangestamp(value) ? return storage_->SetLargestChangestamp(value);
FILE_ERROR_OK : FILE_ERROR_FAILED;
} }
FileError ResourceMetadata::AddEntry(const ResourceEntry& entry, FileError ResourceMetadata::AddEntry(const ResourceEntry& entry,
...@@ -193,27 +223,37 @@ FileError ResourceMetadata::AddEntry(const ResourceEntry& entry, ...@@ -193,27 +223,37 @@ FileError ResourceMetadata::AddEntry(const ResourceEntry& entry,
return FILE_ERROR_NO_LOCAL_SPACE; return FILE_ERROR_NO_LOCAL_SPACE;
ResourceEntry parent; ResourceEntry parent;
if (!storage_->GetEntry(entry.parent_local_id(), &parent) || FileError error = storage_->GetEntry(entry.parent_local_id(), &parent);
!parent.file_info().is_directory()) if (error != FILE_ERROR_OK)
return FILE_ERROR_NOT_FOUND; return error;
if (!parent.file_info().is_directory())
return FILE_ERROR_NOT_A_DIRECTORY;
// Multiple entries with the same resource ID should not be present. // Multiple entries with the same resource ID should not be present.
std::string local_id; std::string local_id;
ResourceEntry existing_entry; ResourceEntry existing_entry;
if (!entry.resource_id().empty() && if (!entry.resource_id().empty()) {
storage_->GetIdByResourceId(entry.resource_id(), &local_id) && error = storage_->GetIdByResourceId(entry.resource_id(), &local_id);
storage_->GetEntry(local_id, &existing_entry)) if (error == FILE_ERROR_OK)
error = storage_->GetEntry(local_id, &existing_entry);
if (error == FILE_ERROR_OK)
return FILE_ERROR_EXISTS; return FILE_ERROR_EXISTS;
else if (error != FILE_ERROR_NOT_FOUND)
return error;
}
// Generate unique local ID when needed. // Generate unique local ID when needed.
while (local_id.empty() || storage_->GetEntry(local_id, &existing_entry)) // We don't check for ID collisions as its probability is extremely low.
if (local_id.empty())
local_id = base::GenerateGUID(); local_id = base::GenerateGUID();
ResourceEntry new_entry(entry); ResourceEntry new_entry(entry);
new_entry.set_local_id(local_id); new_entry.set_local_id(local_id);
if (!PutEntryUnderDirectory(new_entry)) error = PutEntryUnderDirectory(new_entry);
return FILE_ERROR_FAILED; if (error != FILE_ERROR_OK)
return error;
*out_id = local_id; *out_id = local_id;
return FILE_ERROR_OK; return FILE_ERROR_OK;
...@@ -232,12 +272,11 @@ FileError ResourceMetadata::RemoveEntry(const std::string& id) { ...@@ -232,12 +272,11 @@ FileError ResourceMetadata::RemoveEntry(const std::string& id) {
return FILE_ERROR_ACCESS_DENIED; return FILE_ERROR_ACCESS_DENIED;
ResourceEntry entry; ResourceEntry entry;
if (!storage_->GetEntry(id, &entry)) FileError error = storage_->GetEntry(id, &entry);
return FILE_ERROR_NOT_FOUND; if (error != FILE_ERROR_OK)
return error;
if (!RemoveEntryRecursively(id)) return RemoveEntryRecursively(id);
return FILE_ERROR_FAILED;
return FILE_ERROR_OK;
} }
FileError ResourceMetadata::GetResourceEntryById(const std::string& id, FileError ResourceMetadata::GetResourceEntryById(const std::string& id,
...@@ -246,8 +285,7 @@ FileError ResourceMetadata::GetResourceEntryById(const std::string& id, ...@@ -246,8 +285,7 @@ FileError ResourceMetadata::GetResourceEntryById(const std::string& id,
DCHECK(!id.empty()); DCHECK(!id.empty());
DCHECK(out_entry); DCHECK(out_entry);
return storage_->GetEntry(id, out_entry) ? return storage_->GetEntry(id, out_entry);
FILE_ERROR_OK : FILE_ERROR_NOT_FOUND;
} }
FileError ResourceMetadata::GetResourceEntryByPath(const base::FilePath& path, FileError ResourceMetadata::GetResourceEntryByPath(const base::FilePath& path,
...@@ -291,12 +329,15 @@ FileError ResourceMetadata::ReadDirectoryById( ...@@ -291,12 +329,15 @@ FileError ResourceMetadata::ReadDirectoryById(
return FILE_ERROR_NOT_A_DIRECTORY; return FILE_ERROR_NOT_A_DIRECTORY;
std::vector<std::string> children; std::vector<std::string> children;
storage_->GetChildren(id, &children); error = storage_->GetChildren(id, &children);
if (error != FILE_ERROR_OK)
return error;
ResourceEntryVector entries(children.size()); ResourceEntryVector entries(children.size());
for (size_t i = 0; i < children.size(); ++i) { for (size_t i = 0; i < children.size(); ++i) {
if (!storage_->GetEntry(children[i], &entries[i])) error = storage_->GetEntry(children[i], &entries[i]);
return FILE_ERROR_FAILED; if (error != FILE_ERROR_OK)
return error;
} }
out_entries->swap(entries); out_entries->swap(entries);
return FILE_ERROR_OK; return FILE_ERROR_OK;
...@@ -309,8 +350,9 @@ FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) { ...@@ -309,8 +350,9 @@ FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) {
return FILE_ERROR_NO_LOCAL_SPACE; return FILE_ERROR_NO_LOCAL_SPACE;
ResourceEntry old_entry; ResourceEntry old_entry;
if (!storage_->GetEntry(entry.local_id(), &old_entry)) FileError error = storage_->GetEntry(entry.local_id(), &old_entry);
return FILE_ERROR_NOT_FOUND; if (error != FILE_ERROR_OK)
return error;
if (old_entry.parent_local_id().empty() || // Reject root. if (old_entry.parent_local_id().empty() || // Reject root.
old_entry.file_info().is_directory() != // Reject incompatible input. old_entry.file_info().is_directory() != // Reject incompatible input.
...@@ -337,16 +379,15 @@ FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) { ...@@ -337,16 +379,15 @@ FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) {
// Make sure that the new parent exists and it is a directory. // Make sure that the new parent exists and it is a directory.
ResourceEntry new_parent; ResourceEntry new_parent;
if (!storage_->GetEntry(entry.parent_local_id(), &new_parent)) error = storage_->GetEntry(entry.parent_local_id(), &new_parent);
return FILE_ERROR_NOT_FOUND; if (error != FILE_ERROR_OK)
return error;
if (!new_parent.file_info().is_directory()) if (!new_parent.file_info().is_directory())
return FILE_ERROR_NOT_A_DIRECTORY; return FILE_ERROR_NOT_A_DIRECTORY;
// Remove from the old parent and add it to the new parent with the new data. // Remove from the old parent and add it to the new parent with the new data.
if (!PutEntryUnderDirectory(entry)) return PutEntryUnderDirectory(entry);
return FILE_ERROR_FAILED;
return FILE_ERROR_OK;
} }
void ResourceMetadata::GetSubDirectoriesRecursively( void ResourceMetadata::GetSubDirectoriesRecursively(
...@@ -355,11 +396,13 @@ void ResourceMetadata::GetSubDirectoriesRecursively( ...@@ -355,11 +396,13 @@ void ResourceMetadata::GetSubDirectoriesRecursively(
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
std::vector<std::string> children; std::vector<std::string> children;
storage_->GetChildren(id, &children); if (storage_->GetChildren(id, &children) != FILE_ERROR_OK)
return;
for (size_t i = 0; i < children.size(); ++i) { for (size_t i = 0; i < children.size(); ++i) {
ResourceEntry entry; ResourceEntry entry;
if (storage_->GetEntry(children[i], &entry) && if (storage_->GetEntry(children[i], &entry) != FILE_ERROR_OK)
entry.file_info().is_directory()) { return;
if (entry.file_info().is_directory()) {
sub_directories->insert(GetFilePath(children[i])); sub_directories->insert(GetFilePath(children[i]));
GetSubDirectoriesRecursively(children[i], sub_directories); GetSubDirectoriesRecursively(children[i], sub_directories);
} }
...@@ -369,7 +412,9 @@ void ResourceMetadata::GetSubDirectoriesRecursively( ...@@ -369,7 +412,9 @@ void ResourceMetadata::GetSubDirectoriesRecursively(
std::string ResourceMetadata::GetChildId(const std::string& parent_local_id, std::string ResourceMetadata::GetChildId(const std::string& parent_local_id,
const std::string& base_name) { const std::string& base_name) {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
return storage_->GetChild(parent_local_id, base_name); std::string child_local_id;
storage_->GetChild(parent_local_id, base_name, &child_local_id);
return child_local_id;
} }
scoped_ptr<ResourceMetadata::Iterator> ResourceMetadata::GetIterator() { scoped_ptr<ResourceMetadata::Iterator> ResourceMetadata::GetIterator() {
...@@ -383,7 +428,7 @@ base::FilePath ResourceMetadata::GetFilePath(const std::string& id) { ...@@ -383,7 +428,7 @@ base::FilePath ResourceMetadata::GetFilePath(const std::string& id) {
base::FilePath path; base::FilePath path;
ResourceEntry entry; ResourceEntry entry;
if (storage_->GetEntry(id, &entry)) { if (storage_->GetEntry(id, &entry) == FILE_ERROR_OK) {
if (!entry.parent_local_id().empty()) { if (!entry.parent_local_id().empty()) {
path = GetFilePath(entry.parent_local_id()); path = GetFilePath(entry.parent_local_id());
} else if (entry.local_id() != util::kDriveGrandRootLocalId) { } else if (entry.local_id() != util::kDriveGrandRootLocalId) {
...@@ -409,9 +454,11 @@ FileError ResourceMetadata::GetIdByPath(const base::FilePath& file_path, ...@@ -409,9 +454,11 @@ FileError ResourceMetadata::GetIdByPath(const base::FilePath& file_path,
std::string id = util::kDriveGrandRootLocalId; std::string id = util::kDriveGrandRootLocalId;
for (size_t i = 1; i < components.size(); ++i) { for (size_t i = 1; i < components.size(); ++i) {
const std::string component = base::FilePath(components[i]).AsUTF8Unsafe(); const std::string component = base::FilePath(components[i]).AsUTF8Unsafe();
id = storage_->GetChild(id, component); std::string child_id;
if (id.empty()) FileError error = storage_->GetChild(id, component, &child_id);
return FILE_ERROR_NOT_FOUND; if (error != FILE_ERROR_OK)
return error;
id = child_id;
} }
*out_id = id; *out_id = id;
return FILE_ERROR_OK; return FILE_ERROR_OK;
...@@ -420,23 +467,26 @@ FileError ResourceMetadata::GetIdByPath(const base::FilePath& file_path, ...@@ -420,23 +467,26 @@ FileError ResourceMetadata::GetIdByPath(const base::FilePath& file_path,
FileError ResourceMetadata::GetIdByResourceId(const std::string& resource_id, FileError ResourceMetadata::GetIdByResourceId(const std::string& resource_id,
std::string* out_local_id) { std::string* out_local_id) {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
return storage_->GetIdByResourceId(resource_id, out_local_id);
return storage_->GetIdByResourceId(resource_id, out_local_id) ?
FILE_ERROR_OK : FILE_ERROR_NOT_FOUND;
} }
bool ResourceMetadata::PutEntryUnderDirectory(const ResourceEntry& entry) { FileError ResourceMetadata::PutEntryUnderDirectory(const ResourceEntry& entry) {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
DCHECK(!entry.local_id().empty()); DCHECK(!entry.local_id().empty());
DCHECK(!entry.parent_local_id().empty()); DCHECK(!entry.parent_local_id().empty());
std::string base_name;
FileError error = GetDeduplicatedBaseName(entry, &base_name);
if (error != FILE_ERROR_OK)
return error;
ResourceEntry updated_entry(entry); ResourceEntry updated_entry(entry);
updated_entry.set_base_name(GetDeduplicatedBaseName(updated_entry)); updated_entry.set_base_name(base_name);
return storage_->PutEntry(updated_entry); return storage_->PutEntry(updated_entry);
} }
std::string ResourceMetadata::GetDeduplicatedBaseName( FileError ResourceMetadata::GetDeduplicatedBaseName(
const ResourceEntry& entry) { const ResourceEntry& entry,
std::string* base_name) {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
DCHECK(!entry.parent_local_id().empty()); DCHECK(!entry.parent_local_id().empty());
DCHECK(!entry.title().empty()); DCHECK(!entry.title().empty());
...@@ -444,24 +494,31 @@ std::string ResourceMetadata::GetDeduplicatedBaseName( ...@@ -444,24 +494,31 @@ std::string ResourceMetadata::GetDeduplicatedBaseName(
// The entry name may have been changed due to prior name de-duplication. // The entry name may have been changed due to prior name de-duplication.
// We need to first restore the file name based on the title before going // We need to first restore the file name based on the title before going
// through name de-duplication again when it is added to another directory. // through name de-duplication again when it is added to another directory.
std::string base_name = entry.title(); *base_name = entry.title();
if (entry.has_file_specific_info() && if (entry.has_file_specific_info() &&
entry.file_specific_info().is_hosted_document()) { entry.file_specific_info().is_hosted_document()) {
base_name += entry.file_specific_info().document_extension(); *base_name += entry.file_specific_info().document_extension();
} }
base_name = util::NormalizeFileName(base_name); *base_name = util::NormalizeFileName(*base_name);
// If |base_name| is not used, just return it. // If |base_name| is not used, just return it.
if (EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(), bool can_use_name = false;
base_name)) FileError error = EntryCanUseName(storage_, entry.parent_local_id(),
return base_name; entry.local_id(), *base_name,
&can_use_name);
if (error != FILE_ERROR_OK || can_use_name)
return error;
// Find an unused number with binary search. // Find an unused number with binary search.
int smallest_known_unused_modifier = 1; int smallest_known_unused_modifier = 1;
while (true) { while (true) {
if (EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(), error = EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(),
GetUniquifiedName(base_name, GetUniquifiedName(*base_name,
smallest_known_unused_modifier))) smallest_known_unused_modifier),
&can_use_name);
if (error != FILE_ERROR_OK)
return error;
if (can_use_name)
break; break;
const int delta = base::RandInt(1, smallest_known_unused_modifier); const int delta = base::RandInt(1, smallest_known_unused_modifier);
...@@ -477,29 +534,36 @@ std::string ResourceMetadata::GetDeduplicatedBaseName( ...@@ -477,29 +534,36 @@ std::string ResourceMetadata::GetDeduplicatedBaseName(
const int modifier = largest_known_used_modifier + const int modifier = largest_known_used_modifier +
(smallest_known_unused_modifier - largest_known_used_modifier) / 2; (smallest_known_unused_modifier - largest_known_used_modifier) / 2;
if (EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(), error = EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(),
GetUniquifiedName(base_name, modifier))) { GetUniquifiedName(*base_name, modifier),
&can_use_name);
if (error != FILE_ERROR_OK)
return error;
if (can_use_name) {
smallest_known_unused_modifier = modifier; smallest_known_unused_modifier = modifier;
} else { } else {
largest_known_used_modifier = modifier; largest_known_used_modifier = modifier;
} }
} }
return GetUniquifiedName(base_name, smallest_known_unused_modifier); *base_name = GetUniquifiedName(*base_name, smallest_known_unused_modifier);
return FILE_ERROR_OK;
} }
bool ResourceMetadata::RemoveEntryRecursively(const std::string& id) { FileError ResourceMetadata::RemoveEntryRecursively(const std::string& id) {
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
ResourceEntry entry; ResourceEntry entry;
if (!storage_->GetEntry(id, &entry)) FileError error = storage_->GetEntry(id, &entry);
return false; if (error != FILE_ERROR_OK)
return error;
if (entry.file_info().is_directory()) { if (entry.file_info().is_directory()) {
std::vector<std::string> children; std::vector<std::string> children;
storage_->GetChildren(id, &children); storage_->GetChildren(id, &children);
for (size_t i = 0; i < children.size(); ++i) { for (size_t i = 0; i < children.size(); ++i) {
if (!RemoveEntryRecursively(children[i])) error = RemoveEntryRecursively(children[i]);
return false; if (error != FILE_ERROR_OK)
return error;
} }
} }
return storage_->RemoveEntry(id); return storage_->RemoveEntry(id);
......
...@@ -106,7 +106,7 @@ class ResourceMetadata { ...@@ -106,7 +106,7 @@ class ResourceMetadata {
~ResourceMetadata(); ~ResourceMetadata();
// Sets up entries which should be present by default. // Sets up entries which should be present by default.
bool SetUpDefaultEntries(); FileError SetUpDefaultEntries();
// Used to implement Destroy(). // Used to implement Destroy().
void DestroyOnBlockingPool(); void DestroyOnBlockingPool();
...@@ -115,13 +115,14 @@ class ResourceMetadata { ...@@ -115,13 +115,14 @@ class ResourceMetadata {
// parent if there is. This method will also do name de-duplication to ensure // parent if there is. This method will also do name de-duplication to ensure
// that the exposed presentation path does not have naming conflicts. Two // that the exposed presentation path does not have naming conflicts. Two
// files with the same name "Foo" will be renamed to "Foo (1)" and "Foo (2)". // files with the same name "Foo" will be renamed to "Foo (1)" and "Foo (2)".
bool PutEntryUnderDirectory(const ResourceEntry& entry); FileError PutEntryUnderDirectory(const ResourceEntry& entry);
// Returns an unused base name for |entry|. // Returns an unused base name for |entry|.
std::string GetDeduplicatedBaseName(const ResourceEntry& entry); FileError GetDeduplicatedBaseName(const ResourceEntry& entry,
std::string* base_name);
// Removes the entry and its descendants. // Removes the entry and its descendants.
bool RemoveEntryRecursively(const std::string& id); FileError RemoveEntryRecursively(const std::string& id);
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "chrome/browser/chromeos/drive/drive.pb.h" #include "chrome/browser/chromeos/drive/drive.pb.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h" #include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
...@@ -126,7 +127,7 @@ bool IsIdEntryKey(const leveldb::Slice& key) { ...@@ -126,7 +127,7 @@ bool IsIdEntryKey(const leveldb::Slice& key) {
} }
// Converts leveldb::Status to DBInitStatus. // Converts leveldb::Status to DBInitStatus.
DBInitStatus LevelDBStatusToDBInitStatus(const leveldb::Status status) { DBInitStatus LevelDBStatusToDBInitStatus(const leveldb::Status& status) {
if (status.ok()) if (status.ok())
return DB_INIT_SUCCESS; return DB_INIT_SUCCESS;
if (status.IsNotFound()) if (status.IsNotFound())
...@@ -138,6 +139,17 @@ DBInitStatus LevelDBStatusToDBInitStatus(const leveldb::Status status) { ...@@ -138,6 +139,17 @@ DBInitStatus LevelDBStatusToDBInitStatus(const leveldb::Status status) {
return DB_INIT_FAILED; return DB_INIT_FAILED;
} }
// Converts leveldb::Status to FileError.
FileError LevelDBStatusToFileError(const leveldb::Status& status) {
if (status.ok())
return FILE_ERROR_OK;
if (status.IsNotFound())
return FILE_ERROR_NOT_FOUND;
if (leveldb_env::IndicatesDiskFull(status))
return FILE_ERROR_NO_LOCAL_SPACE;
return FILE_ERROR_FAILED;
}
ResourceMetadataHeader GetDefaultHeaderEntry() { ResourceMetadataHeader GetDefaultHeaderEntry() {
ResourceMetadataHeader header; ResourceMetadataHeader header;
header.set_version(ResourceMetadataStorage::kDBVersion); header.set_version(ResourceMetadataStorage::kDBVersion);
...@@ -439,7 +451,7 @@ bool ResourceMetadataStorage::Initialize() { ...@@ -439,7 +451,7 @@ bool ResourceMetadataStorage::Initialize() {
// Check the validity of existing DB. // Check the validity of existing DB.
int db_version = -1; int db_version = -1;
ResourceMetadataHeader header; ResourceMetadataHeader header;
if (GetHeader(&header)) if (GetHeader(&header) == FILE_ERROR_OK)
db_version = header.version(); db_version = header.version();
bool should_discard_db = true; bool should_discard_db = true;
...@@ -481,8 +493,9 @@ bool ResourceMetadataStorage::Initialize() { ...@@ -481,8 +493,9 @@ bool ResourceMetadataStorage::Initialize() {
if (status.ok()) { if (status.ok()) {
resource_map_.reset(db); resource_map_.reset(db);
if (PutHeader(GetDefaultHeaderEntry()) && // Set up header. // Set up header and trash the old DB.
MoveIfPossible(preserved_resource_map_path, // Trash the old DB. if (PutHeader(GetDefaultHeaderEntry()) == FILE_ERROR_OK &&
MoveIfPossible(preserved_resource_map_path,
trashed_resource_map_path)) { trashed_resource_map_path)) {
init_result = open_existing_result == DB_INIT_NOT_FOUND ? init_result = open_existing_result == DB_INIT_NOT_FOUND ?
DB_INIT_CREATED_NEW_DB : DB_INIT_REPLACED_EXISTING_DB_WITH_NEW_DB; DB_INIT_CREATED_NEW_DB : DB_INIT_REPLACED_EXISTING_DB_WITH_NEW_DB;
...@@ -569,30 +582,34 @@ void ResourceMetadataStorage::RecoverCacheInfoFromTrashedResourceMap( ...@@ -569,30 +582,34 @@ void ResourceMetadataStorage::RecoverCacheInfoFromTrashedResourceMap(
} }
} }
bool ResourceMetadataStorage::SetLargestChangestamp( FileError ResourceMetadataStorage::SetLargestChangestamp(
int64 largest_changestamp) { int64 largest_changestamp) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
ResourceMetadataHeader header; ResourceMetadataHeader header;
if (!GetHeader(&header)) { FileError error = GetHeader(&header);
if (error != FILE_ERROR_OK) {
DLOG(ERROR) << "Failed to get the header."; DLOG(ERROR) << "Failed to get the header.";
return false; return error;
} }
header.set_largest_changestamp(largest_changestamp); header.set_largest_changestamp(largest_changestamp);
return PutHeader(header); return PutHeader(header);
} }
int64 ResourceMetadataStorage::GetLargestChangestamp() { FileError ResourceMetadataStorage::GetLargestChangestamp(
int64* largest_changestamp) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
ResourceMetadataHeader header; ResourceMetadataHeader header;
if (!GetHeader(&header)) { FileError error = GetHeader(&header);
if (error != FILE_ERROR_OK) {
DLOG(ERROR) << "Failed to get the header."; DLOG(ERROR) << "Failed to get the header.";
return 0; return error;
} }
return header.largest_changestamp(); *largest_changestamp = header.largest_changestamp();
return FILE_ERROR_OK;
} }
bool ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) { FileError ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
const std::string& id = entry.local_id(); const std::string& id = entry.local_id();
...@@ -604,11 +621,11 @@ bool ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) { ...@@ -604,11 +621,11 @@ bool ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) {
leveldb::Slice(id), leveldb::Slice(id),
&serialized_entry); &serialized_entry);
if (!status.ok() && !status.IsNotFound()) // Unexpected errors. if (!status.ok() && !status.IsNotFound()) // Unexpected errors.
return false; return LevelDBStatusToFileError(status);
ResourceEntry old_entry; ResourceEntry old_entry;
if (status.ok() && !old_entry.ParseFromString(serialized_entry)) if (status.ok() && !old_entry.ParseFromString(serialized_entry))
return false; return FILE_ERROR_FAILED;
// Construct write batch. // Construct write batch.
leveldb::WriteBatch batch; leveldb::WriteBatch batch;
...@@ -636,15 +653,15 @@ bool ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) { ...@@ -636,15 +653,15 @@ bool ResourceMetadataStorage::PutEntry(const ResourceEntry& entry) {
// Put the entry itself. // Put the entry itself.
if (!entry.SerializeToString(&serialized_entry)) { if (!entry.SerializeToString(&serialized_entry)) {
DLOG(ERROR) << "Failed to serialize the entry: " << id; DLOG(ERROR) << "Failed to serialize the entry: " << id;
return false; return FILE_ERROR_FAILED;
} }
batch.Put(id, serialized_entry); batch.Put(id, serialized_entry);
status = resource_map_->Write(leveldb::WriteOptions(), &batch); status = resource_map_->Write(leveldb::WriteOptions(), &batch);
return status.ok(); return LevelDBStatusToFileError(status);
} }
bool ResourceMetadataStorage::GetEntry(const std::string& id, FileError ResourceMetadataStorage::GetEntry(const std::string& id,
ResourceEntry* out_entry) { ResourceEntry* out_entry) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
DCHECK(!id.empty()); DCHECK(!id.empty());
...@@ -653,16 +670,20 @@ bool ResourceMetadataStorage::GetEntry(const std::string& id, ...@@ -653,16 +670,20 @@ bool ResourceMetadataStorage::GetEntry(const std::string& id,
const leveldb::Status status = resource_map_->Get(leveldb::ReadOptions(), const leveldb::Status status = resource_map_->Get(leveldb::ReadOptions(),
leveldb::Slice(id), leveldb::Slice(id),
&serialized_entry); &serialized_entry);
return status.ok() && out_entry->ParseFromString(serialized_entry); if (!status.ok())
return LevelDBStatusToFileError(status);
return out_entry->ParseFromString(serialized_entry) ?
FILE_ERROR_OK : FILE_ERROR_FAILED;
} }
bool ResourceMetadataStorage::RemoveEntry(const std::string& id) { FileError ResourceMetadataStorage::RemoveEntry(const std::string& id) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
DCHECK(!id.empty()); DCHECK(!id.empty());
ResourceEntry entry; ResourceEntry entry;
if (!GetEntry(id, &entry)) FileError error = GetEntry(id, &entry);
return false; if (error != FILE_ERROR_OK)
return error;
leveldb::WriteBatch batch; leveldb::WriteBatch batch;
...@@ -679,7 +700,7 @@ bool ResourceMetadataStorage::RemoveEntry(const std::string& id) { ...@@ -679,7 +700,7 @@ bool ResourceMetadataStorage::RemoveEntry(const std::string& id) {
const leveldb::Status status = resource_map_->Write(leveldb::WriteOptions(), const leveldb::Status status = resource_map_->Write(leveldb::WriteOptions(),
&batch); &batch);
return status.ok(); return LevelDBStatusToFileError(status);
} }
scoped_ptr<ResourceMetadataStorage::Iterator> scoped_ptr<ResourceMetadataStorage::Iterator>
...@@ -691,20 +712,23 @@ ResourceMetadataStorage::GetIterator() { ...@@ -691,20 +712,23 @@ ResourceMetadataStorage::GetIterator() {
return make_scoped_ptr(new Iterator(it.Pass())); return make_scoped_ptr(new Iterator(it.Pass()));
} }
std::string ResourceMetadataStorage::GetChild(const std::string& parent_id, FileError ResourceMetadataStorage::GetChild(const std::string& parent_id,
const std::string& child_name) { const std::string& child_name,
std::string* child_id) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
DCHECK(!parent_id.empty()); DCHECK(!parent_id.empty());
DCHECK(!child_name.empty()); DCHECK(!child_name.empty());
std::string child_id; const leveldb::Status status =
resource_map_->Get(leveldb::ReadOptions(), resource_map_->Get(
leveldb::ReadOptions(),
leveldb::Slice(GetChildEntryKey(parent_id, child_name)), leveldb::Slice(GetChildEntryKey(parent_id, child_name)),
&child_id); child_id);
return child_id; return LevelDBStatusToFileError(status);
} }
void ResourceMetadataStorage::GetChildren(const std::string& parent_id, FileError ResourceMetadataStorage::GetChildren(
const std::string& parent_id,
std::vector<std::string>* children) { std::vector<std::string>* children) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
DCHECK(!parent_id.empty()); DCHECK(!parent_id.empty());
...@@ -718,10 +742,10 @@ void ResourceMetadataStorage::GetChildren(const std::string& parent_id, ...@@ -718,10 +742,10 @@ void ResourceMetadataStorage::GetChildren(const std::string& parent_id,
if (IsChildEntryKey(it->key())) if (IsChildEntryKey(it->key()))
children->push_back(it->value().ToString()); children->push_back(it->value().ToString());
} }
DCHECK(it->status().ok()); return LevelDBStatusToFileError(it->status());
} }
bool ResourceMetadataStorage::PutCacheEntry(const std::string& id, FileError ResourceMetadataStorage::PutCacheEntry(const std::string& id,
const FileCacheEntry& entry) { const FileCacheEntry& entry) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
DCHECK(!id.empty()); DCHECK(!id.empty());
...@@ -729,17 +753,17 @@ bool ResourceMetadataStorage::PutCacheEntry(const std::string& id, ...@@ -729,17 +753,17 @@ bool ResourceMetadataStorage::PutCacheEntry(const std::string& id,
std::string serialized_entry; std::string serialized_entry;
if (!entry.SerializeToString(&serialized_entry)) { if (!entry.SerializeToString(&serialized_entry)) {
DLOG(ERROR) << "Failed to serialize the entry."; DLOG(ERROR) << "Failed to serialize the entry.";
return false; return FILE_ERROR_FAILED;
} }
const leveldb::Status status = resource_map_->Put( const leveldb::Status status = resource_map_->Put(
leveldb::WriteOptions(), leveldb::WriteOptions(),
leveldb::Slice(GetCacheEntryKey(id)), leveldb::Slice(GetCacheEntryKey(id)),
leveldb::Slice(serialized_entry)); leveldb::Slice(serialized_entry));
return status.ok(); return LevelDBStatusToFileError(status);
} }
bool ResourceMetadataStorage::GetCacheEntry(const std::string& id, FileError ResourceMetadataStorage::GetCacheEntry(const std::string& id,
FileCacheEntry* out_entry) { FileCacheEntry* out_entry) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
DCHECK(!id.empty()); DCHECK(!id.empty());
...@@ -749,17 +773,20 @@ bool ResourceMetadataStorage::GetCacheEntry(const std::string& id, ...@@ -749,17 +773,20 @@ bool ResourceMetadataStorage::GetCacheEntry(const std::string& id,
leveldb::ReadOptions(), leveldb::ReadOptions(),
leveldb::Slice(GetCacheEntryKey(id)), leveldb::Slice(GetCacheEntryKey(id)),
&serialized_entry); &serialized_entry);
return status.ok() && out_entry->ParseFromString(serialized_entry); if (!status.ok())
return LevelDBStatusToFileError(status);
return out_entry->ParseFromString(serialized_entry) ?
FILE_ERROR_OK : FILE_ERROR_FAILED;
} }
bool ResourceMetadataStorage::RemoveCacheEntry(const std::string& id) { FileError ResourceMetadataStorage::RemoveCacheEntry(const std::string& id) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
DCHECK(!id.empty()); DCHECK(!id.empty());
const leveldb::Status status = resource_map_->Delete( const leveldb::Status status = resource_map_->Delete(
leveldb::WriteOptions(), leveldb::WriteOptions(),
leveldb::Slice(GetCacheEntryKey(id))); leveldb::Slice(GetCacheEntryKey(id)));
return status.ok(); return LevelDBStatusToFileError(status);
} }
scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> scoped_ptr<ResourceMetadataStorage::CacheEntryIterator>
...@@ -776,7 +803,7 @@ ResourceMetadataStorage::RecoveredCacheInfo::RecoveredCacheInfo() ...@@ -776,7 +803,7 @@ ResourceMetadataStorage::RecoveredCacheInfo::RecoveredCacheInfo()
ResourceMetadataStorage::RecoveredCacheInfo::~RecoveredCacheInfo() {} ResourceMetadataStorage::RecoveredCacheInfo::~RecoveredCacheInfo() {}
bool ResourceMetadataStorage::GetIdByResourceId( FileError ResourceMetadataStorage::GetIdByResourceId(
const std::string& resource_id, const std::string& resource_id,
std::string* out_id) { std::string* out_id) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
...@@ -786,7 +813,7 @@ bool ResourceMetadataStorage::GetIdByResourceId( ...@@ -786,7 +813,7 @@ bool ResourceMetadataStorage::GetIdByResourceId(
leveldb::ReadOptions(), leveldb::ReadOptions(),
leveldb::Slice(GetIdEntryKey(resource_id)), leveldb::Slice(GetIdEntryKey(resource_id)),
out_id); out_id);
return status.ok(); return LevelDBStatusToFileError(status);
} }
ResourceMetadataStorage::~ResourceMetadataStorage() { ResourceMetadataStorage::~ResourceMetadataStorage() {
...@@ -811,24 +838,24 @@ std::string ResourceMetadataStorage::GetChildEntryKey( ...@@ -811,24 +838,24 @@ std::string ResourceMetadataStorage::GetChildEntryKey(
return key; return key;
} }
bool ResourceMetadataStorage::PutHeader( FileError ResourceMetadataStorage::PutHeader(
const ResourceMetadataHeader& header) { const ResourceMetadataHeader& header) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
std::string serialized_header; std::string serialized_header;
if (!header.SerializeToString(&serialized_header)) { if (!header.SerializeToString(&serialized_header)) {
DLOG(ERROR) << "Failed to serialize the header"; DLOG(ERROR) << "Failed to serialize the header";
return false; return FILE_ERROR_FAILED;
} }
const leveldb::Status status = resource_map_->Put( const leveldb::Status status = resource_map_->Put(
leveldb::WriteOptions(), leveldb::WriteOptions(),
leveldb::Slice(GetHeaderDBKey()), leveldb::Slice(GetHeaderDBKey()),
leveldb::Slice(serialized_header)); leveldb::Slice(serialized_header));
return status.ok(); return LevelDBStatusToFileError(status);
} }
bool ResourceMetadataStorage::GetHeader(ResourceMetadataHeader* header) { FileError ResourceMetadataStorage::GetHeader(ResourceMetadataHeader* header) {
base::ThreadRestrictions::AssertIOAllowed(); base::ThreadRestrictions::AssertIOAllowed();
std::string serialized_header; std::string serialized_header;
...@@ -836,7 +863,10 @@ bool ResourceMetadataStorage::GetHeader(ResourceMetadataHeader* header) { ...@@ -836,7 +863,10 @@ bool ResourceMetadataStorage::GetHeader(ResourceMetadataHeader* header) {
leveldb::ReadOptions(), leveldb::ReadOptions(),
leveldb::Slice(GetHeaderDBKey()), leveldb::Slice(GetHeaderDBKey()),
&serialized_header); &serialized_header);
return status.ok() && header->ParseFromString(serialized_header); if (!status.ok())
return LevelDBStatusToFileError(status);
return header->ParseFromString(serialized_header) ?
FILE_ERROR_OK : FILE_ERROR_FAILED;
} }
bool ResourceMetadataStorage::CheckValidity() { bool ResourceMetadataStorage::CheckValidity() {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "chrome/browser/chromeos/drive/drive.pb.h" #include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/file_errors.h"
#include "chrome/browser/drive/drive_service_interface.h" #include "chrome/browser/drive/drive_service_interface.h"
namespace base { namespace base {
...@@ -139,45 +140,47 @@ class ResourceMetadataStorage { ...@@ -139,45 +140,47 @@ class ResourceMetadataStorage {
void RecoverCacheInfoFromTrashedResourceMap(RecoveredCacheInfoMap* out_info); void RecoverCacheInfoFromTrashedResourceMap(RecoveredCacheInfoMap* out_info);
// Sets the largest changestamp. // Sets the largest changestamp.
bool SetLargestChangestamp(int64 largest_changestamp); FileError SetLargestChangestamp(int64 largest_changestamp);
// Gets the largest changestamp. // Gets the largest changestamp.
int64 GetLargestChangestamp(); FileError GetLargestChangestamp(int64* largest_changestamp);
// Puts the entry to this storage. // Puts the entry to this storage.
bool PutEntry(const ResourceEntry& entry); FileError PutEntry(const ResourceEntry& entry);
// Gets an entry stored in this storage. // Gets an entry stored in this storage.
bool GetEntry(const std::string& id, ResourceEntry* out_entry); FileError GetEntry(const std::string& id, ResourceEntry* out_entry);
// Removes an entry from this storage. // Removes an entry from this storage.
bool RemoveEntry(const std::string& id); FileError RemoveEntry(const std::string& id);
// Returns an object to iterate over entries stored in this storage. // Returns an object to iterate over entries stored in this storage.
scoped_ptr<Iterator> GetIterator(); scoped_ptr<Iterator> GetIterator();
// Returns the ID of the parent's child. // Returns the ID of the parent's child.
std::string GetChild(const std::string& parent_id, FileError GetChild(const std::string& parent_id,
const std::string& child_name); const std::string& child_name,
std::string* child_id);
// Returns the IDs of the parent's children. // Returns the IDs of the parent's children.
void GetChildren(const std::string& parent_id, FileError GetChildren(const std::string& parent_id,
std::vector<std::string>* children); std::vector<std::string>* children);
// Puts the cache entry to this storage. // Puts the cache entry to this storage.
bool PutCacheEntry(const std::string& id, const FileCacheEntry& entry); FileError PutCacheEntry(const std::string& id, const FileCacheEntry& entry);
// Gets a cache entry stored in this storage. // Gets a cache entry stored in this storage.
bool GetCacheEntry(const std::string& id, FileCacheEntry* out_entry); FileError GetCacheEntry(const std::string& id, FileCacheEntry* out_entry);
// Removes a cache entry from this storage. // Removes a cache entry from this storage.
bool RemoveCacheEntry(const std::string& id); FileError RemoveCacheEntry(const std::string& id);
// Returns an object to iterate over cache entries stored in this storage. // Returns an object to iterate over cache entries stored in this storage.
scoped_ptr<CacheEntryIterator> GetCacheEntryIterator(); scoped_ptr<CacheEntryIterator> GetCacheEntryIterator();
// Returns the local ID associated with the given resource ID. // Returns the local ID associated with the given resource ID.
bool GetIdByResourceId(const std::string& resource_id, std::string* out_id); FileError GetIdByResourceId(const std::string& resource_id,
std::string* out_id);
private: private:
friend class ResourceMetadataStorageTest; friend class ResourceMetadataStorageTest;
...@@ -193,10 +196,10 @@ class ResourceMetadataStorage { ...@@ -193,10 +196,10 @@ class ResourceMetadataStorage {
const std::string& child_name); const std::string& child_name);
// Puts header. // Puts header.
bool PutHeader(const ResourceMetadataHeader& header); FileError PutHeader(const ResourceMetadataHeader& header);
// Gets header. // Gets header.
bool GetHeader(ResourceMetadataHeader* out_header); FileError GetHeader(ResourceMetadataHeader* out_header);
// Checks validity of the data. // Checks validity of the data.
bool CheckValidity(); bool CheckValidity();
......
...@@ -32,9 +32,9 @@ class ResourceMetadataStorageTest : public testing::Test { ...@@ -32,9 +32,9 @@ class ResourceMetadataStorageTest : public testing::Test {
// Overwrites |storage_|'s version. // Overwrites |storage_|'s version.
void SetDBVersion(int version) { void SetDBVersion(int version) {
ResourceMetadataHeader header; ResourceMetadataHeader header;
ASSERT_TRUE(storage_->GetHeader(&header)); ASSERT_EQ(FILE_ERROR_OK, storage_->GetHeader(&header));
header.set_version(version); header.set_version(version);
EXPECT_TRUE(storage_->PutHeader(header)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutHeader(header));
} }
bool CheckValidity() { bool CheckValidity() {
...@@ -69,8 +69,11 @@ class ResourceMetadataStorageTest : public testing::Test { ...@@ -69,8 +69,11 @@ class ResourceMetadataStorageTest : public testing::Test {
TEST_F(ResourceMetadataStorageTest, LargestChangestamp) { TEST_F(ResourceMetadataStorageTest, LargestChangestamp) {
const int64 kLargestChangestamp = 1234567890; const int64 kLargestChangestamp = 1234567890;
EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp)); EXPECT_EQ(FILE_ERROR_OK,
EXPECT_EQ(kLargestChangestamp, storage_->GetLargestChangestamp()); storage_->SetLargestChangestamp(kLargestChangestamp));
int64 value = 0;
EXPECT_EQ(FILE_ERROR_OK, storage_->GetLargestChangestamp(&value));
EXPECT_EQ(kLargestChangestamp, value);
} }
TEST_F(ResourceMetadataStorageTest, PutEntry) { TEST_F(ResourceMetadataStorageTest, PutEntry) {
...@@ -82,56 +85,60 @@ TEST_F(ResourceMetadataStorageTest, PutEntry) { ...@@ -82,56 +85,60 @@ TEST_F(ResourceMetadataStorageTest, PutEntry) {
// key1 not found. // key1 not found.
ResourceEntry result; ResourceEntry result;
EXPECT_FALSE(storage_->GetEntry(key1, &result)); EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key1, &result));
// Put entry1. // Put entry1.
ResourceEntry entry1; ResourceEntry entry1;
entry1.set_local_id(key1); entry1.set_local_id(key1);
EXPECT_TRUE(storage_->PutEntry(entry1)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry1));
// key1 found. // key1 found.
EXPECT_TRUE(storage_->GetEntry(key1, &result)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(key1, &result));
// key2 not found. // key2 not found.
EXPECT_FALSE(storage_->GetEntry(key2, &result)); EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key2, &result));
// Put entry2 as a child of entry1. // Put entry2 as a child of entry1.
ResourceEntry entry2; ResourceEntry entry2;
entry2.set_local_id(key2); entry2.set_local_id(key2);
entry2.set_parent_local_id(key1); entry2.set_parent_local_id(key1);
entry2.set_base_name(name2); entry2.set_base_name(name2);
EXPECT_TRUE(storage_->PutEntry(entry2)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry2));
// key2 found. // key2 found.
EXPECT_TRUE(storage_->GetEntry(key2, &result)); std::string child_id;
EXPECT_EQ(key2, storage_->GetChild(key1, name2)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(key2, &result));
EXPECT_EQ(FILE_ERROR_OK, storage_->GetChild(key1, name2, &child_id));
EXPECT_EQ(key2, child_id);
// Put entry3 as a child of entry2. // Put entry3 as a child of entry2.
ResourceEntry entry3; ResourceEntry entry3;
entry3.set_local_id(key3); entry3.set_local_id(key3);
entry3.set_parent_local_id(key2); entry3.set_parent_local_id(key2);
entry3.set_base_name(name3); entry3.set_base_name(name3);
EXPECT_TRUE(storage_->PutEntry(entry3)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry3));
// key3 found. // key3 found.
EXPECT_TRUE(storage_->GetEntry(key3, &result)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(key3, &result));
EXPECT_EQ(key3, storage_->GetChild(key2, name3)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetChild(key2, name3, &child_id));
EXPECT_EQ(key3, child_id);
// Change entry3's parent to entry1. // Change entry3's parent to entry1.
entry3.set_parent_local_id(key1); entry3.set_parent_local_id(key1);
EXPECT_TRUE(storage_->PutEntry(entry3)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry3));
// entry3 is a child of entry1 now. // entry3 is a child of entry1 now.
EXPECT_TRUE(storage_->GetChild(key2, name3).empty()); EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetChild(key2, name3, &child_id));
EXPECT_EQ(key3, storage_->GetChild(key1, name3)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetChild(key1, name3, &child_id));
EXPECT_EQ(key3, child_id);
// Remove entries. // Remove entries.
EXPECT_TRUE(storage_->RemoveEntry(key3)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key3));
EXPECT_FALSE(storage_->GetEntry(key3, &result)); EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key3, &result));
EXPECT_TRUE(storage_->RemoveEntry(key2)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key2));
EXPECT_FALSE(storage_->GetEntry(key2, &result)); EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key2, &result));
EXPECT_TRUE(storage_->RemoveEntry(key1)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key1));
EXPECT_FALSE(storage_->GetEntry(key1, &result)); EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key1, &result));
} }
TEST_F(ResourceMetadataStorageTest, Iterator) { TEST_F(ResourceMetadataStorageTest, Iterator) {
...@@ -146,7 +153,7 @@ TEST_F(ResourceMetadataStorageTest, Iterator) { ...@@ -146,7 +153,7 @@ TEST_F(ResourceMetadataStorageTest, Iterator) {
for (size_t i = 0; i < keys.size(); ++i) { for (size_t i = 0; i < keys.size(); ++i) {
ResourceEntry entry; ResourceEntry entry;
entry.set_local_id(keys[i]); entry.set_local_id(keys[i]);
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
} }
// Insert some cache entries. // Insert some cache entries.
...@@ -155,7 +162,7 @@ TEST_F(ResourceMetadataStorageTest, Iterator) { ...@@ -155,7 +162,7 @@ TEST_F(ResourceMetadataStorageTest, Iterator) {
cache_entries[keys[1]].set_md5("bbbbbb"); cache_entries[keys[1]].set_md5("bbbbbb");
for (std::map<std::string, FileCacheEntry>::iterator it = for (std::map<std::string, FileCacheEntry>::iterator it =
cache_entries.begin(); it != cache_entries.end(); ++it) cache_entries.begin(); it != cache_entries.end(); ++it)
EXPECT_TRUE(storage_->PutCacheEntry(it->first, it->second)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry(it->first, it->second));
// Iterate and check the result. // Iterate and check the result.
std::map<std::string, ResourceEntry> found_entries; std::map<std::string, ResourceEntry> found_entries;
...@@ -193,22 +200,22 @@ TEST_F(ResourceMetadataStorageTest, PutCacheEntry) { ...@@ -193,22 +200,22 @@ TEST_F(ResourceMetadataStorageTest, PutCacheEntry) {
// Put cache entries. // Put cache entries.
entry.set_md5(md5_1); entry.set_md5(md5_1);
EXPECT_TRUE(storage_->PutCacheEntry(key1, entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry(key1, entry));
entry.set_md5(md5_2); entry.set_md5(md5_2);
EXPECT_TRUE(storage_->PutCacheEntry(key2, entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry(key2, entry));
// Get cache entires. // Get cache entires.
EXPECT_TRUE(storage_->GetCacheEntry(key1, &entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetCacheEntry(key1, &entry));
EXPECT_EQ(md5_1, entry.md5()); EXPECT_EQ(md5_1, entry.md5());
EXPECT_TRUE(storage_->GetCacheEntry(key2, &entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetCacheEntry(key2, &entry));
EXPECT_EQ(md5_2, entry.md5()); EXPECT_EQ(md5_2, entry.md5());
// Remove cache entries. // Remove cache entries.
EXPECT_TRUE(storage_->RemoveCacheEntry(key1)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveCacheEntry(key1));
EXPECT_FALSE(storage_->GetCacheEntry(key1, &entry)); EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetCacheEntry(key1, &entry));
EXPECT_TRUE(storage_->RemoveCacheEntry(key2)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveCacheEntry(key2));
EXPECT_FALSE(storage_->GetCacheEntry(key2, &entry)); EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetCacheEntry(key2, &entry));
} }
TEST_F(ResourceMetadataStorageTest, CacheEntryIterator) { TEST_F(ResourceMetadataStorageTest, CacheEntryIterator) {
...@@ -227,14 +234,14 @@ TEST_F(ResourceMetadataStorageTest, CacheEntryIterator) { ...@@ -227,14 +234,14 @@ TEST_F(ResourceMetadataStorageTest, CacheEntryIterator) {
for (std::map<std::string, FileCacheEntry>::iterator it = entries.begin(); for (std::map<std::string, FileCacheEntry>::iterator it = entries.begin();
it != entries.end(); ++it) it != entries.end(); ++it)
EXPECT_TRUE(storage_->PutCacheEntry(it->first, it->second)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry(it->first, it->second));
// Insert some dummy entries. // Insert some dummy entries.
ResourceEntry entry; ResourceEntry entry;
entry.set_local_id("entry1"); entry.set_local_id("entry1");
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
entry.set_local_id("entry2"); entry.set_local_id("entry2");
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
// Iterate and check the result. // Iterate and check the result.
scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it =
...@@ -256,21 +263,23 @@ TEST_F(ResourceMetadataStorageTest, GetIdByResourceId) { ...@@ -256,21 +263,23 @@ TEST_F(ResourceMetadataStorageTest, GetIdByResourceId) {
// Resource ID to local ID mapping is not stored yet. // Resource ID to local ID mapping is not stored yet.
std::string id; std::string id;
EXPECT_FALSE(storage_->GetIdByResourceId(resource_id, &id)); EXPECT_EQ(FILE_ERROR_NOT_FOUND,
storage_->GetIdByResourceId(resource_id, &id));
// Put an entry with the resource ID. // Put an entry with the resource ID.
ResourceEntry entry; ResourceEntry entry;
entry.set_local_id(local_id); entry.set_local_id(local_id);
entry.set_resource_id(resource_id); entry.set_resource_id(resource_id);
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
// Can get local ID by resource ID. // Can get local ID by resource ID.
EXPECT_TRUE(storage_->GetIdByResourceId(resource_id, &id)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetIdByResourceId(resource_id, &id));
EXPECT_EQ(local_id, id); EXPECT_EQ(local_id, id);
// Resource ID to local ID mapping is removed. // Resource ID to local ID mapping is removed.
EXPECT_TRUE(storage_->RemoveEntry(local_id)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(local_id));
EXPECT_FALSE(storage_->GetIdByResourceId(resource_id, &id)); EXPECT_EQ(FILE_ERROR_NOT_FOUND,
storage_->GetIdByResourceId(resource_id, &id));
} }
TEST_F(ResourceMetadataStorageTest, GetChildren) { TEST_F(ResourceMetadataStorageTest, GetChildren) {
...@@ -297,7 +306,7 @@ TEST_F(ResourceMetadataStorageTest, GetChildren) { ...@@ -297,7 +306,7 @@ TEST_F(ResourceMetadataStorageTest, GetChildren) {
for (size_t i = 0; i < arraysize(parents_id); ++i) { for (size_t i = 0; i < arraysize(parents_id); ++i) {
ResourceEntry entry; ResourceEntry entry;
entry.set_local_id(parents_id[i]); entry.set_local_id(parents_id[i]);
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
} }
// Put children. // Put children.
...@@ -307,14 +316,15 @@ TEST_F(ResourceMetadataStorageTest, GetChildren) { ...@@ -307,14 +316,15 @@ TEST_F(ResourceMetadataStorageTest, GetChildren) {
entry.set_local_id(children_name_id[i][j].second); entry.set_local_id(children_name_id[i][j].second);
entry.set_parent_local_id(parents_id[i]); entry.set_parent_local_id(parents_id[i]);
entry.set_base_name(children_name_id[i][j].first); entry.set_base_name(children_name_id[i][j].first);
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
} }
} }
// Put some dummy cache entries. // Put some dummy cache entries.
for (size_t i = 0; i < arraysize(parents_id); ++i) { for (size_t i = 0; i < arraysize(parents_id); ++i) {
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
EXPECT_TRUE(storage_->PutCacheEntry(parents_id[i], cache_entry)); EXPECT_EQ(FILE_ERROR_OK,
storage_->PutCacheEntry(parents_id[i], cache_entry));
} }
// Try to get children. // Try to get children.
...@@ -343,8 +353,8 @@ TEST_F(ResourceMetadataStorageTest, OpenExistingDB) { ...@@ -343,8 +353,8 @@ TEST_F(ResourceMetadataStorageTest, OpenExistingDB) {
entry2.set_base_name(child_name1); entry2.set_base_name(child_name1);
// Put some data. // Put some data.
EXPECT_TRUE(storage_->PutEntry(entry1)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry1));
EXPECT_TRUE(storage_->PutEntry(entry2)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry2));
// Close DB and reopen. // Close DB and reopen.
storage_.reset(new ResourceMetadataStorage( storage_.reset(new ResourceMetadataStorage(
...@@ -353,13 +363,16 @@ TEST_F(ResourceMetadataStorageTest, OpenExistingDB) { ...@@ -353,13 +363,16 @@ TEST_F(ResourceMetadataStorageTest, OpenExistingDB) {
// Can read data. // Can read data.
ResourceEntry result; ResourceEntry result;
EXPECT_TRUE(storage_->GetEntry(parent_id1, &result)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(parent_id1, &result));
EXPECT_TRUE(storage_->GetEntry(child_id1, &result)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(child_id1, &result));
EXPECT_EQ(parent_id1, result.parent_local_id()); EXPECT_EQ(parent_id1, result.parent_local_id());
EXPECT_EQ(child_name1, result.base_name()); EXPECT_EQ(child_name1, result.base_name());
EXPECT_EQ(child_id1, storage_->GetChild(parent_id1, child_name1)); std::string child_id;
EXPECT_EQ(FILE_ERROR_OK,
storage_->GetChild(parent_id1, child_name1, &child_id));
EXPECT_EQ(child_id1, child_id);
} }
TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M29) { TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M29) {
...@@ -367,7 +380,8 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M29) { ...@@ -367,7 +380,8 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M29) {
// Construct M29 version DB. // Construct M29 version DB.
SetDBVersion(6); SetDBVersion(6);
EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp)); EXPECT_EQ(FILE_ERROR_OK,
storage_->SetLargestChangestamp(kLargestChangestamp));
leveldb::WriteBatch batch; leveldb::WriteBatch batch;
...@@ -394,12 +408,16 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M29) { ...@@ -394,12 +408,16 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M29) {
// Resource-ID-to-local-ID mapping is added. // Resource-ID-to-local-ID mapping is added.
std::string id; std::string id;
EXPECT_TRUE(storage_->GetIdByResourceId("abcd", &id)); // "file:" is dropped. EXPECT_EQ(FILE_ERROR_OK,
storage_->GetIdByResourceId("abcd", &id)); // "file:" is dropped.
// Data is erased, except cache entries. // Data is erased, except cache entries.
EXPECT_EQ(0, storage_->GetLargestChangestamp()); int64 largest_changestamp = 0;
EXPECT_FALSE(storage_->GetEntry(id, &entry)); EXPECT_EQ(FILE_ERROR_OK,
EXPECT_TRUE(storage_->GetCacheEntry(id, &cache_entry)); storage_->GetLargestChangestamp(&largest_changestamp));
EXPECT_EQ(0, largest_changestamp);
EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(id, &entry));
EXPECT_EQ(FILE_ERROR_OK, storage_->GetCacheEntry(id, &cache_entry));
} }
TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M32) { TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M32) {
...@@ -409,7 +427,8 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M32) { ...@@ -409,7 +427,8 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M32) {
// Construct M32 version DB. // Construct M32 version DB.
SetDBVersion(11); SetDBVersion(11);
EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp)); EXPECT_EQ(FILE_ERROR_OK,
storage_->SetLargestChangestamp(kLargestChangestamp));
leveldb::WriteBatch batch; leveldb::WriteBatch batch;
...@@ -438,11 +457,14 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M32) { ...@@ -438,11 +457,14 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M32) {
// Data is erased, except cache and id mapping entries. // Data is erased, except cache and id mapping entries.
std::string id; std::string id;
EXPECT_TRUE(storage_->GetIdByResourceId(resource_id, &id)); EXPECT_EQ(FILE_ERROR_OK, storage_->GetIdByResourceId(resource_id, &id));
EXPECT_EQ(local_id, id); EXPECT_EQ(local_id, id);
EXPECT_EQ(0, storage_->GetLargestChangestamp()); int64 largest_changestamp = 0;
EXPECT_FALSE(storage_->GetEntry(id, &entry)); EXPECT_EQ(FILE_ERROR_OK,
EXPECT_TRUE(storage_->GetCacheEntry(id, &cache_entry)); storage_->GetLargestChangestamp(&largest_changestamp));
EXPECT_EQ(0, largest_changestamp);
EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(id, &entry));
EXPECT_EQ(FILE_ERROR_OK, storage_->GetCacheEntry(id, &cache_entry));
} }
TEST_F(ResourceMetadataStorageTest, IncompatibleDB_Unknown) { TEST_F(ResourceMetadataStorageTest, IncompatibleDB_Unknown) {
...@@ -450,12 +472,13 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_Unknown) { ...@@ -450,12 +472,13 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_Unknown) {
const std::string key1 = "abcd"; const std::string key1 = "abcd";
// Put some data. // Put some data.
EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp)); EXPECT_EQ(FILE_ERROR_OK,
storage_->SetLargestChangestamp(kLargestChangestamp));
ResourceEntry entry; ResourceEntry entry;
entry.set_local_id(key1); entry.set_local_id(key1);
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
EXPECT_TRUE(storage_->PutCacheEntry(key1, cache_entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry(key1, cache_entry));
// Set newer version, upgrade and reopen DB. // Set newer version, upgrade and reopen DB.
SetDBVersion(ResourceMetadataStorage::kDBVersion + 1); SetDBVersion(ResourceMetadataStorage::kDBVersion + 1);
...@@ -467,9 +490,12 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_Unknown) { ...@@ -467,9 +490,12 @@ TEST_F(ResourceMetadataStorageTest, IncompatibleDB_Unknown) {
ASSERT_TRUE(storage_->Initialize()); ASSERT_TRUE(storage_->Initialize());
// Data is erased because of the incompatible version. // Data is erased because of the incompatible version.
EXPECT_EQ(0, storage_->GetLargestChangestamp()); int64 largest_changestamp = 0;
EXPECT_FALSE(storage_->GetEntry(key1, &entry)); EXPECT_EQ(FILE_ERROR_OK,
EXPECT_FALSE(storage_->GetCacheEntry(key1, &cache_entry)); storage_->GetLargestChangestamp(&largest_changestamp));
EXPECT_EQ(0, largest_changestamp);
EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key1, &entry));
EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetCacheEntry(key1, &cache_entry));
} }
TEST_F(ResourceMetadataStorageTest, WrongPath) { TEST_F(ResourceMetadataStorageTest, WrongPath) {
...@@ -487,24 +513,24 @@ TEST_F(ResourceMetadataStorageTest, RecoverCacheEntriesFromTrashedResourceMap) { ...@@ -487,24 +513,24 @@ TEST_F(ResourceMetadataStorageTest, RecoverCacheEntriesFromTrashedResourceMap) {
// Put some cache entries. // Put some cache entries.
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
cache_entry.set_md5("md5_foo"); cache_entry.set_md5("md5_foo");
EXPECT_TRUE(storage_->PutCacheEntry("id_foo", cache_entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry("id_foo", cache_entry));
cache_entry.set_md5("md5_bar"); cache_entry.set_md5("md5_bar");
cache_entry.set_is_dirty(true); cache_entry.set_is_dirty(true);
EXPECT_TRUE(storage_->PutCacheEntry("id_bar", cache_entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry("id_bar", cache_entry));
// Put entry with id_foo. // Put entry with id_foo.
ResourceEntry entry; ResourceEntry entry;
entry.set_local_id("id_foo"); entry.set_local_id("id_foo");
entry.set_base_name("foo"); entry.set_base_name("foo");
entry.set_title("foo"); entry.set_title("foo");
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
// Put entry with id_bar as a id_foo's child. // Put entry with id_bar as a id_foo's child.
entry.set_local_id("id_bar"); entry.set_local_id("id_bar");
entry.set_parent_local_id("id_foo"); entry.set_parent_local_id("id_foo");
entry.set_base_name("bar"); entry.set_base_name("bar");
entry.set_title("bar"); entry.set_title("bar");
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
// Remove parent-child relationship to make the DB invalid. // Remove parent-child relationship to make the DB invalid.
RemoveChild("id_foo", "bar"); RemoveChild("id_foo", "bar");
...@@ -542,14 +568,14 @@ TEST_F(ResourceMetadataStorageTest, CheckValidity) { ...@@ -542,14 +568,14 @@ TEST_F(ResourceMetadataStorageTest, CheckValidity) {
ResourceEntry entry; ResourceEntry entry;
entry.set_local_id(key1); entry.set_local_id(key1);
entry.set_base_name(name1); entry.set_base_name(name1);
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
EXPECT_TRUE(CheckValidity()); EXPECT_TRUE(CheckValidity());
// Put entry with key2 under key1. // Put entry with key2 under key1.
entry.set_local_id(key2); entry.set_local_id(key2);
entry.set_parent_local_id(key1); entry.set_parent_local_id(key1);
entry.set_base_name(name2); entry.set_base_name(name2);
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
EXPECT_TRUE(CheckValidity()); EXPECT_TRUE(CheckValidity());
RemoveChild(key1, name2); RemoveChild(key1, name2);
...@@ -567,7 +593,7 @@ TEST_F(ResourceMetadataStorageTest, CheckValidity) { ...@@ -567,7 +593,7 @@ TEST_F(ResourceMetadataStorageTest, CheckValidity) {
entry.set_local_id(key3); entry.set_local_id(key3);
entry.set_parent_local_id(key2); entry.set_parent_local_id(key2);
entry.set_base_name(name3); entry.set_base_name(name3);
EXPECT_TRUE(storage_->PutEntry(entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
EXPECT_TRUE(CheckValidity()); EXPECT_TRUE(CheckValidity());
// Parent-child relationship with wrong name. // Parent-child relationship with wrong name.
...@@ -584,23 +610,23 @@ TEST_F(ResourceMetadataStorageTest, CheckValidity) { ...@@ -584,23 +610,23 @@ TEST_F(ResourceMetadataStorageTest, CheckValidity) {
// Add some cache entries. // Add some cache entries.
FileCacheEntry cache_entry; FileCacheEntry cache_entry;
EXPECT_TRUE(storage_->PutCacheEntry(key1, cache_entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry(key1, cache_entry));
EXPECT_TRUE(storage_->PutCacheEntry(key2, cache_entry)); EXPECT_EQ(FILE_ERROR_OK, storage_->PutCacheEntry(key2, cache_entry));
// Remove key2. // Remove key2.
RemoveChild(key1, name2); RemoveChild(key1, name2);
EXPECT_FALSE(CheckValidity()); EXPECT_FALSE(CheckValidity());
EXPECT_TRUE(storage_->RemoveEntry(key2)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key2));
EXPECT_FALSE(CheckValidity()); EXPECT_FALSE(CheckValidity());
// Remove key3. // Remove key3.
RemoveChild(key2, name3); RemoveChild(key2, name3);
EXPECT_FALSE(CheckValidity()); EXPECT_FALSE(CheckValidity());
EXPECT_TRUE(storage_->RemoveEntry(key3)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key3));
EXPECT_TRUE(CheckValidity()); EXPECT_TRUE(CheckValidity());
// Remove key1. // Remove key1.
EXPECT_TRUE(storage_->RemoveEntry(key1)); EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key1));
EXPECT_TRUE(CheckValidity()); EXPECT_TRUE(CheckValidity());
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment