Index: chrome/browser/chromeos/drive/drive_resource_metadata.cc |
diff --git a/chrome/browser/chromeos/drive/drive_resource_metadata.cc b/chrome/browser/chromeos/drive/drive_resource_metadata.cc |
index 5106cc76b247195c079840999742f7c53d914aab..fda302e607d08cdae53b31134789ad42c184c384 100644 |
--- a/chrome/browser/chromeos/drive/drive_resource_metadata.cc |
+++ b/chrome/browser/chromeos/drive/drive_resource_metadata.cc |
@@ -7,6 +7,7 @@ |
#include "base/file_util.h" |
#include "base/stringprintf.h" |
#include "base/strings/string_number_conversions.h" |
+#include "base/sys_info.h" |
#include "chrome/browser/chromeos/drive/drive.pb.h" |
#include "chrome/browser/chromeos/drive/drive_file_system_util.h" |
#include "chrome/browser/chromeos/drive/drive_resource_metadata_storage.h" |
@@ -42,6 +43,14 @@ void RunGetChildDirectoriesCallbackWithResult( |
callback.Run(*result); |
} |
+// Returns true if enough disk space is avilable for DB operation. |
+// TODO(hashimoto): Merge this with DriveCache'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); |
+} |
+ |
} // namespace |
std::string DirectoryFetchInfo::ToString() const { |
@@ -201,6 +210,9 @@ DriveResourceMetadata::~DriveResourceMetadata() { |
DriveFileError DriveResourceMetadata::InitializeOnBlockingPool() { |
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return DRIVE_FILE_ERROR_NO_SPACE; |
+ |
// Initialize the storage. |
if (!storage_->Initialize()) |
return DRIVE_FILE_ERROR_FAILED; |
@@ -235,6 +247,12 @@ void DriveResourceMetadata::DestroyOnBlockingPool() { |
void DriveResourceMetadata::ResetOnBlockingPool() { |
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ // TODO(hashimoto): Return DRIVE_FILE_ERROR_NO_SPACE here. |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) { |
+ LOG(ERROR) << "Required disk space not available."; |
+ return; |
+ } |
+ |
RemoveAllOnBlockingPool(); |
storage_->SetLargestChangestamp(0); |
} |
@@ -451,6 +469,10 @@ int64 DriveResourceMetadata::GetLargestChangestampOnBlockingPool() { |
DriveFileError DriveResourceMetadata::SetLargestChangestampOnBlockingPool( |
int64 value) { |
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return DRIVE_FILE_ERROR_NO_SPACE; |
+ |
storage_->SetLargestChangestamp(value); |
return DRIVE_FILE_OK; |
} |
@@ -463,6 +485,9 @@ DriveResourceMetadata::MoveEntryToDirectoryOnBlockingPool( |
DCHECK(!directory_path.empty()); |
DCHECK(!file_path.empty()); |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return FileMoveResult(DRIVE_FILE_ERROR_NO_SPACE); |
+ |
scoped_ptr<DriveEntryProto> entry = FindEntryByPathSync(file_path); |
if (!entry) |
return FileMoveResult(DRIVE_FILE_ERROR_NOT_FOUND); |
@@ -498,6 +523,10 @@ DriveResourceMetadata::RenameEntryOnBlockingPool( |
DCHECK(!new_name.empty()); |
DVLOG(1) << "RenameEntry " << file_path.value() << " to " << new_name; |
+ |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return FileMoveResult(DRIVE_FILE_ERROR_NO_SPACE); |
+ |
scoped_ptr<DriveEntryProto> entry = FindEntryByPathSync(file_path); |
if (!entry) |
return FileMoveResult(DRIVE_FILE_ERROR_NOT_FOUND); |
@@ -516,6 +545,9 @@ DriveResourceMetadata::RemoveEntryOnBlockingPool( |
const std::string& resource_id) { |
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return FileMoveResult(DRIVE_FILE_ERROR_NO_SPACE); |
+ |
// Disallow deletion of special entries "/drive" and "/drive/other". |
if (util::IsSpecialResourceId(resource_id)) |
return FileMoveResult(DRIVE_FILE_ERROR_ACCESS_DENIED); |
@@ -635,6 +667,11 @@ DriveResourceMetadata::RefreshEntryOnBlockingPool( |
const DriveEntryProto& entry_proto) { |
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) { |
+ return make_scoped_ptr( |
+ new GetEntryInfoWithFilePathResult(DRIVE_FILE_ERROR_NO_SPACE)); |
+ } |
+ |
scoped_ptr<DriveEntryProto> entry = |
storage_->GetEntry(entry_proto.resource_id()); |
if (!entry) { |
@@ -678,6 +715,9 @@ DriveResourceMetadata::RefreshDirectoryOnBlockingPool( |
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
DCHECK(!directory_fetch_info.empty()); |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return FileMoveResult(DRIVE_FILE_ERROR_NO_SPACE); |
+ |
scoped_ptr<DriveEntryProto> directory = storage_->GetEntry( |
directory_fetch_info.resource_id()); |
@@ -695,6 +735,9 @@ DriveResourceMetadata::RefreshDirectoryOnBlockingPool( |
// entries in the loop. We'll process deleted entries afterwards. |
for (DriveEntryProtoMap::const_iterator it = entry_proto_map.begin(); |
it != entry_proto_map.end(); ++it) { |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return FileMoveResult(DRIVE_FILE_ERROR_NO_SPACE); |
+ |
const DriveEntryProto& entry_proto = it->second; |
// Skip if the parent resource ID does not match. This is needed to |
// handle entries with multiple parents. For such entries, the first |
@@ -721,6 +764,9 @@ DriveResourceMetadata::RefreshDirectoryOnBlockingPool( |
scoped_ptr<DriveEntryProtoVector> entries = |
DirectoryChildrenToProtoVector(directory->resource_id()); |
for (size_t i = 0; i < entries->size(); ++i) { |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return FileMoveResult(DRIVE_FILE_ERROR_NO_SPACE); |
+ |
const DriveEntryProto& entry_proto = entries->at(i); |
if (entry_proto_map.count(entry_proto.resource_id()) == 0) |
RemoveDirectoryChild(entry_proto.resource_id()); |
@@ -734,6 +780,9 @@ DriveResourceMetadata::AddEntryOnBlockingPool( |
const DriveEntryProto& entry_proto) { |
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) |
+ return FileMoveResult(DRIVE_FILE_ERROR_NO_SPACE); |
+ |
scoped_ptr<DriveEntryProto> existing_entry = |
storage_->GetEntry(entry_proto.resource_id()); |
if (existing_entry) |
@@ -805,6 +854,12 @@ void DriveResourceMetadata::GetDescendantDirectoryPaths( |
void DriveResourceMetadata::RemoveAllOnBlockingPool() { |
DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ // TODO(hashimoto): Return DRIVE_FILE_ERROR_NO_SPACE here. |
+ if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_)) { |
+ LOG(ERROR) << "Required disk space not available."; |
+ return; |
+ } |
+ |
RemoveDirectoryChildren(util::kDriveGrandRootSpecialResourceId); |
SetUpDefaultEntries(); |
} |