blob: 694e7748178669f609c1db5d1fdebf9f8a764a81 [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)
Darin Petkovf42cc1c2010-09-01 09:03:02 -070090 : processor_(new ActionProcessor()),
91 dbus_service_(NULL),
Darin Petkovc6c135c2010-08-11 13:36:18 -070092 prefs_(prefs),
93 metrics_lib_(metrics_lib),
Darin Petkov1023a602010-08-30 13:47:51 -070094 update_check_scheduler_(NULL),
95 http_response_code_(0),
Darin Petkovc6c135c2010-08-11 13:36:18 -070096 priority_(utils::kProcessPriorityNormal),
97 manage_priority_source_(NULL),
Darin Petkov9d911fa2010-08-19 09:36:08 -070098 download_active_(false),
Darin Petkovc6c135c2010-08-11 13:36:18 -070099 status_(UPDATE_STATUS_IDLE),
100 download_progress_(0.0),
101 last_checked_time_(0),
102 new_version_("0.0.0.0"),
103 new_size_(0) {
Darin Petkovc6c135c2010-08-11 13:36:18 -0700104 if (utils::FileExists(kUpdateCompletedMarker))
105 status_ = UPDATE_STATUS_UPDATED_NEED_REBOOT;
106}
107
108UpdateAttempter::~UpdateAttempter() {
109 CleanupPriorityManagement();
110}
111
Darin Petkov5a7f5652010-07-22 21:40:09 -0700112void UpdateAttempter::Update(const std::string& app_version,
113 const std::string& omaha_url) {
Andrew de los Reyes6b78e292010-05-10 15:54:39 -0700114 if (status_ == UPDATE_STATUS_UPDATED_NEED_REBOOT) {
115 LOG(INFO) << "Not updating b/c we already updated and we're waiting for "
116 << "reboot";
117 return;
118 }
119 if (status_ != UPDATE_STATUS_IDLE) {
120 // Update in progress. Do nothing
121 return;
122 }
Darin Petkov1023a602010-08-30 13:47:51 -0700123 http_response_code_ = 0;
Darin Petkov5a7f5652010-07-22 21:40:09 -0700124 if (!omaha_request_params_.Init(app_version, omaha_url)) {
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700125 LOG(ERROR) << "Unable to initialize Omaha request device params.";
126 return;
127 }
Darin Petkovf42cc1c2010-09-01 09:03:02 -0700128 CHECK(!processor_->IsRunning());
129 processor_->set_delegate(this);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700130
131 // Actions:
Darin Petkov6a5b3222010-07-13 14:55:28 -0700132 shared_ptr<OmahaRequestAction> update_check_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700133 new OmahaRequestAction(prefs_,
134 omaha_request_params_,
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700135 NULL,
136 new LibcurlHttpFetcher));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700137 shared_ptr<OmahaResponseHandlerAction> response_handler_action(
138 new OmahaResponseHandlerAction);
139 shared_ptr<FilesystemCopierAction> filesystem_copier_action(
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700140 new FilesystemCopierAction(false));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700141 shared_ptr<FilesystemCopierAction> kernel_filesystem_copier_action(
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700142 new FilesystemCopierAction(true));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700143 shared_ptr<OmahaRequestAction> download_started_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700144 new OmahaRequestAction(prefs_,
145 omaha_request_params_,
Darin Petkov8c2980e2010-07-16 15:16:49 -0700146 new OmahaEvent(
Darin Petkove17f86b2010-07-20 09:12:01 -0700147 OmahaEvent::kTypeUpdateDownloadStarted),
Darin Petkov8c2980e2010-07-16 15:16:49 -0700148 new LibcurlHttpFetcher));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700149 shared_ptr<DownloadAction> download_action(
150 new DownloadAction(new LibcurlHttpFetcher));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700151 shared_ptr<OmahaRequestAction> download_finished_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700152 new OmahaRequestAction(prefs_,
153 omaha_request_params_,
Darin Petkov8c2980e2010-07-16 15:16:49 -0700154 new OmahaEvent(
Darin Petkove17f86b2010-07-20 09:12:01 -0700155 OmahaEvent::kTypeUpdateDownloadFinished),
Darin Petkov8c2980e2010-07-16 15:16:49 -0700156 new LibcurlHttpFetcher));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700157 shared_ptr<PostinstallRunnerAction> postinstall_runner_action_precommit(
158 new PostinstallRunnerAction(true));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700159 shared_ptr<SetBootableFlagAction> set_bootable_flag_action(
160 new SetBootableFlagAction);
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700161 shared_ptr<PostinstallRunnerAction> postinstall_runner_action_postcommit(
162 new PostinstallRunnerAction(false));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700163 shared_ptr<OmahaRequestAction> update_complete_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700164 new OmahaRequestAction(prefs_,
165 omaha_request_params_,
Darin Petkove17f86b2010-07-20 09:12:01 -0700166 new OmahaEvent(OmahaEvent::kTypeUpdateComplete),
Darin Petkov0dc8e9a2010-07-14 14:51:57 -0700167 new LibcurlHttpFetcher));
Darin Petkov6a5b3222010-07-13 14:55:28 -0700168
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700169 download_action->set_delegate(this);
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700170 response_handler_action_ = response_handler_action;
171
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700172 actions_.push_back(shared_ptr<AbstractAction>(update_check_action));
173 actions_.push_back(shared_ptr<AbstractAction>(response_handler_action));
174 actions_.push_back(shared_ptr<AbstractAction>(filesystem_copier_action));
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700175 actions_.push_back(shared_ptr<AbstractAction>(
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700176 kernel_filesystem_copier_action));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700177 actions_.push_back(shared_ptr<AbstractAction>(download_started_action));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700178 actions_.push_back(shared_ptr<AbstractAction>(download_action));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700179 actions_.push_back(shared_ptr<AbstractAction>(download_finished_action));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700180 actions_.push_back(shared_ptr<AbstractAction>(
181 postinstall_runner_action_precommit));
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700182 actions_.push_back(shared_ptr<AbstractAction>(set_bootable_flag_action));
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700183 actions_.push_back(shared_ptr<AbstractAction>(
184 postinstall_runner_action_postcommit));
Darin Petkov8c2980e2010-07-16 15:16:49 -0700185 actions_.push_back(shared_ptr<AbstractAction>(update_complete_action));
Darin Petkov6a5b3222010-07-13 14:55:28 -0700186
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700187 // Enqueue the actions
188 for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin();
189 it != actions_.end(); ++it) {
Darin Petkovf42cc1c2010-09-01 09:03:02 -0700190 processor_->EnqueueAction(it->get());
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700191 }
192
193 // Bond them together. We have to use the leaf-types when calling
194 // BondActions().
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700195 BondActions(update_check_action.get(),
196 response_handler_action.get());
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700197 BondActions(response_handler_action.get(),
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700198 filesystem_copier_action.get());
199 BondActions(filesystem_copier_action.get(),
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700200 kernel_filesystem_copier_action.get());
201 BondActions(kernel_filesystem_copier_action.get(),
Andrew de los Reyesf9185172010-05-03 11:07:05 -0700202 download_action.get());
Andrew de los Reyesf98bff82010-05-06 13:33:25 -0700203 BondActions(download_action.get(),
204 postinstall_runner_action_precommit.get());
Andrew de los Reyesf9714432010-05-04 10:21:23 -0700205 BondActions(postinstall_runner_action_precommit.get(),
206 set_bootable_flag_action.get());
207 BondActions(set_bootable_flag_action.get(),
208 postinstall_runner_action_postcommit.get());
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700209
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700210 SetStatusAndNotify(UPDATE_STATUS_CHECKING_FOR_UPDATE);
Darin Petkovf42cc1c2010-09-01 09:03:02 -0700211 processor_->StartProcessing();
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700212}
213
Darin Petkov5a7f5652010-07-22 21:40:09 -0700214void UpdateAttempter::CheckForUpdate(const std::string& app_version,
215 const std::string& omaha_url) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700216 if (status_ != UPDATE_STATUS_IDLE) {
217 LOG(INFO) << "Check for update requested, but status is "
218 << UpdateStatusToString(status_) << ", so not checking.";
219 return;
220 }
Darin Petkov5a7f5652010-07-22 21:40:09 -0700221 Update(app_version, omaha_url);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700222}
223
Darin Petkov296889c2010-07-23 16:20:54 -0700224bool UpdateAttempter::RebootIfNeeded() {
225 if (status_ != UPDATE_STATUS_UPDATED_NEED_REBOOT) {
226 LOG(INFO) << "Reboot requested, but status is "
227 << UpdateStatusToString(status_) << ", so not rebooting.";
228 return false;
229 }
230 TEST_AND_RETURN_FALSE(utils::Reboot());
231 return true;
232}
233
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700234// Delegate methods:
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700235void UpdateAttempter::ProcessingDone(const ActionProcessor* processor,
Darin Petkovc1a8b422010-07-19 11:34:49 -0700236 ActionExitCode code) {
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700237 CHECK(response_handler_action_);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700238 LOG(INFO) << "Processing Done.";
Andrew de los Reyes6b78e292010-05-10 15:54:39 -0700239 actions_.clear();
Darin Petkov09f96c32010-07-20 09:24:57 -0700240
Darin Petkovc6c135c2010-08-11 13:36:18 -0700241 // Reset process priority back to normal.
242 CleanupPriorityManagement();
243
Darin Petkov09f96c32010-07-20 09:24:57 -0700244 if (status_ == UPDATE_STATUS_REPORTING_ERROR_EVENT) {
245 LOG(INFO) << "Error event sent.";
246 SetStatusAndNotify(UPDATE_STATUS_IDLE);
247 return;
248 }
249
Darin Petkovc1a8b422010-07-19 11:34:49 -0700250 if (code == kActionCodeSuccess) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700251 SetStatusAndNotify(UPDATE_STATUS_UPDATED_NEED_REBOOT);
Andrew de los Reyes6b78e292010-05-10 15:54:39 -0700252 utils::WriteFile(kUpdateCompletedMarker, "", 0);
Darin Petkov9d65b7b2010-07-20 09:13:01 -0700253
254 // Report the time it took to update the system.
255 int64_t update_time = time(NULL) - last_checked_time_;
256 metrics_lib_->SendToUMA("Installer.UpdateTime",
257 static_cast<int>(update_time), // sample
258 1, // min = 1 second
259 20 * 60, // max = 20 minutes
260 50); // buckets
Darin Petkov09f96c32010-07-20 09:24:57 -0700261 return;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700262 }
Darin Petkov09f96c32010-07-20 09:24:57 -0700263
Darin Petkov1023a602010-08-30 13:47:51 -0700264 if (ScheduleErrorEventAction()) {
Darin Petkov09f96c32010-07-20 09:24:57 -0700265 return;
Darin Petkov1023a602010-08-30 13:47:51 -0700266 }
267 LOG(INFO) << "No update.";
Darin Petkov09f96c32010-07-20 09:24:57 -0700268 SetStatusAndNotify(UPDATE_STATUS_IDLE);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700269}
270
271void UpdateAttempter::ProcessingStopped(const ActionProcessor* processor) {
Darin Petkovc6c135c2010-08-11 13:36:18 -0700272 // Reset process priority back to normal.
273 CleanupPriorityManagement();
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700274 download_progress_ = 0.0;
275 SetStatusAndNotify(UPDATE_STATUS_IDLE);
Andrew de los Reyes6b78e292010-05-10 15:54:39 -0700276 actions_.clear();
Darin Petkov09f96c32010-07-20 09:24:57 -0700277 error_event_.reset(NULL);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700278}
279
280// Called whenever an action has finished processing, either successfully
281// or otherwise.
282void UpdateAttempter::ActionCompleted(ActionProcessor* processor,
283 AbstractAction* action,
Darin Petkovc1a8b422010-07-19 11:34:49 -0700284 ActionExitCode code) {
Darin Petkov1023a602010-08-30 13:47:51 -0700285 // Reset download progress regardless of whether or not the download
286 // action succeeded. Also, get the response code from HTTP request
287 // actions (update download as well as the initial update check
288 // actions).
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700289 const string type = action->Type();
Darin Petkov1023a602010-08-30 13:47:51 -0700290 if (type == DownloadAction::StaticType()) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700291 download_progress_ = 0.0;
Darin Petkov1023a602010-08-30 13:47:51 -0700292 DownloadAction* download_action = dynamic_cast<DownloadAction*>(action);
293 http_response_code_ = download_action->GetHTTPResponseCode();
294 } else if (type == OmahaRequestAction::StaticType()) {
295 OmahaRequestAction* omaha_request_action =
296 dynamic_cast<OmahaRequestAction*>(action);
297 // If the request is not an event, then it's the update-check.
298 if (!omaha_request_action->IsEvent()) {
299 http_response_code_ = omaha_request_action->GetHTTPResponseCode();
300 }
301 }
Darin Petkov09f96c32010-07-20 09:24:57 -0700302 if (code != kActionCodeSuccess) {
Darin Petkov777dbfa2010-07-20 15:03:37 -0700303 // On failure, schedule an error event to be sent to Omaha.
304 CreatePendingErrorEvent(action, code);
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700305 return;
Darin Petkov09f96c32010-07-20 09:24:57 -0700306 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700307 // Find out which action completed.
308 if (type == OmahaResponseHandlerAction::StaticType()) {
Darin Petkov9d911fa2010-08-19 09:36:08 -0700309 // Note that the status will be updated to DOWNLOADING when some
310 // bytes get actually downloaded from the server and the
311 // BytesReceived callback is invoked. This avoids notifying the
312 // user that a download has started in cases when the server and
313 // the client are unable to initiate the download.
Darin Petkov6a5b3222010-07-13 14:55:28 -0700314 OmahaResponseHandlerAction* omaha_response_handler_action =
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700315 dynamic_cast<OmahaResponseHandlerAction*>(action);
316 CHECK(omaha_response_handler_action);
317 const InstallPlan& plan = omaha_response_handler_action->install_plan();
318 last_checked_time_ = time(NULL);
319 // TODO(adlr): put version in InstallPlan
320 new_version_ = "0.0.0.0";
321 new_size_ = plan.size;
Darin Petkovc6c135c2010-08-11 13:36:18 -0700322 SetupPriorityManagement();
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700323 } else if (type == DownloadAction::StaticType()) {
324 SetStatusAndNotify(UPDATE_STATUS_FINALIZING);
325 }
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700326}
327
328// Stop updating. An attempt will be made to record status to the disk
329// so that updates can be resumed later.
330void UpdateAttempter::Terminate() {
331 // TODO(adlr): implement this method.
332 NOTIMPLEMENTED();
333}
334
335// Try to resume from a previously Terminate()d update.
336void UpdateAttempter::ResumeUpdating() {
337 // TODO(adlr): implement this method.
338 NOTIMPLEMENTED();
339}
340
Darin Petkov9d911fa2010-08-19 09:36:08 -0700341void UpdateAttempter::SetDownloadStatus(bool active) {
342 download_active_ = active;
343 LOG(INFO) << "Download status: " << (active ? "active" : "inactive");
344}
345
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700346void UpdateAttempter::BytesReceived(uint64_t bytes_received, uint64_t total) {
Darin Petkov9d911fa2010-08-19 09:36:08 -0700347 if (!download_active_) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700348 LOG(ERROR) << "BytesReceived called while not downloading.";
349 return;
350 }
Darin Petkovaf183052010-08-23 12:07:13 -0700351 double progress = static_cast<double>(bytes_received) /
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700352 static_cast<double>(total);
Darin Petkovaf183052010-08-23 12:07:13 -0700353 // Self throttle based on progress. Also send notifications if
354 // progress is too slow.
355 const double kDeltaPercent = 0.01; // 1%
356 if (status_ != UPDATE_STATUS_DOWNLOADING ||
357 bytes_received == total ||
358 progress - download_progress_ >= kDeltaPercent ||
359 TimeTicks::Now() - last_notify_time_ >= TimeDelta::FromSeconds(10)) {
360 download_progress_ = progress;
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700361 SetStatusAndNotify(UPDATE_STATUS_DOWNLOADING);
362 }
363}
364
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700365bool UpdateAttempter::GetStatus(int64_t* last_checked_time,
366 double* progress,
367 std::string* current_operation,
368 std::string* new_version,
369 int64_t* new_size) {
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700370 *last_checked_time = last_checked_time_;
371 *progress = download_progress_;
372 *current_operation = UpdateStatusToString(status_);
373 *new_version = new_version_;
374 *new_size = new_size_;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700375 return true;
376}
377
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700378void UpdateAttempter::SetStatusAndNotify(UpdateStatus status) {
379 status_ = status;
Darin Petkov1023a602010-08-30 13:47:51 -0700380 if (update_check_scheduler_) {
381 update_check_scheduler_->SetUpdateStatus(status_);
382 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700383 if (!dbus_service_)
384 return;
Darin Petkovaf183052010-08-23 12:07:13 -0700385 last_notify_time_ = TimeTicks::Now();
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700386 update_engine_service_emit_status_update(
387 dbus_service_,
388 last_checked_time_,
389 download_progress_,
390 UpdateStatusToString(status_),
391 new_version_.c_str(),
392 new_size_);
393}
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700394
Darin Petkov777dbfa2010-07-20 15:03:37 -0700395void UpdateAttempter::CreatePendingErrorEvent(AbstractAction* action,
396 ActionExitCode code) {
Darin Petkov09f96c32010-07-20 09:24:57 -0700397 if (error_event_.get()) {
398 // This shouldn't really happen.
399 LOG(WARNING) << "There's already an existing pending error event.";
400 return;
401 }
Darin Petkov777dbfa2010-07-20 15:03:37 -0700402
403 // For now assume that Omaha response action failure means that
404 // there's no update so don't send an event. Also, double check that
405 // the failure has not occurred while sending an error event -- in
406 // which case don't schedule another. This shouldn't really happen
407 // but just in case...
408 if (action->Type() == OmahaResponseHandlerAction::StaticType() ||
409 status_ == UPDATE_STATUS_REPORTING_ERROR_EVENT) {
410 return;
411 }
412
413 code = GetErrorCodeForAction(action, code);
Darin Petkov09f96c32010-07-20 09:24:57 -0700414 error_event_.reset(new OmahaEvent(OmahaEvent::kTypeUpdateComplete,
415 OmahaEvent::kResultError,
416 code));
417}
418
419bool UpdateAttempter::ScheduleErrorEventAction() {
420 if (error_event_.get() == NULL)
421 return false;
422
Darin Petkov1023a602010-08-30 13:47:51 -0700423 LOG(INFO) << "Update failed -- reporting the error event.";
Darin Petkov09f96c32010-07-20 09:24:57 -0700424 shared_ptr<OmahaRequestAction> error_event_action(
Darin Petkov1cbd78f2010-07-29 12:38:34 -0700425 new OmahaRequestAction(prefs_,
426 omaha_request_params_,
Darin Petkov09f96c32010-07-20 09:24:57 -0700427 error_event_.release(), // Pass ownership.
428 new LibcurlHttpFetcher));
429 actions_.push_back(shared_ptr<AbstractAction>(error_event_action));
Darin Petkovf42cc1c2010-09-01 09:03:02 -0700430 processor_->EnqueueAction(error_event_action.get());
Darin Petkov09f96c32010-07-20 09:24:57 -0700431 SetStatusAndNotify(UPDATE_STATUS_REPORTING_ERROR_EVENT);
Darin Petkovf42cc1c2010-09-01 09:03:02 -0700432 processor_->StartProcessing();
Darin Petkov09f96c32010-07-20 09:24:57 -0700433 return true;
434}
435
Darin Petkovc6c135c2010-08-11 13:36:18 -0700436void UpdateAttempter::SetPriority(utils::ProcessPriority priority) {
437 if (priority_ == priority) {
438 return;
439 }
440 if (utils::SetProcessPriority(priority)) {
441 priority_ = priority;
442 LOG(INFO) << "Process priority = " << priority_;
443 }
444}
445
446void UpdateAttempter::SetupPriorityManagement() {
447 if (manage_priority_source_) {
448 LOG(ERROR) << "Process priority timeout source hasn't been destroyed.";
449 CleanupPriorityManagement();
450 }
451 const int kPriorityTimeout = 10 * 60; // 10 minutes
452 manage_priority_source_ = g_timeout_source_new_seconds(kPriorityTimeout);
453 g_source_set_callback(manage_priority_source_,
454 StaticManagePriorityCallback,
455 this,
456 NULL);
457 g_source_attach(manage_priority_source_, NULL);
458 SetPriority(utils::kProcessPriorityLow);
459}
460
461void UpdateAttempter::CleanupPriorityManagement() {
462 if (manage_priority_source_) {
463 g_source_destroy(manage_priority_source_);
464 manage_priority_source_ = NULL;
465 }
466 SetPriority(utils::kProcessPriorityNormal);
467}
468
469gboolean UpdateAttempter::StaticManagePriorityCallback(gpointer data) {
470 return reinterpret_cast<UpdateAttempter*>(data)->ManagePriorityCallback();
471}
472
473bool UpdateAttempter::ManagePriorityCallback() {
474 // If the current process priority is below normal, set it to normal
475 // and let GLib invoke this callback again.
476 if (utils::ComparePriorities(priority_, utils::kProcessPriorityNormal) < 0) {
477 SetPriority(utils::kProcessPriorityNormal);
478 return true;
479 }
480 // Set the priority to high and let GLib destroy the timeout source.
481 SetPriority(utils::kProcessPriorityHigh);
482 manage_priority_source_ = NULL;
483 return false;
484}
485
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700486} // namespace chromeos_update_engine