job_scheduler.h revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
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 <vector>
9
10#include "base/id_map.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/observer_list.h"
13#include "chrome/browser/chromeos/drive/file_system_interface.h"
14#include "chrome/browser/chromeos/drive/job_list.h"
15#include "chrome/browser/chromeos/drive/job_queue.h"
16#include "chrome/browser/drive/drive_service_interface.h"
17#include "chrome/browser/drive/drive_uploader.h"
18#include "net/base/network_change_notifier.h"
19
20class PrefService;
21
22namespace base {
23class SeqencedTaskRunner;
24}
25
26namespace drive {
27
28// The JobScheduler is responsible for queuing and scheduling drive
29// jobs.
30//
31// All jobs are processed in order of priority.
32//   - Jobs that occur as a result of a direct user action are handled
33//     immediately (i.e. the client context is USER_INITIATED).
34//   - Jobs that are done in response to state changes or server actions are run
35//     in the background (i.e. the client context is BACKGROUND).
36//
37// All jobs are retried a maximum of kMaxRetryCount when they fail due to
38// throttling or server error.  The delay before retrying a job is shared
39// between jobs.  It doubles in length on each failure, up to 16 seconds.
40//
41// Jobs are grouped into two types:
42//   - File jobs are any job that transfer the contents of files.
43//     By default, they are only run when connected to WiFi.
44//   - Metadata jobs are any jobs that operate on File metadata or
45//     the directory structure.  Up to kMaxJobCount[METADATA_QUEUE] jobs are run
46//     concurrently.
47//
48// Because jobs are executed by priority and the potential for network failures,
49// there is no guarantee of ordering of operations.
50class JobScheduler
51    : public net::NetworkChangeNotifier::ConnectionTypeObserver,
52      public JobListInterface {
53 public:
54  JobScheduler(PrefService* pref_service,
55               DriveServiceInterface* drive_service,
56               base::SequencedTaskRunner* blocking_task_runner);
57  virtual ~JobScheduler();
58
59  // JobListInterface overrides.
60  virtual std::vector<JobInfo> GetJobInfoList() OVERRIDE;
61  virtual void AddObserver(JobListObserver* observer) OVERRIDE;
62  virtual void RemoveObserver(JobListObserver* observer) OVERRIDE;
63  virtual void CancelJob(JobID job_id) OVERRIDE;
64  virtual void CancelAllJobs() OVERRIDE;
65
66  // Adds a GetAppList operation to the queue.
67  // |callback| must not be null.
68  void GetAppList(const google_apis::GetAppListCallback& callback);
69
70  // Adds a GetAboutResource operation to the queue.
71  // |callback| must not be null.
72  void GetAboutResource(const google_apis::GetAboutResourceCallback& callback);
73
74  // Adds a GetAllResourceList operation to the queue.
75  // |callback| must not be null.
76  void GetAllResourceList(const google_apis::GetResourceListCallback& callback);
77
78  // Adds a GetResourceListInDirectory operation to the queue.
79  // |callback| must not be null.
80  void GetResourceListInDirectory(
81      const std::string& directory_resource_id,
82      const google_apis::GetResourceListCallback& callback);
83
84  // Adds a Search operation to the queue.
85  // |callback| must not be null.
86  void Search(const std::string& search_query,
87              const google_apis::GetResourceListCallback& callback);
88
89  // Adds a GetChangeList operation to the queue.
90  // |callback| must not be null.
91  void GetChangeList(int64 start_changestamp,
92                     const google_apis::GetResourceListCallback& callback);
93
94  // Adds ContinueGetResourceList operation to the queue.
95  // |callback| must not be null.
96  void ContinueGetResourceList(
97      const GURL& next_url,
98      const google_apis::GetResourceListCallback& callback);
99
100  // Adds a GetResourceEntry operation to the queue.
101  void GetResourceEntry(const std::string& resource_id,
102                        const ClientContext& context,
103                        const google_apis::GetResourceEntryCallback& callback);
104
105  // Adds a GetShareUrl operation to the queue.
106  void GetShareUrl(const std::string& resource_id,
107                   const GURL& embed_origin,
108                   const ClientContext& context,
109                   const google_apis::GetShareUrlCallback& callback);
110
111  // Adds a DeleteResource operation to the queue.
112  void DeleteResource(const std::string& resource_id,
113                      const google_apis::EntryActionCallback& callback);
114
115  // Adds a CopyResource operation to the queue.
116  void CopyResource(
117      const std::string& resource_id,
118      const std::string& parent_resource_id,
119      const std::string& new_title,
120      const google_apis::GetResourceEntryCallback& callback);
121
122  // Adds a CopyHostedDocument operation to the queue.
123  void CopyHostedDocument(
124      const std::string& resource_id,
125      const std::string& new_title,
126      const google_apis::GetResourceEntryCallback& callback);
127
128  // Adds a RenameResource operation to the queue.
129  void RenameResource(const std::string& resource_id,
130                      const std::string& new_title,
131                      const google_apis::EntryActionCallback& callback);
132
133  // Adds a TouchResource operation to the queue.
134  void TouchResource(const std::string& resource_id,
135                     const base::Time& modified_date,
136                     const base::Time& last_viewed_by_me_date,
137                     const google_apis::GetResourceEntryCallback& callback);
138
139  // Adds a AddResourceToDirectory operation to the queue.
140  void AddResourceToDirectory(const std::string& parent_resource_id,
141                              const std::string& resource_id,
142                              const google_apis::EntryActionCallback& callback);
143
144  // Adds a RemoveResourceFromDirectory operation to the queue.
145  void RemoveResourceFromDirectory(
146      const std::string& parent_resource_id,
147      const std::string& resource_id,
148      const google_apis::EntryActionCallback& callback);
149
150  // Adds a AddNewDirectory operation to the queue.
151  void AddNewDirectory(const std::string& parent_resource_id,
152                       const std::string& directory_title,
153                       const google_apis::GetResourceEntryCallback& callback);
154
155  // Adds a DownloadFile operation to the queue.
156  JobID DownloadFile(
157      const base::FilePath& virtual_path,
158      const base::FilePath& local_cache_path,
159      const std::string& resource_id,
160      const ClientContext& context,
161      const google_apis::DownloadActionCallback& download_action_callback,
162      const google_apis::GetContentCallback& get_content_callback);
163
164  // Adds an UploadNewFile operation to the queue.
165  void UploadNewFile(const std::string& parent_resource_id,
166                     const base::FilePath& drive_file_path,
167                     const base::FilePath& local_file_path,
168                     const std::string& title,
169                     const std::string& content_type,
170                     const ClientContext& context,
171                     const google_apis::GetResourceEntryCallback& callback);
172
173  // Adds an UploadExistingFile operation to the queue.
174  void UploadExistingFile(
175      const std::string& resource_id,
176      const base::FilePath& drive_file_path,
177      const base::FilePath& local_file_path,
178      const std::string& content_type,
179      const std::string& etag,
180      const ClientContext& context,
181      const google_apis::GetResourceEntryCallback& callback);
182
183  // Adds a CreateFile operation to the queue.
184  void CreateFile(const std::string& parent_resource_id,
185                  const base::FilePath& drive_file_path,
186                  const std::string& title,
187                  const std::string& content_type,
188                  const ClientContext& context,
189                  const google_apis::GetResourceEntryCallback& callback);
190
191 private:
192  friend class JobSchedulerTest;
193
194  enum QueueType {
195    METADATA_QUEUE,
196    FILE_QUEUE,
197    NUM_QUEUES
198  };
199
200  static const int kMaxJobCount[NUM_QUEUES];
201
202  // Represents a single entry in the job map.
203  struct JobEntry {
204    explicit JobEntry(JobType type);
205    ~JobEntry();
206
207    // General user-visible information on the job.
208    JobInfo job_info;
209
210    // Context of the job.
211    ClientContext context;
212
213    // The number of times the jobs is retried due to server errors.
214    int retry_count;
215
216    // The callback to start the job. Called each time it is retry.
217    base::Callback<google_apis::CancelCallback()> task;
218
219    // The callback to cancel the running job. It is returned from task.Run().
220    google_apis::CancelCallback cancel_callback;
221
222    // The callback to notify an error to the client of JobScheduler.
223    // This is used to notify cancel of a job that is not running yet.
224    base::Callback<void(google_apis::GDataErrorCode)> abort_callback;
225  };
226
227  // Parameters for DriveUploader::ResumeUploadFile.
228  struct ResumeUploadParams;
229
230  // Creates a new job and add it to the job map.
231  JobEntry* CreateNewJob(JobType type);
232
233  // Adds the specified job to the queue and starts the job loop for the queue
234  // if needed.
235  void StartJob(JobEntry* job);
236
237  // Adds the specified job to the queue.
238  void QueueJob(JobID job_id);
239
240  // Determines the next job that should run, and starts it.
241  void DoJobLoop(QueueType queue_type);
242
243  // Returns the lowest acceptable priority level of the operations that is
244  // currently allowed to start for the |queue_type|.
245  int GetCurrentAcceptedPriority(QueueType queue_type);
246
247  // Increases the throttle delay if it's below the maximum value, and posts a
248  // task to continue the loop after the delay.
249  void ThrottleAndContinueJobLoop(QueueType queue_type);
250
251  // Resets the throttle delay to the initial value, and continues the job loop.
252  void ResetThrottleAndContinueJobLoop(QueueType queue_type);
253
254  // Retries the job if needed and returns false. Otherwise returns true.
255  bool OnJobDone(JobID job_id, google_apis::GDataErrorCode error);
256
257  // Callback for job finishing with a GetResourceListCallback.
258  void OnGetResourceListJobDone(
259      JobID job_id,
260      const google_apis::GetResourceListCallback& callback,
261      google_apis::GDataErrorCode error,
262      scoped_ptr<google_apis::ResourceList> resource_list);
263
264  // Callback for job finishing with a GetResourceEntryCallback.
265  void OnGetResourceEntryJobDone(
266      JobID job_id,
267      const google_apis::GetResourceEntryCallback& callback,
268      google_apis::GDataErrorCode error,
269      scoped_ptr<google_apis::ResourceEntry> entry);
270
271  // Callback for job finishing with a GetAboutResourceCallback.
272  void OnGetAboutResourceJobDone(
273      JobID job_id,
274      const google_apis::GetAboutResourceCallback& callback,
275      google_apis::GDataErrorCode error,
276      scoped_ptr<google_apis::AboutResource> about_resource);
277
278  // Callback for job finishing with a GetShareUrlCallback.
279  void OnGetShareUrlJobDone(
280      JobID job_id,
281      const google_apis::GetShareUrlCallback& callback,
282      google_apis::GDataErrorCode error,
283      const GURL& share_url);
284
285  // Callback for job finishing with a GetAppListCallback.
286  void OnGetAppListJobDone(
287      JobID job_id,
288      const google_apis::GetAppListCallback& callback,
289      google_apis::GDataErrorCode error,
290      scoped_ptr<google_apis::AppList> app_list);
291
292  // Callback for job finishing with a EntryActionCallback.
293  void OnEntryActionJobDone(JobID job_id,
294                            const google_apis::EntryActionCallback& callback,
295                            google_apis::GDataErrorCode error);
296
297  // Callback for job finishing with a DownloadActionCallback.
298  void OnDownloadActionJobDone(
299      JobID job_id,
300      const google_apis::DownloadActionCallback& callback,
301      google_apis::GDataErrorCode error,
302      const base::FilePath& temp_file);
303
304  // Callback for job finishing with a UploadCompletionCallback.
305  void OnUploadCompletionJobDone(
306      JobID job_id,
307      const ResumeUploadParams& resume_params,
308      const google_apis::GetResourceEntryCallback& callback,
309      google_apis::GDataErrorCode error,
310      const GURL& upload_location,
311      scoped_ptr<google_apis::ResourceEntry> resource_entry);
312
313  // Callback for DriveUploader::ResumeUploadFile().
314  void OnResumeUploadFileDone(
315      JobID job_id,
316      const base::Callback<google_apis::CancelCallback()>& original_task,
317      const google_apis::GetResourceEntryCallback& callback,
318      google_apis::GDataErrorCode error,
319      const GURL& upload_location,
320      scoped_ptr<google_apis::ResourceEntry> resource_entry);
321
322  // Updates the progress status of the specified job.
323  void UpdateProgress(JobID job_id, int64 progress, int64 total);
324
325  // net::NetworkChangeNotifier::ConnectionTypeObserver override.
326  virtual void OnConnectionTypeChanged(
327      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
328
329  // Get the type of queue the specified job should be put in.
330  QueueType GetJobQueueType(JobType type);
331
332  // For testing only.  Disables throttling so that testing is faster.
333  void SetDisableThrottling(bool disable) { disable_throttling_ = disable; }
334
335  // Aborts a job which is not in STATE_RUNNING.
336  void AbortNotRunningJob(JobEntry* job, google_apis::GDataErrorCode error);
337
338  // Notifies updates to observers.
339  void NotifyJobAdded(const JobInfo& job_info);
340  void NotifyJobDone(const JobInfo& job_info,
341                     google_apis::GDataErrorCode error);
342  void NotifyJobUpdated(const JobInfo& job_info);
343
344  // Gets information of the queue of the given type as string.
345  std::string GetQueueInfo(QueueType type) const;
346
347  // Returns a string representation of QueueType.
348  static std::string QueueTypeToString(QueueType type);
349
350  // The number of times operations have failed in a row, capped at
351  // kMaxThrottleCount.  This is used to calculate the delay before running the
352  // next task.
353  int throttle_count_;
354
355  // Disables throttling for testing.
356  bool disable_throttling_;
357
358  // The queues of jobs.
359  scoped_ptr<JobQueue> queue_[NUM_QUEUES];
360
361  // The list of queued job info indexed by job IDs.
362  typedef IDMap<JobEntry, IDMapOwnPointer> JobIDMap;
363  JobIDMap job_map_;
364
365  // The list of observers for the scheduler.
366  ObserverList<JobListObserver> observer_list_;
367
368  DriveServiceInterface* drive_service_;
369  scoped_ptr<DriveUploaderInterface> uploader_;
370
371  PrefService* pref_service_;
372
373  // Note: This should remain the last member so it'll be destroyed and
374  // invalidate its weak pointers before any other members are destroyed.
375  base::WeakPtrFactory<JobScheduler> weak_ptr_factory_;
376  DISALLOW_COPY_AND_ASSIGN(JobScheduler);
377};
378
379}  // namespace drive
380
381#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_JOB_SCHEDULER_H_
382