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