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