Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / sync_task_manager.cc
bloba5c532deccf78d240b2f737a321e2d899eeb7c58
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.
5 #include "chrome/browser/sync_file_system/sync_task_manager.h"
7 #include "base/debug/trace_event.h"
8 #include "base/location.h"
9 #include "chrome/browser/sync_file_system/sync_file_metadata.h"
11 using fileapi::FileSystemURL;
13 namespace sync_file_system {
15 class SyncTaskManager::TaskToken {
16 public:
17 explicit TaskToken(const base::WeakPtr<SyncTaskManager>& manager)
18 : manager_(manager) {
21 void UpdateTask(const tracked_objects::Location& location) {
22 location_ = location;
23 DVLOG(2) << "Token updated: " << location_.ToString();
26 const tracked_objects::Location& location() const { return location_; }
28 ~TaskToken() {
29 // All task on Client must hold TaskToken instance to ensure
30 // no other tasks are running. Also, as soon as a task finishes to work,
31 // it must return the token to TaskManager.
32 // Destroying a token with valid |client| indicates the token was
33 // dropped by a task without returning.
34 if (manager_.get() && manager_->client_.get()) {
35 NOTREACHED()
36 << "Unexpected TaskToken deletion from: " << location_.ToString();
38 // Reinitializes the token.
39 manager_->NotifyTaskDone(
40 make_scoped_ptr(new TaskToken(manager_)),
41 SYNC_STATUS_OK);
45 private:
46 base::WeakPtr<SyncTaskManager> manager_;
47 tracked_objects::Location location_;
49 DISALLOW_COPY_AND_ASSIGN(TaskToken);
52 SyncTaskManager::PendingTask::PendingTask() {}
54 SyncTaskManager::PendingTask::PendingTask(
55 const base::Closure& task, Priority pri, int seq)
56 : task(task), priority(pri), seq(seq) {}
58 SyncTaskManager::PendingTask::~PendingTask() {}
60 bool SyncTaskManager::PendingTaskComparator::operator()(
61 const PendingTask& left,
62 const PendingTask& right) const {
63 if (left.priority != right.priority)
64 return left.priority < right.priority;
65 return left.seq > right.seq;
68 SyncTaskManager::SyncTaskManager(
69 base::WeakPtr<Client> client)
70 : client_(client),
71 last_operation_status_(SYNC_STATUS_OK),
72 pending_task_seq_(0) {
75 SyncTaskManager::~SyncTaskManager() {
76 client_.reset();
77 token_.reset();
80 void SyncTaskManager::Initialize(SyncStatusCode status) {
81 DCHECK(!token_);
82 NotifyTaskDone(make_scoped_ptr(new TaskToken(AsWeakPtr())),
83 status);
86 void SyncTaskManager::ScheduleTask(
87 const Task& task,
88 const SyncStatusCallback& callback) {
89 ScheduleTaskAtPriority(task, PRIORITY_MED, callback);
92 void SyncTaskManager::ScheduleSyncTask(
93 scoped_ptr<SyncTask> task,
94 const SyncStatusCallback& callback) {
95 ScheduleSyncTaskAtPriority(task.Pass(), PRIORITY_MED, callback);
98 void SyncTaskManager::ScheduleTaskAtPriority(
99 const Task& task,
100 Priority priority,
101 const SyncStatusCallback& callback) {
102 scoped_ptr<TaskToken> token(GetToken(FROM_HERE));
103 if (!token) {
104 PushPendingTask(
105 base::Bind(&SyncTaskManager::ScheduleTask, AsWeakPtr(),
106 task, callback),
107 priority);
108 return;
110 task.Run(CreateCompletionCallback(token.Pass(), callback));
113 void SyncTaskManager::ScheduleSyncTaskAtPriority(
114 scoped_ptr<SyncTask> task,
115 Priority priority,
116 const SyncStatusCallback& callback) {
117 scoped_ptr<TaskToken> token(GetToken(FROM_HERE));
118 if (!token) {
119 PushPendingTask(
120 base::Bind(&SyncTaskManager::ScheduleSyncTask,
121 AsWeakPtr(), base::Passed(&task), callback),
122 priority);
123 return;
125 DCHECK(!running_task_);
126 running_task_ = task.Pass();
127 running_task_->Run(CreateCompletionCallback(token.Pass(), callback));
130 bool SyncTaskManager::ScheduleTaskIfIdle(const Task& task,
131 const SyncStatusCallback& callback) {
132 scoped_ptr<TaskToken> token(GetToken(FROM_HERE));
133 if (!token)
134 return false;
135 task.Run(CreateCompletionCallback(token.Pass(), callback));
136 return true;
139 bool SyncTaskManager::ScheduleSyncTaskIfIdle(
140 scoped_ptr<SyncTask> task,
141 const SyncStatusCallback& callback) {
142 scoped_ptr<TaskToken> token(GetToken(FROM_HERE));
143 if (!token)
144 return false;
145 DCHECK(!running_task_);
146 running_task_ = task.Pass();
147 running_task_->Run(CreateCompletionCallback(token.Pass(),
148 callback));
149 return true;
152 void SyncTaskManager::NotifyTaskDone(
153 scoped_ptr<TaskToken> token,
154 SyncStatusCode status) {
155 DCHECK(token);
156 last_operation_status_ = status;
157 token_ = token.Pass();
158 scoped_ptr<SyncTask> task = running_task_.Pass();
159 TRACE_EVENT_ASYNC_END0("Sync FileSystem", "GetToken", this);
161 DVLOG(3) << "NotifyTaskDone: " << "finished with status=" << status
162 << " (" << SyncStatusCodeToString(status) << ")"
163 << " " << token_->location().ToString();
165 bool task_used_network = false;
166 if (task)
167 task_used_network = task->used_network();
169 if (client_)
170 client_->NotifyLastOperationStatus(last_operation_status_,
171 task_used_network);
173 if (!current_callback_.is_null()) {
174 SyncStatusCallback callback = current_callback_;
175 current_callback_.Reset();
176 callback.Run(status);
179 if (!pending_tasks_.empty()) {
180 base::Closure closure = pending_tasks_.top().task;
181 pending_tasks_.pop();
182 closure.Run();
183 return;
186 if (client_)
187 client_->MaybeScheduleNextTask();
190 scoped_ptr<SyncTaskManager::TaskToken> SyncTaskManager::GetToken(
191 const tracked_objects::Location& from_here) {
192 if (!token_)
193 return scoped_ptr<TaskToken>();
194 TRACE_EVENT_ASYNC_BEGIN1("Sync FileSystem", "GetToken", this,
195 "where", from_here.ToString());
196 token_->UpdateTask(from_here);
197 return token_.Pass();
200 SyncStatusCallback SyncTaskManager::CreateCompletionCallback(
201 scoped_ptr<TaskToken> token,
202 const SyncStatusCallback& callback) {
203 DCHECK(token);
204 DCHECK(current_callback_.is_null());
205 current_callback_ = callback;
206 return base::Bind(&SyncTaskManager::NotifyTaskDone,
207 AsWeakPtr(), base::Passed(&token));
210 void SyncTaskManager::PushPendingTask(
211 const base::Closure& closure, Priority priority) {
212 pending_tasks_.push(PendingTask(closure, priority, pending_task_seq_++));
215 } // namespace sync_file_system