extent_utils.cc revision 52490e776a9d34a94fb18ab1fe7d416425e94dda
1// Copyright (c) 2009 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#include "update_engine/payload_generator/extent_utils.h" 6 7#include <string> 8#include <utility> 9#include <vector> 10 11#include <base/logging.h> 12#include <base/macros.h> 13 14#include "update_engine/extent_ranges.h" 15#include "update_engine/payload_constants.h" 16#include "update_engine/payload_generator/annotated_operation.h" 17 18using std::string; 19using std::vector; 20 21namespace chromeos_update_engine { 22 23void AppendBlockToExtents(vector<Extent>* extents, uint64_t block) { 24 // First try to extend the last extent in |extents|, if any. 25 if (!extents->empty()) { 26 Extent& extent = extents->back(); 27 uint64_t next_block = extent.start_block() == kSparseHole ? 28 kSparseHole : extent.start_block() + extent.num_blocks(); 29 if (next_block == block) { 30 extent.set_num_blocks(extent.num_blocks() + 1); 31 return; 32 } 33 } 34 // If unable to extend the last extent, append a new single-block extent. 35 Extent new_extent; 36 new_extent.set_start_block(block); 37 new_extent.set_num_blocks(1); 38 extents->push_back(new_extent); 39} 40 41Extent GetElement(const vector<Extent>& collection, size_t index) { 42 return collection[index]; 43} 44Extent GetElement( 45 const google::protobuf::RepeatedPtrField<Extent>& collection, 46 size_t index) { 47 return collection.Get(index); 48} 49 50void NormalizeExtents(vector<Extent>* extents) { 51 vector<Extent> new_extents; 52 for (const Extent& curr_ext : *extents) { 53 if (new_extents.empty()) { 54 new_extents.push_back(curr_ext); 55 continue; 56 } 57 Extent& last_ext = new_extents.back(); 58 if (last_ext.start_block() + last_ext.num_blocks() == 59 curr_ext.start_block()) { 60 // If the extents are touching, we want to combine them. 61 last_ext.set_num_blocks(last_ext.num_blocks() + curr_ext.num_blocks()); 62 } else { 63 // Otherwise just include the extent as is. 64 new_extents.push_back(curr_ext); 65 } 66 } 67 *extents = new_extents; 68} 69 70vector<Extent> ExtentsSublist(const vector<Extent>& extents, 71 uint64_t block_offset, uint64_t block_count) { 72 vector<Extent> result; 73 uint64_t scanned_blocks = 0; 74 if (block_count == 0) 75 return result; 76 uint64_t end_block_offset = block_offset + block_count; 77 for (const Extent& extent : extents) { 78 // The loop invariant is that if |extents| has enough blocks, there's 79 // still some extent to add to |result|. This implies that at the beginning 80 // of the loop scanned_blocks < block_offset + block_count. 81 if (scanned_blocks + extent.num_blocks() > block_offset) { 82 // This case implies that |extent| has some overlapping with the requested 83 // subsequence. 84 uint64_t new_start = extent.start_block(); 85 uint64_t new_num_blocks = extent.num_blocks(); 86 if (scanned_blocks + new_num_blocks > end_block_offset) { 87 // Cut the end part of the extent. 88 new_num_blocks = end_block_offset - scanned_blocks; 89 } 90 if (block_offset > scanned_blocks) { 91 // Cut the begin part of the extent. 92 new_num_blocks -= block_offset - scanned_blocks; 93 new_start += block_offset - scanned_blocks; 94 } 95 result.push_back(ExtentForRange(new_start, new_num_blocks)); 96 } 97 scanned_blocks += extent.num_blocks(); 98 if (scanned_blocks >= end_block_offset) 99 break; 100 } 101 return result; 102} 103 104bool operator==(const Extent& a, const Extent& b) { 105 return a.start_block() == b.start_block() && a.num_blocks() == b.num_blocks(); 106} 107 108} // namespace chromeos_update_engine 109