OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS 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 "update_engine/update_attempter.h" | 5 #include "update_engine/update_attempter.h" |
6 | |
7 // From 'man clock_gettime': feature test macro: _POSIX_C_SOURCE >= 199309L | |
8 #ifndef _POSIX_C_SOURCE | |
9 #define _POSIX_C_SOURCE 199309L | |
10 #endif // _POSIX_C_SOURCE | |
11 #include <time.h> | |
12 | |
6 #include <tr1/memory> | 13 #include <tr1/memory> |
7 #include <string> | 14 #include <string> |
8 #include <vector> | 15 #include <vector> |
9 #include <glib.h> | 16 #include <glib.h> |
17 #include "update_engine/dbus_service.h" | |
10 #include "update_engine/download_action.h" | 18 #include "update_engine/download_action.h" |
11 #include "update_engine/filesystem_copier_action.h" | 19 #include "update_engine/filesystem_copier_action.h" |
12 #include "update_engine/libcurl_http_fetcher.h" | 20 #include "update_engine/libcurl_http_fetcher.h" |
13 #include "update_engine/omaha_request_prep_action.h" | 21 #include "update_engine/omaha_request_prep_action.h" |
14 #include "update_engine/omaha_response_handler_action.h" | 22 #include "update_engine/omaha_response_handler_action.h" |
15 #include "update_engine/postinstall_runner_action.h" | 23 #include "update_engine/postinstall_runner_action.h" |
16 #include "update_engine/set_bootable_flag_action.h" | 24 #include "update_engine/set_bootable_flag_action.h" |
17 #include "update_engine/update_check_action.h" | 25 #include "update_engine/update_check_action.h" |
18 | 26 |
19 using std::tr1::shared_ptr; | 27 using std::tr1::shared_ptr; |
20 using std::string; | 28 using std::string; |
21 using std::vector; | 29 using std::vector; |
22 | 30 |
23 namespace chromeos_update_engine { | 31 namespace chromeos_update_engine { |
24 | 32 |
33 namespace { | |
34 // Returns true on success. | |
35 bool GetCPUClockTime(struct timespec* out) { | |
36 return clock_gettime(CLOCK_REALTIME, out) == 0; | |
37 } | |
38 // Returns stop - start. | |
39 struct timespec CPUClockTimeElapsed(const struct timespec& start, | |
40 const struct timespec& stop) { | |
41 CHECK(start.tv_sec >= 0); | |
42 CHECK(stop.tv_sec >= 0); | |
43 CHECK(start.tv_nsec >= 0); | |
44 CHECK(stop.tv_nsec >= 0); | |
45 | |
46 const int64 kOneBillion = 1000000000L; | |
Daniel Erat
2010/05/10 19:11:42
nit: int64_t :-)
| |
47 int64 start64 = start.tv_sec * kOneBillion + start.tv_nsec; | |
48 int64 stop64 = stop.tv_sec * kOneBillion + stop.tv_nsec; | |
49 | |
50 int64 result64 = stop64 - start64; | |
51 | |
52 struct timespec ret; | |
53 ret.tv_sec = result64 / kOneBillion; | |
54 ret.tv_nsec = result64 % kOneBillion; | |
55 | |
56 return ret; | |
57 } | |
58 bool CPUClockTimeGreaterThanHalfSecond(const struct timespec& spec) { | |
59 if (spec.tv_sec >= 1) | |
60 return true; | |
61 return (spec.tv_nsec > 500000000); | |
62 } | |
63 } | |
64 | |
65 const char* UpdateStatusToString(UpdateStatus status) { | |
66 switch (status) { | |
67 case UPDATE_STATUS_IDLE: | |
68 return "UPDATE_STATUS_IDLE"; | |
69 case UPDATE_STATUS_CHECKING_FOR_UPDATE: | |
70 return "UPDATE_STATUS_CHECKING_FOR_UPDATE"; | |
71 case UPDATE_STATUS_UPDATE_AVAILABLE: | |
72 return "UPDATE_STATUS_UPDATE_AVAILABLE"; | |
73 case UPDATE_STATUS_DOWNLOADING: | |
74 return "UPDATE_STATUS_DOWNLOADING"; | |
75 case UPDATE_STATUS_VERIFYING: | |
76 return "UPDATE_STATUS_VERIFYING"; | |
77 case UPDATE_STATUS_FINALIZING: | |
78 return "UPDATE_STATUS_FINALIZING"; | |
79 case UPDATE_STATUS_UPDATED_NEED_REBOOT: | |
80 return "UPDATE_STATUS_UPDATED_NEED_REBOOT"; | |
81 default: | |
82 return "unknown status"; | |
83 } | |
84 } | |
85 | |
25 void UpdateAttempter::Update(bool force_full_update) { | 86 void UpdateAttempter::Update(bool force_full_update) { |
26 full_update_ = force_full_update; | 87 full_update_ = force_full_update; |
27 CHECK(!processor_.IsRunning()); | 88 CHECK(!processor_.IsRunning()); |
28 processor_.set_delegate(this); | 89 processor_.set_delegate(this); |
29 | 90 |
30 // Actions: | 91 // Actions: |
31 shared_ptr<OmahaRequestPrepAction> request_prep_action( | 92 shared_ptr<OmahaRequestPrepAction> request_prep_action( |
32 new OmahaRequestPrepAction(force_full_update)); | 93 new OmahaRequestPrepAction(force_full_update)); |
33 shared_ptr<UpdateCheckAction> update_check_action( | 94 shared_ptr<UpdateCheckAction> update_check_action( |
34 new UpdateCheckAction(new LibcurlHttpFetcher)); | 95 new UpdateCheckAction(new LibcurlHttpFetcher)); |
35 shared_ptr<OmahaResponseHandlerAction> response_handler_action( | 96 shared_ptr<OmahaResponseHandlerAction> response_handler_action( |
36 new OmahaResponseHandlerAction); | 97 new OmahaResponseHandlerAction); |
37 shared_ptr<FilesystemCopierAction> filesystem_copier_action( | 98 shared_ptr<FilesystemCopierAction> filesystem_copier_action( |
38 new FilesystemCopierAction(false)); | 99 new FilesystemCopierAction(false)); |
39 shared_ptr<FilesystemCopierAction> kernel_filesystem_copier_action( | 100 shared_ptr<FilesystemCopierAction> kernel_filesystem_copier_action( |
40 new FilesystemCopierAction(true)); | 101 new FilesystemCopierAction(true)); |
41 shared_ptr<DownloadAction> download_action( | 102 shared_ptr<DownloadAction> download_action( |
42 new DownloadAction(new LibcurlHttpFetcher)); | 103 new DownloadAction(new LibcurlHttpFetcher)); |
43 shared_ptr<PostinstallRunnerAction> postinstall_runner_action_precommit( | 104 shared_ptr<PostinstallRunnerAction> postinstall_runner_action_precommit( |
44 new PostinstallRunnerAction(true)); | 105 new PostinstallRunnerAction(true)); |
45 shared_ptr<SetBootableFlagAction> set_bootable_flag_action( | 106 shared_ptr<SetBootableFlagAction> set_bootable_flag_action( |
46 new SetBootableFlagAction); | 107 new SetBootableFlagAction); |
47 shared_ptr<PostinstallRunnerAction> postinstall_runner_action_postcommit( | 108 shared_ptr<PostinstallRunnerAction> postinstall_runner_action_postcommit( |
48 new PostinstallRunnerAction(false)); | 109 new PostinstallRunnerAction(false)); |
49 | 110 |
111 download_action->set_delegate(this); | |
50 response_handler_action_ = response_handler_action; | 112 response_handler_action_ = response_handler_action; |
51 | 113 |
52 actions_.push_back(shared_ptr<AbstractAction>(request_prep_action)); | 114 actions_.push_back(shared_ptr<AbstractAction>(request_prep_action)); |
53 actions_.push_back(shared_ptr<AbstractAction>(update_check_action)); | 115 actions_.push_back(shared_ptr<AbstractAction>(update_check_action)); |
54 actions_.push_back(shared_ptr<AbstractAction>(response_handler_action)); | 116 actions_.push_back(shared_ptr<AbstractAction>(response_handler_action)); |
55 actions_.push_back(shared_ptr<AbstractAction>(filesystem_copier_action)); | 117 actions_.push_back(shared_ptr<AbstractAction>(filesystem_copier_action)); |
56 actions_.push_back(shared_ptr<AbstractAction>( | 118 actions_.push_back(shared_ptr<AbstractAction>( |
57 kernel_filesystem_copier_action)); | 119 kernel_filesystem_copier_action)); |
58 actions_.push_back(shared_ptr<AbstractAction>(download_action)); | 120 actions_.push_back(shared_ptr<AbstractAction>(download_action)); |
59 actions_.push_back(shared_ptr<AbstractAction>( | 121 actions_.push_back(shared_ptr<AbstractAction>( |
(...skipping 20 matching lines...) Expand all Loading... | |
80 kernel_filesystem_copier_action.get()); | 142 kernel_filesystem_copier_action.get()); |
81 BondActions(kernel_filesystem_copier_action.get(), | 143 BondActions(kernel_filesystem_copier_action.get(), |
82 download_action.get()); | 144 download_action.get()); |
83 BondActions(download_action.get(), | 145 BondActions(download_action.get(), |
84 postinstall_runner_action_precommit.get()); | 146 postinstall_runner_action_precommit.get()); |
85 BondActions(postinstall_runner_action_precommit.get(), | 147 BondActions(postinstall_runner_action_precommit.get(), |
86 set_bootable_flag_action.get()); | 148 set_bootable_flag_action.get()); |
87 BondActions(set_bootable_flag_action.get(), | 149 BondActions(set_bootable_flag_action.get(), |
88 postinstall_runner_action_postcommit.get()); | 150 postinstall_runner_action_postcommit.get()); |
89 | 151 |
152 SetStatusAndNotify(UPDATE_STATUS_CHECKING_FOR_UPDATE); | |
90 processor_.StartProcessing(); | 153 processor_.StartProcessing(); |
91 } | 154 } |
92 | 155 |
93 // Delegate method: | 156 void UpdateAttempter::CheckForUpdate() { |
157 if (status_ != UPDATE_STATUS_IDLE) { | |
158 LOG(INFO) << "Check for update requested, but status is " | |
159 << UpdateStatusToString(status_) << ", so not checking."; | |
160 return; | |
161 } | |
162 Update(false); | |
163 } | |
164 | |
165 // Delegate methods: | |
94 void UpdateAttempter::ProcessingDone(const ActionProcessor* processor, | 166 void UpdateAttempter::ProcessingDone(const ActionProcessor* processor, |
95 bool success) { | 167 bool success) { |
96 CHECK(response_handler_action_); | 168 CHECK(response_handler_action_); |
97 if (response_handler_action_->GotNoUpdateResponse()) { | 169 LOG(INFO) << "Processing Done."; |
98 // All done. | 170 if (success) { |
99 g_main_loop_quit(loop_); | 171 SetStatusAndNotify(UPDATE_STATUS_UPDATED_NEED_REBOOT); |
172 } else { | |
173 LOG(INFO) << "Update failed."; | |
174 SetStatusAndNotify(UPDATE_STATUS_IDLE); | |
175 } | |
176 } | |
177 | |
178 void UpdateAttempter::ProcessingStopped(const ActionProcessor* processor) { | |
179 download_progress_ = 0.0; | |
180 SetStatusAndNotify(UPDATE_STATUS_IDLE); | |
181 } | |
182 | |
183 // Called whenever an action has finished processing, either successfully | |
184 // or otherwise. | |
185 void UpdateAttempter::ActionCompleted(ActionProcessor* processor, | |
186 AbstractAction* action, | |
187 bool success) { | |
188 // Reset download progress regardless of whether or not the download action | |
189 // succeeded. | |
190 const string type = action->Type(); | |
191 if (type == DownloadAction::StaticType()) | |
192 download_progress_ = 0.0; | |
193 if (!success) | |
100 return; | 194 return; |
195 // Find out which action completed. | |
196 if (type == OmahaResponseHandlerAction::StaticType()) { | |
197 SetStatusAndNotify(UPDATE_STATUS_DOWNLOADING); | |
198 OmahaResponseHandlerAction* omaha_response_handler_action = | |
199 dynamic_cast<OmahaResponseHandlerAction*>(action); | |
200 CHECK(omaha_response_handler_action); | |
201 const InstallPlan& plan = omaha_response_handler_action->install_plan(); | |
202 last_checked_time_ = time(NULL); | |
203 // TODO(adlr): put version in InstallPlan | |
204 new_version_ = "0.0.0.0"; | |
205 new_size_ = plan.size; | |
206 } else if (type == DownloadAction::StaticType()) { | |
207 SetStatusAndNotify(UPDATE_STATUS_FINALIZING); | |
101 } | 208 } |
102 if (!success) { | |
103 LOG(INFO) << "Update failed."; | |
104 } | |
105 g_main_loop_quit(loop_); | |
106 } | 209 } |
107 | 210 |
108 // Stop updating. An attempt will be made to record status to the disk | 211 // Stop updating. An attempt will be made to record status to the disk |
109 // so that updates can be resumed later. | 212 // so that updates can be resumed later. |
110 void UpdateAttempter::Terminate() { | 213 void UpdateAttempter::Terminate() { |
111 // TODO(adlr): implement this method. | 214 // TODO(adlr): implement this method. |
112 NOTIMPLEMENTED(); | 215 NOTIMPLEMENTED(); |
113 } | 216 } |
114 | 217 |
115 // Try to resume from a previously Terminate()d update. | 218 // Try to resume from a previously Terminate()d update. |
116 void UpdateAttempter::ResumeUpdating() { | 219 void UpdateAttempter::ResumeUpdating() { |
117 // TODO(adlr): implement this method. | 220 // TODO(adlr): implement this method. |
118 NOTIMPLEMENTED(); | 221 NOTIMPLEMENTED(); |
119 } | 222 } |
120 | 223 |
224 void UpdateAttempter::BytesReceived(uint64_t bytes_received, uint64_t total) { | |
225 if (status_ != UPDATE_STATUS_DOWNLOADING) { | |
226 LOG(ERROR) << "BytesReceived called while not downloading."; | |
227 return; | |
228 } | |
229 download_progress_ = static_cast<double>(bytes_received) / | |
230 static_cast<double>(total); | |
231 // We self throttle here | |
232 timespec now; | |
233 now.tv_sec = 0; | |
234 now.tv_nsec = 0; | |
235 if (GetCPUClockTime(&now) && | |
236 CPUClockTimeGreaterThanHalfSecond( | |
237 CPUClockTimeElapsed(last_notify_time_, now))) { | |
238 SetStatusAndNotify(UPDATE_STATUS_DOWNLOADING); | |
239 } | |
240 } | |
241 | |
121 bool UpdateAttempter::GetStatus(int64_t* last_checked_time, | 242 bool UpdateAttempter::GetStatus(int64_t* last_checked_time, |
122 double* progress, | 243 double* progress, |
123 std::string* current_operation, | 244 std::string* current_operation, |
124 std::string* new_version, | 245 std::string* new_version, |
125 int64_t* new_size) { | 246 int64_t* new_size) { |
126 // TODO(adlr): Return actual status. | 247 *last_checked_time = last_checked_time_; |
127 *last_checked_time = 123; | 248 *progress = download_progress_; |
128 *progress = 0.2223; | 249 *current_operation = UpdateStatusToString(status_); |
129 *current_operation = "DOWNLOADING"; | 250 *new_version = new_version_; |
130 *new_version = "0.2.3.8"; | 251 *new_size = new_size_; |
131 *new_size = 10002; | |
132 return true; | 252 return true; |
133 } | 253 } |
134 | 254 |
255 void UpdateAttempter::SetStatusAndNotify(UpdateStatus status) { | |
256 status_ = status; | |
257 if (!dbus_service_) | |
258 return; | |
259 GetCPUClockTime(&last_notify_time_); | |
260 update_engine_service_emit_status_update( | |
261 dbus_service_, | |
262 last_checked_time_, | |
263 download_progress_, | |
264 UpdateStatusToString(status_), | |
265 new_version_.c_str(), | |
266 new_size_); | |
267 } | |
135 | 268 |
136 } // namespace chromeos_update_engine | 269 } // namespace chromeos_update_engine |
OLD | NEW |