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