sync_task_manager.h revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_SYNC_TASK_MANAGER_H_ 6#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_SYNC_TASK_MANAGER_H_ 7 8#include <queue> 9#include <vector> 10 11#include "base/callback.h" 12#include "base/containers/scoped_ptr_hash_map.h" 13#include "base/files/file_path.h" 14#include "base/location.h" 15#include "base/memory/scoped_ptr.h" 16#include "base/memory/weak_ptr.h" 17#include "base/threading/non_thread_safe.h" 18#include "chrome/browser/sync_file_system/drive_backend/sync_task.h" 19#include "chrome/browser/sync_file_system/drive_backend/task_dependency_manager.h" 20#include "chrome/browser/sync_file_system/sync_callbacks.h" 21#include "chrome/browser/sync_file_system/sync_status_code.h" 22#include "chrome/browser/sync_file_system/task_logger.h" 23 24namespace tracked_objects { 25class Location; 26} 27 28namespace sync_file_system { 29namespace drive_backend { 30 31class SyncTaskToken; 32struct BlockingFactor; 33 34// This class manages asynchronous tasks for Sync FileSystem. Each task must be 35// either a Task or a SyncTask. 36// The instance runs single task as the foreground task, and multiple tasks as 37// background tasks. Running background task has a BlockingFactor that 38// describes which task can run in parallel. When a task start running as a 39// background task, SyncTaskManager checks if any running background task 40// doesn't block the new background task, and queues it up if it can't run. 41class SyncTaskManager 42 : public base::NonThreadSafe, 43 public base::SupportsWeakPtr<SyncTaskManager> { 44 public: 45 typedef base::Callback<void(const SyncStatusCallback& callback)> Task; 46 typedef base::Callback<void(scoped_ptr<SyncTaskToken> token)> Continuation; 47 48 enum Priority { 49 PRIORITY_LOW, 50 PRIORITY_MED, 51 PRIORITY_HIGH, 52 }; 53 54 class Client { 55 public: 56 virtual ~Client() {} 57 58 // Called when the manager is idle. 59 virtual void MaybeScheduleNextTask() = 0; 60 61 // Called when the manager is notified a task is done. 62 virtual void NotifyLastOperationStatus( 63 SyncStatusCode last_operation_status, 64 bool last_operation_used_network) = 0; 65 66 virtual void RecordTaskLog(scoped_ptr<TaskLogger::TaskLog> task_log) = 0; 67 }; 68 69 // Runs at most |maximum_background_tasks| parallel as background tasks. 70 // If |maximum_background_tasks| is zero, all task runs as foreground task. 71 SyncTaskManager(base::WeakPtr<Client> client, 72 size_t maximum_background_task); 73 virtual ~SyncTaskManager(); 74 75 // This needs to be called to start task scheduling. 76 // If |status| is not SYNC_STATUS_OK calling this may change the 77 // service status. This should not be called more than once. 78 void Initialize(SyncStatusCode status); 79 80 // Schedules a task at the given priority. 81 void ScheduleTask(const tracked_objects::Location& from_here, 82 const Task& task, 83 Priority priority, 84 const SyncStatusCallback& callback); 85 void ScheduleSyncTask(const tracked_objects::Location& from_here, 86 scoped_ptr<SyncTask> task, 87 Priority priority, 88 const SyncStatusCallback& callback); 89 90 // Runs the posted task only when we're idle. Returns true if tha task is 91 // scheduled. 92 bool ScheduleTaskIfIdle(const tracked_objects::Location& from_here, 93 const Task& task, 94 const SyncStatusCallback& callback); 95 bool ScheduleSyncTaskIfIdle(const tracked_objects::Location& from_here, 96 scoped_ptr<SyncTask> task, 97 const SyncStatusCallback& callback); 98 99 // Notifies SyncTaskManager that the task associated to |token| has finished 100 // with |status|. 101 static void NotifyTaskDone(scoped_ptr<SyncTaskToken> token, 102 SyncStatusCode status); 103 104 // Updates |blocking_factor| associated to the current task by specified 105 // |blocking_factor| and turns the current task to a background task if 106 // the current task is running as a foreground task. 107 // If specified |blocking_factor| is blocked by any other blocking factor 108 // associated to an existing background task, this function waits for the 109 // existing background task to finish. 110 // Upon the task is ready to run as a background task, calls |continuation| 111 // with new SyncTaskToken. 112 // Note that this function once releases previous |blocking_factor| before 113 // applying new |blocking_factor|. So, any other task may be run before 114 // invocation of |continuation|. 115 static void UpdateBlockingFactor(scoped_ptr<SyncTaskToken> current_task_token, 116 scoped_ptr<BlockingFactor> blocking_factor, 117 const Continuation& continuation); 118 119 bool IsRunningTask(int64 task_token_id) const; 120 121 private: 122 struct PendingTask { 123 base::Closure task; 124 Priority priority; 125 int64 seq; 126 127 PendingTask(); 128 PendingTask(const base::Closure& task, Priority pri, int seq); 129 ~PendingTask(); 130 }; 131 132 struct PendingTaskComparator { 133 bool operator()(const PendingTask& left, 134 const PendingTask& right) const; 135 }; 136 137 // Non-static version of NotifyTaskDone. 138 void NotifyTaskDoneBody(scoped_ptr<SyncTaskToken> token, 139 SyncStatusCode status); 140 141 // Non-static version of UpdateBlockingFactor. 142 void UpdateBlockingFactorBody(scoped_ptr<SyncTaskToken> foreground_task_token, 143 scoped_ptr<SyncTaskToken> background_task_token, 144 scoped_ptr<TaskLogger::TaskLog> task_log, 145 scoped_ptr<BlockingFactor> blocking_factor, 146 const Continuation& continuation); 147 148 // This should be called when an async task needs to get a task token. 149 scoped_ptr<SyncTaskToken> GetToken(const tracked_objects::Location& from_here, 150 const SyncStatusCallback& callback); 151 152 scoped_ptr<SyncTaskToken> GetTokenForBackgroundTask( 153 const tracked_objects::Location& from_here, 154 const SyncStatusCallback& callback, 155 scoped_ptr<BlockingFactor> blocking_factor); 156 157 void PushPendingTask(const base::Closure& closure, Priority priority); 158 159 void RunTask(scoped_ptr<SyncTaskToken> token, 160 scoped_ptr<SyncTask> task); 161 162 void StartNextTask(); 163 164 base::WeakPtr<Client> client_; 165 166 // Owns running SyncTask to cancel the task on SyncTaskManager deletion. 167 scoped_ptr<SyncTask> running_foreground_task_; 168 169 // Owns running backgrounded SyncTask to cancel the task on SyncTaskManager 170 // deletion. 171 base::ScopedPtrHashMap<int64, SyncTask> running_background_tasks_; 172 173 size_t maximum_background_task_; 174 175 // Holds pending continuation to move task to background. 176 base::Closure pending_backgrounding_task_; 177 178 std::priority_queue<PendingTask, std::vector<PendingTask>, 179 PendingTaskComparator> pending_tasks_; 180 int64 pending_task_seq_; 181 int64 task_token_seq_; 182 183 // Absence of |token_| implies a task is running. Incoming tasks should 184 // wait for the task to finish in |pending_tasks_| if |token_| is null. 185 // Each task must take TaskToken instance from |token_| and must hold it 186 // until it finished. And the task must return the instance through 187 // NotifyTaskDone when the task finished. 188 scoped_ptr<SyncTaskToken> token_; 189 190 TaskDependencyManager dependency_manager_; 191 192 DISALLOW_COPY_AND_ASSIGN(SyncTaskManager); 193}; 194 195} // namespace drive_backend 196} // namespace sync_file_system 197 198#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_SYNC_TASK_MANAGER_H_ 199