sync_task_manager.h revision effb81e5f8246d0db0270817048dc992db66e9fb
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
23namespace tracked_objects {
24class Location;
25}
26
27namespace sync_file_system {
28namespace drive_backend {
29
30class SyncTaskToken;
31struct BlockingFactor;
32
33class SyncTaskManager
34    : public base::NonThreadSafe,
35      public base::SupportsWeakPtr<SyncTaskManager> {
36 public:
37  typedef base::Callback<void(const SyncStatusCallback& callback)> Task;
38  typedef base::Callback<void(scoped_ptr<SyncTaskToken> token)> Continuation;
39
40  enum Priority {
41    PRIORITY_LOW,
42    PRIORITY_MED,
43    PRIORITY_HIGH,
44  };
45
46  class Client {
47   public:
48    virtual ~Client() {}
49
50    // Called when the manager is idle.
51    virtual void MaybeScheduleNextTask() = 0;
52
53    // Called when the manager is notified a task is done.
54    virtual void NotifyLastOperationStatus(
55        SyncStatusCode last_operation_status,
56        bool last_operation_used_network) = 0;
57  };
58
59  // Runs at most |maximum_background_tasks| parallel as background tasks.
60  // If |maximum_background_tasks| is zero, all task runs as foreground task.
61  SyncTaskManager(base::WeakPtr<Client> client,
62                  size_t maximum_background_task);
63  virtual ~SyncTaskManager();
64
65  // This needs to be called to start task scheduling.
66  // If |status| is not SYNC_STATUS_OK calling this may change the
67  // service status. This should not be called more than once.
68  void Initialize(SyncStatusCode status);
69
70  // Schedules a task at the given priority.
71  void ScheduleTask(const tracked_objects::Location& from_here,
72                    const Task& task,
73                    Priority priority,
74                    const SyncStatusCallback& callback);
75  void ScheduleSyncTask(const tracked_objects::Location& from_here,
76                        scoped_ptr<SyncTask> task,
77                        Priority priority,
78                        const SyncStatusCallback& callback);
79
80  // Runs the posted task only when we're idle.  Returns true if tha task is
81  // scheduled.
82  bool ScheduleTaskIfIdle(const tracked_objects::Location& from_here,
83                          const Task& task,
84                          const SyncStatusCallback& callback);
85  bool ScheduleSyncTaskIfIdle(const tracked_objects::Location& from_here,
86                              scoped_ptr<SyncTask> task,
87                              const SyncStatusCallback& callback);
88
89  static void NotifyTaskDone(scoped_ptr<SyncTaskToken> token,
90                             SyncStatusCode status);
91  static void MoveTaskToBackground(scoped_ptr<SyncTaskToken> token,
92                                   scoped_ptr<BlockingFactor> blocking_factor,
93                                   const Continuation& continuation);
94
95  bool IsRunningTask(int64 task_token_id) const;
96
97 private:
98  struct PendingTask {
99    base::Closure task;
100    Priority priority;
101    int64 seq;
102
103    PendingTask();
104    PendingTask(const base::Closure& task, Priority pri, int seq);
105    ~PendingTask();
106  };
107
108  struct PendingTaskComparator {
109    bool operator()(const PendingTask& left,
110                    const PendingTask& right) const;
111  };
112
113  // Non-static version of NotifyTaskDone.
114  void NotifyTaskDoneBody(scoped_ptr<SyncTaskToken> token,
115                          SyncStatusCode status);
116
117  // Notifies SyncTaskManager that the running task turned to a background task.
118  void NotifyTaskBackgrounded(scoped_ptr<SyncTaskToken> foreground_task_token,
119                              const SyncTaskToken& background_task_token);
120
121  // Non-static version of MoveTaskToBackground.
122  void MoveTaskToBackgroundBody(scoped_ptr<SyncTaskToken> token,
123                                scoped_ptr<BlockingFactor> blocking_factor,
124                                const Continuation& continuation);
125
126  // Returns true if no running background task blocks |blocking_factor|.
127  bool CanRunAsBackgroundTask(const BlockingFactor& blocking_factor);
128
129  // This should be called when an async task needs to get a task token.
130  scoped_ptr<SyncTaskToken> GetToken(const tracked_objects::Location& from_here,
131                                     const SyncStatusCallback& callback);
132
133  scoped_ptr<SyncTaskToken> GetTokenForBackgroundTask(
134      const tracked_objects::Location& from_here,
135      const SyncStatusCallback& callback,
136      scoped_ptr<BlockingFactor> blocking_factor);
137
138  void PushPendingTask(const base::Closure& closure, Priority priority);
139
140  void RunTask(scoped_ptr<SyncTaskToken> token,
141               scoped_ptr<SyncTask> task);
142
143  void StartNextTask();
144
145  base::WeakPtr<Client> client_;
146
147  // Owns running SyncTask to cancel the task on SyncTaskManager deletion.
148  scoped_ptr<SyncTask> running_task_;
149
150  // Owns running backgrounded SyncTask to cancel the task on SyncTaskManager
151  // deletion.
152  base::ScopedPtrHashMap<int64, SyncTask> running_background_task_;
153
154  size_t maximum_background_task_;
155
156  // Holds pending continuation to move task to background.
157  base::Closure pending_backgrounding_task_;
158
159  std::priority_queue<PendingTask, std::vector<PendingTask>,
160                      PendingTaskComparator> pending_tasks_;
161  int64 pending_task_seq_;
162  int64 task_token_seq_;
163
164  // Absence of |token_| implies a task is running. Incoming tasks should
165  // wait for the task to finish in |pending_tasks_| if |token_| is null.
166  // Each task must take TaskToken instance from |token_| and must hold it
167  // until it finished. And the task must return the instance through
168  // NotifyTaskDone when the task finished.
169  scoped_ptr<SyncTaskToken> token_;
170
171  TaskDependencyManager dependency_manager_;
172
173  DISALLOW_COPY_AND_ASSIGN(SyncTaskManager);
174};
175
176}  // namespace drive_backend
177}  // namespace sync_file_system
178
179#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_SYNC_TASK_MANAGER_H_
180