Index: chrome/browser/chromeos/file_system_provider/throttled_file_system.cc |
diff --git a/chrome/browser/chromeos/file_system_provider/throttled_file_system.cc b/chrome/browser/chromeos/file_system_provider/throttled_file_system.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..de4f37f8223b3bedeba8ba5b70c30e14d65c2f30 |
--- /dev/null |
+++ b/chrome/browser/chromeos/file_system_provider/throttled_file_system.cc |
@@ -0,0 +1,218 @@ |
+// 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 <limits> |
+#include <vector> |
+ |
+#include "base/files/file.h" |
+#include "chrome/browser/chromeos/file_system_provider/queue.h" |
+ |
+namespace chromeos { |
+namespace file_system_provider { |
+ |
+ThrottledFileSystem::ThrottledFileSystem( |
+ scoped_ptr<ProvidedFileSystemInterface> file_system) |
+ : file_system_(file_system.Pass()), 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( |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->RequestUnmount(callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::GetMetadata( |
+ const base::FilePath& entry_path, |
+ MetadataFieldMask fields, |
+ const GetMetadataCallback& callback) { |
+ return file_system_->GetMetadata(entry_path, fields, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::ReadDirectory( |
+ const base::FilePath& directory_path, |
+ const storage::AsyncFileUtil::ReadDirectoryCallback& callback) { |
+ return file_system_->ReadDirectory(directory_path, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::ReadFile( |
+ int file_handle, |
+ net::IOBuffer* buffer, |
+ int64 offset, |
+ int length, |
+ const ReadChunkReceivedCallback& callback) { |
+ return file_system_->ReadFile(file_handle, buffer, offset, length, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::OpenFile(const base::FilePath& file_path, |
+ OpenFileMode mode, |
+ const OpenFileCallback& callback) { |
+ const size_t task_token = open_queue_->NewToken(); |
+ return open_queue_->Enqueue( |
+ task_token, |
+ base::Bind( |
+ &ProvidedFileSystemInterface::OpenFile, |
+ base::Unretained(file_system_.get()), // Outlives the queue. |
+ file_path, mode, |
+ base::Bind(&ThrottledFileSystem::OnOpenFileCompleted, |
+ weak_ptr_factory_.GetWeakPtr(), task_token, callback))); |
+} |
+ |
+AbortCallback ThrottledFileSystem::CloseFile( |
+ int file_handle, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->CloseFile( |
+ file_handle, |
+ base::Bind(&ThrottledFileSystem::OnCloseFileCompleted, |
+ weak_ptr_factory_.GetWeakPtr(), file_handle, callback)); |
+} |
+ |
+AbortCallback ThrottledFileSystem::CreateDirectory( |
+ const base::FilePath& directory_path, |
+ bool recursive, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->CreateDirectory(directory_path, recursive, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::DeleteEntry( |
+ const base::FilePath& entry_path, |
+ bool recursive, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->DeleteEntry(entry_path, recursive, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::CreateFile( |
+ const base::FilePath& file_path, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->CreateFile(file_path, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::CopyEntry( |
+ const base::FilePath& source_path, |
+ const base::FilePath& target_path, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->CopyEntry(source_path, target_path, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::WriteFile( |
+ int file_handle, |
+ net::IOBuffer* buffer, |
+ int64 offset, |
+ int length, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->WriteFile(file_handle, buffer, offset, length, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::MoveEntry( |
+ const base::FilePath& source_path, |
+ const base::FilePath& target_path, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->MoveEntry(source_path, target_path, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::Truncate( |
+ const base::FilePath& file_path, |
+ int64 length, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->Truncate(file_path, length, callback); |
+} |
+ |
+AbortCallback ThrottledFileSystem::AddWatcher( |
+ const GURL& origin, |
+ const base::FilePath& entry_path, |
+ bool recursive, |
+ bool persistent, |
+ const storage::AsyncFileUtil::StatusCallback& callback, |
+ const storage::WatcherManager::NotificationCallback& |
+ notification_callback) { |
+ return file_system_->AddWatcher(origin, entry_path, recursive, persistent, |
+ callback, notification_callback); |
+} |
+ |
+void ThrottledFileSystem::RemoveWatcher( |
+ const GURL& origin, |
+ const base::FilePath& entry_path, |
+ bool recursive, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ file_system_->RemoveWatcher(origin, entry_path, recursive, callback); |
+} |
+ |
+const ProvidedFileSystemInfo& ThrottledFileSystem::GetFileSystemInfo() const { |
+ return file_system_->GetFileSystemInfo(); |
+} |
+ |
+RequestManager* ThrottledFileSystem::GetRequestManager() { |
+ return file_system_->GetRequestManager(); |
+} |
+ |
+Watchers* ThrottledFileSystem::GetWatchers() { |
+ return file_system_->GetWatchers(); |
+} |
+ |
+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, |
+ scoped_ptr<ProvidedFileSystemObserver::Changes> changes, |
+ const std::string& tag, |
+ const storage::AsyncFileUtil::StatusCallback& callback) { |
+ return file_system_->Notify(entry_path, recursive, change_type, |
+ changes.Pass(), tag, callback); |
+} |
+ |
+base::WeakPtr<ProvidedFileSystemInterface> ThrottledFileSystem::GetWeakPtr() { |
+ return weak_ptr_factory_.GetWeakPtr(); |
+} |
+ |
+void ThrottledFileSystem::OnOpenFileCompleted(int queue_token, |
+ const OpenFileCallback& callback, |
+ int file_handle, |
+ base::File::Error result) { |
+ open_queue_->Complete(queue_token); |
+ |
+ // 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_->Remove(queue_token); |
+ |
+ callback.Run(file_handle, result); |
+} |
+ |
+void ThrottledFileSystem::OnCloseFileCompleted( |
+ int file_handle, |
+ const 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_->Remove(queue_token); |
+ opened_files_.erase(file_handle); |
+ |
+ callback.Run(result); |
+} |
+ |
+} // namespace file_system_provider |
+} // namespace chromeos |