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