job_scheduler.h revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
1// Copyright (c) 2012 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_CHROMEOS_DRIVE_JOB_SCHEDULER_H_
6#define CHROME_BROWSER_CHROMEOS_DRIVE_JOB_SCHEDULER_H_
7
8#include <list>
9#include <vector>
10
11#include "base/id_map.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/observer_list.h"
14#include "chrome/browser/chromeos/drive/file_system_interface.h"
15#include "chrome/browser/chromeos/drive/job_list.h"
16#include "chrome/browser/google_apis/drive_service_interface.h"
17#include "chrome/browser/google_apis/drive_uploader.h"
18#include "net/base/network_change_notifier.h"
19
20class Profile;
21
22namespace drive {
23
24// The JobScheduler is responsible for queuing and scheduling drive
25// operations.  It is responsible for handling retry logic, rate limiting, as
26// concurrency as appropriate.
27class JobScheduler
28    : public net::NetworkChangeNotifier::ConnectionTypeObserver,
29      public JobListInterface {
30 public:
31  JobScheduler(Profile* profile,
32               google_apis::DriveServiceInterface* drive_service);
33  virtual ~JobScheduler();
34
35  // JobListInterface overrides.
36  virtual std::vector<JobInfo> GetJobInfoList() OVERRIDE;
37  virtual void AddObserver(JobListObserver* observer) OVERRIDE;
38  virtual void RemoveObserver(JobListObserver* observer) OVERRIDE;
39  virtual void CancelJob(JobID job_id) OVERRIDE;
40  virtual void CancelAllJobs() OVERRIDE;
41
42  // Adds a GetAppList operation to the queue.
43  // |callback| must not be null.
44  void GetAppList(const google_apis::GetAppListCallback& callback);
45
46  // Adds a GetAboutResource operation to the queue.
47  // |callback| must not be null.
48  void GetAboutResource(const google_apis::GetAboutResourceCallback& callback);
49
50  // Adds a GetAllResourceList operation to the queue.
51  // |callback| must not be null.
52  void GetAllResourceList(const google_apis::GetResourceListCallback& callback);
53
54  // Adds a GetResourceListInDirectory operation to the queue.
55  // |callback| must not be null.
56  void GetResourceListInDirectory(
57      const std::string& directory_resource_id,
58      const google_apis::GetResourceListCallback& callback);
59
60  // Adds a Search operation to the queue.
61  // |callback| must not be null.
62  void Search(const std::string& search_query,
63              const google_apis::GetResourceListCallback& callback);
64
65  // Adds a GetChangeList operation to the queue.
66  // |callback| must not be null.
67  void GetChangeList(int64 start_changestamp,
68                     const google_apis::GetResourceListCallback& callback);
69
70  // Adds ContinueGetResourceList operation to the queue.
71  // |callback| must not be null.
72  void ContinueGetResourceList(
73      const GURL& feed_url,
74      const google_apis::GetResourceListCallback& callback);
75
76  // Adds a GetResourceEntry operation to the queue.
77  void GetResourceEntry(const std::string& resource_id,
78                        const DriveClientContext& context,
79                        const google_apis::GetResourceEntryCallback& callback);
80
81
82  // Adds a DeleteResource operation to the queue.
83  void DeleteResource(const std::string& resource_id,
84                      const google_apis::EntryActionCallback& callback);
85
86
87  // Adds a CopyHostedDocument operation to the queue.
88  void CopyHostedDocument(
89      const std::string& resource_id,
90      const std::string& new_name,
91      const google_apis::GetResourceEntryCallback& callback);
92
93  // Adds a RenameResource operation to the queue.
94  void RenameResource(const std::string& resource_id,
95                      const std::string& new_name,
96                      const google_apis::EntryActionCallback& callback);
97
98  // Adds a AddResourceToDirectory operation to the queue.
99  void AddResourceToDirectory(const std::string& parent_resource_id,
100                              const std::string& resource_id,
101                              const google_apis::EntryActionCallback& callback);
102
103  // Adds a RemoveResourceFromDirectory operation to the queue.
104  void RemoveResourceFromDirectory(
105      const std::string& parent_resource_id,
106      const std::string& resource_id,
107      const google_apis::EntryActionCallback& callback);
108
109  // Adds a AddNewDirectory operation to the queue.
110  void AddNewDirectory(const std::string& parent_resource_id,
111                       const std::string& directory_name,
112                       const google_apis::GetResourceEntryCallback& callback);
113
114  // Adds a DownloadFile operation to the queue.
115  JobID DownloadFile(
116      const base::FilePath& virtual_path,
117      const base::FilePath& local_cache_path,
118      const GURL& download_url,
119      const DriveClientContext& context,
120      const google_apis::DownloadActionCallback& download_action_callback,
121      const google_apis::GetContentCallback& get_content_callback);
122
123  // Adds an UploadNewFile operation to the queue.
124  void UploadNewFile(const std::string& parent_resource_id,
125                     const base::FilePath& drive_file_path,
126                     const base::FilePath& local_file_path,
127                     const std::string& title,
128                     const std::string& content_type,
129                     const DriveClientContext& context,
130                     const google_apis::UploadCompletionCallback& callback);
131
132  // Adds an UploadExistingFile operation to the queue.
133  void UploadExistingFile(
134      const std::string& resource_id,
135      const base::FilePath& drive_file_path,
136      const base::FilePath& local_file_path,
137      const std::string& content_type,
138      const std::string& etag,
139      const DriveClientContext& context,
140      const google_apis::UploadCompletionCallback& upload_completion_callback);
141
142  // Adds a CreateFile operation to the queue.
143  void CreateFile(const std::string& parent_resource_id,
144                  const base::FilePath& drive_file_path,
145                  const std::string& title,
146                  const std::string& content_type,
147                  const DriveClientContext& context,
148                  const google_apis::UploadCompletionCallback& callback);
149
150 private:
151  friend class JobSchedulerTest;
152
153  enum QueueType {
154    METADATA_QUEUE,
155    FILE_QUEUE,
156    NUM_QUEUES
157  };
158
159  static const int kMaxJobCount[NUM_QUEUES];
160
161  // Represents a single entry in the job map.
162  struct JobEntry {
163    explicit JobEntry(JobType type);
164    ~JobEntry();
165
166    // Returns true when |left| is in higher priority than |right|.
167    // Used for sorting entries from high priority to low priority.
168    static bool Less(const JobEntry& left, const JobEntry& right);
169
170    JobInfo job_info;
171
172    // Context of the job.
173    DriveClientContext context;
174
175    base::Closure task;
176  };
177
178  // Creates a new job and add it to the job map.
179  JobEntry* CreateNewJob(JobType type);
180
181  // Adds the specified job to the queue and starts the job loop for the queue
182  // if needed.
183  void StartJob(JobEntry* job);
184
185  // Adds the specified job to the queue.
186  void QueueJob(JobID job_id);
187
188  // Starts the job loop, if it is not already running.
189  void StartJobLoop(QueueType queue_type);
190
191  // Determines the next job that should run, and starts it.
192  void DoJobLoop(QueueType queue_type);
193
194  // Checks if operations should be suspended, such as if the network is
195  // disconnected.
196  //
197  // Returns true when it should stop, and false if it should continue.
198  bool ShouldStopJobLoop(QueueType queue_type,
199                         const  DriveClientContext& context);
200
201  // Increases the throttle delay if it's below the maximum value, and posts a
202  // task to continue the loop after the delay.
203  void ThrottleAndContinueJobLoop(QueueType queue_type);
204
205  // Resets the throttle delay to the initial value, and continues the job loop.
206  void ResetThrottleAndContinueJobLoop(QueueType queue_type);
207
208  // Retries the job if needed and returns false. Otherwise returns true.
209  bool OnJobDone(JobID job_id, google_apis::GDataErrorCode error);
210
211  // Callback for job finishing with a GetResourceListCallback.
212  void OnGetResourceListJobDone(
213      JobID job_id,
214      const google_apis::GetResourceListCallback& callback,
215      google_apis::GDataErrorCode error,
216      scoped_ptr<google_apis::ResourceList> resource_list);
217
218  // Callback for job finishing with a GetResourceEntryCallback.
219  void OnGetResourceEntryJobDone(
220      JobID job_id,
221      const google_apis::GetResourceEntryCallback& callback,
222      google_apis::GDataErrorCode error,
223      scoped_ptr<google_apis::ResourceEntry> entry);
224
225  // Callback for job finishing with a GetAboutResourceCallback.
226  void OnGetAboutResourceJobDone(
227      JobID job_id,
228      const google_apis::GetAboutResourceCallback& callback,
229      google_apis::GDataErrorCode error,
230      scoped_ptr<google_apis::AboutResource> about_resource);
231
232  // Callback for job finishing with a GetAppListCallback.
233  void OnGetAppListJobDone(
234      JobID job_id,
235      const google_apis::GetAppListCallback& callback,
236      google_apis::GDataErrorCode error,
237      scoped_ptr<google_apis::AppList> app_list);
238
239  // Callback for job finishing with a EntryActionCallback.
240  void OnEntryActionJobDone(JobID job_id,
241                            const google_apis::EntryActionCallback& callback,
242                            google_apis::GDataErrorCode error);
243
244  // Callback for job finishing with a DownloadActionCallback.
245  void OnDownloadActionJobDone(
246      JobID job_id,
247      const google_apis::DownloadActionCallback& callback,
248      google_apis::GDataErrorCode error,
249      const base::FilePath& temp_file);
250
251  // Callback for job finishing with a UploadCompletionCallback.
252  void OnUploadCompletionJobDone(
253      JobID job_id,
254      const google_apis::UploadCompletionCallback& callback,
255      google_apis::GDataErrorCode error,
256      const base::FilePath& drive_path,
257      const base::FilePath& file_path,
258      scoped_ptr<google_apis::ResourceEntry> resource_entry);
259
260  // Updates the progress status of the specified job.
261  void UpdateProgress(JobID job_id, int64 progress, int64 total);
262
263  // net::NetworkChangeNotifier::ConnectionTypeObserver override.
264  virtual void OnConnectionTypeChanged(
265      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
266
267  // Get the type of queue the specified job should be put in.
268  QueueType GetJobQueueType(JobType type);
269
270  // For testing only.  Disables throttling so that testing is faster.
271  void SetDisableThrottling(bool disable) { disable_throttling_ = disable; }
272
273  // Notifies updates to observers.
274  void NotifyJobAdded(const JobInfo& job_info);
275  void NotifyJobDone(const JobInfo& job_info,
276                     google_apis::GDataErrorCode error);
277  void NotifyJobUpdated(const JobInfo& job_info);
278
279  // Gets information of the queue of the given type as string.
280  std::string GetQueueInfo(QueueType type) const;
281
282  // Returns a string representation of QueueType.
283  static std::string QueueTypeToString(QueueType type);
284
285  // Number of jobs in flight for each queue.
286  int jobs_running_[NUM_QUEUES];
287
288  // The number of times operations have failed in a row, capped at
289  // kMaxThrottleCount.  This is used to calculate the delay before running the
290  // next task.
291  int throttle_count_;
292
293  // Disables throttling for testing.
294  bool disable_throttling_;
295
296  // The queues of jobs.
297  std::list<JobID> queue_[NUM_QUEUES];
298
299  // The list of unfinished (= queued or running) job info indexed by job IDs.
300  typedef IDMap<JobEntry, IDMapOwnPointer> JobIDMap;
301  JobIDMap job_map_;
302
303  // The list of observers for the scheduler.
304  ObserverList<JobListObserver> observer_list_;
305
306  google_apis::DriveServiceInterface* drive_service_;
307  scoped_ptr<google_apis::DriveUploaderInterface> uploader_;
308
309  Profile* profile_;
310
311  // Note: This should remain the last member so it'll be destroyed and
312  // invalidate its weak pointers before any other members are destroyed.
313  base::WeakPtrFactory<JobScheduler> weak_ptr_factory_;
314  DISALLOW_COPY_AND_ASSIGN(JobScheduler);
315};
316
317}  // namespace drive
318
319#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_JOB_SCHEDULER_H_
320