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