xref: /aosp_15_r20/system/update_engine/payload_consumer/extent_map.h (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2021 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #ifndef UPDATE_ENGINE_PAYLOAD_CONSUMER_EXTENT_MAP_H_
18*5a923131SAndroid Build Coastguard Worker #define UPDATE_ENGINE_PAYLOAD_CONSUMER_EXTENT_MAP_H_
19*5a923131SAndroid Build Coastguard Worker 
20*5a923131SAndroid Build Coastguard Worker #include <map>
21*5a923131SAndroid Build Coastguard Worker #include <utility>
22*5a923131SAndroid Build Coastguard Worker #include <vector>
23*5a923131SAndroid Build Coastguard Worker 
24*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/utils.h"
25*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_generator/extent_ranges.h"
26*5a923131SAndroid Build Coastguard Worker #include "update_engine/payload_generator/extent_utils.h"
27*5a923131SAndroid Build Coastguard Worker #include "update_engine/update_metadata.pb.h"
28*5a923131SAndroid Build Coastguard Worker 
29*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
30*5a923131SAndroid Build Coastguard Worker 
31*5a923131SAndroid Build Coastguard Worker // Data structure for storing a disjoint set of extents.
32*5a923131SAndroid Build Coastguard Worker // Currently the only usecase is for VABCPartitionWriter to keep track of which
33*5a923131SAndroid Build Coastguard Worker // block belongs to which merge operation. Therefore this class only contains
34*5a923131SAndroid Build Coastguard Worker // the minimal set of functions needed.
35*5a923131SAndroid Build Coastguard Worker template <typename T, typename Comparator = ExtentLess>
36*5a923131SAndroid Build Coastguard Worker class ExtentMap {
37*5a923131SAndroid Build Coastguard Worker  public:
AddExtent(const Extent & extent,T && value)38*5a923131SAndroid Build Coastguard Worker   bool AddExtent(const Extent& extent, T&& value) {
39*5a923131SAndroid Build Coastguard Worker     if (set_.OverlapsWithExtent(extent)) {
40*5a923131SAndroid Build Coastguard Worker       return false;
41*5a923131SAndroid Build Coastguard Worker     }
42*5a923131SAndroid Build Coastguard Worker     const auto& [it, inserted] = map_.insert({extent, std::forward<T>(value)});
43*5a923131SAndroid Build Coastguard Worker     if (inserted) {
44*5a923131SAndroid Build Coastguard Worker       set_.AddExtent(extent);
45*5a923131SAndroid Build Coastguard Worker     }
46*5a923131SAndroid Build Coastguard Worker     return inserted;
47*5a923131SAndroid Build Coastguard Worker   }
48*5a923131SAndroid Build Coastguard Worker 
size()49*5a923131SAndroid Build Coastguard Worker   size_t size() const { return map_.size(); }
50*5a923131SAndroid Build Coastguard Worker 
51*5a923131SAndroid Build Coastguard Worker   // Return a pointer to entry which is intersecting |extent|. If T is already
52*5a923131SAndroid Build Coastguard Worker   // a pointer type, return T on success. This function always return
53*5a923131SAndroid Build Coastguard Worker   // |nullptr| on failure. Therefore you cannot store nullptr as an entry.
Get(const Extent & extent)54*5a923131SAndroid Build Coastguard Worker   std::optional<T> Get(const Extent& extent) const {
55*5a923131SAndroid Build Coastguard Worker     const auto it = map_.find(extent);
56*5a923131SAndroid Build Coastguard Worker     if (it == map_.end()) {
57*5a923131SAndroid Build Coastguard Worker       for (const auto& ext : set_.GetCandidateRange(extent)) {
58*5a923131SAndroid Build Coastguard Worker         // Sometimes there are operations like
59*5a923131SAndroid Build Coastguard Worker         // map.AddExtent({0, 5}, 42);
60*5a923131SAndroid Build Coastguard Worker         // map.Get({2, 1})
61*5a923131SAndroid Build Coastguard Worker         // If the querying extent is completely covered within the key, we still
62*5a923131SAndroid Build Coastguard Worker         // consdier this to be a valid query.
63*5a923131SAndroid Build Coastguard Worker 
64*5a923131SAndroid Build Coastguard Worker         if (ExtentContains(ext, extent)) {
65*5a923131SAndroid Build Coastguard Worker           return map_.at(ext);
66*5a923131SAndroid Build Coastguard Worker         }
67*5a923131SAndroid Build Coastguard Worker         if (ExtentRanges::ExtentsOverlap(ext, extent)) {
68*5a923131SAndroid Build Coastguard Worker           LOG(WARNING) << "Looking up a partially intersecting extent isn't "
69*5a923131SAndroid Build Coastguard Worker                           "supported by "
70*5a923131SAndroid Build Coastguard Worker                           "this data structure. Querying extent: "
71*5a923131SAndroid Build Coastguard Worker                        << extent << ", partial match in map: " << ext;
72*5a923131SAndroid Build Coastguard Worker         }
73*5a923131SAndroid Build Coastguard Worker       }
74*5a923131SAndroid Build Coastguard Worker       return {};
75*5a923131SAndroid Build Coastguard Worker     }
76*5a923131SAndroid Build Coastguard Worker     return {it->second};
77*5a923131SAndroid Build Coastguard Worker   }
78*5a923131SAndroid Build Coastguard Worker 
79*5a923131SAndroid Build Coastguard Worker   // Return a set of extents that are contained in this extent map.
80*5a923131SAndroid Build Coastguard Worker   // If |extent| is completely covered by this extent map, a vector of itself
81*5a923131SAndroid Build Coastguard Worker   // will be returned.
82*5a923131SAndroid Build Coastguard Worker   // If only a subset of |extent| is covered by this extent map, a vector of
83*5a923131SAndroid Build Coastguard Worker   // parts in this map will be returned.
84*5a923131SAndroid Build Coastguard Worker   // If |extent| has no intersection with this map, an empty vector will be
85*5a923131SAndroid Build Coastguard Worker   // returned.
86*5a923131SAndroid Build Coastguard Worker   // E.g. extent map contains [0,5] and [10,15], GetIntersectingExtents([3, 12])
87*5a923131SAndroid Build Coastguard Worker   // would return [3,5] and [10,12]
GetIntersectingExtents(const Extent & extent)88*5a923131SAndroid Build Coastguard Worker   std::vector<Extent> GetIntersectingExtents(const Extent& extent) const {
89*5a923131SAndroid Build Coastguard Worker     return set_.GetIntersectingExtents(extent);
90*5a923131SAndroid Build Coastguard Worker   }
91*5a923131SAndroid Build Coastguard Worker 
92*5a923131SAndroid Build Coastguard Worker   // Complement of |GetIntersectingExtents|, return vector of extents which are
93*5a923131SAndroid Build Coastguard Worker   // part of |extent| but not covered by this map.
GetNonIntersectingExtents(const Extent & extent)94*5a923131SAndroid Build Coastguard Worker   std::vector<Extent> GetNonIntersectingExtents(const Extent& extent) const {
95*5a923131SAndroid Build Coastguard Worker     return FilterExtentRanges({extent}, set_);
96*5a923131SAndroid Build Coastguard Worker   }
97*5a923131SAndroid Build Coastguard Worker 
98*5a923131SAndroid Build Coastguard Worker  private:
99*5a923131SAndroid Build Coastguard Worker   // Get a range of exents that potentially intersect with parameter |extent|
100*5a923131SAndroid Build Coastguard Worker   std::map<Extent, T, Comparator> map_;
101*5a923131SAndroid Build Coastguard Worker   ExtentRanges set_{false};
102*5a923131SAndroid Build Coastguard Worker };
103*5a923131SAndroid Build Coastguard Worker }  // namespace chromeos_update_engine
104*5a923131SAndroid Build Coastguard Worker 
105*5a923131SAndroid Build Coastguard Worker #endif  // UPDATE_ENGINE_PAYLOAD_CONSUMER_EXTENT_MAP_H_
106