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

Side by Side Diff: src/platform/update_engine/delta_diff_generator.cc

Issue 1718001: AU: Class to perform delta updates. (Closed)
Patch Set: fixes for review Created 10 years, 8 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
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium 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_diff_generator.h" 5 #include "update_engine/delta_diff_generator.h"
6 #include <sys/stat.h> 6 #include <sys/stat.h>
7 #include <sys/types.h> 7 #include <sys/types.h>
8 #include <errno.h> 8 #include <errno.h>
9 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <algorithm> 10 #include <algorithm>
(...skipping 20 matching lines...) Expand all
31 using std::set; 31 using std::set;
32 using std::string; 32 using std::string;
33 using std::vector; 33 using std::vector;
34 34
35 namespace chromeos_update_engine { 35 namespace chromeos_update_engine {
36 36
37 typedef DeltaDiffGenerator::Block Block; 37 typedef DeltaDiffGenerator::Block Block;
38 38
39 namespace { 39 namespace {
40 const size_t kBlockSize = 4096; 40 const size_t kBlockSize = 4096;
41 const char* const kBsdiffPath = "/usr/bin/bsdiff"; 41 const uint64_t kVersionNumber = 1;
42 const uint64 kVersionNumber = 1;
43 const char* const kDeltaMagic = "CrAU";
44 42
45 // Stores all Extents for a file into 'out'. Returns true on success. 43 // Stores all Extents for a file into 'out'. Returns true on success.
46 bool GatherExtents(const string& path, 44 bool GatherExtents(const string& path,
47 google::protobuf::RepeatedPtrField<Extent>* out) { 45 google::protobuf::RepeatedPtrField<Extent>* out) {
48 vector<Extent> extents; 46 vector<Extent> extents;
49 TEST_AND_RETURN_FALSE(extent_mapper::ExtentsForFileFibmap(path, &extents)); 47 TEST_AND_RETURN_FALSE(extent_mapper::ExtentsForFileFibmap(path, &extents));
50 DeltaDiffGenerator::StoreExtents(extents, out); 48 DeltaDiffGenerator::StoreExtents(extents, out);
51 return true; 49 return true;
52 } 50 }
53 51
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 out_op->set_dst_length(kBlockSize * block_count); 369 out_op->set_dst_length(kBlockSize * block_count);
372 DeltaDiffGenerator::StoreExtents(extents, out_op->mutable_dst_extents()); 370 DeltaDiffGenerator::StoreExtents(extents, out_op->mutable_dst_extents());
373 371
374 TEST_AND_RETURN_FALSE(utils::WriteAll(blobs_fd, 372 TEST_AND_RETURN_FALSE(utils::WriteAll(blobs_fd,
375 &compressed_data[0], 373 &compressed_data[0],
376 compressed_data.size())); 374 compressed_data.size()));
377 LOG(INFO) << "done with extra blocks"; 375 LOG(INFO) << "done with extra blocks";
378 return true; 376 return true;
379 } 377 }
380 378
381 // Writes the uint64 passed in in host-endian to the file as big-endian. 379 // Writes the uint64_t passed in in host-endian to the file as big-endian.
382 // Returns true on success. 380 // Returns true on success.
383 bool WriteUint64AsBigEndian(FileWriter* writer, const uint64 value) { 381 bool WriteUint64AsBigEndian(FileWriter* writer, const uint64_t value) {
384 uint64 value_be = htobe64(value); 382 uint64_t value_be = htobe64(value);
385 TEST_AND_RETURN_FALSE(writer->Write(&value_be, sizeof(value_be)) == 383 TEST_AND_RETURN_FALSE(writer->Write(&value_be, sizeof(value_be)) ==
386 sizeof(value_be)); 384 sizeof(value_be));
387 return true; 385 return true;
388 } 386 }
389 387
390 // Adds each operation from the graph to the manifest in the order 388 // Adds each operation from the graph to the manifest in the order
391 // specified by 'order'. 389 // specified by 'order'.
392 void InstallOperationsToManifest( 390 void InstallOperationsToManifest(
393 const Graph& graph, 391 const Graph& graph,
394 const vector<Vertex::Index>& order, 392 const vector<Vertex::Index>& order,
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 *out_op = operation; 483 *out_op = operation;
486 484
487 return true; 485 return true;
488 } 486 }
489 487
490 void DeltaDiffGenerator::SubstituteBlocks( 488 void DeltaDiffGenerator::SubstituteBlocks(
491 DeltaArchiveManifest_InstallOperation* op, 489 DeltaArchiveManifest_InstallOperation* op,
492 const vector<Extent>& remove_extents, 490 const vector<Extent>& remove_extents,
493 const vector<Extent>& replace_extents) { 491 const vector<Extent>& replace_extents) {
494 // First, expand out the blocks that op reads from 492 // First, expand out the blocks that op reads from
495 vector<uint64> read_blocks; 493 vector<uint64_t> read_blocks;
496 for (int i = 0; i < op->src_extents_size(); i++) { 494 for (int i = 0; i < op->src_extents_size(); i++) {
497 const Extent& extent = op->src_extents(i); 495 const Extent& extent = op->src_extents(i);
498 if (extent.start_block() == kSparseHole) { 496 if (extent.start_block() == kSparseHole) {
499 read_blocks.resize(read_blocks.size() + extent.num_blocks(), kSparseHole); 497 read_blocks.resize(read_blocks.size() + extent.num_blocks(), kSparseHole);
500 } else { 498 } else {
501 for (uint64 block = extent.start_block(); 499 for (uint64_t block = extent.start_block();
502 block < (extent.start_block() + extent.num_blocks()); block++) { 500 block < (extent.start_block() + extent.num_blocks()); block++) {
503 read_blocks.push_back(block); 501 read_blocks.push_back(block);
504 } 502 }
505 } 503 }
506 } 504 }
507 { 505 {
508 // Expand remove_extents and replace_extents 506 // Expand remove_extents and replace_extents
509 vector<uint64> remove_extents_expanded; 507 vector<uint64_t> remove_extents_expanded;
510 for (vector<Extent>::const_iterator it = remove_extents.begin(); 508 for (vector<Extent>::const_iterator it = remove_extents.begin();
511 it != remove_extents.end(); ++it) { 509 it != remove_extents.end(); ++it) {
512 const Extent& extent = *it; 510 const Extent& extent = *it;
513 for (uint64 block = extent.start_block(); 511 for (uint64_t block = extent.start_block();
514 block < (extent.start_block() + extent.num_blocks()); block++) { 512 block < (extent.start_block() + extent.num_blocks()); block++) {
515 remove_extents_expanded.push_back(block); 513 remove_extents_expanded.push_back(block);
516 } 514 }
517 } 515 }
518 vector<uint64> replace_extents_expanded; 516 vector<uint64_t> replace_extents_expanded;
519 for (vector<Extent>::const_iterator it = replace_extents.begin(); 517 for (vector<Extent>::const_iterator it = replace_extents.begin();
520 it != replace_extents.end(); ++it) { 518 it != replace_extents.end(); ++it) {
521 const Extent& extent = *it; 519 const Extent& extent = *it;
522 for (uint64 block = extent.start_block(); 520 for (uint64_t block = extent.start_block();
523 block < (extent.start_block() + extent.num_blocks()); block++) { 521 block < (extent.start_block() + extent.num_blocks()); block++) {
524 replace_extents_expanded.push_back(block); 522 replace_extents_expanded.push_back(block);
525 } 523 }
526 } 524 }
527 CHECK_EQ(remove_extents_expanded.size(), replace_extents_expanded.size()); 525 CHECK_EQ(remove_extents_expanded.size(), replace_extents_expanded.size());
528 for (vector<uint64>::size_type i = 0; 526 for (vector<uint64_t>::size_type i = 0;
529 i < replace_extents_expanded.size(); i++) { 527 i < replace_extents_expanded.size(); i++) {
530 vector<uint64>::size_type index = 0; 528 vector<uint64_t>::size_type index = 0;
531 CHECK(utils::VectorIndexOf(read_blocks, 529 CHECK(utils::VectorIndexOf(read_blocks,
532 remove_extents_expanded[i], 530 remove_extents_expanded[i],
533 &index)); 531 &index));
534 CHECK(read_blocks[index] == remove_extents_expanded[i]); 532 CHECK(read_blocks[index] == remove_extents_expanded[i]);
535 read_blocks[index] = replace_extents_expanded[i]; 533 read_blocks[index] = replace_extents_expanded[i];
536 } 534 }
537 } 535 }
538 // Convert read_blocks back to extents 536 // Convert read_blocks back to extents
539 op->clear_src_extents(); 537 op->clear_src_extents();
540 vector<Extent> new_extents; 538 vector<Extent> new_extents;
541 for (vector<uint64>::const_iterator it = read_blocks.begin(); 539 for (vector<uint64_t>::const_iterator it = read_blocks.begin();
542 it != read_blocks.end(); ++it) { 540 it != read_blocks.end(); ++it) {
543 graph_utils::AppendBlockToExtents(&new_extents, *it); 541 graph_utils::AppendBlockToExtents(&new_extents, *it);
544 } 542 }
545 DeltaDiffGenerator::StoreExtents(new_extents, op->mutable_src_extents()); 543 DeltaDiffGenerator::StoreExtents(new_extents, op->mutable_src_extents());
546 } 544 }
547 545
548 bool DeltaDiffGenerator::CutEdges(Graph* graph, 546 bool DeltaDiffGenerator::CutEdges(Graph* graph,
549 const vector<Block>& blocks, 547 const vector<Block>& blocks,
550 const set<Edge>& edges) { 548 const set<Edge>& edges) {
551 // First, find enough scratch space for the edges we'll be cutting. 549 // First, find enough scratch space for the edges we'll be cutting.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 int in_fd = open(data_blobs_path.c_str(), O_RDONLY, 0); 644 int in_fd = open(data_blobs_path.c_str(), O_RDONLY, 0);
647 TEST_AND_RETURN_FALSE_ERRNO(in_fd >= 0); 645 TEST_AND_RETURN_FALSE_ERRNO(in_fd >= 0);
648 ScopedFdCloser in_fd_closer(&in_fd); 646 ScopedFdCloser in_fd_closer(&in_fd);
649 647
650 DirectFileWriter writer; 648 DirectFileWriter writer;
651 TEST_AND_RETURN_FALSE( 649 TEST_AND_RETURN_FALSE(
652 writer.Open(new_data_blobs_path.c_str(), 650 writer.Open(new_data_blobs_path.c_str(),
653 O_WRONLY | O_TRUNC | O_CREAT, 651 O_WRONLY | O_TRUNC | O_CREAT,
654 0644) == 0); 652 0644) == 0);
655 ScopedFileWriterCloser writer_closer(&writer); 653 ScopedFileWriterCloser writer_closer(&writer);
656 uint64 out_file_size = 0; 654 uint64_t out_file_size = 0;
657 655
658 for (int i = 0; i < manifest->install_operations_size(); i++) { 656 for (int i = 0; i < manifest->install_operations_size(); i++) {
659 DeltaArchiveManifest_InstallOperation* op = 657 DeltaArchiveManifest_InstallOperation* op =
660 manifest->mutable_install_operations(i); 658 manifest->mutable_install_operations(i);
661 if (!op->has_data_offset()) 659 if (!op->has_data_offset())
662 continue; 660 continue;
663 CHECK(op->has_data_length()); 661 CHECK(op->has_data_length());
664 vector<char> buf(op->data_length()); 662 vector<char> buf(op->data_length());
665 ssize_t rc = pread(in_fd, &buf[0], buf.size(), op->data_offset()); 663 ssize_t rc = pread(in_fd, &buf[0], buf.size(), op->data_offset());
666 TEST_AND_RETURN_FALSE(rc == static_cast<ssize_t>(buf.size())); 664 TEST_AND_RETURN_FALSE(rc == static_cast<ssize_t>(buf.size()));
(...skipping 17 matching lines...) Expand all
684 TEST_AND_RETURN_FALSE_ERRNO(stat(new_image.c_str(), &new_image_stbuf) == 0); 682 TEST_AND_RETURN_FALSE_ERRNO(stat(new_image.c_str(), &new_image_stbuf) == 0);
685 LOG_IF(WARNING, new_image_stbuf.st_size != old_image_stbuf.st_size) 683 LOG_IF(WARNING, new_image_stbuf.st_size != old_image_stbuf.st_size)
686 << "Old and new images are different sizes."; 684 << "Old and new images are different sizes.";
687 LOG_IF(FATAL, new_image_stbuf.st_size % kBlockSize) 685 LOG_IF(FATAL, new_image_stbuf.st_size % kBlockSize)
688 << "New image not a multiple of block size " << kBlockSize; 686 << "New image not a multiple of block size " << kBlockSize;
689 LOG_IF(FATAL, old_image_stbuf.st_size % kBlockSize) 687 LOG_IF(FATAL, old_image_stbuf.st_size % kBlockSize)
690 << "Old image not a multiple of block size " << kBlockSize; 688 << "Old image not a multiple of block size " << kBlockSize;
691 689
692 vector<Block> blocks(min(old_image_stbuf.st_size / kBlockSize, 690 vector<Block> blocks(min(old_image_stbuf.st_size / kBlockSize,
693 new_image_stbuf.st_size / kBlockSize)); 691 new_image_stbuf.st_size / kBlockSize));
694 LOG(INFO) << "w:" << blocks[4097].writer;
695 LOG(INFO) << "invalid: " << Vertex::kInvalidIndex; 692 LOG(INFO) << "invalid: " << Vertex::kInvalidIndex;
696 LOG(INFO) << "len: " << blocks.size(); 693 LOG(INFO) << "len: " << blocks.size();
697 for (vector<Block>::size_type i = 0; i < blocks.size(); i++) { 694 for (vector<Block>::size_type i = 0; i < blocks.size(); i++) {
698 CHECK(blocks[i].reader == Vertex::kInvalidIndex); 695 CHECK(blocks[i].reader == Vertex::kInvalidIndex);
699 CHECK(blocks[i].writer == Vertex::kInvalidIndex); 696 CHECK(blocks[i].writer == Vertex::kInvalidIndex);
700 } 697 }
701 Graph graph; 698 Graph graph;
702 CheckGraph(graph); 699 CheckGraph(graph);
703 700
704 const string kTempFileTemplate("/tmp/CrAU_temp_data.XXXXXX"); 701 const string kTempFileTemplate("/tmp/CrAU_temp_data.XXXXXX");
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 TEST_AND_RETURN_FALSE(utils::MakeTempFile( 771 TEST_AND_RETURN_FALSE(utils::MakeTempFile(
775 "/tmp/CrAU_temp_data.ordered.XXXXXX", 772 "/tmp/CrAU_temp_data.ordered.XXXXXX",
776 &ordered_blobs_path, 773 &ordered_blobs_path,
777 false)); 774 false));
778 TEST_AND_RETURN_FALSE(ReorderDataBlobs(&manifest, 775 TEST_AND_RETURN_FALSE(ReorderDataBlobs(&manifest,
779 temp_file_path, 776 temp_file_path,
780 ordered_blobs_path)); 777 ordered_blobs_path));
781 778
782 // Check that install op blobs are in order and that all blocks are written. 779 // Check that install op blobs are in order and that all blocks are written.
783 { 780 {
784 vector<uint32> written_count(blocks.size(), 0); 781 vector<uint32_t> written_count(blocks.size(), 0);
785 uint64 next_blob_offset = 0; 782 uint64_t next_blob_offset = 0;
786 for (int i = 0; i < manifest.install_operations_size(); i++) { 783 for (int i = 0; i < manifest.install_operations_size(); i++) {
787 const DeltaArchiveManifest_InstallOperation& op = 784 const DeltaArchiveManifest_InstallOperation& op =
788 manifest.install_operations(i); 785 manifest.install_operations(i);
789 for (int j = 0; j < op.dst_extents_size(); j++) { 786 for (int j = 0; j < op.dst_extents_size(); j++) {
790 const Extent& extent = op.dst_extents(j); 787 const Extent& extent = op.dst_extents(j);
791 for (uint64 block = extent.start_block(); 788 for (uint64_t block = extent.start_block();
792 block < (extent.start_block() + extent.num_blocks()); block++) { 789 block < (extent.start_block() + extent.num_blocks()); block++) {
793 written_count[block]++; 790 written_count[block]++;
794 } 791 }
795 } 792 }
796 if (op.has_data_offset()) { 793 if (op.has_data_offset()) {
797 if (op.data_offset() != next_blob_offset) { 794 if (op.data_offset() != next_blob_offset) {
798 LOG(FATAL) << "bad blob offset! " << op.data_offset() << " != " 795 LOG(FATAL) << "bad blob offset! " << op.data_offset() << " != "
799 << next_blob_offset; 796 << next_blob_offset;
800 } 797 }
801 next_blob_offset += op.data_length(); 798 next_blob_offset += op.data_length();
802 } 799 }
803 } 800 }
804 // check all blocks written to 801 // check all blocks written to
805 for (vector<uint32>::size_type i = 0; i < written_count.size(); i++) { 802 for (vector<uint32_t>::size_type i = 0; i < written_count.size(); i++) {
806 if (written_count[i] == 0) { 803 if (written_count[i] == 0) {
807 LOG(FATAL) << "block " << i << " not written!"; 804 LOG(FATAL) << "block " << i << " not written!";
808 } 805 }
809 } 806 }
810 } 807 }
811 808
812 // Serialize protobuf 809 // Serialize protobuf
813 string serialized_manifest; 810 string serialized_manifest;
814 811
815 CheckGraph(graph); 812 CheckGraph(graph);
(...skipping 20 matching lines...) Expand all
836 833
837 // Write protobuf 834 // Write protobuf
838 LOG(INFO) << "Writing final delta file protobuf... " 835 LOG(INFO) << "Writing final delta file protobuf... "
839 << serialized_manifest.size(); 836 << serialized_manifest.size();
840 TEST_AND_RETURN_FALSE(writer.Write(serialized_manifest.data(), 837 TEST_AND_RETURN_FALSE(writer.Write(serialized_manifest.data(),
841 serialized_manifest.size()) == 838 serialized_manifest.size()) ==
842 static_cast<ssize_t>(serialized_manifest.size())); 839 static_cast<ssize_t>(serialized_manifest.size()));
843 840
844 // Append the data blobs 841 // Append the data blobs
845 LOG(INFO) << "Writing final delta file data blobs..."; 842 LOG(INFO) << "Writing final delta file data blobs...";
846 int blobs_fd = open(temp_file_path.c_str(), O_RDONLY, 0); 843 int blobs_fd = open(ordered_blobs_path.c_str(), O_RDONLY, 0);
847 ScopedFdCloser blobs_fd_closer(&blobs_fd); 844 ScopedFdCloser blobs_fd_closer(&blobs_fd);
848 TEST_AND_RETURN_FALSE(blobs_fd >= 0); 845 TEST_AND_RETURN_FALSE(blobs_fd >= 0);
849 for (;;) { 846 for (;;) {
850 char buf[kBlockSize]; 847 char buf[kBlockSize];
851 ssize_t rc = read(blobs_fd, buf, sizeof(buf)); 848 ssize_t rc = read(blobs_fd, buf, sizeof(buf));
852 if (0 == rc) { 849 if (0 == rc) {
853 // EOF 850 // EOF
854 break; 851 break;
855 } 852 }
856 TEST_AND_RETURN_FALSE_ERRNO(rc > 0); 853 TEST_AND_RETURN_FALSE_ERRNO(rc > 0);
857 TEST_AND_RETURN_FALSE(writer.Write(buf, rc) == rc); 854 TEST_AND_RETURN_FALSE(writer.Write(buf, rc) == rc);
858 } 855 }
859 856
860 LOG(INFO) << "All done. Successfully created delta file."; 857 LOG(INFO) << "All done. Successfully created delta file.";
861 return true; 858 return true;
862 } 859 }
863 860
864 }; // namespace chromeos_update_engine 861 }; // namespace chromeos_update_engine
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698