Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: delta_performer.cc

Issue 3620013: AU: Resume interrupted update attempts. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/update_engine.git
Patch Set: fix setup download Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « delta_performer.h ('k') | delta_performer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "update_engine/delta_performer.h" 5 #include "update_engine/delta_performer.h"
6 6
7 #include <endian.h> 7 #include <endian.h>
8 #include <errno.h> 8 #include <errno.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 } 191 }
192 // Remove protobuf and header info from buffer_, so buffer_ contains 192 // Remove protobuf and header info from buffer_, so buffer_ contains
193 // just data blobs 193 // just data blobs
194 manifest_metadata_size_ = strlen(kDeltaMagic) + kDeltaVersionLength + 194 manifest_metadata_size_ = strlen(kDeltaMagic) + kDeltaVersionLength +
195 kDeltaProtobufLengthLength + protobuf_length; 195 kDeltaProtobufLengthLength + protobuf_length;
196 DiscardBufferHeadBytes(manifest_metadata_size_); 196 DiscardBufferHeadBytes(manifest_metadata_size_);
197 LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize, 197 LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize,
198 manifest_metadata_size_)) 198 manifest_metadata_size_))
199 << "Unable to save the manifest metadata size."; 199 << "Unable to save the manifest metadata size.";
200 manifest_valid_ = true; 200 manifest_valid_ = true;
201 block_size_ = manifest_.block_size(); 201 if (!PrimeUpdateState()) {
202 LOG(ERROR) << "Unable to prime the update state.";
203 return -EINVAL;
204 }
202 } 205 }
203 ssize_t total_operations = manifest_.install_operations_size() + 206 ssize_t total_operations = manifest_.install_operations_size() +
204 manifest_.kernel_install_operations_size(); 207 manifest_.kernel_install_operations_size();
205 while (next_operation_num_ < total_operations) { 208 while (next_operation_num_ < total_operations) {
206 const DeltaArchiveManifest_InstallOperation &op = 209 const DeltaArchiveManifest_InstallOperation &op =
207 next_operation_num_ < manifest_.install_operations_size() ? 210 next_operation_num_ < manifest_.install_operations_size() ?
208 manifest_.install_operations(next_operation_num_) : 211 manifest_.install_operations(next_operation_num_) :
209 manifest_.kernel_install_operations( 212 manifest_.kernel_install_operations(
210 next_operation_num_ - manifest_.install_operations_size()); 213 next_operation_num_ - manifest_.install_operations_size());
211 if (!CanPerformInstallOperation(op)) 214 if (!CanPerformInstallOperation(op))
212 break; 215 break;
213 ScopedTerminatorExitUnblocker exit_unblocker = 216 ScopedTerminatorExitUnblocker exit_unblocker =
214 ScopedTerminatorExitUnblocker(); // Avoids a compiler unused var bug. 217 ScopedTerminatorExitUnblocker(); // Avoids a compiler unused var bug.
215 // Log every thousandth operation, and also the first and last ones 218 // Log every thousandth operation, and also the first and last ones
216 if ((next_operation_num_ % 1000 == 0) || 219 if ((next_operation_num_ % 1000 == 0) ||
217 (next_operation_num_ + 1 == total_operations)) { 220 (next_operation_num_ + 1 == total_operations)) {
218 LOG(INFO) << "Performing operation " << (next_operation_num_ + 1) << "/" 221 LOG(INFO) << "Performing operation " << (next_operation_num_ + 1) << "/"
219 << total_operations; 222 << total_operations;
220 } 223 }
221 bool is_kernel_partition = 224 bool is_kernel_partition =
222 (next_operation_num_ >= manifest_.install_operations_size()); 225 (next_operation_num_ >= manifest_.install_operations_size());
223 // If about to start a non-idempotent operation, clear the update state so 226 // If about to start a non-idempotent operation, clear the update state so
224 // that if the operation gets interrupted, we don't try to resume the 227 // that if the operation gets interrupted, we don't try to resume the
225 // update. 228 // update.
226 if (!IsIdempotentOperation(op)) { 229 if (!IsIdempotentOperation(op)) {
227 Terminator::set_exit_blocked(true); 230 Terminator::set_exit_blocked(true);
228 ResetUpdateProgress(prefs_); 231 ResetUpdateProgress(prefs_, true);
229 } 232 }
230 if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE || 233 if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE ||
231 op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) { 234 op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) {
232 if (!PerformReplaceOperation(op, is_kernel_partition)) { 235 if (!PerformReplaceOperation(op, is_kernel_partition)) {
233 LOG(ERROR) << "Failed to perform replace operation " 236 LOG(ERROR) << "Failed to perform replace operation "
234 << next_operation_num_; 237 << next_operation_num_;
235 return -EINVAL; 238 return -EINVAL;
236 } 239 }
237 } else if (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE) { 240 } else if (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE) {
238 if (!PerformMoveOperation(op, is_kernel_partition)) { 241 if (!PerformMoveOperation(op, is_kernel_partition)) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 bool DeltaPerformer::PerformReplaceOperation( 277 bool DeltaPerformer::PerformReplaceOperation(
275 const DeltaArchiveManifest_InstallOperation& operation, 278 const DeltaArchiveManifest_InstallOperation& operation,
276 bool is_kernel_partition) { 279 bool is_kernel_partition) {
277 CHECK(operation.type() == \ 280 CHECK(operation.type() == \
278 DeltaArchiveManifest_InstallOperation_Type_REPLACE || \ 281 DeltaArchiveManifest_InstallOperation_Type_REPLACE || \
279 operation.type() == \ 282 operation.type() == \
280 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ); 283 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ);
281 284
282 // Since we delete data off the beginning of the buffer as we use it, 285 // Since we delete data off the beginning of the buffer as we use it,
283 // the data we need should be exactly at the beginning of the buffer. 286 // the data we need should be exactly at the beginning of the buffer.
284 CHECK_EQ(buffer_offset_, operation.data_offset()); 287 TEST_AND_RETURN_FALSE(buffer_offset_ == operation.data_offset());
285 CHECK_GE(buffer_.size(), operation.data_length()); 288 TEST_AND_RETURN_FALSE(buffer_.size() >= operation.data_length());
286 289
287 // Extract the signature message if it's in this operation. 290 // Extract the signature message if it's in this operation.
288 ExtractSignatureMessage(operation); 291 ExtractSignatureMessage(operation);
289 292
290 DirectExtentWriter direct_writer; 293 DirectExtentWriter direct_writer;
291 ZeroPadExtentWriter zero_pad_writer(&direct_writer); 294 ZeroPadExtentWriter zero_pad_writer(&direct_writer);
292 scoped_ptr<BzipExtentWriter> bzip_writer; 295 scoped_ptr<BzipExtentWriter> bzip_writer;
293 296
294 // Since bzip decompression is optional, we have a variable writer that will 297 // Since bzip decompression is optional, we have a variable writer that will
295 // point to one of the ExtentWriter objects above. 298 // point to one of the ExtentWriter objects above.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 ret.resize(ret.size() - 1); // Strip trailing comma off 401 ret.resize(ret.size() - 1); // Strip trailing comma off
399 *positions_string = ret; 402 *positions_string = ret;
400 return true; 403 return true;
401 } 404 }
402 405
403 bool DeltaPerformer::PerformBsdiffOperation( 406 bool DeltaPerformer::PerformBsdiffOperation(
404 const DeltaArchiveManifest_InstallOperation& operation, 407 const DeltaArchiveManifest_InstallOperation& operation,
405 bool is_kernel_partition) { 408 bool is_kernel_partition) {
406 // Since we delete data off the beginning of the buffer as we use it, 409 // Since we delete data off the beginning of the buffer as we use it,
407 // the data we need should be exactly at the beginning of the buffer. 410 // the data we need should be exactly at the beginning of the buffer.
408 CHECK_EQ(buffer_offset_, operation.data_offset()); 411 TEST_AND_RETURN_FALSE(buffer_offset_ == operation.data_offset());
409 CHECK_GE(buffer_.size(), operation.data_length()); 412 TEST_AND_RETURN_FALSE(buffer_.size() >= operation.data_length());
410 413
411 string input_positions; 414 string input_positions;
412 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.src_extents(), 415 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.src_extents(),
413 block_size_, 416 block_size_,
414 operation.src_length(), 417 operation.src_length(),
415 &input_positions)); 418 &input_positions));
416 string output_positions; 419 string output_positions;
417 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.dst_extents(), 420 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.dst_extents(),
418 block_size_, 421 block_size_,
419 operation.dst_length(), 422 operation.dst_length(),
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 !sha256_context.empty()); 567 !sha256_context.empty());
565 568
566 int64_t manifest_metadata_size = 0; 569 int64_t manifest_metadata_size = 0;
567 TEST_AND_RETURN_FALSE(prefs->GetInt64(kPrefsManifestMetadataSize, 570 TEST_AND_RETURN_FALSE(prefs->GetInt64(kPrefsManifestMetadataSize,
568 &manifest_metadata_size) && 571 &manifest_metadata_size) &&
569 manifest_metadata_size > 0); 572 manifest_metadata_size > 0);
570 573
571 return true; 574 return true;
572 } 575 }
573 576
574 bool DeltaPerformer::ResetUpdateProgress(PrefsInterface* prefs) { 577 bool DeltaPerformer::ResetUpdateProgress(PrefsInterface* prefs, bool quick) {
575 TEST_AND_RETURN_FALSE(prefs->SetInt64(kPrefsUpdateStateNextOperation, 578 TEST_AND_RETURN_FALSE(prefs->SetInt64(kPrefsUpdateStateNextOperation,
576 kUpdateStateOperationInvalid)); 579 kUpdateStateOperationInvalid));
580 if (!quick) {
581 prefs->SetString(kPrefsUpdateCheckResponseHash, "");
582 prefs->SetInt64(kPrefsUpdateStateNextDataOffset, -1);
583 prefs->SetString(kPrefsUpdateStateSHA256Context, "");
584 prefs->SetString(kPrefsUpdateStateSignedSHA256Context, "");
585 prefs->SetInt64(kPrefsManifestMetadataSize, -1);
586 }
577 return true; 587 return true;
578 } 588 }
579 589
580 bool DeltaPerformer::CheckpointUpdateProgress() { 590 bool DeltaPerformer::CheckpointUpdateProgress() {
581 Terminator::set_exit_blocked(true); 591 Terminator::set_exit_blocked(true);
582 if (last_updated_buffer_offset_ != buffer_offset_) { 592 if (last_updated_buffer_offset_ != buffer_offset_) {
583 // Resets the progress in case we die in the middle of the state update. 593 // Resets the progress in case we die in the middle of the state update.
584 ResetUpdateProgress(prefs_); 594 ResetUpdateProgress(prefs_, true);
585 TEST_AND_RETURN_FALSE( 595 TEST_AND_RETURN_FALSE(
586 prefs_->SetString(kPrefsUpdateStateSHA256Context, 596 prefs_->SetString(kPrefsUpdateStateSHA256Context,
587 hash_calculator_.GetContext())); 597 hash_calculator_.GetContext()));
588 TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextDataOffset, 598 TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextDataOffset,
589 buffer_offset_)); 599 buffer_offset_));
590 last_updated_buffer_offset_ = buffer_offset_; 600 last_updated_buffer_offset_ = buffer_offset_;
591 } 601 }
592 TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextOperation, 602 TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextOperation,
593 next_operation_num_)); 603 next_operation_num_));
594 return true; 604 return true;
595 } 605 }
596 606
607 bool DeltaPerformer::PrimeUpdateState() {
608 CHECK(manifest_valid_);
609 block_size_ = manifest_.block_size();
610
611 int64_t next_operation = kUpdateStateOperationInvalid;
612 if (!prefs_->GetInt64(kPrefsUpdateStateNextOperation, &next_operation) ||
613 next_operation == kUpdateStateOperationInvalid ||
614 next_operation <= 0) {
615 // Initiating a new update, no more state needs to be initialized.
616 return true;
617 }
618 next_operation_num_ = next_operation;
619
620 // Resuming an update -- load the rest of the update state.
621 int64_t next_data_offset = -1;
622 TEST_AND_RETURN_FALSE(prefs_->GetInt64(kPrefsUpdateStateNextDataOffset,
623 &next_data_offset) &&
624 next_data_offset >= 0);
625 buffer_offset_ = next_data_offset;
626
627 // The signed hash context may be empty if the interrupted update didn't reach
628 // the signature blob.
629 prefs_->GetString(kPrefsUpdateStateSignedSHA256Context,
630 &signed_hash_context_);
631
632 string hash_context;
633 TEST_AND_RETURN_FALSE(prefs_->GetString(kPrefsUpdateStateSHA256Context,
634 &hash_context) &&
635 hash_calculator_.SetContext(hash_context));
636
637 int64_t manifest_metadata_size = 0;
638 TEST_AND_RETURN_FALSE(prefs_->GetInt64(kPrefsManifestMetadataSize,
639 &manifest_metadata_size) &&
640 manifest_metadata_size > 0);
641 manifest_metadata_size_ = manifest_metadata_size;
642
643 return true;
644 }
645
597 } // namespace chromeos_update_engine 646 } // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « delta_performer.h ('k') | delta_performer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698