OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/drive/drive_scheduler.h" | 5 #include "chrome/browser/chromeos/drive/drive_scheduler.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 const DriveScheduler::QueueEntry* left, | 48 const DriveScheduler::QueueEntry* left, |
49 const DriveScheduler::QueueEntry* right) { | 49 const DriveScheduler::QueueEntry* right) { |
50 return (right->context.type == BACKGROUND && | 50 return (right->context.type == BACKGROUND && |
51 left->context.type != BACKGROUND); | 51 left->context.type != BACKGROUND); |
52 } | 52 } |
53 | 53 |
54 DriveScheduler::DriveScheduler( | 54 DriveScheduler::DriveScheduler( |
55 Profile* profile, | 55 Profile* profile, |
56 google_apis::DriveServiceInterface* drive_service, | 56 google_apis::DriveServiceInterface* drive_service, |
57 google_apis::DriveUploaderInterface* uploader) | 57 google_apis::DriveUploaderInterface* uploader) |
58 : job_loop_is_running_(false), | 58 : next_job_id_(0), |
59 next_job_id_(0), | |
60 throttle_count_(0), | 59 throttle_count_(0), |
61 disable_throttling_(false), | 60 disable_throttling_(false), |
62 drive_service_(drive_service), | 61 drive_service_(drive_service), |
63 uploader_(uploader), | 62 uploader_(uploader), |
64 profile_(profile), | 63 profile_(profile), |
65 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 64 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
66 initialized_(false) { | 65 initialized_(false) { |
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 67 for (int i = 0; i < NUM_QUEUES; ++i) { |
| 68 job_loop_is_running_[i] = false; |
| 69 } |
68 } | 70 } |
69 | 71 |
70 DriveScheduler::~DriveScheduler() { | 72 DriveScheduler::~DriveScheduler() { |
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
72 DCHECK(initialized_); | 74 DCHECK(initialized_); |
73 STLDeleteElements(&queue_); | 75 for (int i = 0; i < NUM_QUEUES; ++i) { |
| 76 STLDeleteElements(&queue_[i]); |
| 77 } |
74 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 78 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
75 } | 79 } |
76 | 80 |
77 void DriveScheduler::Initialize() { | 81 void DriveScheduler::Initialize() { |
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
79 | 83 |
80 // Initialize() may be called more than once for the lifetime when the | 84 // Initialize() may be called more than once for the lifetime when the |
81 // file system is remounted. | 85 // file system is remounted. |
82 if (initialized_) | 86 if (initialized_) |
83 return; | 87 return; |
84 | 88 |
85 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | 89 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); |
86 initialized_ = true; | 90 initialized_ = true; |
87 } | 91 } |
88 | 92 |
89 void DriveScheduler::GetAccountMetadata( | 93 void DriveScheduler::GetAccountMetadata( |
90 const google_apis::GetAccountMetadataCallback& callback) { | 94 const google_apis::GetAccountMetadataCallback& callback) { |
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
92 DCHECK(!callback.is_null()); | 96 DCHECK(!callback.is_null()); |
93 | 97 |
94 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_ACCOUNT_METADATA)); | 98 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_ACCOUNT_METADATA)); |
95 new_job->get_account_metadata_callback = callback; | 99 new_job->get_account_metadata_callback = callback; |
96 | 100 |
97 QueueJob(new_job.Pass()); | 101 QueueJob(new_job.Pass()); |
98 | 102 |
99 StartJobLoop(); | 103 StartJobLoop(GetJobQueueType(TYPE_GET_ACCOUNT_METADATA)); |
100 } | 104 } |
101 | 105 |
102 void DriveScheduler::GetAppList( | 106 void DriveScheduler::GetAppList( |
103 const google_apis::GetAppListCallback& callback) { | 107 const google_apis::GetAppListCallback& callback) { |
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
105 DCHECK(!callback.is_null()); | 109 DCHECK(!callback.is_null()); |
106 | 110 |
107 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_APP_LIST)); | 111 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_APP_LIST)); |
108 new_job->get_app_list_callback = callback; | 112 new_job->get_app_list_callback = callback; |
109 | 113 |
110 QueueJob(new_job.Pass()); | 114 QueueJob(new_job.Pass()); |
111 | 115 |
112 StartJobLoop(); | 116 StartJobLoop(GetJobQueueType(TYPE_GET_APP_LIST)); |
113 } | 117 } |
114 | 118 |
115 void DriveScheduler::GetResourceList( | 119 void DriveScheduler::GetResourceList( |
116 const GURL& feed_url, | 120 const GURL& feed_url, |
117 int64 start_changestamp, | 121 int64 start_changestamp, |
118 const std::string& search_query, | 122 const std::string& search_query, |
119 bool shared_with_me, | 123 bool shared_with_me, |
120 const std::string& directory_resource_id, | 124 const std::string& directory_resource_id, |
121 const google_apis::GetResourceListCallback& callback) { | 125 const google_apis::GetResourceListCallback& callback) { |
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
123 DCHECK(!callback.is_null()); | 127 DCHECK(!callback.is_null()); |
124 | 128 |
125 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_RESOURCE_LIST)); | 129 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_RESOURCE_LIST)); |
126 new_job->feed_url = feed_url; | 130 new_job->feed_url = feed_url; |
127 new_job->start_changestamp = start_changestamp; | 131 new_job->start_changestamp = start_changestamp; |
128 new_job->search_query = search_query; | 132 new_job->search_query = search_query; |
129 new_job->shared_with_me = shared_with_me; | 133 new_job->shared_with_me = shared_with_me; |
130 new_job->directory_resource_id = directory_resource_id; | 134 new_job->directory_resource_id = directory_resource_id; |
131 new_job->get_resource_list_callback = callback; | 135 new_job->get_resource_list_callback = callback; |
132 | 136 |
133 QueueJob(new_job.Pass()); | 137 QueueJob(new_job.Pass()); |
134 | 138 |
135 StartJobLoop(); | 139 StartJobLoop(GetJobQueueType(TYPE_GET_RESOURCE_LIST)); |
136 } | 140 } |
137 | 141 |
138 void DriveScheduler::GetResourceEntry( | 142 void DriveScheduler::GetResourceEntry( |
139 const std::string& resource_id, | 143 const std::string& resource_id, |
140 const DriveClientContext& context, | 144 const DriveClientContext& context, |
141 const google_apis::GetResourceEntryCallback& callback) { | 145 const google_apis::GetResourceEntryCallback& callback) { |
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
143 DCHECK(!callback.is_null()); | 147 DCHECK(!callback.is_null()); |
144 | 148 |
145 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_RESOURCE_ENTRY)); | 149 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_RESOURCE_ENTRY)); |
146 new_job->resource_id = resource_id; | 150 new_job->resource_id = resource_id; |
147 new_job->context = context; | 151 new_job->context = context; |
148 new_job->get_resource_entry_callback = callback; | 152 new_job->get_resource_entry_callback = callback; |
149 | 153 |
150 QueueJob(new_job.Pass()); | 154 QueueJob(new_job.Pass()); |
151 | 155 |
152 StartJobLoop(); | 156 StartJobLoop(GetJobQueueType(TYPE_GET_RESOURCE_ENTRY)); |
153 } | 157 } |
154 | 158 |
155 void DriveScheduler::DeleteResource( | 159 void DriveScheduler::DeleteResource( |
156 const std::string& resource_id, | 160 const std::string& resource_id, |
157 const google_apis::EntryActionCallback& callback) { | 161 const google_apis::EntryActionCallback& callback) { |
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
159 DCHECK(!callback.is_null()); | 163 DCHECK(!callback.is_null()); |
160 | 164 |
161 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_DELETE_RESOURCE)); | 165 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_DELETE_RESOURCE)); |
162 new_job->resource_id = resource_id; | 166 new_job->resource_id = resource_id; |
163 new_job->entry_action_callback = callback; | 167 new_job->entry_action_callback = callback; |
164 | 168 |
165 QueueJob(new_job.Pass()); | 169 QueueJob(new_job.Pass()); |
166 | 170 |
167 StartJobLoop(); | 171 StartJobLoop(GetJobQueueType(TYPE_DELETE_RESOURCE)); |
168 } | 172 } |
169 | 173 |
170 | 174 |
171 void DriveScheduler::CopyHostedDocument( | 175 void DriveScheduler::CopyHostedDocument( |
172 const std::string& resource_id, | 176 const std::string& resource_id, |
173 const std::string& new_name, | 177 const std::string& new_name, |
174 const google_apis::GetResourceEntryCallback& callback) { | 178 const google_apis::GetResourceEntryCallback& callback) { |
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
176 DCHECK(!callback.is_null()); | 180 DCHECK(!callback.is_null()); |
177 | 181 |
178 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_COPY_HOSTED_DOCUMENT)); | 182 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_COPY_HOSTED_DOCUMENT)); |
179 new_job->resource_id = resource_id; | 183 new_job->resource_id = resource_id; |
180 new_job->new_name = new_name; | 184 new_job->new_name = new_name; |
181 new_job->get_resource_entry_callback = callback; | 185 new_job->get_resource_entry_callback = callback; |
182 | 186 |
183 QueueJob(new_job.Pass()); | 187 QueueJob(new_job.Pass()); |
184 | 188 |
185 StartJobLoop(); | 189 StartJobLoop(GetJobQueueType(TYPE_COPY_HOSTED_DOCUMENT)); |
186 } | 190 } |
187 | 191 |
188 void DriveScheduler::RenameResource( | 192 void DriveScheduler::RenameResource( |
189 const std::string& resource_id, | 193 const std::string& resource_id, |
190 const std::string& new_name, | 194 const std::string& new_name, |
191 const google_apis::EntryActionCallback& callback) { | 195 const google_apis::EntryActionCallback& callback) { |
192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
193 DCHECK(!callback.is_null()); | 197 DCHECK(!callback.is_null()); |
194 | 198 |
195 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_RENAME_RESOURCE)); | 199 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_RENAME_RESOURCE)); |
196 new_job->resource_id = resource_id; | 200 new_job->resource_id = resource_id; |
197 new_job->new_name = new_name; | 201 new_job->new_name = new_name; |
198 new_job->entry_action_callback = callback; | 202 new_job->entry_action_callback = callback; |
199 | 203 |
200 QueueJob(new_job.Pass()); | 204 QueueJob(new_job.Pass()); |
201 | 205 |
202 StartJobLoop(); | 206 StartJobLoop(GetJobQueueType(TYPE_RENAME_RESOURCE)); |
203 } | 207 } |
204 | 208 |
205 void DriveScheduler::AddResourceToDirectory( | 209 void DriveScheduler::AddResourceToDirectory( |
206 const std::string& parent_resource_id, | 210 const std::string& parent_resource_id, |
207 const std::string& resource_id, | 211 const std::string& resource_id, |
208 const google_apis::EntryActionCallback& callback) { | 212 const google_apis::EntryActionCallback& callback) { |
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
210 DCHECK(!callback.is_null()); | 214 DCHECK(!callback.is_null()); |
211 | 215 |
212 scoped_ptr<QueueEntry> new_job( | 216 scoped_ptr<QueueEntry> new_job( |
213 new QueueEntry(TYPE_ADD_RESOURCE_TO_DIRECTORY)); | 217 new QueueEntry(TYPE_ADD_RESOURCE_TO_DIRECTORY)); |
214 new_job->parent_resource_id = parent_resource_id; | 218 new_job->parent_resource_id = parent_resource_id; |
215 new_job->resource_id = resource_id; | 219 new_job->resource_id = resource_id; |
216 new_job->entry_action_callback = callback; | 220 new_job->entry_action_callback = callback; |
217 | 221 |
218 QueueJob(new_job.Pass()); | 222 QueueJob(new_job.Pass()); |
219 | 223 |
220 StartJobLoop(); | 224 StartJobLoop(GetJobQueueType(TYPE_ADD_RESOURCE_TO_DIRECTORY)); |
221 } | 225 } |
222 | 226 |
223 void DriveScheduler::RemoveResourceFromDirectory( | 227 void DriveScheduler::RemoveResourceFromDirectory( |
224 const std::string& parent_resource_id, | 228 const std::string& parent_resource_id, |
225 const std::string& resource_id, | 229 const std::string& resource_id, |
226 const google_apis::EntryActionCallback& callback) { | 230 const google_apis::EntryActionCallback& callback) { |
227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
228 | 232 |
229 scoped_ptr<QueueEntry> new_job( | 233 scoped_ptr<QueueEntry> new_job( |
230 new QueueEntry(TYPE_REMOVE_RESOURCE_FROM_DIRECTORY)); | 234 new QueueEntry(TYPE_REMOVE_RESOURCE_FROM_DIRECTORY)); |
231 new_job->parent_resource_id = parent_resource_id; | 235 new_job->parent_resource_id = parent_resource_id; |
232 new_job->resource_id = resource_id; | 236 new_job->resource_id = resource_id; |
233 new_job->entry_action_callback = callback; | 237 new_job->entry_action_callback = callback; |
234 | 238 |
235 QueueJob(new_job.Pass()); | 239 QueueJob(new_job.Pass()); |
236 | 240 |
237 StartJobLoop(); | 241 StartJobLoop(GetJobQueueType(TYPE_REMOVE_RESOURCE_FROM_DIRECTORY)); |
238 } | 242 } |
239 | 243 |
240 void DriveScheduler::AddNewDirectory( | 244 void DriveScheduler::AddNewDirectory( |
241 const std::string& parent_resource_id, | 245 const std::string& parent_resource_id, |
242 const std::string& directory_name, | 246 const std::string& directory_name, |
243 const google_apis::GetResourceEntryCallback& callback) { | 247 const google_apis::GetResourceEntryCallback& callback) { |
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
245 | 249 |
246 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_ADD_NEW_DIRECTORY)); | 250 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_ADD_NEW_DIRECTORY)); |
247 new_job->parent_resource_id = parent_resource_id; | 251 new_job->parent_resource_id = parent_resource_id; |
248 new_job->directory_name = directory_name; | 252 new_job->directory_name = directory_name; |
249 new_job->get_resource_entry_callback = callback; | 253 new_job->get_resource_entry_callback = callback; |
250 | 254 |
251 QueueJob(new_job.Pass()); | 255 QueueJob(new_job.Pass()); |
252 | 256 |
253 StartJobLoop(); | 257 StartJobLoop(GetJobQueueType(TYPE_ADD_NEW_DIRECTORY)); |
254 } | 258 } |
255 | 259 |
256 void DriveScheduler::DownloadFile( | 260 void DriveScheduler::DownloadFile( |
257 const base::FilePath& virtual_path, | 261 const base::FilePath& virtual_path, |
258 const base::FilePath& local_cache_path, | 262 const base::FilePath& local_cache_path, |
259 const GURL& download_url, | 263 const GURL& download_url, |
260 const DriveClientContext& context, | 264 const DriveClientContext& context, |
261 const google_apis::DownloadActionCallback& download_action_callback, | 265 const google_apis::DownloadActionCallback& download_action_callback, |
262 const google_apis::GetContentCallback& get_content_callback) { | 266 const google_apis::GetContentCallback& get_content_callback) { |
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
264 | 268 |
265 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_DOWNLOAD_FILE)); | 269 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_DOWNLOAD_FILE)); |
266 new_job->virtual_path = virtual_path; | 270 new_job->virtual_path = virtual_path; |
267 new_job->local_cache_path = local_cache_path; | 271 new_job->local_cache_path = local_cache_path; |
268 new_job->download_url = download_url; | 272 new_job->download_url = download_url; |
269 new_job->context = context; | 273 new_job->context = context; |
270 new_job->download_action_callback = download_action_callback; | 274 new_job->download_action_callback = download_action_callback; |
271 new_job->get_content_callback = get_content_callback; | 275 new_job->get_content_callback = get_content_callback; |
272 | 276 |
273 QueueJob(new_job.Pass()); | 277 QueueJob(new_job.Pass()); |
274 | 278 |
275 StartJobLoop(); | 279 StartJobLoop(GetJobQueueType(TYPE_DOWNLOAD_FILE)); |
276 } | 280 } |
277 | 281 |
278 void DriveScheduler::UploadExistingFile( | 282 void DriveScheduler::UploadExistingFile( |
279 const GURL& upload_location, | 283 const GURL& upload_location, |
280 const base::FilePath& drive_file_path, | 284 const base::FilePath& drive_file_path, |
281 const base::FilePath& local_file_path, | 285 const base::FilePath& local_file_path, |
282 const std::string& content_type, | 286 const std::string& content_type, |
283 const std::string& etag, | 287 const std::string& etag, |
284 const DriveClientContext& context, | 288 const DriveClientContext& context, |
285 const google_apis::UploadCompletionCallback& upload_completion_callback) { | 289 const google_apis::UploadCompletionCallback& upload_completion_callback) { |
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
287 | 291 |
288 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_UPLOAD_EXISTING_FILE)); | 292 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_UPLOAD_EXISTING_FILE)); |
289 new_job->upload_location = upload_location; | 293 new_job->upload_location = upload_location; |
290 new_job->drive_file_path = drive_file_path; | 294 new_job->drive_file_path = drive_file_path; |
291 new_job->local_file_path = local_file_path; | 295 new_job->local_file_path = local_file_path; |
292 new_job->content_type = content_type; | 296 new_job->content_type = content_type; |
293 new_job->etag = etag; | 297 new_job->etag = etag; |
294 new_job->upload_completion_callback = upload_completion_callback; | 298 new_job->upload_completion_callback = upload_completion_callback; |
295 new_job->context = context; | 299 new_job->context = context; |
296 | 300 |
297 QueueJob(new_job.Pass()); | 301 QueueJob(new_job.Pass()); |
298 | 302 |
299 StartJobLoop(); | 303 StartJobLoop(GetJobQueueType(TYPE_UPLOAD_EXISTING_FILE)); |
300 } | 304 } |
301 | 305 |
302 void DriveScheduler::QueueJob(scoped_ptr<QueueEntry> job) { | 306 void DriveScheduler::QueueJob(scoped_ptr<QueueEntry> job) { |
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
304 | 308 |
305 queue_.push_back(job.release()); | 309 QueueType queue_type = GetJobQueueType(job->job_info.job_type); |
306 queue_.sort(&QueueEntry::Compare); | 310 std::list<QueueEntry*>& queue = queue_[queue_type]; |
| 311 |
| 312 queue.push_back(job.release()); |
| 313 queue.sort(&QueueEntry::Compare); |
307 } | 314 } |
308 | 315 |
309 void DriveScheduler::StartJobLoop() { | 316 void DriveScheduler::StartJobLoop(QueueType queue_type) { |
310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
311 | 318 |
312 if (!job_loop_is_running_) | 319 if (!job_loop_is_running_[queue_type]) |
313 DoJobLoop(); | 320 DoJobLoop(queue_type); |
314 } | 321 } |
315 | 322 |
316 void DriveScheduler::DoJobLoop() { | 323 void DriveScheduler::DoJobLoop(QueueType queue_type) { |
317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
318 | 325 |
319 if (queue_.empty() || ShouldStopJobLoop()) { | 326 if (queue_[queue_type].empty()) { |
320 // Note that |queue_| is not cleared so the sync loop can resume. | 327 // Note that |queue_| is not cleared so the sync loop can resume. |
321 job_loop_is_running_ = false; | 328 job_loop_is_running_[queue_type] = false; |
322 return; | 329 return; |
323 } | 330 } |
324 job_loop_is_running_ = true; | 331 |
| 332 // Check if we should defer based on the first item in the queue |
| 333 if (ShouldStopJobLoop(queue_type, queue_[queue_type].front()->context)) { |
| 334 job_loop_is_running_[queue_type] = false; |
| 335 return; |
| 336 } |
| 337 |
| 338 job_loop_is_running_[queue_type] = true; |
325 | 339 |
326 // Should copy before calling queue_.pop_front(). | 340 // Should copy before calling queue_.pop_front(). |
327 scoped_ptr<QueueEntry> queue_entry(queue_.front()); | 341 scoped_ptr<QueueEntry> queue_entry(queue_[queue_type].front()); |
328 queue_.pop_front(); | 342 queue_[queue_type].pop_front(); |
329 | 343 |
330 JobInfo& job_info = queue_entry->job_info; | 344 JobInfo& job_info = queue_entry->job_info; |
331 job_info.state = STATE_RUNNING; | 345 job_info.state = STATE_RUNNING; |
332 | 346 |
333 // The some arguments are evaluated after bind, so we copy the pointer to the | 347 // The some arguments are evaluated after bind, so we copy the pointer to the |
334 // QueueEntry | 348 // QueueEntry |
335 QueueEntry* entry = queue_entry.get(); | 349 QueueEntry* entry = queue_entry.get(); |
336 | 350 |
337 switch (job_info.job_type) { | 351 switch (job_info.job_type) { |
338 case TYPE_GET_ACCOUNT_METADATA: { | 352 case TYPE_GET_ACCOUNT_METADATA: { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 weak_ptr_factory_.GetWeakPtr(), | 471 weak_ptr_factory_.GetWeakPtr(), |
458 base::Passed(&queue_entry))); | 472 base::Passed(&queue_entry))); |
459 } | 473 } |
460 break; | 474 break; |
461 | 475 |
462 // There is no default case so that there will be a compiler error if a type | 476 // There is no default case so that there will be a compiler error if a type |
463 // is added but unhandled. | 477 // is added but unhandled. |
464 } | 478 } |
465 } | 479 } |
466 | 480 |
467 bool DriveScheduler::ShouldStopJobLoop() { | 481 bool DriveScheduler::ShouldStopJobLoop(QueueType queue_type, |
| 482 const DriveClientContext& context) { |
468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
469 | 484 |
470 // Should stop if the gdata feature was disabled while running the fetch | 485 // Should stop if the gdata feature was disabled while running the fetch |
471 // loop. | 486 // loop. |
472 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDrive)) | 487 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDrive)) |
473 return true; | 488 return true; |
474 | 489 |
475 // Should stop if the network is not online. | 490 // Should stop if the network is not online. |
476 if (net::NetworkChangeNotifier::IsOffline()) | 491 if (net::NetworkChangeNotifier::IsOffline()) |
477 return true; | 492 return true; |
478 | 493 |
479 // TODO(zork): This is a temporary fix for crbug.com/172270. It should be | 494 if (queue_type == FILE_QUEUE && context.type == BACKGROUND) { |
480 // re-enabled once it's merged. | 495 // Should stop if the current connection is on cellular network, and |
481 // | 496 // fetching is disabled over cellular. |
482 // Should stop if the current connection is on cellular network, and | 497 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDriveOverCellular) && |
483 // fetching is disabled over cellular. | 498 net::NetworkChangeNotifier::IsConnectionCellular( |
484 // if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDriveOverCellular) && | 499 net::NetworkChangeNotifier::GetConnectionType())) |
485 // net::NetworkChangeNotifier::IsConnectionCellular( | 500 return true; |
486 // net::NetworkChangeNotifier::GetConnectionType())) | 501 } |
487 // return true; | |
488 | 502 |
489 return false; | 503 return false; |
490 } | 504 } |
491 | 505 |
492 void DriveScheduler::ThrottleAndContinueJobLoop() { | 506 void DriveScheduler::ThrottleAndContinueJobLoop(QueueType queue_type) { |
493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 507 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
494 | 508 |
495 if (throttle_count_ < kMaxThrottleCount) | 509 if (throttle_count_ < kMaxThrottleCount) |
496 throttle_count_++; | 510 throttle_count_++; |
497 | 511 |
498 base::TimeDelta delay; | 512 base::TimeDelta delay; |
499 if (disable_throttling_) { | 513 if (disable_throttling_) { |
500 delay = base::TimeDelta::FromSeconds(0); | 514 delay = base::TimeDelta::FromSeconds(0); |
501 } else { | 515 } else { |
502 delay = | 516 delay = |
503 base::TimeDelta::FromSeconds(pow(2, throttle_count_ - 1)) + | 517 base::TimeDelta::FromSeconds(pow(2, throttle_count_ - 1)) + |
504 base::TimeDelta::FromMilliseconds(base::RandInt(0, 1000)); | 518 base::TimeDelta::FromMilliseconds(base::RandInt(0, 1000)); |
505 } | 519 } |
506 VLOG(1) << "Throttling for " << delay.InMillisecondsF(); | 520 VLOG(1) << "Throttling for " << delay.InMillisecondsF(); |
507 | 521 |
508 const bool posted = base::MessageLoopProxy::current()->PostDelayedTask( | 522 const bool posted = base::MessageLoopProxy::current()->PostDelayedTask( |
509 FROM_HERE, | 523 FROM_HERE, |
510 base::Bind(&DriveScheduler::DoJobLoop, | 524 base::Bind(&DriveScheduler::DoJobLoop, |
511 weak_ptr_factory_.GetWeakPtr()), | 525 weak_ptr_factory_.GetWeakPtr(), |
| 526 queue_type), |
512 delay); | 527 delay); |
513 DCHECK(posted); | 528 DCHECK(posted); |
514 } | 529 } |
515 | 530 |
516 void DriveScheduler::ResetThrottleAndContinueJobLoop() { | 531 void DriveScheduler::ResetThrottleAndContinueJobLoop(QueueType queue_type) { |
517 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
518 | 533 |
519 // Post a task to continue the job loop. This allows us to finish handling | 534 // Post a task to continue the job loop. This allows us to finish handling |
520 // the current job before starting the next one. | 535 // the current job before starting the next one. |
521 throttle_count_ = 0; | 536 throttle_count_ = 0; |
522 base::MessageLoopProxy::current()->PostTask(FROM_HERE, | 537 base::MessageLoopProxy::current()->PostTask(FROM_HERE, |
523 base::Bind(&DriveScheduler::DoJobLoop, | 538 base::Bind(&DriveScheduler::DoJobLoop, |
524 weak_ptr_factory_.GetWeakPtr())); | 539 weak_ptr_factory_.GetWeakPtr(), |
| 540 queue_type)); |
525 } | 541 } |
526 | 542 |
527 scoped_ptr<DriveScheduler::QueueEntry> DriveScheduler::OnJobDone( | 543 scoped_ptr<DriveScheduler::QueueEntry> DriveScheduler::OnJobDone( |
528 scoped_ptr<DriveScheduler::QueueEntry> queue_entry, | 544 scoped_ptr<DriveScheduler::QueueEntry> queue_entry, |
529 DriveFileError error) { | 545 DriveFileError error) { |
530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
531 | 547 |
| 548 QueueType queue_type = GetJobQueueType(queue_entry->job_info.job_type); |
| 549 |
532 // Retry, depending on the error. | 550 // Retry, depending on the error. |
533 if (error == DRIVE_FILE_ERROR_THROTTLED) { | 551 if (error == DRIVE_FILE_ERROR_THROTTLED) { |
534 queue_entry->job_info.state = STATE_RETRY; | 552 queue_entry->job_info.state = STATE_RETRY; |
535 | 553 |
536 // Requeue the job. | 554 // Requeue the job. |
537 QueueJob(queue_entry.Pass()); | 555 QueueJob(queue_entry.Pass()); |
538 | 556 |
539 ThrottleAndContinueJobLoop(); | 557 ThrottleAndContinueJobLoop(queue_type); |
540 | 558 |
541 return scoped_ptr<DriveScheduler::QueueEntry>(); | 559 return scoped_ptr<DriveScheduler::QueueEntry>(); |
542 } else { | 560 } else { |
543 ResetThrottleAndContinueJobLoop(); | 561 ResetThrottleAndContinueJobLoop(queue_type); |
544 | 562 |
545 // Send the entry back. | 563 // Send the entry back. |
546 return queue_entry.Pass(); | 564 return queue_entry.Pass(); |
547 } | 565 } |
548 } | 566 } |
549 | 567 |
550 void DriveScheduler::OnGetResourceListJobDone( | 568 void DriveScheduler::OnGetResourceListJobDone( |
551 scoped_ptr<DriveScheduler::QueueEntry> queue_entry, | 569 scoped_ptr<DriveScheduler::QueueEntry> queue_entry, |
552 google_apis::GDataErrorCode error, | 570 google_apis::GDataErrorCode error, |
553 scoped_ptr<google_apis::ResourceList> resource_list) { | 571 scoped_ptr<google_apis::ResourceList> resource_list) { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 error, drive_path, file_path, resource_entry.Pass()); | 691 error, drive_path, file_path, resource_entry.Pass()); |
674 } | 692 } |
675 | 693 |
676 void DriveScheduler::OnConnectionTypeChanged( | 694 void DriveScheduler::OnConnectionTypeChanged( |
677 net::NetworkChangeNotifier::ConnectionType type) { | 695 net::NetworkChangeNotifier::ConnectionType type) { |
678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 696 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
679 | 697 |
680 // Resume the job loop if the network is back online. Note that we don't | 698 // Resume the job loop if the network is back online. Note that we don't |
681 // need to check the type of the network as it will be checked in | 699 // need to check the type of the network as it will be checked in |
682 // ShouldStopJobLoop() as soon as the loop is resumed. | 700 // ShouldStopJobLoop() as soon as the loop is resumed. |
683 if (!net::NetworkChangeNotifier::IsOffline()) | 701 if (!net::NetworkChangeNotifier::IsOffline()) { |
684 StartJobLoop(); | 702 for (int i = METADATA_QUEUE; i < NUM_QUEUES; ++i) { |
| 703 StartJobLoop(static_cast<QueueType>(i)); |
| 704 } |
| 705 } |
| 706 } |
| 707 |
| 708 DriveScheduler::QueueType DriveScheduler::GetJobQueueType(JobType type) { |
| 709 switch (type) { |
| 710 case TYPE_GET_ACCOUNT_METADATA: |
| 711 case TYPE_GET_APP_LIST: |
| 712 case TYPE_GET_RESOURCE_LIST: |
| 713 case TYPE_GET_RESOURCE_ENTRY: |
| 714 case TYPE_DELETE_RESOURCE: |
| 715 case TYPE_COPY_HOSTED_DOCUMENT: |
| 716 case TYPE_RENAME_RESOURCE: |
| 717 case TYPE_ADD_RESOURCE_TO_DIRECTORY: |
| 718 case TYPE_REMOVE_RESOURCE_FROM_DIRECTORY: |
| 719 case TYPE_ADD_NEW_DIRECTORY: |
| 720 return METADATA_QUEUE; |
| 721 |
| 722 case TYPE_DOWNLOAD_FILE: |
| 723 case TYPE_UPLOAD_EXISTING_FILE: |
| 724 return FILE_QUEUE; |
| 725 } |
| 726 NOTREACHED(); |
| 727 return FILE_QUEUE; |
685 } | 728 } |
686 | 729 |
687 } // namespace drive | 730 } // namespace drive |
OLD | NEW |