iceberg-cpp
Loading...
Searching...
No Matches
data_file_set.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#pragma once
21
25
26#include <cstdint>
27#include <iterator>
28#include <memory>
29#include <optional>
30#include <span>
31#include <string>
32#include <string_view>
33#include <unordered_map>
34#include <vector>
35
36#include "iceberg/iceberg_export.h"
38#include "iceberg/util/string_util.h"
39
40namespace iceberg {
41
44class ICEBERG_EXPORT DataFileSet {
45 public:
46 using value_type = std::shared_ptr<DataFile>;
47 using iterator = typename std::vector<value_type>::iterator;
48 using const_iterator = typename std::vector<value_type>::const_iterator;
49 using difference_type = typename std::vector<value_type>::difference_type;
50
51 DataFileSet() = default;
52 DataFileSet(const DataFileSet& other) : elements_(other.elements_) { RebuildIndex(); }
53 DataFileSet& operator=(const DataFileSet& other) {
54 if (this != &other) {
55 elements_ = other.elements_;
56 RebuildIndex();
57 }
58 return *this;
59 }
60 DataFileSet(DataFileSet&&) noexcept = default;
61 DataFileSet& operator=(DataFileSet&&) noexcept = default;
62
67 std::pair<iterator, bool> insert(const value_type& file) { return InsertImpl(file); }
68
70 std::pair<iterator, bool> insert(value_type&& file) {
71 return InsertImpl(std::move(file));
72 }
73
75 bool contains(const DataFile& file) const {
76 return index_by_path_.contains(file.file_path);
77 }
78
80 bool contains(const value_type& file) const {
81 return file != nullptr && contains(*file);
82 }
83
85 size_t size() const { return elements_.size(); }
86
88 bool empty() const { return elements_.empty(); }
89
91 void clear() {
92 elements_.clear();
93 index_by_path_.clear();
94 }
95
97 iterator begin() { return elements_.begin(); }
98 const_iterator begin() const { return elements_.begin(); }
99 const_iterator cbegin() const { return elements_.cbegin(); }
100
102 iterator end() { return elements_.end(); }
103 const_iterator end() const { return elements_.end(); }
104 const_iterator cend() const { return elements_.cend(); }
105
107 std::span<const value_type> as_span() const { return elements_; }
108
109 private:
110 std::pair<iterator, bool> InsertImpl(value_type file) {
111 if (!file) {
112 return {elements_.end(), false};
113 }
114
115 auto [index_iter, inserted] =
116 index_by_path_.try_emplace(file->file_path, elements_.size());
117 if (!inserted) {
118 auto pos = static_cast<difference_type>(index_iter->second);
119 return {elements_.begin() + pos, false};
120 }
121
122 elements_.push_back(std::move(file));
123 return {std::prev(elements_.end()), true};
124 }
125
126 void RebuildIndex() {
127 index_by_path_.clear();
128 for (size_t i = 0; i < elements_.size(); ++i) {
129 if (elements_[i] != nullptr) {
130 index_by_path_.try_emplace(elements_[i]->file_path, i);
131 }
132 }
133 }
134
135 // Vector to preserve insertion order
136 std::vector<value_type> elements_;
137 std::unordered_map<std::string_view, size_t, StringHash, StringEqual> index_by_path_;
138};
139
144class ICEBERG_EXPORT DeleteFileSet {
145 public:
146 using value_type = std::shared_ptr<DataFile>;
147 using iterator = typename std::vector<value_type>::iterator;
148 using const_iterator = typename std::vector<value_type>::const_iterator;
149 using difference_type = typename std::vector<value_type>::difference_type;
150
151 DeleteFileSet() = default;
152 DeleteFileSet(const DeleteFileSet& other) : elements_(other.elements_) {
153 RebuildIndex();
154 }
155 DeleteFileSet& operator=(const DeleteFileSet& other) {
156 if (this != &other) {
157 elements_ = other.elements_;
158 RebuildIndex();
159 }
160 return *this;
161 }
162 DeleteFileSet(DeleteFileSet&&) noexcept = default;
163 DeleteFileSet& operator=(DeleteFileSet&&) noexcept = default;
164
169 std::pair<iterator, bool> insert(const value_type& file) { return InsertImpl(file); }
170
172 std::pair<iterator, bool> insert(value_type&& file) {
173 return InsertImpl(std::move(file));
174 }
175
177 bool contains(const DataFile& file) const {
178 return index_by_file_.contains(DeleteFileKey(file));
179 }
180
182 bool contains(const value_type& file) const {
183 return file != nullptr && contains(*file);
184 }
185
187 size_t size() const { return elements_.size(); }
188
190 bool empty() const { return elements_.empty(); }
191
193 void clear() {
194 elements_.clear();
195 index_by_file_.clear();
196 }
197
199 iterator begin() { return elements_.begin(); }
200 const_iterator begin() const { return elements_.begin(); }
201 const_iterator cbegin() const { return elements_.cbegin(); }
202
204 iterator end() { return elements_.end(); }
205 const_iterator end() const { return elements_.end(); }
206 const_iterator cend() const { return elements_.cend(); }
207
209 std::span<const value_type> as_span() const { return elements_; }
210
211 private:
212 struct DeleteFileKey {
213 explicit DeleteFileKey(const DataFile& file)
214 : path(file.file_path),
215 content_offset(file.content_offset),
216 content_size_in_bytes(file.content_size_in_bytes) {}
217
218 std::string path;
219 std::optional<int64_t> content_offset;
220 std::optional<int64_t> content_size_in_bytes;
221
222 bool operator==(const DeleteFileKey& other) const = default;
223 };
224
225 struct DeleteFileKeyHash {
226 size_t operator()(const DeleteFileKey& key) const {
227 size_t hash = std::hash<std::string>{}(key.path);
228 auto combine = [&hash](const auto& value) {
229 size_t value_hash = value.has_value() ? std::hash<int64_t>{}(*value) : 0;
230 hash ^= value_hash + 0x9e3779b9 + (hash << 6) + (hash >> 2);
231 };
232 combine(key.content_offset);
233 combine(key.content_size_in_bytes);
234 return hash;
235 }
236 };
237
238 std::pair<iterator, bool> InsertImpl(value_type file) {
239 if (!file) {
240 return {elements_.end(), false};
241 }
242
243 auto [index_iter, inserted] =
244 index_by_file_.try_emplace(DeleteFileKey(*file), elements_.size());
245 if (!inserted) {
246 auto pos = static_cast<difference_type>(index_iter->second);
247 return {elements_.begin() + pos, false};
248 }
249
250 elements_.push_back(std::move(file));
251 return {std::prev(elements_.end()), true};
252 }
253
254 void RebuildIndex() {
255 index_by_file_.clear();
256 for (size_t i = 0; i < elements_.size(); ++i) {
257 if (elements_[i] != nullptr) {
258 index_by_file_.try_emplace(DeleteFileKey(*elements_[i]), i);
259 }
260 }
261 }
262
263 // Vector to preserve insertion order.
264 std::vector<value_type> elements_;
265 std::unordered_map<DeleteFileKey, size_t, DeleteFileKeyHash> index_by_file_;
266};
267
268} // namespace iceberg
A set of DataFile pointers with insertion order preserved and deduplicated by file path.
Definition data_file_set.h:44
bool contains(const value_type &file) const
Returns whether an equivalent data file exists in the set.
Definition data_file_set.h:80
bool contains(const DataFile &file) const
Returns whether an equivalent data file exists in the set.
Definition data_file_set.h:75
iterator end()
Get iterator to the end.
Definition data_file_set.h:102
void clear()
Clear all elements from the set.
Definition data_file_set.h:91
std::span< const value_type > as_span() const
Get a non-owning view of the data files in insertion order.
Definition data_file_set.h:107
size_t size() const
Get the number of elements in the set.
Definition data_file_set.h:85
std::pair< iterator, bool > insert(const value_type &file)
Insert a data file into the set.
Definition data_file_set.h:67
iterator begin()
Get iterator to the beginning.
Definition data_file_set.h:97
bool empty() const
Check if the set is empty.
Definition data_file_set.h:88
std::pair< iterator, bool > insert(value_type &&file)
Insert a data file into the set (move version).
Definition data_file_set.h:70
A set of delete-file pointers deduplicated by delete-file identity.
Definition data_file_set.h:144
bool contains(const DataFile &file) const
Returns whether an equivalent delete file exists in the set.
Definition data_file_set.h:177
bool contains(const value_type &file) const
Returns whether an equivalent delete file exists in the set.
Definition data_file_set.h:182
std::pair< iterator, bool > insert(const value_type &file)
Insert a delete file into the set.
Definition data_file_set.h:169
std::span< const value_type > as_span() const
Get a non-owning view of the delete files in insertion order.
Definition data_file_set.h:209
std::pair< iterator, bool > insert(value_type &&file)
Insert a delete file into the set (move version).
Definition data_file_set.h:172
iterator begin()
Get iterator to the beginning.
Definition data_file_set.h:199
bool empty() const
Check if the set is empty.
Definition data_file_set.h:190
iterator end()
Get iterator to the end.
Definition data_file_set.h:204
void clear()
Clear all elements from the set.
Definition data_file_set.h:193
size_t size() const
Get the number of elements in the set.
Definition data_file_set.h:187
DataFile carries data file path, partition tuple, metrics, ...
Definition manifest_entry.h:62
std::string file_path
Definition manifest_entry.h:76