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