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