blob: 3614cad06c6466bec87914106bc4d1a760ff5c4a [file] [log] [blame]
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -07001// 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
3// found in the LICENSE file.
4
5#include "update_engine/update_attempter.h"
Andrew de los Reyes63b96d72010-05-10 13:08:54 -07006
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
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070013#include <tr1/memory>
14#include <string>
15#include <vector>
Darin Petkov9d65b7b2010-07-20 09:13:01 -070016
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070017#include <glib.h>
Darin Petkov1023a602010-08-30 13:47:51 -070018#include <metrics/metrics_library.h>
Darin Petkov9d65b7b2010-07-20 09:13:01 -070019
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070020#include "update_engine/dbus_service.h"
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070021#include "update_engine/download_action.h"
22#include "update_engine/filesystem_copier_action.h"
23#include "update_engine/libcurl_http_fetcher.h"
Darin Petkov6a5b3222010-07-13 14:55:28 -070024#include "update_engine/omaha_request_action.h"
Darin Petkova4a8a8c2010-07-15 22:21:12 -070025#include "update_engine/omaha_request_params.h"
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070026#include "update_engine/omaha_response_handler_action.h"
27#include "update_engine/postinstall_runner_action.h"
28#include "update_engine/set_bootable_flag_action.h"
Darin Petkov1023a602010-08-30 13:47:51 -070029#include "update_engine/update_check_scheduler.h"
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070030
Darin Petkovaf183052010-08-23 12:07:13 -070031using base::TimeDelta;
32using base::TimeTicks;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070033using std::tr1::shared_ptr;
34using std::string;
35using std::vector;
36
37namespace chromeos_update_engine {
38
Andrew de los Reyes6b78e292010-05-10 15:54:39 -070039const char* kUpdateCompletedMarker = "/tmp/update_engine_autoupdate_completed";
40
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070041const char* UpdateStatusToString(UpdateStatus status) {
42 switch (status) {
43 case UPDATE_STATUS_IDLE:
44 return "UPDATE_STATUS_IDLE";
45 case UPDATE_STATUS_CHECKING_FOR_UPDATE:
46 return "UPDATE_STATUS_CHECKING_FOR_UPDATE";
47 case UPDATE_STATUS_UPDATE_AVAILABLE:
48 return "UPDATE_STATUS_UPDATE_AVAILABLE";
49 case UPDATE_STATUS_DOWNLOADING:
50 return "UPDATE_STATUS_DOWNLOADING";
51 case UPDATE_STATUS_VERIFYING:
52 return "UPDATE_STATUS_VERIFYING";
53 case UPDATE_STATUS_FINALIZING:
54 return "UPDATE_STATUS_FINALIZING";
55 case UPDATE_STATUS_UPDATED_NEED_REBOOT:
56 return "UPDATE_STATUS_UPDATED_NEED_REBOOT";
Darin Petkov09f96c32010-07-20 09:24:57 -070057 case UPDATE_STATUS_REPORTING_ERROR_EVENT:
58 return "UPDATE_STATUS_REPORTING_ERROR_EVENT";
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070059 default:
60 return "unknown status";
61 }
62}
63
Darin Petkov777dbfa2010-07-20 15:03:37 -070064// Turns a generic kActionCodeError to a generic error code specific
65// to |action| (e.g., kActionCodeFilesystemCopierError). If |code| is
66// not kActionCodeError, or the action is not matched, returns |code|
67// unchanged.
68ActionExitCode GetErrorCodeForAction(AbstractAction* action,
69 ActionExitCode code) {
70 if (code != kActionCodeError)
71 return code;
72
73 const string type = action->Type();
74 if (type == OmahaRequestAction::StaticType())
75 return kActionCodeOmahaRequestError;
76 if (type == OmahaResponseHandlerAction::StaticType())
77 return kActionCodeOmahaResponseHandlerError;
78 if (type == FilesystemCopierAction::StaticType())
79 return kActionCodeFilesystemCopierError;
80 if (type == PostinstallRunnerAction::StaticType())
81 return kActionCodePostinstallRunnerError;
82 if (type == SetBootableFlagAction::StaticType())
83 return kActionCodeSetBootableFlagError;
84
85 return code;
86}
87
Darin Petkovc6c135c2010-08-11 13:36:18 -070088UpdateAttempter::UpdateAttempter(PrefsInterface* prefs,
89 MetricsLibraryInterface* metrics_lib)
90 : dbus_service_(NULL),
91 prefs_(prefs),
92 metrics_lib_(metrics_lib),
Darin Petkov1023a602010-08-30 13:47:51 -070093 update_check_scheduler_(NULL),
94 http_response_code_(0),
Darin Petkovc6c135c2010-08-11 13:36:18 -070095 priority_(utils::kProcessPriorityNormal),
96 manage_priority_source_(NULL),
Darin Petkov9d911fa2010-08-19 09:36:08 -070097 download_active_(false),
Darin Petkovc6c135c2010-08-11 13:36:18 -070098 status_(UPDATE_STATUS_IDLE),
99 download_progress_(0.0),
100 last_checked_time_(0),
101 new_version_("0.0.0.0"),
102 new_size_(0) {
Darin Petkovc6c135c2010-08-11 13:36:18 -0700103 if (utils::FileExists(kUpdateCompletedMarker))
104 status_ = UPDATE_STATUS_UPDATED_NEED_REBOOT;
105}
106
107UpdateAttempter::~UpdateAttempter() {
108 CleanupPriorityManagement();
109}
110
Darin Petkov5a7f5652010-07-22 21:40:09 -0700111void UpdateAttempter::Update(const std::string& app_version,
112 const std::string& omaha_url) {
Andrew de los Reyes6b78e292010-05-10 15:54:39 -0700113 if (status_ == UPDATE_STATUS_UPDATED_NEED_REBOOT) {
114 LOG(INFO) << "Not updating b/c we already updated and we're waiting for "
115 << "reboot";
116 return;
117 }
118 if (status_ != UPDATE_STATUS_IDLE) {
119 // Update in progress. Do nothing
120 return;
121 }
Darin Petkov1023a602010-08-30 13:47:51 -0700122 http_response_code_ = 0;
Darin Petkov5a7f5652010-07-22 21:40:09 -0700123 if (!omaha_request_params_.Init(app_version, omaha_url)) {
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700124 LOG(ERROR) << "Unable to initialize Omaha request device params.";
125 return;
126 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700127 CHECK(!processor_.IsRunning());
128 processor_.set_delegate(this);
129
130 // Actions:
Darin Petkov6a5b3222010-07-13 14:55:28 -0700131 shared_ptr<OmahaRequestAction> update_check_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700132 new OmahaRequestAction(prefs_,
133 omaha_request_params_,
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700134 NULL,
135 new LibcurlHttpFetcher));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700136 shared_ptr<OmahaResponseHandlerAction> response_handler_action(
137 new OmahaResponseHandlerAction);
138 shared_ptr<FilesystemCopierAction> filesystem_copier_action(
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700139 new FilesystemCopierAction(false));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700140 shared_ptr<FilesystemCopierAction> kernel_filesystem_copier_action(
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700141 new FilesystemCopierAction(true));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700142 shared_ptr<OmahaRequestAction> download_started_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700143 new OmahaRequestAction(prefs_,
144 omaha_request_params_,
Darin Petkov8c2980e2010-07-16 15:16:49 -0700145 new OmahaEvent(
Darin Petkove17f86b2010-07-20 09:12:01 -0700146 OmahaEvent::kTypeUpdateDownloadStarted),
Darin Petkov8c2980e2010-07-16 15:16:49 -0700147 new LibcurlHttpFetcher));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700148 shared_ptr<DownloadAction> download_action(
149 new DownloadAction(new LibcurlHttpFetcher));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700150 shared_ptr<OmahaRequestAction> download_finished_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700151 new OmahaRequestAction(prefs_,
152 omaha_request_params_,
Darin Petkov8c2980e2010-07-16 15:16:49 -0700153 new OmahaEvent(
Darin Petkove17f86b2010-07-20 09:12:01 -0700154 OmahaEvent::kTypeUpdateDownloadFinished),
Darin Petkov8c2980e2010-07-16 15:16:49 -0700155 new LibcurlHttpFetcher));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700156 shared_ptr<PostinstallRunnerAction> postinstall_runner_action_precommit(
157 new PostinstallRunnerAction(true));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700158 shared_ptr<SetBootableFlagAction> set_bootable_flag_action(
159 new SetBootableFlagAction);
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700160 shared_ptr<PostinstallRunnerAction> postinstall_runner_action_postcommit(
161 new PostinstallRunnerAction(false));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700162 shared_ptr<OmahaRequestAction> update_complete_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700163 new OmahaRequestAction(prefs_,
164 omaha_request_params_,
Darin Petkove17f86b2010-07-20 09:12:01 -0700165 new OmahaEvent(OmahaEvent::kTypeUpdateComplete),
Darin Petkov0dc8e9a2010-07-14 14:51:57 -0700166 new LibcurlHttpFetcher));
Darin Petkov6a5b3222010-07-13 14:55:28 -0700167
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700168 download_action->set_delegate(this);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700169 response_handler_action_ = response_handler_action;
170
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700171 actions_.push_back(shared_ptr<AbstractAction>(update_check_action));
172 actions_.push_back(shared_ptr<AbstractAction>(response_handler_action));
173 actions_.push_back(shared_ptr<AbstractAction>(filesystem_copier_action));
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700174 actions_.push_back(shared_ptr<AbstractAction>(
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700175 kernel_filesystem_copier_action));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700176 actions_.push_back(shared_ptr<AbstractAction>(download_started_action));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700177 actions_.push_back(shared_ptr<AbstractAction>(download_action));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700178 actions_.push_back(shared_ptr<AbstractAction>(download_finished_action));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700179 actions_.push_back(shared_ptr<AbstractAction>(
180 postinstall_runner_action_precommit));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700181 actions_.push_back(shared_ptr<AbstractAction>(set_bootable_flag_action));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700182 actions_.push_back(shared_ptr<AbstractAction>(
183 postinstall_runner_action_postcommit));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700184 actions_.push_back(shared_ptr<AbstractAction>(update_complete_action));
Darin Petkov6a5b3222010-07-13 14:55:28 -0700185
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700186 // Enqueue the actions
187 for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin();
188 it != actions_.end(); ++it) {
189 processor_.EnqueueAction(it->get());
190 }
191
192 // Bond them together. We have to use the leaf-types when calling
193 // BondActions().
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700194 BondActions(update_check_action.get(),
195 response_handler_action.get());
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700196 BondActions(response_handler_action.get(),
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700197 filesystem_copier_action.get());
198 BondActions(filesystem_copier_action.get(),
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700199 kernel_filesystem_copier_action.get());
200 BondActions(kernel_filesystem_copier_action.get(),
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700201 download_action.get());
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700202 BondActions(download_action.get(),
203 postinstall_runner_action_precommit.get());
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700204 BondActions(postinstall_runner_action_precommit.get(),
205 set_bootable_flag_action.get());
206 BondActions(set_bootable_flag_action.get(),
207 postinstall_runner_action_postcommit.get());
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700208
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700209 SetStatusAndNotify(UPDATE_STATUS_CHECKING_FOR_UPDATE);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700210 processor_.StartProcessing();
211}
212
Darin Petkov5a7f5652010-07-22 21:40:09 -0700213void UpdateAttempter::CheckForUpdate(const std::string& app_version,
214 const std::string& omaha_url) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700215 if (status_ != UPDATE_STATUS_IDLE) {
216 LOG(INFO) << "Check for update requested, but status is "
217 << UpdateStatusToString(status_) << ", so not checking.";
218 return;
219 }
Darin Petkov5a7f5652010-07-22 21:40:09 -0700220 Update(app_version, omaha_url);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700221}
222
Darin Petkov296889c2010-07-23 16:20:54 -0700223bool UpdateAttempter::RebootIfNeeded() {
224 if (status_ != UPDATE_STATUS_UPDATED_NEED_REBOOT) {
225 LOG(INFO) << "Reboot requested, but status is "
226 << UpdateStatusToString(status_) << ", so not rebooting.";
227 return false;
228 }
229 TEST_AND_RETURN_FALSE(utils::Reboot());
230 return true;
231}
232
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700233// Delegate methods:
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700234void UpdateAttempter::ProcessingDone(const ActionProcessor* processor,
Darin Petkovc1a8b422010-07-19 11:34:49 -0700235 ActionExitCode code) {
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700236 CHECK(response_handler_action_);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700237 LOG(INFO) << "Processing Done.";
Andrew de los Reyes6b78e292010-05-10 15:54:39 -0700238 actions_.clear();
Darin Petkov09f96c32010-07-20 09:24:57 -0700239
Darin Petkovc6c135c2010-08-11 13:36:18 -0700240 // Reset process priority back to normal.
241 CleanupPriorityManagement();
242
Darin Petkov09f96c32010-07-20 09:24:57 -0700243 if (status_ == UPDATE_STATUS_REPORTING_ERROR_EVENT) {
244 LOG(INFO) << "Error event sent.";
245 SetStatusAndNotify(UPDATE_STATUS_IDLE);
246 return;
247 }
248
Darin Petkovc1a8b422010-07-19 11:34:49 -0700249 if (code == kActionCodeSuccess) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700250 SetStatusAndNotify(UPDATE_STATUS_UPDATED_NEED_REBOOT);
Andrew de los Reyes6b78e292010-05-10 15:54:39 -0700251 utils::WriteFile(kUpdateCompletedMarker, "", 0);
Darin Petkov9d65b7b2010-07-20 09:13:01 -0700252
253 // Report the time it took to update the system.
254 int64_t update_time = time(NULL) - last_checked_time_;
255 metrics_lib_->SendToUMA("Installer.UpdateTime",
256 static_cast<int>(update_time), // sample
257 1, // min = 1 second
258 20 * 60, // max = 20 minutes
259 50); // buckets
Darin Petkov09f96c32010-07-20 09:24:57 -0700260 return;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700261 }
Darin Petkov09f96c32010-07-20 09:24:57 -0700262
Darin Petkov1023a602010-08-30 13:47:51 -0700263 if (ScheduleErrorEventAction()) {
Darin Petkov09f96c32010-07-20 09:24:57 -0700264 return;
Darin Petkov1023a602010-08-30 13:47:51 -0700265 }
266 LOG(INFO) << "No update.";
Darin Petkov09f96c32010-07-20 09:24:57 -0700267 SetStatusAndNotify(UPDATE_STATUS_IDLE);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700268}
269
270void UpdateAttempter::ProcessingStopped(const ActionProcessor* processor) {
Darin Petkovc6c135c2010-08-11 13:36:18 -0700271 // Reset process priority back to normal.
272 CleanupPriorityManagement();
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700273 download_progress_ = 0.0;
274 SetStatusAndNotify(UPDATE_STATUS_IDLE);
Andrew de los Reyes6b78e292010-05-10 15:54:39 -0700275 actions_.clear();
Darin Petkov09f96c32010-07-20 09:24:57 -0700276 error_event_.reset(NULL);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700277}
278
279// Called whenever an action has finished processing, either successfully
280// or otherwise.
281void UpdateAttempter::ActionCompleted(ActionProcessor* processor,
282 AbstractAction* action,
Darin Petkovc1a8b422010-07-19 11:34:49 -0700283 ActionExitCode code) {
Darin Petkov1023a602010-08-30 13:47:51 -0700284 // Reset download progress regardless of whether or not the download
285 // action succeeded. Also, get the response code from HTTP request
286 // actions (update download as well as the initial update check
287 // actions).
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700288 const string type = action->Type();
Darin Petkov1023a602010-08-30 13:47:51 -0700289 if (type == DownloadAction::StaticType()) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700290 download_progress_ = 0.0;
Darin Petkov1023a602010-08-30 13:47:51 -0700291 DownloadAction* download_action = dynamic_cast<DownloadAction*>(action);
292 http_response_code_ = download_action->GetHTTPResponseCode();
293 } else if (type == OmahaRequestAction::StaticType()) {
294 OmahaRequestAction* omaha_request_action =
295 dynamic_cast<OmahaRequestAction*>(action);
296 // If the request is not an event, then it's the update-check.
297 if (!omaha_request_action->IsEvent()) {
298 http_response_code_ = omaha_request_action->GetHTTPResponseCode();
299 }
300 }
Darin Petkov09f96c32010-07-20 09:24:57 -0700301 if (code != kActionCodeSuccess) {
Darin Petkov777dbfa2010-07-20 15:03:37 -0700302 // On failure, schedule an error event to be sent to Omaha.
303 CreatePendingErrorEvent(action, code);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700304 return;
Darin Petkov09f96c32010-07-20 09:24:57 -0700305 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700306 // Find out which action completed.
307 if (type == OmahaResponseHandlerAction::StaticType()) {
Darin Petkov9d911fa2010-08-19 09:36:08 -0700308 // Note that the status will be updated to DOWNLOADING when some
309 // bytes get actually downloaded from the server and the
310 // BytesReceived callback is invoked. This avoids notifying the
311 // user that a download has started in cases when the server and
312 // the client are unable to initiate the download.
Darin Petkov6a5b3222010-07-13 14:55:28 -0700313 OmahaResponseHandlerAction* omaha_response_handler_action =
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700314 dynamic_cast<OmahaResponseHandlerAction*>(action);
315 CHECK(omaha_response_handler_action);
316 const InstallPlan& plan = omaha_response_handler_action->install_plan();
317 last_checked_time_ = time(NULL);
318 // TODO(adlr): put version in InstallPlan
319 new_version_ = "0.0.0.0";
320 new_size_ = plan.size;
Darin Petkovc6c135c2010-08-11 13:36:18 -0700321 SetupPriorityManagement();
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700322 } else if (type == DownloadAction::StaticType()) {
323 SetStatusAndNotify(UPDATE_STATUS_FINALIZING);
324 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700325}
326
327// Stop updating. An attempt will be made to record status to the disk
328// so that updates can be resumed later.
329void UpdateAttempter::Terminate() {
330 // TODO(adlr): implement this method.
331 NOTIMPLEMENTED();
332}
333
334// Try to resume from a previously Terminate()d update.
335void UpdateAttempter::ResumeUpdating() {
336 // TODO(adlr): implement this method.
337 NOTIMPLEMENTED();
338}
339
Darin Petkov9d911fa2010-08-19 09:36:08 -0700340void UpdateAttempter::SetDownloadStatus(bool active) {
341 download_active_ = active;
342 LOG(INFO) << "Download status: " << (active ? "active" : "inactive");
343}
344
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700345void UpdateAttempter::BytesReceived(uint64_t bytes_received, uint64_t total) {
Darin Petkov9d911fa2010-08-19 09:36:08 -0700346 if (!download_active_) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700347 LOG(ERROR) << "BytesReceived called while not downloading.";
348 return;
349 }
Darin Petkovaf183052010-08-23 12:07:13 -0700350 double progress = static_cast<double>(bytes_received) /
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700351 static_cast<double>(total);
Darin Petkovaf183052010-08-23 12:07:13 -0700352 // Self throttle based on progress. Also send notifications if
353 // progress is too slow.
354 const double kDeltaPercent = 0.01; // 1%
355 if (status_ != UPDATE_STATUS_DOWNLOADING ||
356 bytes_received == total ||
357 progress - download_progress_ >= kDeltaPercent ||
358 TimeTicks::Now() - last_notify_time_ >= TimeDelta::FromSeconds(10)) {
359 download_progress_ = progress;
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700360 SetStatusAndNotify(UPDATE_STATUS_DOWNLOADING);
361 }
362}
363
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700364bool UpdateAttempter::GetStatus(int64_t* last_checked_time,
365 double* progress,
366 std::string* current_operation,
367 std::string* new_version,
368 int64_t* new_size) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700369 *last_checked_time = last_checked_time_;
370 *progress = download_progress_;
371 *current_operation = UpdateStatusToString(status_);
372 *new_version = new_version_;
373 *new_size = new_size_;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700374 return true;
375}
376
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700377void UpdateAttempter::SetStatusAndNotify(UpdateStatus status) {
378 status_ = status;
Darin Petkov1023a602010-08-30 13:47:51 -0700379 if (update_check_scheduler_) {
380 update_check_scheduler_->SetUpdateStatus(status_);
381 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700382 if (!dbus_service_)
383 return;
Darin Petkovaf183052010-08-23 12:07:13 -0700384 last_notify_time_ = TimeTicks::Now();
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700385 update_engine_service_emit_status_update(
386 dbus_service_,
387 last_checked_time_,
388 download_progress_,
389 UpdateStatusToString(status_),
390 new_version_.c_str(),
391 new_size_);
392}
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700393
Darin Petkov777dbfa2010-07-20 15:03:37 -0700394void UpdateAttempter::CreatePendingErrorEvent(AbstractAction* action,
395 ActionExitCode code) {
Darin Petkov09f96c32010-07-20 09:24:57 -0700396 if (error_event_.get()) {
397 // This shouldn't really happen.
398 LOG(WARNING) << "There's already an existing pending error event.";
399 return;
400 }
Darin Petkov777dbfa2010-07-20 15:03:37 -0700401
402 // For now assume that Omaha response action failure means that
403 // there's no update so don't send an event. Also, double check that
404 // the failure has not occurred while sending an error event -- in
405 // which case don't schedule another. This shouldn't really happen
406 // but just in case...
407 if (action->Type() == OmahaResponseHandlerAction::StaticType() ||
408 status_ == UPDATE_STATUS_REPORTING_ERROR_EVENT) {
409 return;
410 }
411
412 code = GetErrorCodeForAction(action, code);
Darin Petkov09f96c32010-07-20 09:24:57 -0700413 error_event_.reset(new OmahaEvent(OmahaEvent::kTypeUpdateComplete,
414 OmahaEvent::kResultError,
415 code));
416}
417
418bool UpdateAttempter::ScheduleErrorEventAction() {
419 if (error_event_.get() == NULL)
420 return false;
421
Darin Petkov1023a602010-08-30 13:47:51 -0700422 LOG(INFO) << "Update failed -- reporting the error event.";
Darin Petkov09f96c32010-07-20 09:24:57 -0700423 shared_ptr<OmahaRequestAction> error_event_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700424 new OmahaRequestAction(prefs_,
425 omaha_request_params_,
Darin Petkov09f96c32010-07-20 09:24:57 -0700426 error_event_.release(), // Pass ownership.
427 new LibcurlHttpFetcher));
428 actions_.push_back(shared_ptr<AbstractAction>(error_event_action));
429 processor_.EnqueueAction(error_event_action.get());
430 SetStatusAndNotify(UPDATE_STATUS_REPORTING_ERROR_EVENT);
431 processor_.StartProcessing();
432 return true;
433}
434
Darin Petkovc6c135c2010-08-11 13:36:18 -0700435void UpdateAttempter::SetPriority(utils::ProcessPriority priority) {
436 if (priority_ == priority) {
437 return;
438 }
439 if (utils::SetProcessPriority(priority)) {
440 priority_ = priority;
441 LOG(INFO) << "Process priority = " << priority_;
442 }
443}
444
445void UpdateAttempter::SetupPriorityManagement() {
446 if (manage_priority_source_) {
447 LOG(ERROR) << "Process priority timeout source hasn't been destroyed.";
448 CleanupPriorityManagement();
449 }
450 const int kPriorityTimeout = 10 * 60; // 10 minutes
451 manage_priority_source_ = g_timeout_source_new_seconds(kPriorityTimeout);
452 g_source_set_callback(manage_priority_source_,
453 StaticManagePriorityCallback,
454 this,
455 NULL);
456 g_source_attach(manage_priority_source_, NULL);
457 SetPriority(utils::kProcessPriorityLow);
458}
459
460void UpdateAttempter::CleanupPriorityManagement() {
461 if (manage_priority_source_) {
462 g_source_destroy(manage_priority_source_);
463 manage_priority_source_ = NULL;
464 }
465 SetPriority(utils::kProcessPriorityNormal);
466}
467
468gboolean UpdateAttempter::StaticManagePriorityCallback(gpointer data) {
469 return reinterpret_cast<UpdateAttempter*>(data)->ManagePriorityCallback();
470}
471
472bool UpdateAttempter::ManagePriorityCallback() {
473 // If the current process priority is below normal, set it to normal
474 // and let GLib invoke this callback again.
475 if (utils::ComparePriorities(priority_, utils::kProcessPriorityNormal) < 0) {
476 SetPriority(utils::kProcessPriorityNormal);
477 return true;
478 }
479 // Set the priority to high and let GLib destroy the timeout source.
480 SetPriority(utils::kProcessPriorityHigh);
481 manage_priority_source_ = NULL;
482 return false;
483}
484
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700485} // namespace chromeos_update_engine