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