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/rand_util.h" | 10 #include "base/rand_util.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 DriveScheduler::JobInfo::JobInfo(JobType in_job_type, FilePath in_file_path) | 27 DriveScheduler::JobInfo::JobInfo(JobType in_job_type, FilePath in_file_path) |
28 : job_type(in_job_type), | 28 : job_type(in_job_type), |
29 job_id(-1), | 29 job_id(-1), |
30 completed_bytes(0), | 30 completed_bytes(0), |
31 total_bytes(0), | 31 total_bytes(0), |
32 file_path(in_file_path), | 32 file_path(in_file_path), |
33 state(STATE_NONE) { | 33 state(STATE_NONE) { |
34 } | 34 } |
35 | 35 |
36 DriveScheduler::QueueEntry::QueueEntry(JobType in_job_type, | 36 DriveScheduler::QueueEntry::QueueEntry(JobType in_job_type, |
37 FilePath in_file_path) | 37 FilePath in_file_path, |
38 : job_info(TYPE_REMOVE, in_file_path) { | 38 FileOperationCallback in_callback) |
| 39 : job_info(in_job_type, in_file_path), |
| 40 callback(in_callback), |
| 41 is_recursive(false) { |
39 } | 42 } |
40 | 43 |
41 DriveScheduler::QueueEntry::~QueueEntry() { | 44 DriveScheduler::QueueEntry::~QueueEntry() { |
42 } | 45 } |
43 | 46 |
44 DriveScheduler::RemoveJobPrivate::RemoveJobPrivate( | |
45 bool in_is_recursive, | |
46 FileOperationCallback in_callback) | |
47 : is_recursive(in_is_recursive), | |
48 callback(in_callback) { | |
49 } | |
50 | |
51 DriveScheduler::RemoveJobPrivate::~RemoveJobPrivate() { | |
52 } | |
53 | |
54 DriveScheduler::DriveScheduler(Profile* profile, | 47 DriveScheduler::DriveScheduler(Profile* profile, |
55 file_system::DriveOperations* drive_operations) | 48 file_system::DriveOperations* drive_operations) |
56 : job_loop_is_running_(false), | 49 : job_loop_is_running_(false), |
57 next_job_id_(0), | 50 next_job_id_(0), |
58 throttle_count_(0), | 51 throttle_count_(0), |
59 disable_throttling_(false), | 52 disable_throttling_(false), |
60 drive_operations_(drive_operations), | 53 drive_operations_(drive_operations), |
61 profile_(profile), | 54 profile_(profile), |
62 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 55 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
64 } | 57 } |
65 | 58 |
66 DriveScheduler::~DriveScheduler() { | 59 DriveScheduler::~DriveScheduler() { |
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
68 | 61 |
69 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 62 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
70 } | 63 } |
71 | 64 |
72 void DriveScheduler::Initialize() { | 65 void DriveScheduler::Initialize() { |
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
74 | 67 |
75 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | 68 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); |
76 } | 69 } |
77 | 70 |
| 71 void DriveScheduler::Move(const FilePath& src_file_path, |
| 72 const FilePath& dest_file_path, |
| 73 const FileOperationCallback& callback) { |
| 74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 75 |
| 76 scoped_ptr<QueueEntry> new_job( |
| 77 new QueueEntry(TYPE_MOVE, src_file_path, callback)); |
| 78 new_job->dest_file_path = dest_file_path; |
| 79 |
| 80 QueueJob(new_job.Pass()); |
| 81 |
| 82 StartJobLoop(); |
| 83 } |
78 | 84 |
79 void DriveScheduler::Remove(const FilePath& file_path, | 85 void DriveScheduler::Remove(const FilePath& file_path, |
80 bool is_recursive, | 86 bool is_recursive, |
81 const FileOperationCallback& callback) { | 87 const FileOperationCallback& callback) { |
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
83 | 89 |
84 QueueEntry* new_job = new QueueEntry(TYPE_REMOVE, file_path); | 90 scoped_ptr<QueueEntry> new_job( |
85 new_job->remove_private.reset(new RemoveJobPrivate(is_recursive, callback)); | 91 new QueueEntry(TYPE_REMOVE, file_path, callback)); |
| 92 new_job->is_recursive = is_recursive; |
86 | 93 |
87 QueueJob(new_job); | 94 QueueJob(new_job.Pass()); |
88 | 95 |
89 StartJobLoop(); | 96 StartJobLoop(); |
90 } | 97 } |
91 | 98 |
92 int DriveScheduler::QueueJob(QueueEntry* job) { | 99 int DriveScheduler::QueueJob(scoped_ptr<QueueEntry> job) { |
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
94 | 101 |
95 int job_id = next_job_id_; | 102 int job_id = next_job_id_; |
96 job->job_info.job_id = job_id; | 103 job->job_info.job_id = job_id; |
97 next_job_id_++; | 104 next_job_id_++; |
98 | 105 |
99 queue_.push_back(job_id); | 106 queue_.push_back(job_id); |
100 | 107 |
101 DCHECK(job_info_.find(job_id) == job_info_.end()); | 108 DCHECK(job_info_map_.find(job_id) == job_info_map_.end()); |
102 job_info_[job_id] = make_linked_ptr(job); | 109 job_info_map_[job_id] = make_linked_ptr(job.release()); |
103 | 110 |
104 return job_id; | 111 return job_id; |
105 } | 112 } |
106 | 113 |
107 void DriveScheduler::StartJobLoop() { | 114 void DriveScheduler::StartJobLoop() { |
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
109 | 116 |
110 if (!job_loop_is_running_) | 117 if (!job_loop_is_running_) |
111 DoJobLoop(); | 118 DoJobLoop(); |
112 } | 119 } |
113 | 120 |
114 void DriveScheduler::DoJobLoop() { | 121 void DriveScheduler::DoJobLoop() { |
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
116 | 123 |
117 if (queue_.empty() || ShouldStopJobLoop()) { | 124 if (queue_.empty() || ShouldStopJobLoop()) { |
118 // Note that |queue_| is not cleared so the sync loop can resume. | 125 // Note that |queue_| is not cleared so the sync loop can resume. |
119 job_loop_is_running_ = false; | 126 job_loop_is_running_ = false; |
120 return; | 127 return; |
121 } | 128 } |
122 job_loop_is_running_ = true; | 129 job_loop_is_running_ = true; |
123 | 130 |
124 // Should copy before calling queue_.pop_front(). | 131 // Should copy before calling queue_.pop_front(). |
125 int job_id = queue_.front(); | 132 int job_id = queue_.front(); |
126 queue_.pop_front(); | 133 queue_.pop_front(); |
127 | 134 |
128 JobMap::iterator job_iter = job_info_.find(job_id); | 135 JobMap::iterator job_iter = job_info_map_.find(job_id); |
129 DCHECK(job_iter != job_info_.end()); | 136 DCHECK(job_iter != job_info_map_.end()); |
130 | 137 |
131 JobInfo& job_info = job_iter->second->job_info; | 138 JobInfo& job_info = job_iter->second->job_info; |
132 job_info.state = STATE_RUNNING; | 139 job_info.state = STATE_RUNNING; |
133 | 140 |
134 switch (job_info.job_type) { | 141 switch (job_info.job_type) { |
135 case TYPE_REMOVE: { | 142 case TYPE_MOVE: { |
136 DCHECK(job_iter->second->remove_private.get()); | 143 drive_operations_->Move( |
137 | |
138 drive_operations_->Remove( | |
139 job_info.file_path, | 144 job_info.file_path, |
140 job_iter->second->remove_private->is_recursive, | 145 job_iter->second->dest_file_path, |
141 base::Bind(&DriveScheduler::OnRemoveDone, | 146 base::Bind(&DriveScheduler::OnJobDone, |
142 weak_ptr_factory_.GetWeakPtr(), | 147 weak_ptr_factory_.GetWeakPtr(), |
143 job_id)); | 148 job_id)); |
144 } | 149 } |
| 150 break; |
| 151 |
| 152 case TYPE_REMOVE: { |
| 153 drive_operations_->Remove( |
| 154 job_info.file_path, |
| 155 job_iter->second->is_recursive, |
| 156 base::Bind(&DriveScheduler::OnJobDone, |
| 157 weak_ptr_factory_.GetWeakPtr(), |
| 158 job_id)); |
| 159 } |
145 break; | 160 break; |
146 } | 161 } |
147 | 162 |
148 } | 163 } |
149 | 164 |
150 bool DriveScheduler::ShouldStopJobLoop() { | 165 bool DriveScheduler::ShouldStopJobLoop() { |
151 // Should stop if the gdata feature was disabled while running the fetch | 166 // Should stop if the gdata feature was disabled while running the fetch |
152 // loop. | 167 // loop. |
153 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableGData)) | 168 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableGData)) |
154 return true; | 169 return true; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 DCHECK(posted); | 205 DCHECK(posted); |
191 } | 206 } |
192 | 207 |
193 void DriveScheduler::ResetThrottleAndContinueJobLoop() { | 208 void DriveScheduler::ResetThrottleAndContinueJobLoop() { |
194 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
195 | 210 |
196 throttle_count_ = 0; | 211 throttle_count_ = 0; |
197 DoJobLoop(); | 212 DoJobLoop(); |
198 } | 213 } |
199 | 214 |
200 void DriveScheduler::OnRemoveDone(int job_id, DriveFileError error) { | 215 void DriveScheduler::OnJobDone(int job_id, DriveFileError error) { |
201 JobMap::iterator job_iter = job_info_.find(job_id); | 216 JobMap::iterator job_iter = job_info_map_.find(job_id); |
202 DCHECK(job_iter != job_info_.end()); | 217 DCHECK(job_iter != job_info_map_.end()); |
203 | 218 |
204 // Retry, depending on the error. | 219 // Retry, depending on the error. |
205 if (error == DRIVE_FILE_ERROR_THROTTLED || | 220 if (error == DRIVE_FILE_ERROR_THROTTLED || |
206 error == DRIVE_FILE_ERROR_NO_CONNECTION) { | 221 error == DRIVE_FILE_ERROR_NO_CONNECTION) { |
207 job_iter->second->job_info.state = STATE_RETRY; | 222 job_iter->second->job_info.state = STATE_RETRY; |
208 | 223 |
209 // Requeue the job. | 224 // Requeue the job. |
210 queue_.push_back(job_id); | 225 queue_.push_back(job_id); |
211 ThrottleAndContinueJobLoop(); | 226 ThrottleAndContinueJobLoop(); |
212 } else { | 227 } else { |
213 DCHECK(job_iter->second->remove_private.get()); | |
214 | |
215 // Handle the callback. | 228 // Handle the callback. |
216 if (!job_iter->second->remove_private->callback.is_null()) { | 229 if (!job_iter->second->callback.is_null()) { |
217 MessageLoop::current()->PostTask(FROM_HERE, | 230 MessageLoop::current()->PostTask(FROM_HERE, |
218 base::Bind(job_iter->second->remove_private->callback, error)); | 231 base::Bind(job_iter->second->callback, error)); |
219 } | 232 } |
220 | 233 |
221 // Delete the job. | 234 // Delete the job. |
222 job_info_.erase(job_id); | 235 job_info_map_.erase(job_id); |
223 ResetThrottleAndContinueJobLoop(); | 236 ResetThrottleAndContinueJobLoop(); |
224 } | 237 } |
225 } | 238 } |
226 | 239 |
227 void DriveScheduler::OnConnectionTypeChanged( | 240 void DriveScheduler::OnConnectionTypeChanged( |
228 net::NetworkChangeNotifier::ConnectionType type) { | 241 net::NetworkChangeNotifier::ConnectionType type) { |
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
230 | 243 |
231 // Resume the job loop if the network is back online. Note that we don't | 244 // Resume the job loop if the network is back online. Note that we don't |
232 // need to check the type of the network as it will be checked in | 245 // need to check the type of the network as it will be checked in |
233 // ShouldStopJobLoop() as soon as the loop is resumed. | 246 // ShouldStopJobLoop() as soon as the loop is resumed. |
234 if (!net::NetworkChangeNotifier::IsOffline()) | 247 if (!net::NetworkChangeNotifier::IsOffline()) |
235 StartJobLoop(); | 248 StartJobLoop(); |
236 } | 249 } |
237 | 250 |
238 } // namespace drive | 251 } // namespace drive |
OLD | NEW |