| Index: delta_performer.cc
|
| diff --git a/delta_performer.cc b/delta_performer.cc
|
| index 2436797210fa895738ee43d28d8f9fd7d4180c25..6143ec5ae6556f405144ef91a135fc9fb9a6a47c 100644
|
| --- a/delta_performer.cc
|
| +++ b/delta_performer.cc
|
| @@ -21,6 +21,7 @@
|
| #include "update_engine/extent_writer.h"
|
| #include "update_engine/graph_types.h"
|
| #include "update_engine/payload_signer.h"
|
| +#include "update_engine/prefs_interface.h"
|
| #include "update_engine/subprocess.h"
|
|
|
| using std::min;
|
| @@ -36,6 +37,18 @@ const int kDeltaVersionLength = 8;
|
| const int kDeltaProtobufLengthLength = 8;
|
| const char kUpdatePayloadPublicKeyPath[] =
|
| "/usr/share/update_engine/update-payload-key.pub.pem";
|
| +const int kUpdateStateOperationInvalid = -1;
|
| +
|
| +// Returns true if |op| is idempotent -- i.e., if we can interrupt it and repeat
|
| +// it safely. Returns false otherwise.
|
| +bool IsIdempotentOperation(const DeltaArchiveManifest_InstallOperation& op) {
|
| + if (op.src_extents_size() == 0) {
|
| + return true;
|
| + }
|
| + // TODO(petkov): Cover the case where the source and target extents don't
|
| + // intersect.
|
| + return false;
|
| +}
|
|
|
| // Converts extents to a human-readable string, for use by DumpUpdateProto().
|
| string ExtentsToString(const RepeatedPtrField<Extent>& extents) {
|
| @@ -177,10 +190,13 @@ ssize_t DeltaPerformer::Write(const void* bytes, size_t count) {
|
| }
|
| // Remove protobuf and header info from buffer_, so buffer_ contains
|
| // just data blobs
|
| - DiscardBufferHeadBytes(strlen(kDeltaMagic) +
|
| - kDeltaVersionLength +
|
| - kDeltaProtobufLengthLength + protobuf_length,
|
| + size_t metadata_size = strlen(kDeltaMagic) + kDeltaVersionLength +
|
| + kDeltaProtobufLengthLength + protobuf_length;
|
| + DiscardBufferHeadBytes(metadata_size,
|
| true); // do_hash
|
| + LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize,
|
| + metadata_size))
|
| + << "Unable to save the manifest metadata size.";
|
| manifest_valid_ = true;
|
| block_size_ = manifest_.block_size();
|
| }
|
| @@ -202,6 +218,12 @@ ssize_t DeltaPerformer::Write(const void* bytes, size_t count) {
|
| }
|
| bool is_kernel_partition =
|
| (next_operation_num_ >= manifest_.install_operations_size());
|
| + // If about to start a non-idempotent operation, clear the update state so
|
| + // that if the operation gets interrupted, we don't try to resume the
|
| + // update.
|
| + if (!IsIdempotentOperation(op)) {
|
| + ResetUpdateProgress();
|
| + }
|
| if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE ||
|
| op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) {
|
| if (!PerformReplaceOperation(op, is_kernel_partition)) {
|
| @@ -223,6 +245,7 @@ ssize_t DeltaPerformer::Write(const void* bytes, size_t count) {
|
| }
|
| }
|
| next_operation_num_++;
|
| + CheckpointUpdateProgress();
|
| }
|
| return count;
|
| }
|
| @@ -489,4 +512,22 @@ void DeltaPerformer::DiscardBufferHeadBytes(size_t count, bool do_hash) {
|
| buffer_.erase(buffer_.begin(), buffer_.begin() + count);
|
| }
|
|
|
| +bool DeltaPerformer::ResetUpdateProgress() {
|
| + TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextOperation,
|
| + kUpdateStateOperationInvalid));
|
| + return true;
|
| +}
|
| +
|
| +bool DeltaPerformer::CheckpointUpdateProgress() {
|
| + // First reset the progress in case we die in the middle of the state update.
|
| + ResetUpdateProgress();
|
| + TEST_AND_RETURN_FALSE(prefs_->SetString(kPrefsUpdateStateSignedSHA256Context,
|
| + hash_calculator_.GetContext()));
|
| + TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextDataOffset,
|
| + buffer_offset_));
|
| + TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextOperation,
|
| + next_operation_num_));
|
| + return true;
|
| +}
|
| +
|
| } // namespace chromeos_update_engine
|
|
|