ab_generator.cc revision 8cc502dacbccdab96824d42287f230ce04004784
114158570d3995008dc93a628004118b87a6bca01Alex Deymo// Copyright 2015 The Chromium OS Authors. All rights reserved. 214158570d3995008dc93a628004118b87a6bca01Alex Deymo// Use of this source code is governed by a BSD-style license that can be 314158570d3995008dc93a628004118b87a6bca01Alex Deymo// found in the LICENSE file. 414158570d3995008dc93a628004118b87a6bca01Alex Deymo 514158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/payload_generator/ab_generator.h" 614158570d3995008dc93a628004118b87a6bca01Alex Deymo 714158570d3995008dc93a628004118b87a6bca01Alex Deymo#include <algorithm> 814158570d3995008dc93a628004118b87a6bca01Alex Deymo 914158570d3995008dc93a628004118b87a6bca01Alex Deymo#include <base/strings/stringprintf.h> 1014158570d3995008dc93a628004118b87a6bca01Alex Deymo 1114158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/bzip.h" 1214158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/delta_performer.h" 1314158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/payload_generator/annotated_operation.h" 1414158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/payload_generator/delta_diff_generator.h" 1514158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/payload_generator/delta_diff_utils.h" 1614158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/utils.h" 1714158570d3995008dc93a628004118b87a6bca01Alex Deymo 1814158570d3995008dc93a628004118b87a6bca01Alex Deymousing std::string; 1914158570d3995008dc93a628004118b87a6bca01Alex Deymousing std::vector; 2014158570d3995008dc93a628004118b87a6bca01Alex Deymo 2114158570d3995008dc93a628004118b87a6bca01Alex Deymonamespace chromeos_update_engine { 2214158570d3995008dc93a628004118b87a6bca01Alex Deymo 2314158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::GenerateOperations( 2414158570d3995008dc93a628004118b87a6bca01Alex Deymo const PayloadGenerationConfig& config, 258cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file, 2614158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* rootfs_ops, 2714158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* kernel_ops) { 2814158570d3995008dc93a628004118b87a6bca01Alex Deymo 292d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo ssize_t hard_chunk_blocks = (config.hard_chunk_size == -1 ? -1 : 302d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo config.hard_chunk_size / config.block_size); 312d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo size_t soft_chunk_blocks = config.soft_chunk_size / config.block_size; 3214158570d3995008dc93a628004118b87a6bca01Alex Deymo 3314158570d3995008dc93a628004118b87a6bca01Alex Deymo rootfs_ops->clear(); 34b42b98db059a12c44110588fc0b3d5f82d32a2f8Alex Deymo TEST_AND_RETURN_FALSE(diff_utils::DeltaReadPartition( 3514158570d3995008dc93a628004118b87a6bca01Alex Deymo rootfs_ops, 36b42b98db059a12c44110588fc0b3d5f82d32a2f8Alex Deymo config.source.rootfs, 37b42b98db059a12c44110588fc0b3d5f82d32a2f8Alex Deymo config.target.rootfs, 382d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo hard_chunk_blocks, 392d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo soft_chunk_blocks, 408cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file, 4114158570d3995008dc93a628004118b87a6bca01Alex Deymo true)); // src_ops_allowed 4214158570d3995008dc93a628004118b87a6bca01Alex Deymo LOG(INFO) << "done reading normal files"; 4314158570d3995008dc93a628004118b87a6bca01Alex Deymo 4414158570d3995008dc93a628004118b87a6bca01Alex Deymo // Read kernel partition 45b42b98db059a12c44110588fc0b3d5f82d32a2f8Alex Deymo TEST_AND_RETURN_FALSE(diff_utils::DeltaReadPartition( 4614158570d3995008dc93a628004118b87a6bca01Alex Deymo kernel_ops, 47b42b98db059a12c44110588fc0b3d5f82d32a2f8Alex Deymo config.source.kernel, 48b42b98db059a12c44110588fc0b3d5f82d32a2f8Alex Deymo config.target.kernel, 492d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo hard_chunk_blocks, 502d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo soft_chunk_blocks, 518cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file, 5214158570d3995008dc93a628004118b87a6bca01Alex Deymo true)); // src_ops_allowed 5314158570d3995008dc93a628004118b87a6bca01Alex Deymo LOG(INFO) << "done reading kernel"; 5414158570d3995008dc93a628004118b87a6bca01Alex Deymo 5514158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(FragmentOperations(rootfs_ops, 5614158570d3995008dc93a628004118b87a6bca01Alex Deymo config.target.rootfs.path, 578cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 5814158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(FragmentOperations(kernel_ops, 5914158570d3995008dc93a628004118b87a6bca01Alex Deymo config.target.kernel.path, 608cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 6114158570d3995008dc93a628004118b87a6bca01Alex Deymo SortOperationsByDestination(rootfs_ops); 6214158570d3995008dc93a628004118b87a6bca01Alex Deymo SortOperationsByDestination(kernel_ops); 632d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo 642d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo // Use the soft_chunk_size when merging operations to prevent merging all 652d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo // the operations into a huge one if there's no hard limit. 662d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo size_t merge_chunk_blocks = soft_chunk_blocks; 672d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo if (hard_chunk_blocks != -1 && 682d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo static_cast<size_t>(hard_chunk_blocks) < soft_chunk_blocks) { 692d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo merge_chunk_blocks = hard_chunk_blocks; 702d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo } 712d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo 7214158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(MergeOperations(rootfs_ops, 732d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo merge_chunk_blocks, 7414158570d3995008dc93a628004118b87a6bca01Alex Deymo config.target.rootfs.path, 758cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 7614158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(MergeOperations(kernel_ops, 772d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo merge_chunk_blocks, 7814158570d3995008dc93a628004118b87a6bca01Alex Deymo config.target.kernel.path, 798cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 8014158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 8114158570d3995008dc93a628004118b87a6bca01Alex Deymo} 8214158570d3995008dc93a628004118b87a6bca01Alex Deymo 8314158570d3995008dc93a628004118b87a6bca01Alex Deymovoid ABGenerator::SortOperationsByDestination( 8414158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* aops) { 853b2c7d0e6d859e6fc75c82b3417f87cf5968a49dAlex Deymo sort(aops->begin(), aops->end(), diff_utils::CompareAopsByDestination); 8614158570d3995008dc93a628004118b87a6bca01Alex Deymo} 8714158570d3995008dc93a628004118b87a6bca01Alex Deymo 8814158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::FragmentOperations( 8914158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* aops, 9014158570d3995008dc93a628004118b87a6bca01Alex Deymo const string& target_part_path, 918cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file) { 9214158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation> fragmented_aops; 9314158570d3995008dc93a628004118b87a6bca01Alex Deymo for (const AnnotatedOperation& aop : *aops) { 9414158570d3995008dc93a628004118b87a6bca01Alex Deymo if (aop.op.type() == 9514158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY) { 9614158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(SplitSourceCopy(aop, &fragmented_aops)); 9714158570d3995008dc93a628004118b87a6bca01Alex Deymo } else if ((aop.op.type() == 9814158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE) || 9914158570d3995008dc93a628004118b87a6bca01Alex Deymo (aop.op.type() == 10014158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ)) { 10114158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(SplitReplaceOrReplaceBz(aop, &fragmented_aops, 1028cc502dacbccdab96824d42287f230ce04004784Sen Jiang target_part_path, 1038cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 10414158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 10514158570d3995008dc93a628004118b87a6bca01Alex Deymo fragmented_aops.push_back(aop); 10614158570d3995008dc93a628004118b87a6bca01Alex Deymo } 10714158570d3995008dc93a628004118b87a6bca01Alex Deymo } 10814158570d3995008dc93a628004118b87a6bca01Alex Deymo *aops = fragmented_aops; 10914158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 11014158570d3995008dc93a628004118b87a6bca01Alex Deymo} 11114158570d3995008dc93a628004118b87a6bca01Alex Deymo 11214158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::SplitSourceCopy( 11314158570d3995008dc93a628004118b87a6bca01Alex Deymo const AnnotatedOperation& original_aop, 11414158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* result_aops) { 11514158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation original_op = original_aop.op; 11614158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(original_op.type() == 11714158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY); 11814158570d3995008dc93a628004118b87a6bca01Alex Deymo // Keeps track of the index of curr_src_ext. 11914158570d3995008dc93a628004118b87a6bca01Alex Deymo int curr_src_ext_index = 0; 12014158570d3995008dc93a628004118b87a6bca01Alex Deymo Extent curr_src_ext = original_op.src_extents(curr_src_ext_index); 12114158570d3995008dc93a628004118b87a6bca01Alex Deymo for (int i = 0; i < original_op.dst_extents_size(); i++) { 12214158570d3995008dc93a628004118b87a6bca01Alex Deymo Extent dst_ext = original_op.dst_extents(i); 12314158570d3995008dc93a628004118b87a6bca01Alex Deymo // The new operation which will have only one dst extent. 12414158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation new_op; 12514158570d3995008dc93a628004118b87a6bca01Alex Deymo uint64_t blocks_left = dst_ext.num_blocks(); 12614158570d3995008dc93a628004118b87a6bca01Alex Deymo while (blocks_left > 0) { 12714158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_src_ext.num_blocks() <= blocks_left) { 12814158570d3995008dc93a628004118b87a6bca01Alex Deymo // If the curr_src_ext is smaller than dst_ext, add it. 12914158570d3995008dc93a628004118b87a6bca01Alex Deymo blocks_left -= curr_src_ext.num_blocks(); 13014158570d3995008dc93a628004118b87a6bca01Alex Deymo *(new_op.add_src_extents()) = curr_src_ext; 13114158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_src_ext_index + 1 < original_op.src_extents().size()) { 13214158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_src_ext = original_op.src_extents(++curr_src_ext_index); 13314158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 13414158570d3995008dc93a628004118b87a6bca01Alex Deymo break; 13514158570d3995008dc93a628004118b87a6bca01Alex Deymo } 13614158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 13714158570d3995008dc93a628004118b87a6bca01Alex Deymo // Split src_exts that are bigger than the dst_ext we're dealing with. 13814158570d3995008dc93a628004118b87a6bca01Alex Deymo Extent first_ext; 13914158570d3995008dc93a628004118b87a6bca01Alex Deymo first_ext.set_num_blocks(blocks_left); 14014158570d3995008dc93a628004118b87a6bca01Alex Deymo first_ext.set_start_block(curr_src_ext.start_block()); 14114158570d3995008dc93a628004118b87a6bca01Alex Deymo *(new_op.add_src_extents()) = first_ext; 14214158570d3995008dc93a628004118b87a6bca01Alex Deymo // Keep the second half of the split op. 14314158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_src_ext.set_num_blocks(curr_src_ext.num_blocks() - blocks_left); 14414158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_src_ext.set_start_block(curr_src_ext.start_block() + blocks_left); 14514158570d3995008dc93a628004118b87a6bca01Alex Deymo blocks_left -= first_ext.num_blocks(); 14614158570d3995008dc93a628004118b87a6bca01Alex Deymo } 14714158570d3995008dc93a628004118b87a6bca01Alex Deymo } 14814158570d3995008dc93a628004118b87a6bca01Alex Deymo // Fix up our new operation and add it to the results. 14914158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_type(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY); 15014158570d3995008dc93a628004118b87a6bca01Alex Deymo *(new_op.add_dst_extents()) = dst_ext; 15114158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_src_length(dst_ext.num_blocks() * kBlockSize); 15214158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_dst_length(dst_ext.num_blocks() * kBlockSize); 15314158570d3995008dc93a628004118b87a6bca01Alex Deymo 15414158570d3995008dc93a628004118b87a6bca01Alex Deymo AnnotatedOperation new_aop; 15514158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aop.op = new_op; 15614158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aop.name = base::StringPrintf("%s:%d", original_aop.name.c_str(), i); 15714158570d3995008dc93a628004118b87a6bca01Alex Deymo result_aops->push_back(new_aop); 15814158570d3995008dc93a628004118b87a6bca01Alex Deymo } 15914158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_src_ext_index != original_op.src_extents().size() - 1) { 16014158570d3995008dc93a628004118b87a6bca01Alex Deymo LOG(FATAL) << "Incorrectly split SOURCE_COPY operation. Did not use all " 16114158570d3995008dc93a628004118b87a6bca01Alex Deymo << "source extents."; 16214158570d3995008dc93a628004118b87a6bca01Alex Deymo } 16314158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 16414158570d3995008dc93a628004118b87a6bca01Alex Deymo} 16514158570d3995008dc93a628004118b87a6bca01Alex Deymo 16614158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::SplitReplaceOrReplaceBz( 16714158570d3995008dc93a628004118b87a6bca01Alex Deymo const AnnotatedOperation& original_aop, 16814158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* result_aops, 16914158570d3995008dc93a628004118b87a6bca01Alex Deymo const string& target_part_path, 1708cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file) { 17114158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation original_op = original_aop.op; 17214158570d3995008dc93a628004118b87a6bca01Alex Deymo const bool is_replace = 17314158570d3995008dc93a628004118b87a6bca01Alex Deymo original_op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE; 17414158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE( 17514158570d3995008dc93a628004118b87a6bca01Alex Deymo is_replace || 17614158570d3995008dc93a628004118b87a6bca01Alex Deymo (original_op.type() == 17714158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ)); 17814158570d3995008dc93a628004118b87a6bca01Alex Deymo 17914158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t data_offset = original_op.data_offset(); 18014158570d3995008dc93a628004118b87a6bca01Alex Deymo for (int i = 0; i < original_op.dst_extents_size(); i++) { 18114158570d3995008dc93a628004118b87a6bca01Alex Deymo Extent dst_ext = original_op.dst_extents(i); 18214158570d3995008dc93a628004118b87a6bca01Alex Deymo // Make a new operation with only one dst extent. 18314158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation new_op; 18414158570d3995008dc93a628004118b87a6bca01Alex Deymo *(new_op.add_dst_extents()) = dst_ext; 18514158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t data_size = dst_ext.num_blocks() * kBlockSize; 18614158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_dst_length(data_size); 18714158570d3995008dc93a628004118b87a6bca01Alex Deymo // If this is a REPLACE, attempt to reuse portions of the existing blob. 18814158570d3995008dc93a628004118b87a6bca01Alex Deymo if (is_replace) { 18914158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE); 19014158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_data_length(data_size); 19114158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_data_offset(data_offset); 19214158570d3995008dc93a628004118b87a6bca01Alex Deymo data_offset += data_size; 19314158570d3995008dc93a628004118b87a6bca01Alex Deymo } 19414158570d3995008dc93a628004118b87a6bca01Alex Deymo 19514158570d3995008dc93a628004118b87a6bca01Alex Deymo AnnotatedOperation new_aop; 19614158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aop.op = new_op; 19714158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aop.name = base::StringPrintf("%s:%d", original_aop.name.c_str(), i); 1988cc502dacbccdab96824d42287f230ce04004784Sen Jiang TEST_AND_RETURN_FALSE(AddDataAndSetType(&new_aop, target_part_path, 1998cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 20014158570d3995008dc93a628004118b87a6bca01Alex Deymo 20114158570d3995008dc93a628004118b87a6bca01Alex Deymo result_aops->push_back(new_aop); 20214158570d3995008dc93a628004118b87a6bca01Alex Deymo } 20314158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 20414158570d3995008dc93a628004118b87a6bca01Alex Deymo} 20514158570d3995008dc93a628004118b87a6bca01Alex Deymo 20614158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::MergeOperations(vector<AnnotatedOperation>* aops, 2072d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo size_t chunk_blocks, 20814158570d3995008dc93a628004118b87a6bca01Alex Deymo const string& target_part_path, 2098cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file) { 21014158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation> new_aops; 21114158570d3995008dc93a628004118b87a6bca01Alex Deymo for (const AnnotatedOperation& curr_aop : *aops) { 21214158570d3995008dc93a628004118b87a6bca01Alex Deymo if (new_aops.empty()) { 21314158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aops.push_back(curr_aop); 21414158570d3995008dc93a628004118b87a6bca01Alex Deymo continue; 21514158570d3995008dc93a628004118b87a6bca01Alex Deymo } 21614158570d3995008dc93a628004118b87a6bca01Alex Deymo AnnotatedOperation& last_aop = new_aops.back(); 21714158570d3995008dc93a628004118b87a6bca01Alex Deymo 21814158570d3995008dc93a628004118b87a6bca01Alex Deymo if (last_aop.op.dst_extents_size() <= 0 || 21914158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.dst_extents_size() <= 0) { 22014158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aops.push_back(curr_aop); 22114158570d3995008dc93a628004118b87a6bca01Alex Deymo continue; 22214158570d3995008dc93a628004118b87a6bca01Alex Deymo } 22314158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t last_dst_idx = last_aop.op.dst_extents_size() - 1; 22414158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t last_end_block = 22514158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.dst_extents(last_dst_idx).start_block() + 22614158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.dst_extents(last_dst_idx).num_blocks(); 22714158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t curr_start_block = curr_aop.op.dst_extents(0).start_block(); 22814158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t combined_block_count = 22914158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.dst_extents(last_dst_idx).num_blocks() + 23014158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.dst_extents(0).num_blocks(); 23114158570d3995008dc93a628004118b87a6bca01Alex Deymo bool good_op_type = 23214158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.type() == 23314158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY || 23414158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.type() == 23514158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE || 23614158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.type() == 23714158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ; 23814158570d3995008dc93a628004118b87a6bca01Alex Deymo if (good_op_type && 23914158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.type() == curr_aop.op.type() && 24014158570d3995008dc93a628004118b87a6bca01Alex Deymo last_end_block == curr_start_block && 2412d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo combined_block_count <= chunk_blocks) { 24214158570d3995008dc93a628004118b87a6bca01Alex Deymo // If the operations have the same type (which is a type that we can 24314158570d3995008dc93a628004118b87a6bca01Alex Deymo // merge), are contiguous, are fragmented to have one destination extent, 24414158570d3995008dc93a628004118b87a6bca01Alex Deymo // and their combined block count would be less than chunk size, merge 24514158570d3995008dc93a628004118b87a6bca01Alex Deymo // them. 24614158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.name = base::StringPrintf("%s,%s", 24714158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.name.c_str(), 24814158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.name.c_str()); 24914158570d3995008dc93a628004118b87a6bca01Alex Deymo 25014158570d3995008dc93a628004118b87a6bca01Alex Deymo ExtendExtents(last_aop.op.mutable_src_extents(), 25114158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.src_extents()); 25214158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_aop.op.src_length() > 0) 25314158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.set_src_length(last_aop.op.src_length() + 25414158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.src_length()); 25514158570d3995008dc93a628004118b87a6bca01Alex Deymo ExtendExtents(last_aop.op.mutable_dst_extents(), 25614158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.dst_extents()); 25714158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_aop.op.dst_length() > 0) 25814158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.set_dst_length(last_aop.op.dst_length() + 25914158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.dst_length()); 26014158570d3995008dc93a628004118b87a6bca01Alex Deymo // Set the data length to zero so we know to add the blob later. 26114158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_aop.op.type() == 26214158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE || 26314158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.type() == 26414158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) { 26514158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.set_data_length(0); 26614158570d3995008dc93a628004118b87a6bca01Alex Deymo } 26714158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 26814158570d3995008dc93a628004118b87a6bca01Alex Deymo // Otherwise just include the extent as is. 26914158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aops.push_back(curr_aop); 27014158570d3995008dc93a628004118b87a6bca01Alex Deymo } 27114158570d3995008dc93a628004118b87a6bca01Alex Deymo } 27214158570d3995008dc93a628004118b87a6bca01Alex Deymo 27314158570d3995008dc93a628004118b87a6bca01Alex Deymo // Set the blobs for REPLACE/REPLACE_BZ operations that have been merged. 27414158570d3995008dc93a628004118b87a6bca01Alex Deymo for (AnnotatedOperation& curr_aop : new_aops) { 27514158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_aop.op.data_length() == 0 && 27614158570d3995008dc93a628004118b87a6bca01Alex Deymo (curr_aop.op.type() == 27714158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE || 27814158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.type() == 27914158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ)) { 28014158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(AddDataAndSetType(&curr_aop, target_part_path, 2818cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 28214158570d3995008dc93a628004118b87a6bca01Alex Deymo } 28314158570d3995008dc93a628004118b87a6bca01Alex Deymo } 28414158570d3995008dc93a628004118b87a6bca01Alex Deymo 28514158570d3995008dc93a628004118b87a6bca01Alex Deymo *aops = new_aops; 28614158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 28714158570d3995008dc93a628004118b87a6bca01Alex Deymo} 28814158570d3995008dc93a628004118b87a6bca01Alex Deymo 28914158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::AddDataAndSetType(AnnotatedOperation* aop, 29014158570d3995008dc93a628004118b87a6bca01Alex Deymo const string& target_part_path, 2918cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file) { 29214158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE( 29314158570d3995008dc93a628004118b87a6bca01Alex Deymo aop->op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE || 29414158570d3995008dc93a628004118b87a6bca01Alex Deymo aop->op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ); 29514158570d3995008dc93a628004118b87a6bca01Alex Deymo 29614158570d3995008dc93a628004118b87a6bca01Alex Deymo chromeos::Blob data(aop->op.dst_length()); 29714158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<Extent> dst_extents; 29814158570d3995008dc93a628004118b87a6bca01Alex Deymo ExtentsToVector(aop->op.dst_extents(), &dst_extents); 29914158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(utils::ReadExtents(target_part_path, 30014158570d3995008dc93a628004118b87a6bca01Alex Deymo dst_extents, 30114158570d3995008dc93a628004118b87a6bca01Alex Deymo &data, 30214158570d3995008dc93a628004118b87a6bca01Alex Deymo data.size(), 30314158570d3995008dc93a628004118b87a6bca01Alex Deymo kBlockSize)); 30414158570d3995008dc93a628004118b87a6bca01Alex Deymo 30514158570d3995008dc93a628004118b87a6bca01Alex Deymo chromeos::Blob data_bz; 30614158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(BzipCompress(data, &data_bz)); 30714158570d3995008dc93a628004118b87a6bca01Alex Deymo CHECK(!data_bz.empty()); 30814158570d3995008dc93a628004118b87a6bca01Alex Deymo 30914158570d3995008dc93a628004118b87a6bca01Alex Deymo chromeos::Blob* data_p = nullptr; 31014158570d3995008dc93a628004118b87a6bca01Alex Deymo DeltaArchiveManifest_InstallOperation_Type new_op_type; 31114158570d3995008dc93a628004118b87a6bca01Alex Deymo if (data_bz.size() < data.size()) { 31214158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op_type = DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ; 31314158570d3995008dc93a628004118b87a6bca01Alex Deymo data_p = &data_bz; 31414158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 31514158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op_type = DeltaArchiveManifest_InstallOperation_Type_REPLACE; 31614158570d3995008dc93a628004118b87a6bca01Alex Deymo data_p = &data; 31714158570d3995008dc93a628004118b87a6bca01Alex Deymo } 31814158570d3995008dc93a628004118b87a6bca01Alex Deymo 3198cc502dacbccdab96824d42287f230ce04004784Sen Jiang // If the operation doesn't point to a data blob, then we add it. 3208cc502dacbccdab96824d42287f230ce04004784Sen Jiang if (aop->op.type() != new_op_type || 3218cc502dacbccdab96824d42287f230ce04004784Sen Jiang aop->op.data_length() != data_p->size()) { 32214158570d3995008dc93a628004118b87a6bca01Alex Deymo aop->op.set_type(new_op_type); 3238cc502dacbccdab96824d42287f230ce04004784Sen Jiang aop->SetOperationBlob(data_p, blob_file); 32414158570d3995008dc93a628004118b87a6bca01Alex Deymo } 32514158570d3995008dc93a628004118b87a6bca01Alex Deymo 32614158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 32714158570d3995008dc93a628004118b87a6bca01Alex Deymo} 32814158570d3995008dc93a628004118b87a6bca01Alex Deymo 32914158570d3995008dc93a628004118b87a6bca01Alex Deymo} // namespace chromeos_update_engine 330