| Index: chrome/browser/chromeos/drive/resource_metadata.cc
|
| diff --git a/chrome/browser/chromeos/drive/resource_metadata.cc b/chrome/browser/chromeos/drive/resource_metadata.cc
|
| deleted file mode 100644
|
| index 1842fe5bcd8c77a5fdaba4b85314be91c9ee5c83..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/chromeos/drive/resource_metadata.cc
|
| +++ /dev/null
|
| @@ -1,607 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/chromeos/drive/resource_metadata.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/guid.h"
|
| -#include "base/location.h"
|
| -#include "base/rand_util.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/sys_info.h"
|
| -#include "chrome/browser/chromeos/drive/file_cache.h"
|
| -#include "chrome/browser/chromeos/drive/file_system_core_util.h"
|
| -#include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
|
| -#include "components/drive/drive.pb.h"
|
| -
|
| -namespace drive {
|
| -namespace internal {
|
| -namespace {
|
| -
|
| -// Returns true if enough disk space is available for DB operation.
|
| -// TODO(hashimoto): Merge this with FileCache's FreeDiskSpaceGetterInterface.
|
| -bool EnoughDiskSpaceIsAvailableForDBOperation(const base::FilePath& path) {
|
| - const int64 kRequiredDiskSpaceInMB = 128; // 128 MB seems to be large enough.
|
| - return base::SysInfo::AmountOfFreeDiskSpace(path) >=
|
| - kRequiredDiskSpaceInMB * (1 << 20);
|
| -}
|
| -
|
| -// Returns a file name with a uniquifier appended. (e.g. "File (1).txt")
|
| -std::string GetUniquifiedName(const std::string& name, int uniquifier) {
|
| - base::FilePath name_path = base::FilePath::FromUTF8Unsafe(name);
|
| - name_path = name_path.InsertBeforeExtensionASCII(
|
| - base::StringPrintf(" (%d)", uniquifier));
|
| - return name_path.AsUTF8Unsafe();
|
| -}
|
| -
|
| -// Returns true when there is no entry with the specified name under the parent
|
| -// other than the specified entry.
|
| -FileError EntryCanUseName(ResourceMetadataStorage* storage,
|
| - const std::string& parent_local_id,
|
| - const std::string& local_id,
|
| - const std::string& base_name,
|
| - bool* result) {
|
| - std::string existing_entry_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;
|
| -}
|
| -
|
| -// Returns true when the ID is used by an immutable entry.
|
| -bool IsImmutableEntry(const std::string& id) {
|
| - return id == util::kDriveGrandRootLocalId ||
|
| - id == util::kDriveOtherDirLocalId ||
|
| - id == util::kDriveTrashDirLocalId;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -ResourceMetadata::ResourceMetadata(
|
| - ResourceMetadataStorage* storage,
|
| - FileCache* cache,
|
| - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
|
| - : blocking_task_runner_(blocking_task_runner),
|
| - storage_(storage),
|
| - cache_(cache) {
|
| -}
|
| -
|
| -FileError ResourceMetadata::Initialize() {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - return SetUpDefaultEntries();
|
| -}
|
| -
|
| -void ResourceMetadata::Destroy() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - blocking_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ResourceMetadata::DestroyOnBlockingPool,
|
| - base::Unretained(this)));
|
| -}
|
| -
|
| -FileError ResourceMetadata::Reset() {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
|
| - return FILE_ERROR_NO_LOCAL_SPACE;
|
| -
|
| - FileError error = storage_->SetLargestChangestamp(0);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - // Remove all root entries.
|
| - scoped_ptr<Iterator> it = GetIterator();
|
| - for (; !it->IsAtEnd(); it->Advance()) {
|
| - if (it->GetValue().parent_local_id().empty()) {
|
| - error = RemoveEntryRecursively(it->GetID());
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - }
|
| - }
|
| - if (it->HasError())
|
| - return FILE_ERROR_FAILED;
|
| -
|
| - return SetUpDefaultEntries();
|
| -}
|
| -
|
| -ResourceMetadata::~ResourceMetadata() {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -}
|
| -
|
| -FileError ResourceMetadata::SetUpDefaultEntries() {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - // Initialize "/drive".
|
| - ResourceEntry entry;
|
| - FileError error = storage_->GetEntry(util::kDriveGrandRootLocalId, &entry);
|
| - if (error == FILE_ERROR_NOT_FOUND) {
|
| - ResourceEntry root;
|
| - root.mutable_file_info()->set_is_directory(true);
|
| - root.set_local_id(util::kDriveGrandRootLocalId);
|
| - root.set_title(util::kDriveGrandRootDirName);
|
| - root.set_base_name(util::kDriveGrandRootDirName);
|
| - error = storage_->PutEntry(root);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - } else if (error == FILE_ERROR_OK) {
|
| - if (!entry.resource_id().empty()) {
|
| - // Old implementations used kDriveGrandRootLocalId as a resource ID.
|
| - entry.clear_resource_id();
|
| - error = storage_->PutEntry(entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - }
|
| - } else {
|
| - return error;
|
| - }
|
| -
|
| - // Initialize "/drive/other".
|
| - error = storage_->GetEntry(util::kDriveOtherDirLocalId, &entry);
|
| - if (error == FILE_ERROR_NOT_FOUND) {
|
| - ResourceEntry other_dir;
|
| - other_dir.mutable_file_info()->set_is_directory(true);
|
| - other_dir.set_local_id(util::kDriveOtherDirLocalId);
|
| - other_dir.set_parent_local_id(util::kDriveGrandRootLocalId);
|
| - other_dir.set_title(util::kDriveOtherDirName);
|
| - error = PutEntryUnderDirectory(other_dir);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - } else if (error == FILE_ERROR_OK) {
|
| - if (!entry.resource_id().empty()) {
|
| - // Old implementations used kDriveOtherDirLocalId as a resource ID.
|
| - entry.clear_resource_id();
|
| - error = storage_->PutEntry(entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - }
|
| - } else {
|
| - return error;
|
| - }
|
| -
|
| - // Initialize "drive/trash".
|
| - error = storage_->GetEntry(util::kDriveTrashDirLocalId, &entry);
|
| - if (error == FILE_ERROR_NOT_FOUND) {
|
| - ResourceEntry trash_dir;
|
| - trash_dir.mutable_file_info()->set_is_directory(true);
|
| - trash_dir.set_local_id(util::kDriveTrashDirLocalId);
|
| - trash_dir.set_parent_local_id(util::kDriveGrandRootLocalId);
|
| - trash_dir.set_title(util::kDriveTrashDirName);
|
| - error = PutEntryUnderDirectory(trash_dir);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - } else if (error != FILE_ERROR_OK) {
|
| - return error;
|
| - }
|
| -
|
| - // Initialize "drive/root".
|
| - std::string child_id;
|
| - error = storage_->GetChild(
|
| - util::kDriveGrandRootLocalId, util::kDriveMyDriveRootDirName, &child_id);
|
| - if (error == FILE_ERROR_NOT_FOUND) {
|
| - ResourceEntry mydrive;
|
| - mydrive.mutable_file_info()->set_is_directory(true);
|
| - mydrive.set_parent_local_id(util::kDriveGrandRootLocalId);
|
| - mydrive.set_title(util::kDriveMyDriveRootDirName);
|
| -
|
| - std::string local_id;
|
| - error = AddEntry(mydrive, &local_id);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - } else if (error != FILE_ERROR_OK) {
|
| - return error;
|
| - }
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -void ResourceMetadata::DestroyOnBlockingPool() {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - delete this;
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetLargestChangestamp(int64* out_value) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - return storage_->GetLargestChangestamp(out_value);
|
| -}
|
| -
|
| -FileError ResourceMetadata::SetLargestChangestamp(int64 value) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
|
| - return FILE_ERROR_NO_LOCAL_SPACE;
|
| -
|
| - return storage_->SetLargestChangestamp(value);
|
| -}
|
| -
|
| -FileError ResourceMetadata::AddEntry(const ResourceEntry& entry,
|
| - std::string* out_id) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - DCHECK(entry.local_id().empty());
|
| -
|
| - if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
|
| - return FILE_ERROR_NO_LOCAL_SPACE;
|
| -
|
| - ResourceEntry parent;
|
| - FileError error = storage_->GetEntry(entry.parent_local_id(), &parent);
|
| - if (error != FILE_ERROR_OK)
|
| - 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.
|
| - std::string local_id;
|
| - ResourceEntry existing_entry;
|
| - if (!entry.resource_id().empty()) {
|
| - error = storage_->GetIdByResourceId(entry.resource_id(), &local_id);
|
| - if (error == FILE_ERROR_OK)
|
| - error = storage_->GetEntry(local_id, &existing_entry);
|
| -
|
| - if (error == FILE_ERROR_OK)
|
| - return FILE_ERROR_EXISTS;
|
| - else if (error != FILE_ERROR_NOT_FOUND)
|
| - return error;
|
| - }
|
| -
|
| - // Generate unique local ID when needed.
|
| - // We don't check for ID collisions as its probability is extremely low.
|
| - if (local_id.empty())
|
| - local_id = base::GenerateGUID();
|
| -
|
| - ResourceEntry new_entry(entry);
|
| - new_entry.set_local_id(local_id);
|
| -
|
| - error = PutEntryUnderDirectory(new_entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - *out_id = local_id;
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -FileError ResourceMetadata::RemoveEntry(const std::string& id) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
|
| - return FILE_ERROR_NO_LOCAL_SPACE;
|
| -
|
| - // Disallow deletion of default entries.
|
| - if (IsImmutableEntry(id))
|
| - return FILE_ERROR_ACCESS_DENIED;
|
| -
|
| - ResourceEntry entry;
|
| - FileError error = storage_->GetEntry(id, &entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - return RemoveEntryRecursively(id);
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetResourceEntryById(const std::string& id,
|
| - ResourceEntry* out_entry) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - DCHECK(!id.empty());
|
| - DCHECK(out_entry);
|
| -
|
| - return storage_->GetEntry(id, out_entry);
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetResourceEntryByPath(const base::FilePath& path,
|
| - ResourceEntry* out_entry) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - DCHECK(out_entry);
|
| -
|
| - std::string id;
|
| - FileError error = GetIdByPath(path, &id);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - return GetResourceEntryById(id, out_entry);
|
| -}
|
| -
|
| -FileError ResourceMetadata::ReadDirectoryByPath(
|
| - const base::FilePath& path,
|
| - ResourceEntryVector* out_entries) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - DCHECK(out_entries);
|
| -
|
| - std::string id;
|
| - FileError error = GetIdByPath(path, &id);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - return ReadDirectoryById(id, out_entries);
|
| -}
|
| -
|
| -FileError ResourceMetadata::ReadDirectoryById(
|
| - const std::string& id,
|
| - ResourceEntryVector* out_entries) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - DCHECK(out_entries);
|
| -
|
| - ResourceEntry entry;
|
| - FileError error = GetResourceEntryById(id, &entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - if (!entry.file_info().is_directory())
|
| - return FILE_ERROR_NOT_A_DIRECTORY;
|
| -
|
| - std::vector<std::string> children;
|
| - error = storage_->GetChildren(id, &children);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - ResourceEntryVector entries(children.size());
|
| - for (size_t i = 0; i < children.size(); ++i) {
|
| - error = storage_->GetEntry(children[i], &entries[i]);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - }
|
| - out_entries->swap(entries);
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - if (!EnoughDiskSpaceIsAvailableForDBOperation(storage_->directory_path()))
|
| - return FILE_ERROR_NO_LOCAL_SPACE;
|
| -
|
| - ResourceEntry old_entry;
|
| - FileError error = storage_->GetEntry(entry.local_id(), &old_entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - if (IsImmutableEntry(entry.local_id()) ||
|
| - old_entry.file_info().is_directory() != // Reject incompatible input.
|
| - entry.file_info().is_directory())
|
| - return FILE_ERROR_INVALID_OPERATION;
|
| -
|
| - if (!entry.resource_id().empty()) {
|
| - // Multiple entries cannot share the same resource ID.
|
| - std::string local_id;
|
| - FileError error = GetIdByResourceId(entry.resource_id(), &local_id);
|
| - switch (error) {
|
| - case FILE_ERROR_OK:
|
| - if (local_id != entry.local_id())
|
| - return FILE_ERROR_INVALID_OPERATION;
|
| - break;
|
| -
|
| - case FILE_ERROR_NOT_FOUND:
|
| - break;
|
| -
|
| - default:
|
| - return error;
|
| - }
|
| - }
|
| -
|
| - // Make sure that the new parent exists and it is a directory.
|
| - ResourceEntry new_parent;
|
| - error = storage_->GetEntry(entry.parent_local_id(), &new_parent);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - if (!new_parent.file_info().is_directory())
|
| - return FILE_ERROR_NOT_A_DIRECTORY;
|
| -
|
| - // Do not overwrite cache states.
|
| - // Cache state should be changed via FileCache.
|
| - ResourceEntry updated_entry(entry);
|
| - if (old_entry.file_specific_info().has_cache_state()) {
|
| - *updated_entry.mutable_file_specific_info()->mutable_cache_state() =
|
| - old_entry.file_specific_info().cache_state();
|
| - } else if (updated_entry.file_specific_info().has_cache_state()) {
|
| - updated_entry.mutable_file_specific_info()->clear_cache_state();
|
| - }
|
| - // Remove from the old parent and add it to the new parent with the new data.
|
| - return PutEntryUnderDirectory(updated_entry);
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetSubDirectoriesRecursively(
|
| - const std::string& id,
|
| - std::set<base::FilePath>* sub_directories) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - std::vector<std::string> children;
|
| - FileError error = storage_->GetChildren(id, &children);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - for (size_t i = 0; i < children.size(); ++i) {
|
| - ResourceEntry entry;
|
| - error = storage_->GetEntry(children[i], &entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - if (entry.file_info().is_directory()) {
|
| - base::FilePath path;
|
| - error = GetFilePath(children[i], &path);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - sub_directories->insert(path);
|
| - GetSubDirectoriesRecursively(children[i], sub_directories);
|
| - }
|
| - }
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetChildId(const std::string& parent_local_id,
|
| - const std::string& base_name,
|
| - std::string* out_child_id) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - return storage_->GetChild(parent_local_id, base_name, out_child_id);
|
| -}
|
| -
|
| -scoped_ptr<ResourceMetadata::Iterator> ResourceMetadata::GetIterator() {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - return storage_->GetIterator();
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetFilePath(const std::string& id,
|
| - base::FilePath* out_file_path) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - ResourceEntry entry;
|
| - FileError error = storage_->GetEntry(id, &entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - base::FilePath path;
|
| - if (!entry.parent_local_id().empty()) {
|
| - error = GetFilePath(entry.parent_local_id(), &path);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - } else if (entry.local_id() != util::kDriveGrandRootLocalId) {
|
| - DVLOG(1) << "Entries not under the grand root don't have paths.";
|
| - return FILE_ERROR_NOT_FOUND;
|
| - }
|
| - path = path.Append(base::FilePath::FromUTF8Unsafe(entry.base_name()));
|
| - *out_file_path = path;
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetIdByPath(const base::FilePath& file_path,
|
| - std::string* out_id) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - // Start from the root.
|
| - std::vector<base::FilePath::StringType> components;
|
| - file_path.GetComponents(&components);
|
| - if (components.empty() ||
|
| - components[0] != util::GetDriveGrandRootPath().value())
|
| - return FILE_ERROR_NOT_FOUND;
|
| -
|
| - // Iterate over the remaining components.
|
| - std::string id = util::kDriveGrandRootLocalId;
|
| - for (size_t i = 1; i < components.size(); ++i) {
|
| - const std::string component = base::FilePath(components[i]).AsUTF8Unsafe();
|
| - std::string child_id;
|
| - FileError error = storage_->GetChild(id, component, &child_id);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - id = child_id;
|
| - }
|
| - *out_id = id;
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetIdByResourceId(const std::string& resource_id,
|
| - std::string* out_local_id) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - return storage_->GetIdByResourceId(resource_id, out_local_id);
|
| -}
|
| -
|
| -FileError ResourceMetadata::PutEntryUnderDirectory(const ResourceEntry& entry) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - DCHECK(!entry.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);
|
| - updated_entry.set_base_name(base_name);
|
| - return storage_->PutEntry(updated_entry);
|
| -}
|
| -
|
| -FileError ResourceMetadata::GetDeduplicatedBaseName(
|
| - const ResourceEntry& entry,
|
| - std::string* base_name) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| - DCHECK(!entry.parent_local_id().empty());
|
| - DCHECK(!entry.title().empty());
|
| -
|
| - // 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
|
| - // through name de-duplication again when it is added to another directory.
|
| - *base_name = entry.title();
|
| - if (entry.has_file_specific_info() &&
|
| - entry.file_specific_info().is_hosted_document()) {
|
| - *base_name += entry.file_specific_info().document_extension();
|
| - }
|
| - *base_name = util::NormalizeFileName(*base_name);
|
| -
|
| - // If |base_name| is not used, just return it.
|
| - bool can_use_name = false;
|
| - FileError error = EntryCanUseName(storage_, entry.parent_local_id(),
|
| - 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.
|
| - int smallest_known_unused_modifier = 1;
|
| - while (true) {
|
| - error = EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(),
|
| - GetUniquifiedName(*base_name,
|
| - smallest_known_unused_modifier),
|
| - &can_use_name);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - if (can_use_name)
|
| - break;
|
| -
|
| - const int delta = base::RandInt(1, smallest_known_unused_modifier);
|
| - if (smallest_known_unused_modifier <= INT_MAX - delta) {
|
| - smallest_known_unused_modifier += delta;
|
| - } else { // No luck finding an unused number. Try again.
|
| - smallest_known_unused_modifier = 1;
|
| - }
|
| - }
|
| -
|
| - int largest_known_used_modifier = 1;
|
| - while (smallest_known_unused_modifier - largest_known_used_modifier > 1) {
|
| - const int modifier = largest_known_used_modifier +
|
| - (smallest_known_unused_modifier - largest_known_used_modifier) / 2;
|
| -
|
| - error = EntryCanUseName(storage_, entry.parent_local_id(), entry.local_id(),
|
| - GetUniquifiedName(*base_name, modifier),
|
| - &can_use_name);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - if (can_use_name) {
|
| - smallest_known_unused_modifier = modifier;
|
| - } else {
|
| - largest_known_used_modifier = modifier;
|
| - }
|
| - }
|
| - *base_name = GetUniquifiedName(*base_name, smallest_known_unused_modifier);
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -FileError ResourceMetadata::RemoveEntryRecursively(const std::string& id) {
|
| - DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
|
| -
|
| - ResourceEntry entry;
|
| - FileError error = storage_->GetEntry(id, &entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - if (entry.file_info().is_directory()) {
|
| - std::vector<std::string> children;
|
| - error = storage_->GetChildren(id, &children);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - for (size_t i = 0; i < children.size(); ++i) {
|
| - error = RemoveEntryRecursively(children[i]);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - }
|
| - }
|
| -
|
| - error = cache_->Remove(id);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - return storage_->RemoveEntry(id);
|
| -}
|
| -
|
| -} // namespace internal
|
| -} // namespace drive
|
|
|