ab_generator.cc revision 38818fbf1f2f937051b5bcc01ff74539a3c9b27d
1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2015 The Android Open Source Project 3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License. 6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at 7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software 11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and 14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License. 15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 1614158570d3995008dc93a628004118b87a6bca01Alex Deymo 1714158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/payload_generator/ab_generator.h" 1814158570d3995008dc93a628004118b87a6bca01Alex Deymo 1914158570d3995008dc93a628004118b87a6bca01Alex Deymo#include <algorithm> 2014158570d3995008dc93a628004118b87a6bca01Alex Deymo 2114158570d3995008dc93a628004118b87a6bca01Alex Deymo#include <base/strings/stringprintf.h> 2214158570d3995008dc93a628004118b87a6bca01Alex Deymo 2339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/hash_calculator.h" 2439910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h" 2539910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/payload_constants.h" 2614158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/payload_generator/annotated_operation.h" 27abdc0115548985d8ca3f3f2aeb1283741ce409a6Alex Deymo#include "update_engine/payload_generator/bzip.h" 2814158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/payload_generator/delta_diff_generator.h" 2914158570d3995008dc93a628004118b87a6bca01Alex Deymo#include "update_engine/payload_generator/delta_diff_utils.h" 3014158570d3995008dc93a628004118b87a6bca01Alex Deymo 3114158570d3995008dc93a628004118b87a6bca01Alex Deymousing std::string; 3214158570d3995008dc93a628004118b87a6bca01Alex Deymousing std::vector; 3314158570d3995008dc93a628004118b87a6bca01Alex Deymo 3414158570d3995008dc93a628004118b87a6bca01Alex Deymonamespace chromeos_update_engine { 3514158570d3995008dc93a628004118b87a6bca01Alex Deymo 3614158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::GenerateOperations( 3714158570d3995008dc93a628004118b87a6bca01Alex Deymo const PayloadGenerationConfig& config, 38ebdf17d4202c67933764135bfc1cece629829201Sen Jiang const PartitionConfig& old_part, 39ebdf17d4202c67933764135bfc1cece629829201Sen Jiang const PartitionConfig& new_part, 408cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file, 41ebdf17d4202c67933764135bfc1cece629829201Sen Jiang vector<AnnotatedOperation>* aops) { 42625406cee9a90ac2ed895f480286b7f0e8497f38Sen Jiang TEST_AND_RETURN_FALSE(old_part.name == new_part.name); 4314158570d3995008dc93a628004118b87a6bca01Alex Deymo 442d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo ssize_t hard_chunk_blocks = (config.hard_chunk_size == -1 ? -1 : 452d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo config.hard_chunk_size / config.block_size); 462d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo size_t soft_chunk_blocks = config.soft_chunk_size / config.block_size; 4714158570d3995008dc93a628004118b87a6bca01Alex Deymo 48ebdf17d4202c67933764135bfc1cece629829201Sen Jiang aops->clear(); 4938818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo TEST_AND_RETURN_FALSE(diff_utils::DeltaReadPartition(aops, 5038818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo old_part, 5138818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo new_part, 5238818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo hard_chunk_blocks, 5338818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo soft_chunk_blocks, 5438818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo config.version, 5538818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo blob_file)); 56625406cee9a90ac2ed895f480286b7f0e8497f38Sen Jiang LOG(INFO) << "done reading " << new_part.name; 5714158570d3995008dc93a628004118b87a6bca01Alex Deymo 58ebdf17d4202c67933764135bfc1cece629829201Sen Jiang TEST_AND_RETURN_FALSE(FragmentOperations(aops, 59ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part.path, 608cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 61ebdf17d4202c67933764135bfc1cece629829201Sen Jiang SortOperationsByDestination(aops); 622d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo 632d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo // Use the soft_chunk_size when merging operations to prevent merging all 642d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo // the operations into a huge one if there's no hard limit. 652d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo size_t merge_chunk_blocks = soft_chunk_blocks; 662d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo if (hard_chunk_blocks != -1 && 672d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo static_cast<size_t>(hard_chunk_blocks) < soft_chunk_blocks) { 682d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo merge_chunk_blocks = hard_chunk_blocks; 692d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo } 702d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo 71ebdf17d4202c67933764135bfc1cece629829201Sen Jiang TEST_AND_RETURN_FALSE(MergeOperations(aops, 722d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo merge_chunk_blocks, 73ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part.path, 748cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 7582352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang 7638818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo if (config.version.minor >= kOpSrcHashMinorPayloadVersion) 7782352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang TEST_AND_RETURN_FALSE(AddSourceHash(aops, old_part.path)); 7882352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang 7914158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 8014158570d3995008dc93a628004118b87a6bca01Alex Deymo} 8114158570d3995008dc93a628004118b87a6bca01Alex Deymo 8214158570d3995008dc93a628004118b87a6bca01Alex Deymovoid ABGenerator::SortOperationsByDestination( 8314158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* aops) { 843b2c7d0e6d859e6fc75c82b3417f87cf5968a49dAlex Deymo sort(aops->begin(), aops->end(), diff_utils::CompareAopsByDestination); 8514158570d3995008dc93a628004118b87a6bca01Alex Deymo} 8614158570d3995008dc93a628004118b87a6bca01Alex Deymo 8714158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::FragmentOperations( 8814158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* aops, 8914158570d3995008dc93a628004118b87a6bca01Alex Deymo const string& target_part_path, 908cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file) { 9114158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation> fragmented_aops; 9214158570d3995008dc93a628004118b87a6bca01Alex Deymo for (const AnnotatedOperation& aop : *aops) { 93a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo if (aop.op.type() == InstallOperation::SOURCE_COPY) { 9414158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(SplitSourceCopy(aop, &fragmented_aops)); 95a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo } else if ((aop.op.type() == InstallOperation::REPLACE) || 96a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo (aop.op.type() == InstallOperation::REPLACE_BZ)) { 9714158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(SplitReplaceOrReplaceBz(aop, &fragmented_aops, 988cc502dacbccdab96824d42287f230ce04004784Sen Jiang target_part_path, 998cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 10014158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 10114158570d3995008dc93a628004118b87a6bca01Alex Deymo fragmented_aops.push_back(aop); 10214158570d3995008dc93a628004118b87a6bca01Alex Deymo } 10314158570d3995008dc93a628004118b87a6bca01Alex Deymo } 10414158570d3995008dc93a628004118b87a6bca01Alex Deymo *aops = fragmented_aops; 10514158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 10614158570d3995008dc93a628004118b87a6bca01Alex Deymo} 10714158570d3995008dc93a628004118b87a6bca01Alex Deymo 10814158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::SplitSourceCopy( 10914158570d3995008dc93a628004118b87a6bca01Alex Deymo const AnnotatedOperation& original_aop, 11014158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* result_aops) { 111a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo InstallOperation original_op = original_aop.op; 112a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo TEST_AND_RETURN_FALSE(original_op.type() == InstallOperation::SOURCE_COPY); 11314158570d3995008dc93a628004118b87a6bca01Alex Deymo // Keeps track of the index of curr_src_ext. 11414158570d3995008dc93a628004118b87a6bca01Alex Deymo int curr_src_ext_index = 0; 11514158570d3995008dc93a628004118b87a6bca01Alex Deymo Extent curr_src_ext = original_op.src_extents(curr_src_ext_index); 11614158570d3995008dc93a628004118b87a6bca01Alex Deymo for (int i = 0; i < original_op.dst_extents_size(); i++) { 11714158570d3995008dc93a628004118b87a6bca01Alex Deymo Extent dst_ext = original_op.dst_extents(i); 11814158570d3995008dc93a628004118b87a6bca01Alex Deymo // The new operation which will have only one dst extent. 119a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo InstallOperation new_op; 12014158570d3995008dc93a628004118b87a6bca01Alex Deymo uint64_t blocks_left = dst_ext.num_blocks(); 12114158570d3995008dc93a628004118b87a6bca01Alex Deymo while (blocks_left > 0) { 12214158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_src_ext.num_blocks() <= blocks_left) { 12314158570d3995008dc93a628004118b87a6bca01Alex Deymo // If the curr_src_ext is smaller than dst_ext, add it. 12414158570d3995008dc93a628004118b87a6bca01Alex Deymo blocks_left -= curr_src_ext.num_blocks(); 12514158570d3995008dc93a628004118b87a6bca01Alex Deymo *(new_op.add_src_extents()) = curr_src_ext; 12614158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_src_ext_index + 1 < original_op.src_extents().size()) { 12714158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_src_ext = original_op.src_extents(++curr_src_ext_index); 12814158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 12914158570d3995008dc93a628004118b87a6bca01Alex Deymo break; 13014158570d3995008dc93a628004118b87a6bca01Alex Deymo } 13114158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 13214158570d3995008dc93a628004118b87a6bca01Alex Deymo // Split src_exts that are bigger than the dst_ext we're dealing with. 13314158570d3995008dc93a628004118b87a6bca01Alex Deymo Extent first_ext; 13414158570d3995008dc93a628004118b87a6bca01Alex Deymo first_ext.set_num_blocks(blocks_left); 13514158570d3995008dc93a628004118b87a6bca01Alex Deymo first_ext.set_start_block(curr_src_ext.start_block()); 13614158570d3995008dc93a628004118b87a6bca01Alex Deymo *(new_op.add_src_extents()) = first_ext; 13714158570d3995008dc93a628004118b87a6bca01Alex Deymo // Keep the second half of the split op. 13814158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_src_ext.set_num_blocks(curr_src_ext.num_blocks() - blocks_left); 13914158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_src_ext.set_start_block(curr_src_ext.start_block() + blocks_left); 14014158570d3995008dc93a628004118b87a6bca01Alex Deymo blocks_left -= first_ext.num_blocks(); 14114158570d3995008dc93a628004118b87a6bca01Alex Deymo } 14214158570d3995008dc93a628004118b87a6bca01Alex Deymo } 14314158570d3995008dc93a628004118b87a6bca01Alex Deymo // Fix up our new operation and add it to the results. 144a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo new_op.set_type(InstallOperation::SOURCE_COPY); 14514158570d3995008dc93a628004118b87a6bca01Alex Deymo *(new_op.add_dst_extents()) = dst_ext; 14614158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_src_length(dst_ext.num_blocks() * kBlockSize); 14714158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_dst_length(dst_ext.num_blocks() * kBlockSize); 14814158570d3995008dc93a628004118b87a6bca01Alex Deymo 14914158570d3995008dc93a628004118b87a6bca01Alex Deymo AnnotatedOperation new_aop; 15014158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aop.op = new_op; 15114158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aop.name = base::StringPrintf("%s:%d", original_aop.name.c_str(), i); 15214158570d3995008dc93a628004118b87a6bca01Alex Deymo result_aops->push_back(new_aop); 15314158570d3995008dc93a628004118b87a6bca01Alex Deymo } 15414158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_src_ext_index != original_op.src_extents().size() - 1) { 15514158570d3995008dc93a628004118b87a6bca01Alex Deymo LOG(FATAL) << "Incorrectly split SOURCE_COPY operation. Did not use all " 15614158570d3995008dc93a628004118b87a6bca01Alex Deymo << "source extents."; 15714158570d3995008dc93a628004118b87a6bca01Alex Deymo } 15814158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 15914158570d3995008dc93a628004118b87a6bca01Alex Deymo} 16014158570d3995008dc93a628004118b87a6bca01Alex Deymo 16114158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::SplitReplaceOrReplaceBz( 16214158570d3995008dc93a628004118b87a6bca01Alex Deymo const AnnotatedOperation& original_aop, 16314158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation>* result_aops, 16414158570d3995008dc93a628004118b87a6bca01Alex Deymo const string& target_part_path, 1658cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file) { 166a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo InstallOperation original_op = original_aop.op; 167a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo const bool is_replace = original_op.type() == InstallOperation::REPLACE; 168a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo TEST_AND_RETURN_FALSE(is_replace || 169a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo original_op.type() == InstallOperation::REPLACE_BZ); 17014158570d3995008dc93a628004118b87a6bca01Alex Deymo 17114158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t data_offset = original_op.data_offset(); 17214158570d3995008dc93a628004118b87a6bca01Alex Deymo for (int i = 0; i < original_op.dst_extents_size(); i++) { 17314158570d3995008dc93a628004118b87a6bca01Alex Deymo Extent dst_ext = original_op.dst_extents(i); 17414158570d3995008dc93a628004118b87a6bca01Alex Deymo // Make a new operation with only one dst extent. 175a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo InstallOperation new_op; 17614158570d3995008dc93a628004118b87a6bca01Alex Deymo *(new_op.add_dst_extents()) = dst_ext; 17714158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t data_size = dst_ext.num_blocks() * kBlockSize; 17814158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_dst_length(data_size); 17914158570d3995008dc93a628004118b87a6bca01Alex Deymo // If this is a REPLACE, attempt to reuse portions of the existing blob. 18014158570d3995008dc93a628004118b87a6bca01Alex Deymo if (is_replace) { 181a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo new_op.set_type(InstallOperation::REPLACE); 18214158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_data_length(data_size); 18314158570d3995008dc93a628004118b87a6bca01Alex Deymo new_op.set_data_offset(data_offset); 18414158570d3995008dc93a628004118b87a6bca01Alex Deymo data_offset += data_size; 18514158570d3995008dc93a628004118b87a6bca01Alex Deymo } 18614158570d3995008dc93a628004118b87a6bca01Alex Deymo 18714158570d3995008dc93a628004118b87a6bca01Alex Deymo AnnotatedOperation new_aop; 18814158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aop.op = new_op; 18914158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aop.name = base::StringPrintf("%s:%d", original_aop.name.c_str(), i); 1908cc502dacbccdab96824d42287f230ce04004784Sen Jiang TEST_AND_RETURN_FALSE(AddDataAndSetType(&new_aop, target_part_path, 1918cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 19214158570d3995008dc93a628004118b87a6bca01Alex Deymo 19314158570d3995008dc93a628004118b87a6bca01Alex Deymo result_aops->push_back(new_aop); 19414158570d3995008dc93a628004118b87a6bca01Alex Deymo } 19514158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 19614158570d3995008dc93a628004118b87a6bca01Alex Deymo} 19714158570d3995008dc93a628004118b87a6bca01Alex Deymo 19814158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::MergeOperations(vector<AnnotatedOperation>* aops, 1992d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo size_t chunk_blocks, 20014158570d3995008dc93a628004118b87a6bca01Alex Deymo const string& target_part_path, 2018cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file) { 20214158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<AnnotatedOperation> new_aops; 20314158570d3995008dc93a628004118b87a6bca01Alex Deymo for (const AnnotatedOperation& curr_aop : *aops) { 20414158570d3995008dc93a628004118b87a6bca01Alex Deymo if (new_aops.empty()) { 20514158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aops.push_back(curr_aop); 20614158570d3995008dc93a628004118b87a6bca01Alex Deymo continue; 20714158570d3995008dc93a628004118b87a6bca01Alex Deymo } 20814158570d3995008dc93a628004118b87a6bca01Alex Deymo AnnotatedOperation& last_aop = new_aops.back(); 20914158570d3995008dc93a628004118b87a6bca01Alex Deymo 21014158570d3995008dc93a628004118b87a6bca01Alex Deymo if (last_aop.op.dst_extents_size() <= 0 || 21114158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.dst_extents_size() <= 0) { 21214158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aops.push_back(curr_aop); 21314158570d3995008dc93a628004118b87a6bca01Alex Deymo continue; 21414158570d3995008dc93a628004118b87a6bca01Alex Deymo } 21514158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t last_dst_idx = last_aop.op.dst_extents_size() - 1; 21614158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t last_end_block = 21714158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.dst_extents(last_dst_idx).start_block() + 21814158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.dst_extents(last_dst_idx).num_blocks(); 21914158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t curr_start_block = curr_aop.op.dst_extents(0).start_block(); 22014158570d3995008dc93a628004118b87a6bca01Alex Deymo uint32_t combined_block_count = 22114158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.dst_extents(last_dst_idx).num_blocks() + 22214158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.dst_extents(0).num_blocks(); 223a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo bool good_op_type = curr_aop.op.type() == InstallOperation::SOURCE_COPY || 224a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo curr_aop.op.type() == InstallOperation::REPLACE || 225a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo curr_aop.op.type() == InstallOperation::REPLACE_BZ; 22614158570d3995008dc93a628004118b87a6bca01Alex Deymo if (good_op_type && 22714158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.type() == curr_aop.op.type() && 22814158570d3995008dc93a628004118b87a6bca01Alex Deymo last_end_block == curr_start_block && 2292d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo combined_block_count <= chunk_blocks) { 23014158570d3995008dc93a628004118b87a6bca01Alex Deymo // If the operations have the same type (which is a type that we can 23114158570d3995008dc93a628004118b87a6bca01Alex Deymo // merge), are contiguous, are fragmented to have one destination extent, 23214158570d3995008dc93a628004118b87a6bca01Alex Deymo // and their combined block count would be less than chunk size, merge 23314158570d3995008dc93a628004118b87a6bca01Alex Deymo // them. 23414158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.name = base::StringPrintf("%s,%s", 23514158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.name.c_str(), 23614158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.name.c_str()); 23714158570d3995008dc93a628004118b87a6bca01Alex Deymo 23814158570d3995008dc93a628004118b87a6bca01Alex Deymo ExtendExtents(last_aop.op.mutable_src_extents(), 23914158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.src_extents()); 24014158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_aop.op.src_length() > 0) 24114158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.set_src_length(last_aop.op.src_length() + 24214158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.src_length()); 24314158570d3995008dc93a628004118b87a6bca01Alex Deymo ExtendExtents(last_aop.op.mutable_dst_extents(), 24414158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.dst_extents()); 24514158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_aop.op.dst_length() > 0) 24614158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.set_dst_length(last_aop.op.dst_length() + 24714158570d3995008dc93a628004118b87a6bca01Alex Deymo curr_aop.op.dst_length()); 24814158570d3995008dc93a628004118b87a6bca01Alex Deymo // Set the data length to zero so we know to add the blob later. 249a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo if (curr_aop.op.type() == InstallOperation::REPLACE || 250a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo curr_aop.op.type() == InstallOperation::REPLACE_BZ) { 25114158570d3995008dc93a628004118b87a6bca01Alex Deymo last_aop.op.set_data_length(0); 25214158570d3995008dc93a628004118b87a6bca01Alex Deymo } 25314158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 25414158570d3995008dc93a628004118b87a6bca01Alex Deymo // Otherwise just include the extent as is. 25514158570d3995008dc93a628004118b87a6bca01Alex Deymo new_aops.push_back(curr_aop); 25614158570d3995008dc93a628004118b87a6bca01Alex Deymo } 25714158570d3995008dc93a628004118b87a6bca01Alex Deymo } 25814158570d3995008dc93a628004118b87a6bca01Alex Deymo 25914158570d3995008dc93a628004118b87a6bca01Alex Deymo // Set the blobs for REPLACE/REPLACE_BZ operations that have been merged. 26014158570d3995008dc93a628004118b87a6bca01Alex Deymo for (AnnotatedOperation& curr_aop : new_aops) { 26114158570d3995008dc93a628004118b87a6bca01Alex Deymo if (curr_aop.op.data_length() == 0 && 262a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo (curr_aop.op.type() == InstallOperation::REPLACE || 263a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo curr_aop.op.type() == InstallOperation::REPLACE_BZ)) { 26414158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(AddDataAndSetType(&curr_aop, target_part_path, 2658cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file)); 26614158570d3995008dc93a628004118b87a6bca01Alex Deymo } 26714158570d3995008dc93a628004118b87a6bca01Alex Deymo } 26814158570d3995008dc93a628004118b87a6bca01Alex Deymo 26914158570d3995008dc93a628004118b87a6bca01Alex Deymo *aops = new_aops; 27014158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 27114158570d3995008dc93a628004118b87a6bca01Alex Deymo} 27214158570d3995008dc93a628004118b87a6bca01Alex Deymo 27314158570d3995008dc93a628004118b87a6bca01Alex Deymobool ABGenerator::AddDataAndSetType(AnnotatedOperation* aop, 27414158570d3995008dc93a628004118b87a6bca01Alex Deymo const string& target_part_path, 2758cc502dacbccdab96824d42287f230ce04004784Sen Jiang BlobFileWriter* blob_file) { 276a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo TEST_AND_RETURN_FALSE(aop->op.type() == InstallOperation::REPLACE || 277a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo aop->op.type() == InstallOperation::REPLACE_BZ); 27814158570d3995008dc93a628004118b87a6bca01Alex Deymo 2793f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob data(aop->op.dst_length()); 28014158570d3995008dc93a628004118b87a6bca01Alex Deymo vector<Extent> dst_extents; 28114158570d3995008dc93a628004118b87a6bca01Alex Deymo ExtentsToVector(aop->op.dst_extents(), &dst_extents); 28214158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(utils::ReadExtents(target_part_path, 28314158570d3995008dc93a628004118b87a6bca01Alex Deymo dst_extents, 28414158570d3995008dc93a628004118b87a6bca01Alex Deymo &data, 28514158570d3995008dc93a628004118b87a6bca01Alex Deymo data.size(), 28614158570d3995008dc93a628004118b87a6bca01Alex Deymo kBlockSize)); 28714158570d3995008dc93a628004118b87a6bca01Alex Deymo 2883f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob data_bz; 28914158570d3995008dc93a628004118b87a6bca01Alex Deymo TEST_AND_RETURN_FALSE(BzipCompress(data, &data_bz)); 29014158570d3995008dc93a628004118b87a6bca01Alex Deymo CHECK(!data_bz.empty()); 29114158570d3995008dc93a628004118b87a6bca01Alex Deymo 2923f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob* data_p = nullptr; 293a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo InstallOperation_Type new_op_type; 29414158570d3995008dc93a628004118b87a6bca01Alex Deymo if (data_bz.size() < data.size()) { 295a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo new_op_type = InstallOperation::REPLACE_BZ; 29614158570d3995008dc93a628004118b87a6bca01Alex Deymo data_p = &data_bz; 29714158570d3995008dc93a628004118b87a6bca01Alex Deymo } else { 298a12ee11c78ac6d7c2605921a4006b6a7416e0c35Alex Deymo new_op_type = InstallOperation::REPLACE; 29914158570d3995008dc93a628004118b87a6bca01Alex Deymo data_p = &data; 30014158570d3995008dc93a628004118b87a6bca01Alex Deymo } 30114158570d3995008dc93a628004118b87a6bca01Alex Deymo 3028cc502dacbccdab96824d42287f230ce04004784Sen Jiang // If the operation doesn't point to a data blob, then we add it. 3038cc502dacbccdab96824d42287f230ce04004784Sen Jiang if (aop->op.type() != new_op_type || 3048cc502dacbccdab96824d42287f230ce04004784Sen Jiang aop->op.data_length() != data_p->size()) { 30514158570d3995008dc93a628004118b87a6bca01Alex Deymo aop->op.set_type(new_op_type); 3068cc502dacbccdab96824d42287f230ce04004784Sen Jiang aop->SetOperationBlob(data_p, blob_file); 30714158570d3995008dc93a628004118b87a6bca01Alex Deymo } 30814158570d3995008dc93a628004118b87a6bca01Alex Deymo 30914158570d3995008dc93a628004118b87a6bca01Alex Deymo return true; 31014158570d3995008dc93a628004118b87a6bca01Alex Deymo} 31114158570d3995008dc93a628004118b87a6bca01Alex Deymo 31282352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiangbool ABGenerator::AddSourceHash(vector<AnnotatedOperation>* aops, 31382352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang const string& source_part_path) { 31482352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang for (AnnotatedOperation& aop : *aops) { 31582352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang if (aop.op.src_extents_size() == 0) 31682352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang continue; 31782352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang 31882352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang vector<Extent> src_extents; 31982352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang ExtentsToVector(aop.op.src_extents(), &src_extents); 32082352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang brillo::Blob src_data, src_hash; 32182352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang uint64_t src_length = 32282352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang aop.op.has_src_length() 32382352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang ? aop.op.src_length() 32482352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang : BlocksInExtents(aop.op.src_extents()) * kBlockSize; 32582352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang TEST_AND_RETURN_FALSE(utils::ReadExtents( 32682352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang source_part_path, src_extents, &src_data, src_length, kBlockSize)); 32739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo TEST_AND_RETURN_FALSE(HashCalculator::RawHashOfData(src_data, &src_hash)); 32882352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size()); 32982352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang } 33082352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang return true; 33182352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang} 33282352f97b4621dbf6af8308ff0b0b17b0968b53aSen Jiang 33314158570d3995008dc93a628004118b87a6bca01Alex Deymo} // namespace chromeos_update_engine 334