blob: 27c67ec4f2e451660c3c5deb5f0b681ece92a296 [file] [log] [blame]
Kelvin Zhangd567c8b2021-07-08 14:10:23 -04001//
2// Copyright (C) 2021 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_CONSUMER_EXTENT_MAP_H_
18#define UPDATE_ENGINE_PAYLOAD_CONSUMER_EXTENT_MAP_H_
19
Kelvin Zhangd567c8b2021-07-08 14:10:23 -040020#include <map>
21#include <utility>
Colin Cross26b82b12021-12-22 10:09:19 -080022#include <vector>
Kelvin Zhangd567c8b2021-07-08 14:10:23 -040023
24#include "update_engine/common/utils.h"
25#include "update_engine/payload_generator/extent_ranges.h"
Colin Cross26b82b12021-12-22 10:09:19 -080026#include "update_engine/payload_generator/extent_utils.h"
Kelvin Zhangd567c8b2021-07-08 14:10:23 -040027#include "update_engine/update_metadata.pb.h"
28
29namespace chromeos_update_engine {
30
31// Data structure for storing a disjoint set of extents.
32// Currently the only usecase is for VABCPartitionWriter to keep track of which
33// block belongs to which merge operation. Therefore this class only contains
34// the minimal set of functions needed.
35template <typename T, typename Comparator = ExtentLess>
36class ExtentMap {
37 public:
38 bool AddExtent(const Extent& extent, T&& value) {
Kelvin Zhang9351f5d2021-08-17 19:29:49 -070039 if (set_.OverlapsWithExtent(extent)) {
Kelvin Zhangd567c8b2021-07-08 14:10:23 -040040 return false;
41 }
42 const auto& [it, inserted] = map_.insert({extent, std::forward<T>(value)});
43 if (inserted) {
44 set_.AddExtent(extent);
45 }
46 return inserted;
47 }
48
49 size_t size() const { return map_.size(); }
50
51 // Return a pointer to entry which is intersecting |extent|. If T is already
52 // a pointer type, return T on success. This function always return
53 // |nullptr| on failure. Therefore you cannot store nullptr as an entry.
54 std::optional<T> Get(const Extent& extent) const {
55 const auto it = map_.find(extent);
56 if (it == map_.end()) {
Kelvin Zhangaf9b9b22021-08-18 18:30:11 -070057 for (const auto& ext : set_.GetCandidateRange(extent)) {
Kelvin Zhangcb9932f2023-01-20 15:39:33 -080058 // Sometimes there are operations like
59 // map.AddExtent({0, 5}, 42);
60 // map.Get({2, 1})
61 // If the querying extent is completely covered within the key, we still
62 // consdier this to be a valid query.
63
64 if (ExtentContains(ext, extent)) {
65 return map_.at(ext);
66 }
Kelvin Zhangaf9b9b22021-08-18 18:30:11 -070067 if (ExtentRanges::ExtentsOverlap(ext, extent)) {
68 LOG(WARNING) << "Looking up a partially intersecting extent isn't "
69 "supported by "
70 "this data structure. Querying extent: "
71 << extent << ", partial match in map: " << ext;
72 }
73 }
Kelvin Zhangd567c8b2021-07-08 14:10:23 -040074 return {};
75 }
76 return {it->second};
77 }
78
79 // Return a set of extents that are contained in this extent map.
80 // If |extent| is completely covered by this extent map, a vector of itself
81 // will be returned.
82 // If only a subset of |extent| is covered by this extent map, a vector of
83 // parts in this map will be returned.
84 // If |extent| has no intersection with this map, an empty vector will be
85 // returned.
86 // E.g. extent map contains [0,5] and [10,15], GetIntersectingExtents([3, 12])
87 // would return [3,5] and [10,12]
88 std::vector<Extent> GetIntersectingExtents(const Extent& extent) const {
89 return set_.GetIntersectingExtents(extent);
90 }
91
92 // Complement of |GetIntersectingExtents|, return vector of extents which are
93 // part of |extent| but not covered by this map.
94 std::vector<Extent> GetNonIntersectingExtents(const Extent& extent) const {
95 return FilterExtentRanges({extent}, set_);
96 }
97
98 private:
99 // Get a range of exents that potentially intersect with parameter |extent|
100 std::map<Extent, T, Comparator> map_;
Kelvin Zhangbef99c32021-08-18 09:57:02 -0700101 ExtentRanges set_{false};
Kelvin Zhangd567c8b2021-07-08 14:10:23 -0400102};
103} // namespace chromeos_update_engine
104
105#endif // UPDATE_ENGINE_PAYLOAD_CONSUMER_EXTENT_MAP_H_