ab_generator.h revision 14158570d3995008dc93a628004118b87a6bca01
1// Copyright 2015 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef UPDATE_ENGINE_PAYLOAD_GENERATOR_AB_GENERATOR_H_ 6#define UPDATE_ENGINE_PAYLOAD_GENERATOR_AB_GENERATOR_H_ 7 8#include <string> 9#include <vector> 10 11#include <base/macros.h> 12#include <chromeos/secure_blob.h> 13 14#include "update_engine/payload_constants.h" 15#include "update_engine/payload_generator/extent_utils.h" 16#include "update_engine/payload_generator/filesystem_interface.h" 17#include "update_engine/payload_generator/operations_generator.h" 18#include "update_engine/payload_generator/payload_generation_config.h" 19#include "update_engine/update_metadata.pb.h" 20 21namespace chromeos_update_engine { 22 23// The ABGenerator is an operations generator that generates payloads using the 24// A-to-B operations SOURCE_COPY and SOURCE_BSDIFF introduced in the payload 25// minor version 2 format. 26class ABGenerator : public OperationsGenerator { 27 public: 28 ABGenerator() = default; 29 30 // Generate the update payload operations for the kernel and rootfs using 31 // SOURCE_* operations, used for generating deltas for the minor version 32 // kSourceMinorPayloadVersion. This function will generate operations in the 33 // rootfs that will read blocks from the source partition in random order and 34 // write the new image on the target partition, also possibly in random order. 35 // The rootfs operations are stored in |rootfs_ops| and should be executed in 36 // that order. The kernel operations are stored in |kernel_ops|. All 37 // the offsets in the operations reference the data written to |data_file_fd|. 38 // The total amount of data written to that file is stored in 39 // |data_file_size|. 40 bool GenerateOperations( 41 const PayloadGenerationConfig& config, 42 int data_file_fd, 43 off_t* data_file_size, 44 std::vector<AnnotatedOperation>* rootfs_ops, 45 std::vector<AnnotatedOperation>* kernel_ops) override; 46 47 // Split the operations in the vector of AnnotatedOperations |aops| 48 // such that for every operation there is only one dst extent and updates 49 // |aops| with the new list of operations. All kinds of operations are 50 // fragmented except BSDIFF and SOURCE_BSDIFF operations. 51 // The |target_rootfs_part| is the filename of the new image, where the 52 // destination extents refer to. The blobs of the operations in |aops| should 53 // reference the file |data_fd| whose initial size is |*data_file_size|. The 54 // file contents and the value pointed by |data_file_size| are updated if 55 // needed. 56 static bool FragmentOperations(std::vector<AnnotatedOperation>* aops, 57 const std::string& target_rootfs_part, 58 int data_fd, 59 off_t* data_file_size); 60 61 // Takes a vector of AnnotatedOperations |aops| and sorts them by the first 62 // start block in their destination extents. Sets |aops| to a vector of the 63 // sorted operations. 64 static void SortOperationsByDestination( 65 std::vector<AnnotatedOperation>* aops); 66 67 // Takes an SOURCE_COPY install operation, |aop|, and adds one operation for 68 // each dst extent in |aop| to |ops|. The new operations added to |ops| will 69 // have only one dst extent. The src extents are split so the number of blocks 70 // in the src and dst extents are equal. 71 // E.g. we have a SOURCE_COPY operation: 72 // src extents: [(1, 3), (5, 1), (7, 1)], dst extents: [(2, 2), (6, 3)] 73 // Then we will get 2 new operations: 74 // 1. src extents: [(1, 2)], dst extents: [(2, 2)] 75 // 2. src extents: [(3, 1),(5, 1),(7, 1)], dst extents: [(6, 3)] 76 static bool SplitSourceCopy(const AnnotatedOperation& original_aop, 77 std::vector<AnnotatedOperation>* result_aops); 78 79 // Takes a REPLACE/REPLACE_BZ operation |aop|, and adds one operation for each 80 // dst extent in |aop| to |ops|. The new operations added to |ops| will have 81 // only one dst extent each, and may be either a REPLACE or REPLACE_BZ 82 // depending on whether compression is advantageous. 83 static bool SplitReplaceOrReplaceBz( 84 const AnnotatedOperation& original_aop, 85 std::vector<AnnotatedOperation>* result_aops, 86 const std::string& target_part, 87 int data_fd, 88 off_t* data_file_size); 89 90 // Takes a sorted (by first destination extent) vector of operations |aops| 91 // and merges SOURCE_COPY, REPLACE, and REPLACE_BZ operations in that vector. 92 // It will merge two operations if: 93 // - They are of the same type. 94 // - They are contiguous. 95 // - Their combined blocks do not exceed |chunk_size|. 96 static bool MergeOperations(std::vector<AnnotatedOperation>* aops, 97 off_t chunk_size, 98 const std::string& target_part, 99 int data_fd, 100 off_t* data_file_size); 101 102 private: 103 // Adds the data payload for a REPLACE/REPLACE_BZ operation |aop| by reading 104 // its output extents from |target_part_path| and appending a corresponding 105 // data blob to |data_fd|. The blob will be compressed if this is smaller than 106 // the uncompressed form, and the operation type will be set accordingly. 107 // |*data_file_size| will be updated as well. If the operation happens to have 108 // the right type and already points to a data blob, we check whether its 109 // content is identical to the new one, in which case nothing is written. 110 static bool AddDataAndSetType(AnnotatedOperation* aop, 111 const std::string& target_part_path, 112 int data_fd, 113 off_t* data_file_size); 114 115 DISALLOW_COPY_AND_ASSIGN(ABGenerator); 116}; 117 118} // namespace chromeos_update_engine 119 120#endif // UPDATE_ENGINE_PAYLOAD_GENERATOR_AB_GENERATOR_H_ 121