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