1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/sync_file_system/local/syncable_file_operation_runner.h" 6 7 #include <algorithm> 8 #include <functional> 9 10 #include "base/callback.h" 11 #include "base/stl_util.h" 12 13 using storage::FileSystemURL; 14 15 namespace sync_file_system { 16 17 // SyncableFileOperationRunner::Task ------------------------------------------- 18 19 // static 20 void SyncableFileOperationRunner::Task::CancelAndDelete( 21 SyncableFileOperationRunner::Task* task) { 22 task->Cancel(); 23 delete task; 24 } 25 26 bool SyncableFileOperationRunner::Task::IsRunnable( 27 LocalFileSyncStatus* status) const { 28 for (size_t i = 0; i < target_paths().size(); ++i) { 29 if (!status->IsWritable(target_paths()[i])) 30 return false; 31 } 32 return true; 33 } 34 35 void SyncableFileOperationRunner::Task::Start(LocalFileSyncStatus* status) { 36 for (size_t i = 0; i < target_paths().size(); ++i) { 37 DCHECK(status->IsWritable(target_paths()[i])); 38 status->StartWriting(target_paths()[i]); 39 } 40 Run(); 41 } 42 43 // SyncableFileOperationRunner ------------------------------------------------- 44 45 SyncableFileOperationRunner::SyncableFileOperationRunner( 46 int64 max_inflight_tasks, 47 LocalFileSyncStatus* sync_status) 48 : sync_status_(sync_status), 49 max_inflight_tasks_(max_inflight_tasks), 50 num_inflight_tasks_(0) { 51 DCHECK(CalledOnValidThread()); 52 sync_status_->AddObserver(this); 53 } 54 55 SyncableFileOperationRunner::~SyncableFileOperationRunner() { 56 DCHECK(CalledOnValidThread()); 57 for_each(pending_tasks_.begin(), pending_tasks_.end(), 58 SyncableFileOperationRunner::Task::CancelAndDelete); 59 } 60 61 void SyncableFileOperationRunner::OnSyncEnabled(const FileSystemURL& url) { 62 } 63 64 void SyncableFileOperationRunner::OnWriteEnabled(const FileSystemURL& url) { 65 DCHECK(CalledOnValidThread()); 66 RunNextRunnableTask(); 67 } 68 69 void SyncableFileOperationRunner::PostOperationTask(scoped_ptr<Task> task) { 70 DCHECK(CalledOnValidThread()); 71 pending_tasks_.push_back(task.release()); 72 RunNextRunnableTask(); 73 } 74 75 void SyncableFileOperationRunner::RunNextRunnableTask() { 76 DCHECK(CalledOnValidThread()); 77 for (std::list<Task*>::iterator iter = pending_tasks_.begin(); 78 iter != pending_tasks_.end() && ShouldStartMoreTasks();) { 79 if ((*iter)->IsRunnable(sync_status())) { 80 ++num_inflight_tasks_; 81 DCHECK_GE(num_inflight_tasks_, 1); 82 scoped_ptr<Task> task(*iter); 83 pending_tasks_.erase(iter++); 84 task->Start(sync_status()); 85 continue; 86 } 87 ++iter; 88 } 89 } 90 91 void SyncableFileOperationRunner::OnOperationCompleted( 92 const std::vector<FileSystemURL>& target_paths) { 93 --num_inflight_tasks_; 94 DCHECK_GE(num_inflight_tasks_, 0); 95 for (size_t i = 0; i < target_paths.size(); ++i) { 96 DCHECK(sync_status()->IsWriting(target_paths[i])); 97 sync_status()->EndWriting(target_paths[i]); 98 } 99 RunNextRunnableTask(); 100 } 101 102 bool SyncableFileOperationRunner::ShouldStartMoreTasks() const { 103 return num_inflight_tasks_ < max_inflight_tasks_; 104 } 105 106 } // namespace sync_file_system 107