OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h" | 5 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h" | 10 #include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h" |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 DCHECK(!manager); | 148 DCHECK(!manager); |
149 continuation.Run(current_task_token.Pass()); | 149 continuation.Run(current_task_token.Pass()); |
150 return; | 150 return; |
151 } | 151 } |
152 | 152 |
153 if (!manager) | 153 if (!manager) |
154 return; | 154 return; |
155 | 155 |
156 scoped_ptr<SyncTaskToken> foreground_task_token; | 156 scoped_ptr<SyncTaskToken> foreground_task_token; |
157 scoped_ptr<SyncTaskToken> background_task_token; | 157 scoped_ptr<SyncTaskToken> background_task_token; |
| 158 scoped_ptr<TaskLogger::TaskLog> task_log = current_task_token->PassTaskLog(); |
158 if (current_task_token->token_id() == SyncTaskToken::kForegroundTaskTokenID) | 159 if (current_task_token->token_id() == SyncTaskToken::kForegroundTaskTokenID) |
159 foreground_task_token = current_task_token.Pass(); | 160 foreground_task_token = current_task_token.Pass(); |
160 else | 161 else |
161 background_task_token = current_task_token.Pass(); | 162 background_task_token = current_task_token.Pass(); |
162 | 163 |
163 manager->UpdateBlockingFactorBody(foreground_task_token.Pass(), | 164 manager->UpdateBlockingFactorBody(foreground_task_token.Pass(), |
164 background_task_token.Pass(), | 165 background_task_token.Pass(), |
| 166 task_log.Pass(), |
165 blocking_factor.Pass(), | 167 blocking_factor.Pass(), |
166 continuation); | 168 continuation); |
167 } | 169 } |
168 | 170 |
169 bool SyncTaskManager::IsRunningTask(int64 token_id) const { | 171 bool SyncTaskManager::IsRunningTask(int64 token_id) const { |
170 // If the client is gone, all task should be aborted. | 172 // If the client is gone, all task should be aborted. |
171 if (!client_) | 173 if (!client_) |
172 return false; | 174 return false; |
173 | 175 |
174 if (token_id == SyncTaskToken::kForegroundTaskTokenID) | 176 if (token_id == SyncTaskToken::kForegroundTaskTokenID) |
175 return true; | 177 return true; |
176 | 178 |
177 return ContainsKey(running_background_tasks_, token_id); | 179 return ContainsKey(running_background_tasks_, token_id); |
178 } | 180 } |
179 | 181 |
180 void SyncTaskManager::NotifyTaskDoneBody(scoped_ptr<SyncTaskToken> token, | 182 void SyncTaskManager::NotifyTaskDoneBody(scoped_ptr<SyncTaskToken> token, |
181 SyncStatusCode status) { | 183 SyncStatusCode status) { |
182 DCHECK(token); | 184 DCHECK(token); |
183 | 185 |
184 DVLOG(3) << "NotifyTaskDone: " << "finished with status=" << status | 186 DVLOG(3) << "NotifyTaskDone: " << "finished with status=" << status |
185 << " (" << SyncStatusCodeToString(status) << ")" | 187 << " (" << SyncStatusCodeToString(status) << ")" |
186 << " " << token_->location().ToString(); | 188 << " " << token_->location().ToString(); |
187 | 189 |
188 if (token->blocking_factor()) { | 190 if (token->blocking_factor()) { |
189 dependency_manager_.Erase(token->blocking_factor()); | 191 dependency_manager_.Erase(token->blocking_factor()); |
190 token->clear_blocking_factor(); | 192 token->clear_blocking_factor(); |
191 } | 193 } |
192 | 194 |
193 // TODO(tzik): Record TaskLog to |client_| here. | 195 if (client_) |
| 196 client_->RecordTaskLog(token->PassTaskLog()); |
194 | 197 |
195 scoped_ptr<SyncTask> task; | 198 scoped_ptr<SyncTask> task; |
196 SyncStatusCallback callback = token->callback(); | 199 SyncStatusCallback callback = token->callback(); |
197 token->clear_callback(); | 200 token->clear_callback(); |
198 if (token->token_id() == SyncTaskToken::kForegroundTaskTokenID) { | 201 if (token->token_id() == SyncTaskToken::kForegroundTaskTokenID) { |
199 token_ = token.Pass(); | 202 token_ = token.Pass(); |
200 task = running_foreground_task_.Pass(); | 203 task = running_foreground_task_.Pass(); |
201 } else { | 204 } else { |
202 task = running_background_tasks_.take_and_erase(token->token_id()); | 205 task = running_background_tasks_.take_and_erase(token->token_id()); |
203 } | 206 } |
204 | 207 |
205 bool task_used_network = false; | 208 bool task_used_network = false; |
206 if (task) | 209 if (task) |
207 task_used_network = task->used_network(); | 210 task_used_network = task->used_network(); |
208 | 211 |
209 if (client_) | 212 if (client_) |
210 client_->NotifyLastOperationStatus(status, task_used_network); | 213 client_->NotifyLastOperationStatus(status, task_used_network); |
211 | 214 |
212 if (!callback.is_null()) | 215 if (!callback.is_null()) |
213 callback.Run(status); | 216 callback.Run(status); |
214 | 217 |
215 StartNextTask(); | 218 StartNextTask(); |
216 } | 219 } |
217 | 220 |
218 void SyncTaskManager::UpdateBlockingFactorBody( | 221 void SyncTaskManager::UpdateBlockingFactorBody( |
219 scoped_ptr<SyncTaskToken> foreground_task_token, | 222 scoped_ptr<SyncTaskToken> foreground_task_token, |
220 scoped_ptr<SyncTaskToken> background_task_token, | 223 scoped_ptr<SyncTaskToken> background_task_token, |
| 224 scoped_ptr<TaskLogger::TaskLog> task_log, |
221 scoped_ptr<BlockingFactor> blocking_factor, | 225 scoped_ptr<BlockingFactor> blocking_factor, |
222 const Continuation& continuation) { | 226 const Continuation& continuation) { |
223 // Run the task directly if the parallelization is disabled. | 227 // Run the task directly if the parallelization is disabled. |
224 if (!maximum_background_task_) { | 228 if (!maximum_background_task_) { |
225 DCHECK(foreground_task_token); | 229 DCHECK(foreground_task_token); |
226 DCHECK(!background_task_token); | 230 DCHECK(!background_task_token); |
227 continuation.Run(foreground_task_token.Pass()); | 231 continuation.Run(foreground_task_token.Pass()); |
228 return; | 232 return; |
229 } | 233 } |
230 | 234 |
231 // Clear existing |blocking_factor| from |dependency_manager_| before | 235 // Clear existing |blocking_factor| from |dependency_manager_| before |
232 // getting |foreground_task_token|, so that we can avoid dead lock. | 236 // getting |foreground_task_token|, so that we can avoid dead lock. |
233 if (background_task_token && background_task_token->blocking_factor()) { | 237 if (background_task_token && background_task_token->blocking_factor()) { |
234 dependency_manager_.Erase(background_task_token->blocking_factor()); | 238 dependency_manager_.Erase(background_task_token->blocking_factor()); |
235 background_task_token->clear_blocking_factor(); | 239 background_task_token->clear_blocking_factor(); |
236 } | 240 } |
237 | 241 |
238 // Try to get |foreground_task_token|. If it's not available, wait for | 242 // Try to get |foreground_task_token|. If it's not available, wait for |
239 // current foreground task to finish. | 243 // current foreground task to finish. |
240 if (!foreground_task_token) { | 244 if (!foreground_task_token) { |
241 DCHECK(background_task_token); | 245 DCHECK(background_task_token); |
242 foreground_task_token = GetToken(background_task_token->location(), | 246 foreground_task_token = GetToken(background_task_token->location(), |
243 SyncStatusCallback()); | 247 SyncStatusCallback()); |
244 if (!foreground_task_token) { | 248 if (!foreground_task_token) { |
245 PushPendingTask( | 249 PushPendingTask( |
246 base::Bind(&SyncTaskManager::UpdateBlockingFactorBody, | 250 base::Bind(&SyncTaskManager::UpdateBlockingFactorBody, |
247 AsWeakPtr(), | 251 AsWeakPtr(), |
248 base::Passed(&foreground_task_token), | 252 base::Passed(&foreground_task_token), |
249 base::Passed(&background_task_token), | 253 base::Passed(&background_task_token), |
| 254 base::Passed(&task_log), |
250 base::Passed(&blocking_factor), | 255 base::Passed(&blocking_factor), |
251 continuation), | 256 continuation), |
252 PRIORITY_HIGH); | 257 PRIORITY_HIGH); |
253 StartNextTask(); | 258 StartNextTask(); |
254 return; | 259 return; |
255 } | 260 } |
256 } | 261 } |
257 | 262 |
258 // Check if the task can run as a background task now. | 263 // Check if the task can run as a background task now. |
259 // If there are too many task running or any other task blocks current | 264 // If there are too many task running or any other task blocks current |
260 // task, wait for any other task to finish. | 265 // task, wait for any other task to finish. |
261 bool task_number_limit_exceeded = | 266 bool task_number_limit_exceeded = |
262 !background_task_token && | 267 !background_task_token && |
263 running_background_tasks_.size() >= maximum_background_task_; | 268 running_background_tasks_.size() >= maximum_background_task_; |
264 if (task_number_limit_exceeded || | 269 if (task_number_limit_exceeded || |
265 !dependency_manager_.Insert(blocking_factor.get())) { | 270 !dependency_manager_.Insert(blocking_factor.get())) { |
266 DCHECK(!running_background_tasks_.empty()); | 271 DCHECK(!running_background_tasks_.empty()); |
267 DCHECK(pending_backgrounding_task_.is_null()); | 272 DCHECK(pending_backgrounding_task_.is_null()); |
268 | 273 |
269 // Wait for NotifyTaskDone to release a |blocking_factor|. | 274 // Wait for NotifyTaskDone to release a |blocking_factor|. |
270 pending_backgrounding_task_ = | 275 pending_backgrounding_task_ = |
271 base::Bind(&SyncTaskManager::UpdateBlockingFactorBody, | 276 base::Bind(&SyncTaskManager::UpdateBlockingFactorBody, |
272 AsWeakPtr(), | 277 AsWeakPtr(), |
273 base::Passed(&foreground_task_token), | 278 base::Passed(&foreground_task_token), |
274 base::Passed(&background_task_token), | 279 base::Passed(&background_task_token), |
| 280 base::Passed(&task_log), |
275 base::Passed(&blocking_factor), | 281 base::Passed(&blocking_factor), |
276 continuation); | 282 continuation); |
277 return; | 283 return; |
278 } | 284 } |
279 | 285 |
280 if (background_task_token) { | 286 if (background_task_token) { |
281 background_task_token->set_blocking_factor(blocking_factor.Pass()); | 287 background_task_token->set_blocking_factor(blocking_factor.Pass()); |
282 } else { | 288 } else { |
283 tracked_objects::Location from_here = foreground_task_token->location(); | 289 tracked_objects::Location from_here = foreground_task_token->location(); |
284 SyncStatusCallback callback = foreground_task_token->callback(); | 290 SyncStatusCallback callback = foreground_task_token->callback(); |
285 foreground_task_token->clear_callback(); | 291 foreground_task_token->clear_callback(); |
286 | 292 |
287 background_task_token = | 293 background_task_token = |
288 SyncTaskToken::CreateForBackgroundTask( | 294 SyncTaskToken::CreateForBackgroundTask( |
289 AsWeakPtr(), | 295 AsWeakPtr(), |
290 task_token_seq_++, | 296 task_token_seq_++, |
291 blocking_factor.Pass()); | 297 blocking_factor.Pass()); |
292 background_task_token->UpdateTask(from_here, callback); | 298 background_task_token->UpdateTask(from_here, callback); |
293 running_background_tasks_.set(background_task_token->token_id(), | 299 running_background_tasks_.set(background_task_token->token_id(), |
294 running_foreground_task_.Pass()); | 300 running_foreground_task_.Pass()); |
295 } | 301 } |
296 | 302 |
297 token_ = foreground_task_token.Pass(); | 303 token_ = foreground_task_token.Pass(); |
298 StartNextTask(); | 304 StartNextTask(); |
| 305 background_task_token->SetTaskLog(task_log.Pass()); |
299 continuation.Run(background_task_token.Pass()); | 306 continuation.Run(background_task_token.Pass()); |
300 } | 307 } |
301 | 308 |
302 scoped_ptr<SyncTaskToken> SyncTaskManager::GetToken( | 309 scoped_ptr<SyncTaskToken> SyncTaskManager::GetToken( |
303 const tracked_objects::Location& from_here, | 310 const tracked_objects::Location& from_here, |
304 const SyncStatusCallback& callback) { | 311 const SyncStatusCallback& callback) { |
305 if (!token_) | 312 if (!token_) |
306 return scoped_ptr<SyncTaskToken>(); | 313 return scoped_ptr<SyncTaskToken>(); |
307 token_->UpdateTask(from_here, callback); | 314 token_->UpdateTask(from_here, callback); |
308 return token_.Pass(); | 315 return token_.Pass(); |
309 } | 316 } |
310 | 317 |
311 void SyncTaskManager::PushPendingTask( | 318 void SyncTaskManager::PushPendingTask( |
312 const base::Closure& closure, Priority priority) { | 319 const base::Closure& closure, Priority priority) { |
313 pending_tasks_.push(PendingTask(closure, priority, pending_task_seq_++)); | 320 pending_tasks_.push(PendingTask(closure, priority, pending_task_seq_++)); |
314 } | 321 } |
315 | 322 |
316 void SyncTaskManager::RunTask(scoped_ptr<SyncTaskToken> token, | 323 void SyncTaskManager::RunTask(scoped_ptr<SyncTaskToken> token, |
317 scoped_ptr<SyncTask> task) { | 324 scoped_ptr<SyncTask> task) { |
318 DCHECK(!running_foreground_task_); | 325 DCHECK(!running_foreground_task_); |
| 326 |
| 327 token->SetTaskLog(make_scoped_ptr(new TaskLogger::TaskLog)); |
| 328 |
319 running_foreground_task_ = task.Pass(); | 329 running_foreground_task_ = task.Pass(); |
320 running_foreground_task_->RunPreflight(token.Pass()); | 330 running_foreground_task_->RunPreflight(token.Pass()); |
321 } | 331 } |
322 | 332 |
323 void SyncTaskManager::StartNextTask() { | 333 void SyncTaskManager::StartNextTask() { |
324 if (!pending_backgrounding_task_.is_null()) { | 334 if (!pending_backgrounding_task_.is_null()) { |
325 base::Closure closure = pending_backgrounding_task_; | 335 base::Closure closure = pending_backgrounding_task_; |
326 pending_backgrounding_task_.Reset(); | 336 pending_backgrounding_task_.Reset(); |
327 closure.Run(); | 337 closure.Run(); |
328 return; | 338 return; |
329 } | 339 } |
330 | 340 |
331 if (!pending_tasks_.empty()) { | 341 if (!pending_tasks_.empty()) { |
332 base::Closure closure = pending_tasks_.top().task; | 342 base::Closure closure = pending_tasks_.top().task; |
333 pending_tasks_.pop(); | 343 pending_tasks_.pop(); |
334 closure.Run(); | 344 closure.Run(); |
335 return; | 345 return; |
336 } | 346 } |
337 | 347 |
338 if (client_) | 348 if (client_) |
339 client_->MaybeScheduleNextTask(); | 349 client_->MaybeScheduleNextTask(); |
340 } | 350 } |
341 | 351 |
342 } // namespace drive_backend | 352 } // namespace drive_backend |
343 } // namespace sync_file_system | 353 } // namespace sync_file_system |
OLD | NEW |