job_scheduler.h revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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 <list> 9#include <vector> 10 11#include "base/id_map.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/observer_list.h" 14#include "chrome/browser/chromeos/drive/file_system_interface.h" 15#include "chrome/browser/chromeos/drive/job_list.h" 16#include "chrome/browser/google_apis/drive_service_interface.h" 17#include "chrome/browser/google_apis/drive_uploader.h" 18#include "net/base/network_change_notifier.h" 19 20class Profile; 21 22namespace drive { 23 24// The JobScheduler is responsible for queuing and scheduling drive 25// operations. It is responsible for handling retry logic, rate limiting, as 26// concurrency as appropriate. 27class JobScheduler 28 : public net::NetworkChangeNotifier::ConnectionTypeObserver, 29 public JobListInterface { 30 public: 31 JobScheduler(Profile* profile, 32 google_apis::DriveServiceInterface* drive_service); 33 virtual ~JobScheduler(); 34 35 // JobListInterface overrides. 36 virtual std::vector<JobInfo> GetJobInfoList() OVERRIDE; 37 virtual void AddObserver(JobListObserver* observer) OVERRIDE; 38 virtual void RemoveObserver(JobListObserver* observer) OVERRIDE; 39 virtual void CancelJob(JobID job_id) OVERRIDE; 40 virtual void CancelAllJobs() OVERRIDE; 41 42 // Adds a GetAppList operation to the queue. 43 // |callback| must not be null. 44 void GetAppList(const google_apis::GetAppListCallback& callback); 45 46 // Adds a GetAboutResource operation to the queue. 47 // |callback| must not be null. 48 void GetAboutResource(const google_apis::GetAboutResourceCallback& callback); 49 50 // Adds a GetAllResourceList operation to the queue. 51 // |callback| must not be null. 52 void GetAllResourceList(const google_apis::GetResourceListCallback& callback); 53 54 // Adds a GetResourceListInDirectory operation to the queue. 55 // |callback| must not be null. 56 void GetResourceListInDirectory( 57 const std::string& directory_resource_id, 58 const google_apis::GetResourceListCallback& callback); 59 60 // Adds a Search operation to the queue. 61 // |callback| must not be null. 62 void Search(const std::string& search_query, 63 const google_apis::GetResourceListCallback& callback); 64 65 // Adds a GetChangeList operation to the queue. 66 // |callback| must not be null. 67 void GetChangeList(int64 start_changestamp, 68 const google_apis::GetResourceListCallback& callback); 69 70 // Adds ContinueGetResourceList operation to the queue. 71 // |callback| must not be null. 72 void ContinueGetResourceList( 73 const GURL& feed_url, 74 const google_apis::GetResourceListCallback& callback); 75 76 // Adds a GetResourceEntry operation to the queue. 77 void GetResourceEntry(const std::string& resource_id, 78 const DriveClientContext& context, 79 const google_apis::GetResourceEntryCallback& callback); 80 81 82 // Adds a DeleteResource operation to the queue. 83 void DeleteResource(const std::string& resource_id, 84 const google_apis::EntryActionCallback& callback); 85 86 87 // Adds a CopyHostedDocument operation to the queue. 88 void CopyHostedDocument( 89 const std::string& resource_id, 90 const std::string& new_name, 91 const google_apis::GetResourceEntryCallback& callback); 92 93 // Adds a RenameResource operation to the queue. 94 void RenameResource(const std::string& resource_id, 95 const std::string& new_name, 96 const google_apis::EntryActionCallback& callback); 97 98 // Adds a AddResourceToDirectory operation to the queue. 99 void AddResourceToDirectory(const std::string& parent_resource_id, 100 const std::string& resource_id, 101 const google_apis::EntryActionCallback& callback); 102 103 // Adds a RemoveResourceFromDirectory operation to the queue. 104 void RemoveResourceFromDirectory( 105 const std::string& parent_resource_id, 106 const std::string& resource_id, 107 const google_apis::EntryActionCallback& callback); 108 109 // Adds a AddNewDirectory operation to the queue. 110 void AddNewDirectory(const std::string& parent_resource_id, 111 const std::string& directory_name, 112 const google_apis::GetResourceEntryCallback& callback); 113 114 // Adds a DownloadFile operation to the queue. 115 JobID DownloadFile( 116 const base::FilePath& virtual_path, 117 const base::FilePath& local_cache_path, 118 const GURL& download_url, 119 const DriveClientContext& context, 120 const google_apis::DownloadActionCallback& download_action_callback, 121 const google_apis::GetContentCallback& get_content_callback); 122 123 // Adds an UploadNewFile operation to the queue. 124 void UploadNewFile(const std::string& parent_resource_id, 125 const base::FilePath& drive_file_path, 126 const base::FilePath& local_file_path, 127 const std::string& title, 128 const std::string& content_type, 129 const DriveClientContext& context, 130 const google_apis::UploadCompletionCallback& callback); 131 132 // Adds an UploadExistingFile operation to the queue. 133 void UploadExistingFile( 134 const std::string& resource_id, 135 const base::FilePath& drive_file_path, 136 const base::FilePath& local_file_path, 137 const std::string& content_type, 138 const std::string& etag, 139 const DriveClientContext& context, 140 const google_apis::UploadCompletionCallback& upload_completion_callback); 141 142 // Adds a CreateFile operation to the queue. 143 void CreateFile(const std::string& parent_resource_id, 144 const base::FilePath& drive_file_path, 145 const std::string& title, 146 const std::string& content_type, 147 const DriveClientContext& context, 148 const google_apis::UploadCompletionCallback& callback); 149 150 private: 151 friend class JobSchedulerTest; 152 153 enum QueueType { 154 METADATA_QUEUE, 155 FILE_QUEUE, 156 NUM_QUEUES 157 }; 158 159 static const int kMaxJobCount[NUM_QUEUES]; 160 161 // Represents a single entry in the job map. 162 struct JobEntry { 163 explicit JobEntry(JobType type); 164 ~JobEntry(); 165 166 // Returns true when |left| is in higher priority than |right|. 167 // Used for sorting entries from high priority to low priority. 168 static bool Less(const JobEntry& left, const JobEntry& right); 169 170 JobInfo job_info; 171 172 // Context of the job. 173 DriveClientContext context; 174 175 base::Closure task; 176 }; 177 178 // Creates a new job and add it to the job map. 179 JobEntry* CreateNewJob(JobType type); 180 181 // Adds the specified job to the queue and starts the job loop for the queue 182 // if needed. 183 void StartJob(JobEntry* job); 184 185 // Adds the specified job to the queue. 186 void QueueJob(JobID job_id); 187 188 // Starts the job loop, if it is not already running. 189 void StartJobLoop(QueueType queue_type); 190 191 // Determines the next job that should run, and starts it. 192 void DoJobLoop(QueueType queue_type); 193 194 // Checks if operations should be suspended, such as if the network is 195 // disconnected. 196 // 197 // Returns true when it should stop, and false if it should continue. 198 bool ShouldStopJobLoop(QueueType queue_type, 199 const DriveClientContext& context); 200 201 // Increases the throttle delay if it's below the maximum value, and posts a 202 // task to continue the loop after the delay. 203 void ThrottleAndContinueJobLoop(QueueType queue_type); 204 205 // Resets the throttle delay to the initial value, and continues the job loop. 206 void ResetThrottleAndContinueJobLoop(QueueType queue_type); 207 208 // Retries the job if needed and returns false. Otherwise returns true. 209 bool OnJobDone(JobID job_id, google_apis::GDataErrorCode error); 210 211 // Callback for job finishing with a GetResourceListCallback. 212 void OnGetResourceListJobDone( 213 JobID job_id, 214 const google_apis::GetResourceListCallback& callback, 215 google_apis::GDataErrorCode error, 216 scoped_ptr<google_apis::ResourceList> resource_list); 217 218 // Callback for job finishing with a GetResourceEntryCallback. 219 void OnGetResourceEntryJobDone( 220 JobID job_id, 221 const google_apis::GetResourceEntryCallback& callback, 222 google_apis::GDataErrorCode error, 223 scoped_ptr<google_apis::ResourceEntry> entry); 224 225 // Callback for job finishing with a GetAboutResourceCallback. 226 void OnGetAboutResourceJobDone( 227 JobID job_id, 228 const google_apis::GetAboutResourceCallback& callback, 229 google_apis::GDataErrorCode error, 230 scoped_ptr<google_apis::AboutResource> about_resource); 231 232 // Callback for job finishing with a GetAppListCallback. 233 void OnGetAppListJobDone( 234 JobID job_id, 235 const google_apis::GetAppListCallback& callback, 236 google_apis::GDataErrorCode error, 237 scoped_ptr<google_apis::AppList> app_list); 238 239 // Callback for job finishing with a EntryActionCallback. 240 void OnEntryActionJobDone(JobID job_id, 241 const google_apis::EntryActionCallback& callback, 242 google_apis::GDataErrorCode error); 243 244 // Callback for job finishing with a DownloadActionCallback. 245 void OnDownloadActionJobDone( 246 JobID job_id, 247 const google_apis::DownloadActionCallback& callback, 248 google_apis::GDataErrorCode error, 249 const base::FilePath& temp_file); 250 251 // Callback for job finishing with a UploadCompletionCallback. 252 void OnUploadCompletionJobDone( 253 JobID job_id, 254 const google_apis::UploadCompletionCallback& callback, 255 google_apis::GDataErrorCode error, 256 const base::FilePath& drive_path, 257 const base::FilePath& file_path, 258 scoped_ptr<google_apis::ResourceEntry> resource_entry); 259 260 // Updates the progress status of the specified job. 261 void UpdateProgress(JobID job_id, int64 progress, int64 total); 262 263 // net::NetworkChangeNotifier::ConnectionTypeObserver override. 264 virtual void OnConnectionTypeChanged( 265 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE; 266 267 // Get the type of queue the specified job should be put in. 268 QueueType GetJobQueueType(JobType type); 269 270 // For testing only. Disables throttling so that testing is faster. 271 void SetDisableThrottling(bool disable) { disable_throttling_ = disable; } 272 273 // Notifies updates to observers. 274 void NotifyJobAdded(const JobInfo& job_info); 275 void NotifyJobDone(const JobInfo& job_info, 276 google_apis::GDataErrorCode error); 277 void NotifyJobUpdated(const JobInfo& job_info); 278 279 // Gets information of the queue of the given type as string. 280 std::string GetQueueInfo(QueueType type) const; 281 282 // Returns a string representation of QueueType. 283 static std::string QueueTypeToString(QueueType type); 284 285 // Number of jobs in flight for each queue. 286 int jobs_running_[NUM_QUEUES]; 287 288 // The number of times operations have failed in a row, capped at 289 // kMaxThrottleCount. This is used to calculate the delay before running the 290 // next task. 291 int throttle_count_; 292 293 // Disables throttling for testing. 294 bool disable_throttling_; 295 296 // The queues of jobs. 297 std::list<JobID> queue_[NUM_QUEUES]; 298 299 // The list of unfinished (= queued or running) job info indexed by job IDs. 300 typedef IDMap<JobEntry, IDMapOwnPointer> JobIDMap; 301 JobIDMap job_map_; 302 303 // The list of observers for the scheduler. 304 ObserverList<JobListObserver> observer_list_; 305 306 google_apis::DriveServiceInterface* drive_service_; 307 scoped_ptr<google_apis::DriveUploaderInterface> uploader_; 308 309 Profile* profile_; 310 311 // Note: This should remain the last member so it'll be destroyed and 312 // invalidate its weak pointers before any other members are destroyed. 313 base::WeakPtrFactory<JobScheduler> weak_ptr_factory_; 314 DISALLOW_COPY_AND_ASSIGN(JobScheduler); 315}; 316 317} // namespace drive 318 319#endif // CHROME_BROWSER_CHROMEOS_DRIVE_JOB_SCHEDULER_H_ 320