// Copyright 2013 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 "webkit/browser/fileapi/syncable/syncable_file_operation_runner.h" #include #include #include "base/callback.h" #include "base/stl_util.h" #include "webkit/browser/fileapi/syncable/local_file_sync_status.h" using fileapi::FileSystemURL; namespace sync_file_system { // SyncableFileOperationRunner::Task ------------------------------------------- // static void SyncableFileOperationRunner::Task::CancelAndDelete( SyncableFileOperationRunner::Task* task) { task->Cancel(); delete task; } bool SyncableFileOperationRunner::Task::IsRunnable( LocalFileSyncStatus* status) const { for (size_t i = 0; i < target_paths().size(); ++i) { if (!status->IsWritable(target_paths()[i])) return false; } return true; } void SyncableFileOperationRunner::Task::Start(LocalFileSyncStatus* status) { for (size_t i = 0; i < target_paths().size(); ++i) { DCHECK(status->IsWritable(target_paths()[i])); status->StartWriting(target_paths()[i]); } Run(); } // SyncableFileOperationRunner ------------------------------------------------- SyncableFileOperationRunner::SyncableFileOperationRunner( int64 max_inflight_tasks, LocalFileSyncStatus* sync_status) : sync_status_(sync_status), max_inflight_tasks_(max_inflight_tasks), num_inflight_tasks_(0) { DCHECK(CalledOnValidThread()); sync_status_->AddObserver(this); } SyncableFileOperationRunner::~SyncableFileOperationRunner() { DCHECK(CalledOnValidThread()); for_each(pending_tasks_.begin(), pending_tasks_.end(), SyncableFileOperationRunner::Task::CancelAndDelete); } void SyncableFileOperationRunner::OnSyncEnabled(const FileSystemURL& url) { } void SyncableFileOperationRunner::OnWriteEnabled(const FileSystemURL& url) { DCHECK(CalledOnValidThread()); RunNextRunnableTask(); } void SyncableFileOperationRunner::PostOperationTask(scoped_ptr task) { DCHECK(CalledOnValidThread()); pending_tasks_.push_back(task.release()); RunNextRunnableTask(); } void SyncableFileOperationRunner::RunNextRunnableTask() { DCHECK(CalledOnValidThread()); for (std::list::iterator iter = pending_tasks_.begin(); iter != pending_tasks_.end() && ShouldStartMoreTasks();) { if ((*iter)->IsRunnable(sync_status())) { ++num_inflight_tasks_; DCHECK_GE(num_inflight_tasks_, 1); scoped_ptr task(*iter); pending_tasks_.erase(iter++); task->Start(sync_status()); continue; } ++iter; } } void SyncableFileOperationRunner::OnOperationCompleted( const std::vector& target_paths) { --num_inflight_tasks_; DCHECK_GE(num_inflight_tasks_, 0); for (size_t i = 0; i < target_paths.size(); ++i) { DCHECK(sync_status()->IsWriting(target_paths[i])); sync_status()->EndWriting(target_paths[i]); } RunNextRunnableTask(); } bool SyncableFileOperationRunner::ShouldStartMoreTasks() const { return num_inflight_tasks_ < max_inflight_tasks_; } } // namespace sync_file_system