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