ab_generator.cc revision abdc0115548985d8ca3f3f2aeb1283741ce409a6
1773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// 2773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// Copyright (C) 2015 The Android Open Source Project 3773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// 4773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// Licensed under the Apache License, Version 2.0 (the "License"); 5773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// you may not use this file except in compliance with the License. 6773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// You may obtain a copy of the License at 7773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// 8773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// http://www.apache.org/licenses/LICENSE-2.0 9773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// 10773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// Unless required by applicable law or agreed to in writing, software 11773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// distributed under the License is distributed on an "AS IS" BASIS, 12773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// See the License for the specific language governing permissions and 14773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// limitations under the License. 15773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi// 16773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi 17daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten#include "update_engine/payload_generator/ab_generator.h" 18f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi 1975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi#include <algorithm> 20773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi 21a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten#include <base/strings/stringprintf.h> 22a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten 2375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi#include "update_engine/delta_performer.h" 241ae30e37f39fcfe7937a707b789e49a7d68112baJean-Michel Trivi#include "update_engine/payload_generator/annotated_operation.h" 2505ccff2aaa3e1507cdc7ab3b244c973c6708e009Jean-Michel Trivi#include "update_engine/payload_generator/bzip.h" 26a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#include "update_engine/payload_generator/delta_diff_generator.h" 27a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#include "update_engine/payload_generator/delta_diff_utils.h" 28a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#include "update_engine/utils.h" 29a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi 30a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Triviusing std::string; 31a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Triviusing std::vector; 32a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi 33a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivinamespace chromeos_update_engine { 34a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi 35a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivibool ABGenerator::GenerateOperations( 36a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi const PayloadGenerationConfig& config, 37a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi const PartitionConfig& old_part, 38a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi const PartitionConfig& new_part, 39a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi BlobFileWriter* blob_file, 40a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi vector<AnnotatedOperation>* aops) { 41a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi TEST_AND_RETURN_FALSE(old_part.name == new_part.name); 42a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi 43a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi ssize_t hard_chunk_blocks = (config.hard_chunk_size == -1 ? -1 : 44a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi config.hard_chunk_size / config.block_size); 45a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi size_t soft_chunk_blocks = config.soft_chunk_size / config.block_size; 46a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi 476a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi aops->clear(); 486a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi TEST_AND_RETURN_FALSE(diff_utils::DeltaReadPartition( 49712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi aops, 50712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi old_part, 511fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi new_part, 521fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi hard_chunk_blocks, 536a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi soft_chunk_blocks, 54d739e18bea1deaf7c487f99a512c0ae7649615c2Jean-Michel Trivi blob_file, 556a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi true)); // src_ops_allowed 566a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi LOG(INFO) << "done reading " << new_part.name; 574614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi 584614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi TEST_AND_RETURN_FALSE(FragmentOperations(aops, 5945d40b8ac4cd8f3f73813a26334c7e5ecc3cb73cJean-Michel Trivi new_part.path, 601fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi blob_file)); 611fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi SortOperationsByDestination(aops); 621fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi 631fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi // Use the soft_chunk_size when merging operations to prevent merging all 644614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi // the operations into a huge one if there's no hard limit. 651fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi size_t merge_chunk_blocks = soft_chunk_blocks; 661fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi if (hard_chunk_blocks != -1 && 671fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi static_cast<size_t>(hard_chunk_blocks) < soft_chunk_blocks) { 681fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi merge_chunk_blocks = hard_chunk_blocks; 691fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi } 70e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten 71b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten TEST_AND_RETURN_FALSE(MergeOperations(aops, 721fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi merge_chunk_blocks, 731fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi new_part.path, 741fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi blob_file)); 751fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi return true; 76b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten} 771fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi 781fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivivoid ABGenerator::SortOperationsByDestination( 791fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi vector<AnnotatedOperation>* aops) { 801fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi sort(aops->begin(), aops->end(), diff_utils::CompareAopsByDestination); 81b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten} 821fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi 831fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivibool ABGenerator::FragmentOperations( 841fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi vector<AnnotatedOperation>* aops, 851fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi const string& target_part_path, 861fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi BlobFileWriter* blob_file) { 871fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi vector<AnnotatedOperation> fragmented_aops; 881fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi for (const AnnotatedOperation& aop : *aops) { 891fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi if (aop.op.type() == InstallOperation::SOURCE_COPY) { 901fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi TEST_AND_RETURN_FALSE(SplitSourceCopy(aop, &fragmented_aops)); 91b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten } else if ((aop.op.type() == InstallOperation::REPLACE) || 921fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi (aop.op.type() == InstallOperation::REPLACE_BZ)) { 931fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi TEST_AND_RETURN_FALSE(SplitReplaceOrReplaceBz(aop, &fragmented_aops, 941fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi target_part_path, 951fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi blob_file)); 96b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten } else { 971fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi fragmented_aops.push_back(aop); 981fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi } 991fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi } 1001fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi *aops = fragmented_aops; 101b91e32605ecf39e34ad39936b1ee193bb4e30225Glenn Kasten return true; 1021fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi} 1031fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi 1041fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivibool ABGenerator::SplitSourceCopy( 1051fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi const AnnotatedOperation& original_aop, 1061fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi vector<AnnotatedOperation>* result_aops) { 1071fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi InstallOperation original_op = original_aop.op; 1081fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi TEST_AND_RETURN_FALSE(original_op.type() == InstallOperation::SOURCE_COPY); 1091fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi // Keeps track of the index of curr_src_ext. 1101fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi int curr_src_ext_index = 0; 1116a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi Extent curr_src_ext = original_op.src_extents(curr_src_ext_index); 1126a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi for (int i = 0; i < original_op.dst_extents_size(); i++) { 113172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi Extent dst_ext = original_op.dst_extents(i); 114172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi // The new operation which will have only one dst extent. 115ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi InstallOperation new_op; 116172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi uint64_t blocks_left = dst_ext.num_blocks(); 117172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi while (blocks_left > 0) { 118a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi if (curr_src_ext.num_blocks() <= blocks_left) { 119f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi // If the curr_src_ext is smaller than dst_ext, add it. 1201fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi blocks_left -= curr_src_ext.num_blocks(); 121f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi *(new_op.add_src_extents()) = curr_src_ext; 12245d40b8ac4cd8f3f73813a26334c7e5ecc3cb73cJean-Michel Trivi if (curr_src_ext_index + 1 < original_op.src_extents().size()) { 123f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi curr_src_ext = original_op.src_extents(++curr_src_ext_index); 1241fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi } else { 125e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten break; 126e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten } 127f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi } else { 128f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi // Split src_exts that are bigger than the dst_ext we're dealing with. 1291fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi Extent first_ext; 130e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten first_ext.set_num_blocks(blocks_left); 131e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten first_ext.set_start_block(curr_src_ext.start_block()); 1326a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi *(new_op.add_src_extents()) = first_ext; 133e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten // Keep the second half of the split op. 134e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten curr_src_ext.set_num_blocks(curr_src_ext.num_blocks() - blocks_left); 1356a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi curr_src_ext.set_start_block(curr_src_ext.start_block() + blocks_left); 1366a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi blocks_left -= first_ext.num_blocks(); 137e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten } 138e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten } 139f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi // Fix up our new operation and add it to the results. 140f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi new_op.set_type(InstallOperation::SOURCE_COPY); 1411fec6cc920db52e63c67eafd2034e52b8eb5780dJean-Michel Trivi *(new_op.add_dst_extents()) = dst_ext; 142ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi new_op.set_src_length(dst_ext.num_blocks() * kBlockSize); 143ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi new_op.set_dst_length(dst_ext.num_blocks() * kBlockSize); 144ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi 145ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi AnnotatedOperation new_aop; 146ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi new_aop.op = new_op; 147ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi new_aop.name = base::StringPrintf("%s:%d", original_aop.name.c_str(), i); 148ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi result_aops->push_back(new_aop); 149ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi } 150ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi if (curr_src_ext_index != original_op.src_extents().size() - 1) { 151ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi LOG(FATAL) << "Incorrectly split SOURCE_COPY operation. Did not use all " 152ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi << "source extents."; 153ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi } 154ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi return true; 155ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi} 156ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi 157ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivibool ABGenerator::SplitReplaceOrReplaceBz( 158ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi const AnnotatedOperation& original_aop, 1594614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi vector<AnnotatedOperation>* result_aops, 1604614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi const string& target_part_path, 1614614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi BlobFileWriter* blob_file) { 162e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi InstallOperation original_op = original_aop.op; 16349e4076e940559bc204d0f0aa7ab412986445bfaGlenn Kasten const bool is_replace = original_op.type() == InstallOperation::REPLACE; 1644614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi TEST_AND_RETURN_FALSE(is_replace || 1654614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi original_op.type() == InstallOperation::REPLACE_BZ); 1664614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi 1674614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi uint32_t data_offset = original_op.data_offset(); 1684614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi for (int i = 0; i < original_op.dst_extents_size(); i++) { 1694614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi Extent dst_ext = original_op.dst_extents(i); 1704614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi // Make a new operation with only one dst extent. 1714614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi InstallOperation new_op; 1724614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi *(new_op.add_dst_extents()) = dst_ext; 1734614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi uint32_t data_size = dst_ext.num_blocks() * kBlockSize; 1744614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi new_op.set_dst_length(data_size); 1754614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi // If this is a REPLACE, attempt to reuse portions of the existing blob. 1764614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi if (is_replace) { 1774614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi new_op.set_type(InstallOperation::REPLACE); 1784614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi new_op.set_data_length(data_size); 179e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi new_op.set_data_offset(data_offset); 18049e4076e940559bc204d0f0aa7ab412986445bfaGlenn Kasten data_offset += data_size; 1814614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi } 1824614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi 1834614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi AnnotatedOperation new_aop; 1844614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi new_aop.op = new_op; 1854614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi new_aop.name = base::StringPrintf("%s:%d", original_aop.name.c_str(), i); 1864614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi TEST_AND_RETURN_FALSE(AddDataAndSetType(&new_aop, target_part_path, 1874614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi blob_file)); 1884614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi 1894614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi result_aops->push_back(new_aop); 1904614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi } 1914614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi return true; 1924614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi} 1934614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi 1944614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivibool ABGenerator::MergeOperations(vector<AnnotatedOperation>* aops, 1954614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi size_t chunk_blocks, 1964614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi const string& target_part_path, 197e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi BlobFileWriter* blob_file) { 1984614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi vector<AnnotatedOperation> new_aops; 1994614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi for (const AnnotatedOperation& curr_aop : *aops) { 2004614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi if (new_aops.empty()) { 2014614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi new_aops.push_back(curr_aop); 2024614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi continue; 2034614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi } 2044614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi AnnotatedOperation& last_aop = new_aops.back(); 2054614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi 2064614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi if (last_aop.op.dst_extents_size() <= 0 || 2074614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi curr_aop.op.dst_extents_size() <= 0) { 2084614bf6ff570bc1593e07f796d2d8d28c6424c50Jean-Michel Trivi new_aops.push_back(curr_aop); 209f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi continue; 210f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi } 211f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi uint32_t last_dst_idx = last_aop.op.dst_extents_size() - 1; 21224430c9070298f12e68b84c921add38da6ad0490Jean-Michel Trivi uint32_t last_end_block = 213e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi last_aop.op.dst_extents(last_dst_idx).start_block() + 214e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi last_aop.op.dst_extents(last_dst_idx).num_blocks(); 215e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi uint32_t curr_start_block = curr_aop.op.dst_extents(0).start_block(); 216e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi uint32_t combined_block_count = 217e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi last_aop.op.dst_extents(last_dst_idx).num_blocks() + 218e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi curr_aop.op.dst_extents(0).num_blocks(); 219e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi bool good_op_type = curr_aop.op.type() == InstallOperation::SOURCE_COPY || 220e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi curr_aop.op.type() == InstallOperation::REPLACE || 221e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi curr_aop.op.type() == InstallOperation::REPLACE_BZ; 222e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi if (good_op_type && 223e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi last_aop.op.type() == curr_aop.op.type() && 224e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi last_end_block == curr_start_block && 225e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi combined_block_count <= chunk_blocks) { 226e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi // If the operations have the same type (which is a type that we can 227fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten // merge), are contiguous, are fragmented to have one destination extent, 228fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten // and their combined block count would be less than chunk size, merge 22925d7efb86cd78b868afef12a30ef557f91d97552Jean-Michel Trivi // them. 23025d7efb86cd78b868afef12a30ef557f91d97552Jean-Michel Trivi last_aop.name = base::StringPrintf("%s,%s", 231e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi last_aop.name.c_str(), 232e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi curr_aop.name.c_str()); 233e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi 234fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten ExtendExtents(last_aop.op.mutable_src_extents(), 235ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi curr_aop.op.src_extents()); 236fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten if (curr_aop.op.src_length() > 0) 237e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi last_aop.op.set_src_length(last_aop.op.src_length() + 238e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi curr_aop.op.src_length()); 239e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi ExtendExtents(last_aop.op.mutable_dst_extents(), 240e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi curr_aop.op.dst_extents()); 24125d7efb86cd78b868afef12a30ef557f91d97552Jean-Michel Trivi if (curr_aop.op.dst_length() > 0) 242ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi last_aop.op.set_dst_length(last_aop.op.dst_length() + 243ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi curr_aop.op.dst_length()); 244ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi // Set the data length to zero so we know to add the blob later. 245ca98a6831e18865542985b7cc97da25708b54b9cJean-Michel Trivi if (curr_aop.op.type() == InstallOperation::REPLACE || 246fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten curr_aop.op.type() == InstallOperation::REPLACE_BZ) { 247e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi last_aop.op.set_data_length(0); 248e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi } 249e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi } else { 250e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi // Otherwise just include the extent as is. 25125d7efb86cd78b868afef12a30ef557f91d97552Jean-Michel Trivi new_aops.push_back(curr_aop); 252e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi } 253e8c5f1974de23ca3e0a2a41a8f2bda35b554290fJean-Michel Trivi } 254a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi 255a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi // Set the blobs for REPLACE/REPLACE_BZ operations that have been merged. 256a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi for (AnnotatedOperation& curr_aop : new_aops) { 257a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi if (curr_aop.op.data_length() == 0 && 258a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi (curr_aop.op.type() == InstallOperation::REPLACE || 259a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi curr_aop.op.type() == InstallOperation::REPLACE_BZ)) { 260a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi TEST_AND_RETURN_FALSE(AddDataAndSetType(&curr_aop, target_part_path, 261a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi blob_file)); 262a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi } 263fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten } 264fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten 265a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi *aops = new_aops; 266a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi return true; 267a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi} 268fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten 269fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kastenbool ABGenerator::AddDataAndSetType(AnnotatedOperation* aop, 270fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten const string& target_part_path, 271a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi BlobFileWriter* blob_file) { 272a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi TEST_AND_RETURN_FALSE(aop->op.type() == InstallOperation::REPLACE || 273a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi aop->op.type() == InstallOperation::REPLACE_BZ); 274a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi 275a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi brillo::Blob data(aop->op.dst_length()); 276a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi vector<Extent> dst_extents; 277a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi ExtentsToVector(aop->op.dst_extents(), &dst_extents); 278a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi TEST_AND_RETURN_FALSE(utils::ReadExtents(target_part_path, 279a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi dst_extents, 280fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten &data, 281fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten data.size(), 282fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten kBlockSize)); 283a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi 284a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi brillo::Blob data_bz; 285a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi TEST_AND_RETURN_FALSE(BzipCompress(data, &data_bz)); 286a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi CHECK(!data_bz.empty()); 287a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi 288a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi brillo::Blob* data_p = nullptr; 289a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi InstallOperation_Type new_op_type; 290a05622c974763d8ca038f3d39743c926309ab2c2Jean-Michel Trivi if (data_bz.size() < data.size()) { 291f8acf4b469cdc9d2fe08fb7f6ca007365efc8bc1Jean-Michel Trivi new_op_type = InstallOperation::REPLACE_BZ; 29275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi data_p = &data_bz; 29375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi } else { 29475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi new_op_type = InstallOperation::REPLACE; 29575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi data_p = &data; 29675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi } 29775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi 29875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi // If the operation doesn't point to a data blob, then we add it. 29975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi if (aop->op.type() != new_op_type || 30075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi aop->op.data_length() != data_p->size()) { 30175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi aop->op.set_type(new_op_type); 30275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi aop->SetOperationBlob(data_p, blob_file); 30375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi } 30475e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi 30575e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi return true; 30675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi} 30775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi 30875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi} // namespace chromeos_update_engine 30975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi