• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 class PrefService;
21 
22 namespace base {
23 class SeqencedTaskRunner;
24 }
25 
26 namespace 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.
47 class 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 TrashResource operation to the queue.
115   void TrashResource(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 UpdateResource operation to the queue.
128   void UpdateResource(
129       const std::string& resource_id,
130       const std::string& parent_resource_id,
131       const std::string& new_title,
132       const base::Time& last_modified,
133       const base::Time& last_viewed_by_me,
134       const ClientContext& context,
135       const google_apis::GetResourceEntryCallback& callback);
136 
137   // Adds a RenameResource operation to the queue.
138   void RenameResource(const std::string& resource_id,
139                       const std::string& new_title,
140                       const google_apis::EntryActionCallback& callback);
141 
142   // Adds a AddResourceToDirectory operation to the queue.
143   void AddResourceToDirectory(const std::string& parent_resource_id,
144                               const std::string& resource_id,
145                               const google_apis::EntryActionCallback& callback);
146 
147   // Adds a RemoveResourceFromDirectory operation to the queue.
148   void RemoveResourceFromDirectory(
149       const std::string& parent_resource_id,
150       const std::string& resource_id,
151       const ClientContext& context,
152       const google_apis::EntryActionCallback& callback);
153 
154   // Adds a AddNewDirectory operation to the queue.
155   void AddNewDirectory(const std::string& parent_resource_id,
156                        const std::string& directory_title,
157                        const google_apis::GetResourceEntryCallback& callback);
158 
159   // Adds a DownloadFile operation to the queue.
160   // The first two arguments |virtual_path| and |expected_file_size| are used
161   // only for filling JobInfo for the operation so that observers can get the
162   // detail. The actual operation never refers these values.
163   JobID DownloadFile(
164       const base::FilePath& virtual_path,
165       int64 expected_file_size,
166       const base::FilePath& local_cache_path,
167       const std::string& resource_id,
168       const ClientContext& context,
169       const google_apis::DownloadActionCallback& download_action_callback,
170       const google_apis::GetContentCallback& get_content_callback);
171 
172   // Adds an UploadNewFile operation to the queue.
173   void UploadNewFile(const std::string& parent_resource_id,
174                      const base::FilePath& drive_file_path,
175                      const base::FilePath& local_file_path,
176                      const std::string& title,
177                      const std::string& content_type,
178                      const ClientContext& context,
179                      const google_apis::GetResourceEntryCallback& callback);
180 
181   // Adds an UploadExistingFile operation to the queue.
182   void UploadExistingFile(
183       const std::string& resource_id,
184       const base::FilePath& drive_file_path,
185       const base::FilePath& local_file_path,
186       const std::string& content_type,
187       const std::string& etag,
188       const ClientContext& context,
189       const google_apis::GetResourceEntryCallback& callback);
190 
191   // Adds a CreateFile operation to the queue.
192   void CreateFile(const std::string& parent_resource_id,
193                   const base::FilePath& drive_file_path,
194                   const std::string& title,
195                   const std::string& content_type,
196                   const ClientContext& context,
197                   const google_apis::GetResourceEntryCallback& callback);
198 
199   // Adds a GetResourceListInDirectoryByWapi operation to the queue.
200   // |callback| must not be null.
201   void GetResourceListInDirectoryByWapi(
202       const std::string& directory_resource_id,
203       const google_apis::GetResourceListCallback& callback);
204 
205   // Adds GetRemainingResourceList operation to the queue.
206   // |callback| must not be null.
207   void GetRemainingResourceList(
208       const GURL& next_link,
209       const google_apis::GetResourceListCallback& 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 GetResourceListCallback.
274   void OnGetResourceListJobDone(
275       JobID job_id,
276       const google_apis::GetResourceListCallback& callback,
277       google_apis::GDataErrorCode error,
278       scoped_ptr<google_apis::ResourceList> resource_list);
279 
280   // Callback for job finishing with a GetResourceEntryCallback.
281   void OnGetResourceEntryJobDone(
282       JobID job_id,
283       const google_apis::GetResourceEntryCallback& callback,
284       google_apis::GDataErrorCode error,
285       scoped_ptr<google_apis::ResourceEntry> entry);
286 
287   // Callback for job finishing with a AboutResourceCallback.
288   void OnGetAboutResourceJobDone(
289       JobID job_id,
290       const google_apis::AboutResourceCallback& callback,
291       google_apis::GDataErrorCode error,
292       scoped_ptr<google_apis::AboutResource> about_resource);
293 
294   // Callback for job finishing with a GetShareUrlCallback.
295   void OnGetShareUrlJobDone(
296       JobID job_id,
297       const google_apis::GetShareUrlCallback& callback,
298       google_apis::GDataErrorCode error,
299       const GURL& share_url);
300 
301   // Callback for job finishing with a AppListCallback.
302   void OnGetAppListJobDone(
303       JobID job_id,
304       const google_apis::AppListCallback& callback,
305       google_apis::GDataErrorCode error,
306       scoped_ptr<google_apis::AppList> app_list);
307 
308   // Callback for job finishing with a EntryActionCallback.
309   void OnEntryActionJobDone(JobID job_id,
310                             const google_apis::EntryActionCallback& callback,
311                             google_apis::GDataErrorCode error);
312 
313   // Callback for job finishing with a DownloadActionCallback.
314   void OnDownloadActionJobDone(
315       JobID job_id,
316       const google_apis::DownloadActionCallback& callback,
317       google_apis::GDataErrorCode error,
318       const base::FilePath& temp_file);
319 
320   // Callback for job finishing with a UploadCompletionCallback.
321   void OnUploadCompletionJobDone(
322       JobID job_id,
323       const ResumeUploadParams& resume_params,
324       const google_apis::GetResourceEntryCallback& callback,
325       google_apis::GDataErrorCode error,
326       const GURL& upload_location,
327       scoped_ptr<google_apis::ResourceEntry> resource_entry);
328 
329   // Callback for DriveUploader::ResumeUploadFile().
330   void OnResumeUploadFileDone(
331       JobID job_id,
332       const base::Callback<google_apis::CancelCallback()>& original_task,
333       const google_apis::GetResourceEntryCallback& callback,
334       google_apis::GDataErrorCode error,
335       const GURL& upload_location,
336       scoped_ptr<google_apis::ResourceEntry> resource_entry);
337 
338   // Updates the progress status of the specified job.
339   void UpdateProgress(JobID job_id, int64 progress, int64 total);
340 
341   // net::NetworkChangeNotifier::ConnectionTypeObserver override.
342   virtual void OnConnectionTypeChanged(
343       net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
344 
345   // Get the type of queue the specified job should be put in.
346   QueueType GetJobQueueType(JobType type);
347 
348   // For testing only.  Disables throttling so that testing is faster.
SetDisableThrottling(bool disable)349   void SetDisableThrottling(bool disable) { disable_throttling_ = disable; }
350 
351   // Aborts a job which is not in STATE_RUNNING.
352   void AbortNotRunningJob(JobEntry* job, google_apis::GDataErrorCode error);
353 
354   // Notifies updates to observers.
355   void NotifyJobAdded(const JobInfo& job_info);
356   void NotifyJobDone(const JobInfo& job_info,
357                      google_apis::GDataErrorCode error);
358   void NotifyJobUpdated(const JobInfo& job_info);
359 
360   // Gets information of the queue of the given type as string.
361   std::string GetQueueInfo(QueueType type) const;
362 
363   // Returns a string representation of QueueType.
364   static std::string QueueTypeToString(QueueType type);
365 
366   // The number of times operations have failed in a row, capped at
367   // kMaxThrottleCount.  This is used to calculate the delay before running the
368   // next task.
369   int throttle_count_;
370 
371   // Jobs should not start running until this time. Used for throttling.
372   base::Time wait_until_;
373 
374   // Disables throttling for testing.
375   bool disable_throttling_;
376 
377   // The queues of jobs.
378   scoped_ptr<JobQueue> queue_[NUM_QUEUES];
379 
380   // The list of queued job info indexed by job IDs.
381   typedef IDMap<JobEntry, IDMapOwnPointer> JobIDMap;
382   JobIDMap job_map_;
383 
384   // The list of observers for the scheduler.
385   ObserverList<JobListObserver> observer_list_;
386 
387   DriveServiceInterface* drive_service_;
388   scoped_ptr<DriveUploaderInterface> uploader_;
389 
390   PrefService* pref_service_;
391 
392   // Note: This should remain the last member so it'll be destroyed and
393   // invalidate its weak pointers before any other members are destroyed.
394   base::WeakPtrFactory<JobScheduler> weak_ptr_factory_;
395   DISALLOW_COPY_AND_ASSIGN(JobScheduler);
396 };
397 
398 }  // namespace drive
399 
400 #endif  // CHROME_BROWSER_CHROMEOS_DRIVE_JOB_SCHEDULER_H_
401