| 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 |