ab_generator.h revision efa62d959cf8f225477ab85d8ff42d5150007cf8
1//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#ifndef UPDATE_ENGINE_PAYLOAD_GENERATOR_AB_GENERATOR_H_
18#define UPDATE_ENGINE_PAYLOAD_GENERATOR_AB_GENERATOR_H_
19
20#include <string>
21#include <vector>
22
23#include <base/macros.h>
24#include <brillo/secure_blob.h>
25
26#include "update_engine/payload_consumer/payload_constants.h"
27#include "update_engine/payload_generator/blob_file_writer.h"
28#include "update_engine/payload_generator/extent_utils.h"
29#include "update_engine/payload_generator/filesystem_interface.h"
30#include "update_engine/payload_generator/operations_generator.h"
31#include "update_engine/payload_generator/payload_generation_config.h"
32#include "update_engine/update_metadata.pb.h"
33
34namespace chromeos_update_engine {
35
36// The ABGenerator is an operations generator that generates payloads using the
37// A-to-B operations SOURCE_COPY and SOURCE_BSDIFF introduced in the payload
38// minor version 2 format.
39class ABGenerator : public OperationsGenerator {
40 public:
41  ABGenerator() = default;
42
43  // Generate the update payload operations for the given partition using
44  // SOURCE_* operations, used for generating deltas for the minor version
45  // kSourceMinorPayloadVersion. This function will generate operations in the
46  // partition that will read blocks from the source partition in random order
47  // and write the new image on the target partition, also possibly in random
48  // order. The operations are stored in |aops| and should be executed in that
49  // order. All the offsets in the operations reference the data written to
50  // |blob_file|.
51  bool GenerateOperations(
52      const PayloadGenerationConfig& config,
53      const PartitionConfig& old_part,
54      const PartitionConfig& new_part,
55      BlobFileWriter* blob_file,
56      std::vector<AnnotatedOperation>* aops) override;
57
58  // Split the operations in the vector of AnnotatedOperations |aops| such that
59  // for every operation there is only one dst extent and updates |aops| with
60  // the new list of operations. All kinds of operations are fragmented except
61  // BSDIFF and SOURCE_BSDIFF, PUFFDIFF and BROTLI_BSDIFF operations.  The
62  // |target_part_path| is the filename of the new image, where the destination
63  // extents refer to. The blobs of the operations in |aops| should reference
64  // |blob_file|. |blob_file| are updated if needed.
65  static bool FragmentOperations(const PayloadVersion& version,
66                                 std::vector<AnnotatedOperation>* aops,
67                                 const std::string& target_part_path,
68                                 BlobFileWriter* blob_file);
69
70  // Takes a vector of AnnotatedOperations |aops| and sorts them by the first
71  // start block in their destination extents. Sets |aops| to a vector of the
72  // sorted operations.
73  static void SortOperationsByDestination(
74      std::vector<AnnotatedOperation>* aops);
75
76  // Takes an SOURCE_COPY install operation, |aop|, and adds one operation for
77  // each dst extent in |aop| to |ops|. The new operations added to |ops| will
78  // have only one dst extent. The src extents are split so the number of blocks
79  // in the src and dst extents are equal.
80  // E.g. we have a SOURCE_COPY operation:
81  //   src extents: [(1, 3), (5, 1), (7, 1)], dst extents: [(2, 2), (6, 3)]
82  // Then we will get 2 new operations:
83  //   1. src extents: [(1, 2)], dst extents: [(2, 2)]
84  //   2. src extents: [(3, 1),(5, 1),(7, 1)], dst extents: [(6, 3)]
85  static bool SplitSourceCopy(const AnnotatedOperation& original_aop,
86                              std::vector<AnnotatedOperation>* result_aops);
87
88  // Takes a REPLACE, REPLACE_BZ or REPLACE_XZ operation |aop|, and adds one
89  // operation for each dst extent in |aop| to |ops|. The new operations added
90  // to |ops| will have only one dst extent each, and may be of a different
91  // type depending on whether compression is advantageous.
92  static bool SplitAReplaceOp(const PayloadVersion& version,
93                              const AnnotatedOperation& original_aop,
94                              const std::string& target_part,
95                              std::vector<AnnotatedOperation>* result_aops,
96                              BlobFileWriter* blob_file);
97
98  // Takes a sorted (by first destination extent) vector of operations |aops|
99  // and merges SOURCE_COPY, REPLACE, REPLACE_BZ and REPLACE_XZ, operations in
100  // that vector.
101  // It will merge two operations if:
102  //   - They are both REPLACE_*, or they are both SOURCE_COPY,
103  //   - Their destination blocks are contiguous.
104  //   - Their combined blocks do not exceed |chunk_blocks| blocks.
105  // Note that unlike other methods, you can't pass a negative number in
106  // |chunk_blocks|.
107  static bool MergeOperations(std::vector<AnnotatedOperation>* aops,
108                              const PayloadVersion& version,
109                              size_t chunk_blocks,
110                              const std::string& target_part,
111                              BlobFileWriter* blob_file);
112
113  // Takes a vector of AnnotatedOperations |aops|, adds source hash to all
114  // operations that have src_extents.
115  static bool AddSourceHash(std::vector<AnnotatedOperation>* aops,
116                            const std::string& source_part_path);
117
118 private:
119  // Adds the data payload for a REPLACE/REPLACE_BZ/REPLACE_XZ operation |aop|
120  // by reading its output extents from |target_part_path| and appending a
121  // corresponding data blob to |blob_file|. The blob will be compressed if this
122  // is smaller than the uncompressed form, and the operation type will be set
123  // accordingly. |*blob_file| will be updated as well. If the operation happens
124  // to have the right type and already points to a data blob, nothing is
125  // written. Caller should only set type and data blob if it's valid.
126  static bool AddDataAndSetType(AnnotatedOperation* aop,
127                                const PayloadVersion& version,
128                                const std::string& target_part_path,
129                                BlobFileWriter* blob_file);
130
131  DISALLOW_COPY_AND_ASSIGN(ABGenerator);
132};
133
134}  // namespace chromeos_update_engine
135
136#endif  // UPDATE_ENGINE_PAYLOAD_GENERATOR_AB_GENERATOR_H_
137