blob: 11053a2f7d0e9e90701459af74f492f18096ed65 [file] [log] [blame]
// 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 "chrome/browser/sync_file_system/local/syncable_file_operation_runner.h"
#include <algorithm>
#include <functional>
#include "base/callback.h"
#include "base/stl_util.h"
using storage::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> task) {
DCHECK(CalledOnValidThread());
pending_tasks_.push_back(task.release());
RunNextRunnableTask();
}
void SyncableFileOperationRunner::RunNextRunnableTask() {
DCHECK(CalledOnValidThread());
for (std::list<Task*>::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> task(*iter);
pending_tasks_.erase(iter++);
task->Start(sync_status());
continue;
}
++iter;
}
}
void SyncableFileOperationRunner::OnOperationCompleted(
const std::vector<FileSystemURL>& 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