blob: b153fa7e5dfb8a8c7bdaa5dd11080480e8c18e68 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "update_engine/payload_state.h"
#include <base/logging.h>
#include <base/stringprintf.h>
#include "update_engine/omaha_request_action.h"
#include "update_engine/prefs.h"
using std::string;
namespace chromeos_update_engine {
// Returns a string containing that subset of the fields from the OmahaResponse
// which we're interested in persisting for the purpose of detecting whether
// we should clear the rest of the payload state when we get a new
// OmahaResponse.
static string GetFilteredResponse(const OmahaResponse& response) {
string mini_response = StringPrintf("NumURLs = %d\n",
response.payload_urls.size());
for (size_t i = 0; i < response.payload_urls.size(); i++)
mini_response += StringPrintf("Url%d = %s\n",
i, response.payload_urls[i].c_str());
mini_response += StringPrintf("Payload Size = %llu\n"
"Payload Sha256 Hash = %s\n"
"Metadata Size = %llu\n"
"Metadata Signature = %s\n",
response.size,
response.hash.c_str(),
response.metadata_size,
response.metadata_signature.c_str());
return mini_response;
}
bool PayloadState::Initialize(PrefsInterface* prefs) {
CHECK(prefs);
prefs_ = prefs;
LoadResponse();
LoadUrlIndex();
LogPayloadState();
return true;
}
void PayloadState::LogPayloadState() {
LOG(INFO) << "Current Payload State:\n"
<< "Current Response = \n" << response_
<< "Current URL Index = " << url_index_;
}
void PayloadState::SetResponse(const OmahaResponse& omaha_response) {
CHECK(prefs_);
num_urls_ = omaha_response.payload_urls.size();
string new_response = GetFilteredResponse(omaha_response);
bool has_response_changed = (response_ != new_response);
response_ = new_response;
LOG(INFO) << "Stored Response = \n" << response_;
prefs_->SetString(kPrefsCurrentResponse, response_);
if (has_response_changed) {
LOG(INFO) << "Resetting all payload state as this is a new response";
SetUrlIndex(0);
}
}
void PayloadState::UpdateFailed(ActionExitCode error) {
LOG(INFO) << "Updating payload state for error code: " << error;
if (!num_urls_) {
// Since we don't persist num_urls_, it's possible that we get an error in
// our communication to Omaha before even OmahaRequestAction code had a
// chance to call SetResponse (which sets num_urls_). So we should not
// advance the url_index_ in such cases.
LOG(INFO) << "Ignoring failures until we get a valid Omaha response.";
return;
}
// chromium-os:37206: Classify the errors and advance the URL index at
// different rates for different errors in the next CL. Until then, advance
// URL index on every single error.
uint32_t next_url_index = GetUrlIndex() + 1;
if (next_url_index < num_urls_) {
LOG(INFO) << "Advancing the URL index for next attempt";
} else {
LOG(INFO) << "Resetting the current URL index (" << GetUrlIndex() << ") to "
<< "0 as we only have " << num_urls_ << " URL(s)";
next_url_index = 0;
// TODO(jaysri): This is the place where we should increment the
// payload_attempt_number so that we can back-off appropriately.
}
SetUrlIndex(next_url_index);
}
string PayloadState::LoadResponse() {
CHECK(prefs_);
string stored_value;
if (prefs_->Exists(kPrefsCurrentResponse) &&
prefs_->GetString(kPrefsCurrentResponse, &stored_value)) {
response_ = stored_value;
}
return response_;
}
uint32_t PayloadState::LoadUrlIndex() {
CHECK(prefs_);
int64_t stored_value;
if (prefs_->Exists(kPrefsCurrentUrlIndex) &&
prefs_->GetInt64(kPrefsCurrentUrlIndex, &stored_value)) {
url_index_ = stored_value;
}
return url_index_;
}
void PayloadState::SetUrlIndex(uint32_t url_index) {
CHECK(prefs_);
// TODO(jaysri): When we implement failure count, make sure to reset
// the failure count when url index changes.
url_index_ = url_index;
LOG(INFO) << "Current URL Index = " << url_index_;
prefs_->SetInt64(kPrefsCurrentUrlIndex, url_index_);
}
} // namespace chromeos_update_engine