blob: d682fca95f69dbc6ebd2d6342d6e8f2820f76c60 [file] [log] [blame]
// Copyright 2015 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/file_system_provider/throttled_file_system.h"
#include <stddef.h>
#include <limits>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/files/file.h"
#include "chrome/browser/chromeos/file_system_provider/queue.h"
namespace chromeos {
namespace file_system_provider {
ThrottledFileSystem::ThrottledFileSystem(
std::unique_ptr<ProvidedFileSystemInterface> file_system)
: file_system_(std::move(file_system)), weak_ptr_factory_(this) {
const int opened_files_limit =
file_system_->GetFileSystemInfo().opened_files_limit();
open_queue_.reset(opened_files_limit
? new Queue(static_cast<size_t>(opened_files_limit))
: new Queue(std::numeric_limits<size_t>::max()));
}
ThrottledFileSystem::~ThrottledFileSystem() {
}
AbortCallback ThrottledFileSystem::RequestUnmount(
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->RequestUnmount(std::move(callback));
}
AbortCallback ThrottledFileSystem::GetMetadata(const base::FilePath& entry_path,
MetadataFieldMask fields,
GetMetadataCallback callback) {
return file_system_->GetMetadata(entry_path, fields, std::move(callback));
}
AbortCallback ThrottledFileSystem::GetActions(
const std::vector<base::FilePath>& entry_paths,
GetActionsCallback callback) {
return file_system_->GetActions(entry_paths, std::move(callback));
}
AbortCallback ThrottledFileSystem::ExecuteAction(
const std::vector<base::FilePath>& entry_paths,
const std::string& action_id,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->ExecuteAction(entry_paths, action_id,
std::move(callback));
}
AbortCallback ThrottledFileSystem::ReadDirectory(
const base::FilePath& directory_path,
storage::AsyncFileUtil::ReadDirectoryCallback callback) {
return file_system_->ReadDirectory(directory_path, callback);
}
AbortCallback ThrottledFileSystem::ReadFile(
int file_handle,
net::IOBuffer* buffer,
int64_t offset,
int length,
ReadChunkReceivedCallback callback) {
return file_system_->ReadFile(file_handle, buffer, offset, length, callback);
}
AbortCallback ThrottledFileSystem::OpenFile(const base::FilePath& file_path,
OpenFileMode mode,
OpenFileCallback callback) {
const size_t task_token = open_queue_->NewToken();
open_queue_->Enqueue(
task_token,
base::BindOnce(
&ProvidedFileSystemInterface::OpenFile,
base::Unretained(file_system_.get()), // Outlives the queue.
file_path, mode,
base::Bind(&ThrottledFileSystem::OnOpenFileCompleted,
weak_ptr_factory_.GetWeakPtr(), task_token,
std::move(callback))));
return base::Bind(&ThrottledFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(),
task_token);
}
AbortCallback ThrottledFileSystem::CloseFile(
int file_handle,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->CloseFile(
file_handle, base::BindOnce(&ThrottledFileSystem::OnCloseFileCompleted,
weak_ptr_factory_.GetWeakPtr(), file_handle,
std::move(callback)));
}
AbortCallback ThrottledFileSystem::CreateDirectory(
const base::FilePath& directory_path,
bool recursive,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->CreateDirectory(directory_path, recursive,
std::move(callback));
}
AbortCallback ThrottledFileSystem::DeleteEntry(
const base::FilePath& entry_path,
bool recursive,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->DeleteEntry(entry_path, recursive, std::move(callback));
}
AbortCallback ThrottledFileSystem::CreateFile(
const base::FilePath& file_path,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->CreateFile(file_path, std::move(callback));
}
AbortCallback ThrottledFileSystem::CopyEntry(
const base::FilePath& source_path,
const base::FilePath& target_path,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->CopyEntry(source_path, target_path, std::move(callback));
}
AbortCallback ThrottledFileSystem::WriteFile(
int file_handle,
net::IOBuffer* buffer,
int64_t offset,
int length,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->WriteFile(file_handle, buffer, offset, length,
std::move(callback));
}
AbortCallback ThrottledFileSystem::MoveEntry(
const base::FilePath& source_path,
const base::FilePath& target_path,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->MoveEntry(source_path, target_path, std::move(callback));
}
AbortCallback ThrottledFileSystem::Truncate(
const base::FilePath& file_path,
int64_t length,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->Truncate(file_path, length, std::move(callback));
}
AbortCallback ThrottledFileSystem::AddWatcher(
const GURL& origin,
const base::FilePath& entry_path,
bool recursive,
bool persistent,
storage::AsyncFileUtil::StatusCallback callback,
const storage::WatcherManager::NotificationCallback&
notification_callback) {
return file_system_->AddWatcher(origin, entry_path, recursive, persistent,
std::move(callback), notification_callback);
}
void ThrottledFileSystem::RemoveWatcher(
const GURL& origin,
const base::FilePath& entry_path,
bool recursive,
storage::AsyncFileUtil::StatusCallback callback) {
file_system_->RemoveWatcher(origin, entry_path, recursive,
std::move(callback));
}
const ProvidedFileSystemInfo& ThrottledFileSystem::GetFileSystemInfo() const {
return file_system_->GetFileSystemInfo();
}
RequestManager* ThrottledFileSystem::GetRequestManager() {
return file_system_->GetRequestManager();
}
Watchers* ThrottledFileSystem::GetWatchers() {
return file_system_->GetWatchers();
}
const OpenedFiles& ThrottledFileSystem::GetOpenedFiles() const {
return file_system_->GetOpenedFiles();
}
void ThrottledFileSystem::AddObserver(ProvidedFileSystemObserver* observer) {
file_system_->AddObserver(observer);
}
void ThrottledFileSystem::RemoveObserver(ProvidedFileSystemObserver* observer) {
file_system_->RemoveObserver(observer);
}
void ThrottledFileSystem::Notify(
const base::FilePath& entry_path,
bool recursive,
storage::WatcherManager::ChangeType change_type,
std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
const std::string& tag,
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->Notify(entry_path, recursive, change_type,
std::move(changes), tag, std::move(callback));
}
void ThrottledFileSystem::Configure(
storage::AsyncFileUtil::StatusCallback callback) {
return file_system_->Configure(std::move(callback));
}
base::WeakPtr<ProvidedFileSystemInterface> ThrottledFileSystem::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
void ThrottledFileSystem::Abort(int queue_token) {
open_queue_->Abort(queue_token);
}
void ThrottledFileSystem::OnOpenFileCompleted(int queue_token,
OpenFileCallback callback,
int file_handle,
base::File::Error result) {
// If the file is opened successfully then hold the queue token until the file
// is closed.
if (result == base::File::FILE_OK)
opened_files_[file_handle] = queue_token;
else
open_queue_->Complete(queue_token);
std::move(callback).Run(file_handle, result);
}
void ThrottledFileSystem::OnCloseFileCompleted(
int file_handle,
storage::AsyncFileUtil::StatusCallback callback,
base::File::Error result) {
// Closing is always final. Even if an error happened, the file is considered
// closed on the C++ side. Release the task from the queue, so other files
// which are enqueued can be opened.
const auto it = opened_files_.find(file_handle);
DCHECK(it != opened_files_.end());
const int queue_token = it->second;
open_queue_->Complete(queue_token);
opened_files_.erase(file_handle);
std::move(callback).Run(result);
}
} // namespace file_system_provider
} // namespace chromeos