Home | History | Annotate | Download | only in local
      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