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