AU: A basic framework for sending error events when update attempt fails.
Currently, only a generic kTypeUpdateComplete/kResultError/kActionCodeError
will be sent.
BUG=560
TEST=unit test, gmerged, forced updates, inspected logs.
Review URL: http://codereview.chromium.org/3042007
diff --git a/update_attempter.cc b/update_attempter.cc
index 3f20126..ee1cf00 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -83,6 +83,8 @@
return "UPDATE_STATUS_FINALIZING";
case UPDATE_STATUS_UPDATED_NEED_REBOOT:
return "UPDATE_STATUS_UPDATED_NEED_REBOOT";
+ case UPDATE_STATUS_REPORTING_ERROR_EVENT:
+ return "UPDATE_STATUS_REPORTING_ERROR_EVENT";
default:
return "unknown status";
}
@@ -199,6 +201,13 @@
CHECK(response_handler_action_);
LOG(INFO) << "Processing Done.";
actions_.clear();
+
+ if (status_ == UPDATE_STATUS_REPORTING_ERROR_EVENT) {
+ LOG(INFO) << "Error event sent.";
+ SetStatusAndNotify(UPDATE_STATUS_IDLE);
+ return;
+ }
+
if (code == kActionCodeSuccess) {
SetStatusAndNotify(UPDATE_STATUS_UPDATED_NEED_REBOOT);
utils::WriteFile(kUpdateCompletedMarker, "", 0);
@@ -210,16 +219,20 @@
1, // min = 1 second
20 * 60, // max = 20 minutes
50); // buckets
- } else {
- LOG(INFO) << "Update failed.";
- SetStatusAndNotify(UPDATE_STATUS_IDLE);
+ return;
}
+
+ LOG(INFO) << "Update failed.";
+ if (ScheduleErrorEventAction())
+ return;
+ SetStatusAndNotify(UPDATE_STATUS_IDLE);
}
void UpdateAttempter::ProcessingStopped(const ActionProcessor* processor) {
download_progress_ = 0.0;
SetStatusAndNotify(UPDATE_STATUS_IDLE);
actions_.clear();
+ error_event_.reset(NULL);
}
// Called whenever an action has finished processing, either successfully
@@ -232,8 +245,19 @@
const string type = action->Type();
if (type == DownloadAction::StaticType())
download_progress_ = 0.0;
- if (code != kActionCodeSuccess)
+ if (code != kActionCodeSuccess) {
+ // On failure, schedule an error event to be sent to Omaha. For
+ // now assume that Omaha response action failure means that
+ // there's no update so don't send an event. Also, double check
+ // that the failure has not occurred while sending an error event
+ // -- in which case don't schedule another. This shouldn't really
+ // happen but just in case...
+ if (type != OmahaResponseHandlerAction::StaticType() &&
+ status_ != UPDATE_STATUS_REPORTING_ERROR_EVENT) {
+ CreatePendingErrorEvent(code);
+ }
return;
+ }
// Find out which action completed.
if (type == OmahaResponseHandlerAction::StaticType()) {
SetStatusAndNotify(UPDATE_STATUS_DOWNLOADING);
@@ -308,4 +332,30 @@
new_size_);
}
+void UpdateAttempter::CreatePendingErrorEvent(ActionExitCode code) {
+ if (error_event_.get()) {
+ // This shouldn't really happen.
+ LOG(WARNING) << "There's already an existing pending error event.";
+ return;
+ }
+ error_event_.reset(new OmahaEvent(OmahaEvent::kTypeUpdateComplete,
+ OmahaEvent::kResultError,
+ code));
+}
+
+bool UpdateAttempter::ScheduleErrorEventAction() {
+ if (error_event_.get() == NULL)
+ return false;
+
+ shared_ptr<OmahaRequestAction> error_event_action(
+ new OmahaRequestAction(omaha_request_params_,
+ error_event_.release(), // Pass ownership.
+ new LibcurlHttpFetcher));
+ actions_.push_back(shared_ptr<AbstractAction>(error_event_action));
+ processor_.EnqueueAction(error_event_action.get());
+ SetStatusAndNotify(UPDATE_STATUS_REPORTING_ERROR_EVENT);
+ processor_.StartProcessing();
+ return true;
+}
+
} // namespace chromeos_update_engine
diff --git a/update_attempter.h b/update_attempter.h
index 5eda43f..e84c479 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -29,7 +29,8 @@
UPDATE_STATUS_DOWNLOADING,
UPDATE_STATUS_VERIFYING,
UPDATE_STATUS_FINALIZING,
- UPDATE_STATUS_UPDATED_NEED_REBOOT
+ UPDATE_STATUS_UPDATED_NEED_REBOOT,
+ UPDATE_STATUS_REPORTING_ERROR_EVENT,
};
const char* UpdateStatusToString(UpdateStatus status);
@@ -87,6 +88,16 @@
// over dbus.
void SetStatusAndNotify(UpdateStatus status);
+ // Creates an error event object in |error_event_| to be included in
+ // an OmahaRequestAction once the current action processor is done.
+ void CreatePendingErrorEvent(ActionExitCode code);
+
+ // If there's a pending error event allocated in |error_event_|,
+ // schedules an OmahaRequestAction with that event in the current
+ // processor, clears the pending event, updates the status and
+ // returns true. Returns false otherwise.
+ bool ScheduleErrorEventAction();
+
struct timespec last_notify_time_;
std::vector<std::tr1::shared_ptr<AbstractAction> > actions_;
@@ -102,6 +113,9 @@
// Pointer to the UMA metrics collection library.
MetricsLibraryInterface* metrics_lib_;
+ // Pending error event, if any.
+ scoped_ptr<OmahaEvent> error_event_;
+
// For status:
UpdateStatus status_;
double download_progress_;