iceberg-cpp
Loading...
Searching...
No Matches
snapshot_update.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
24
25#include <atomic>
26#include <functional>
27#include <memory>
28#include <mutex>
29#include <optional>
30#include <span>
31#include <string>
32#include <unordered_map>
33#include <unordered_set>
34#include <vector>
35
36#include "iceberg/compat/compiler.h"
38#include "iceberg/result.h"
39#include "iceberg/snapshot.h"
40#include "iceberg/type_fwd.h"
43
44namespace iceberg {
45
61class ICEBERG_EXPORT SnapshotUpdate : public PendingUpdate {
62 public:
64 struct ApplyResult {
65 // Null when applying an unconfigured update to an empty table.
66 std::shared_ptr<Snapshot> snapshot;
67 std::string target_branch;
68 bool stage_only = false;
69 };
70
71 ~SnapshotUpdate() override;
72
73 Kind kind() const override { return Kind::kUpdateSnapshot; }
74 bool IsRetryable() const override { return true; }
75 Status Commit() override;
76
81#if ICEBERG_CXX20_COMPAT
82 SnapshotUpdate& ReportWith(std::shared_ptr<MetricsReporter> reporter) {
83 SetReporter(std::move(reporter));
84 return *this;
85 }
86#else
87 auto& ReportWith(this auto& self, std::shared_ptr<MetricsReporter> reporter) {
88 static_cast<SnapshotUpdate&>(self).SetReporter(std::move(reporter));
89 return self;
90 }
91#endif
92
98#if ICEBERG_CXX20_COMPAT
99 SnapshotUpdate& DeleteWith(std::function<Status(const std::string&)> delete_func) {
100 SetDeleteFunction(std::move(delete_func));
101 return *this;
102 }
103#else
104 auto& DeleteWith(this auto& self,
105 std::function<Status(const std::string&)> delete_func) {
106 static_cast<SnapshotUpdate&>(self).SetDeleteFunction(std::move(delete_func));
107 return self;
108 }
109#endif
110
117#if ICEBERG_CXX20_COMPAT
118 SnapshotUpdate& StageOnly() {
119 SetStageOnly();
120 return *this;
121 }
122#else
123 auto& StageOnly(this auto& self) {
124 static_cast<SnapshotUpdate&>(self).SetStageOnly();
125 return self;
126 }
127#endif
128
133#if ICEBERG_CXX20_COMPAT
134 SnapshotUpdate& ScanManifestsWith(Executor& executor) {
135 SetPlanExecutor(executor);
136 return *this;
137 }
138#else
139 auto& ScanManifestsWith(this auto& self, Executor& executor) {
140 static_cast<SnapshotUpdate&>(self).SetPlanExecutor(executor);
141 return self;
142 }
143#endif
144
149#if ICEBERG_CXX20_COMPAT
150 SnapshotUpdate& ToBranch(const std::string& branch) {
151 SetTargetBranch(branch);
152 return *this;
153 }
154#else
155 auto& ToBranch(this auto& self, const std::string& branch) {
156 static_cast<SnapshotUpdate&>(self).SetTargetBranch(branch);
157 return self;
158 }
159#endif
160
166#if ICEBERG_CXX20_COMPAT
167 SnapshotUpdate& Set(const std::string& property, const std::string& value) {
168 SetSummaryProperty(property, value);
169 return *this;
170 }
171#else
172 auto& Set(this auto& self, const std::string& property, const std::string& value) {
173 static_cast<SnapshotUpdate&>(self).SetSummaryProperty(property, value);
174 return self;
175 }
176#endif
177
188#if ICEBERG_CXX20_COMPAT
189 SnapshotUpdate& WriteManifestsWith(Executor& executor, int32_t parallelism) {
190 SetManifestWriter(executor, parallelism);
191 return *this;
192 }
193#else
194 auto& WriteManifestsWith(this auto& self, Executor& executor, int32_t parallelism) {
195 static_cast<SnapshotUpdate&>(self).SetManifestWriter(executor, parallelism);
196 return self;
197 }
198#endif
199
200 protected:
201 friend class Transaction;
202
205 Status Finalize(const TableMetadata& committed) override;
206 Status CleanStaged() override;
207
209 std::shared_ptr<DataFile> file;
210 std::optional<int64_t> data_sequence_number;
211 };
212
213 explicit SnapshotUpdate(std::shared_ptr<TransactionContext> ctx);
214
222 std::span<const std::shared_ptr<DataFile>> files,
223 const std::shared_ptr<PartitionSpec>& spec,
224 std::optional<int64_t> data_sequence_number = std::nullopt);
225
226 Result<std::vector<ManifestFile>> WriteDeleteManifests(
227 std::span<const ContentFileWithSequenceNumber> files,
228 const std::shared_ptr<PartitionSpec>& spec);
229
230 const std::string& target_branch() const { return target_branch_; }
231 bool can_inherit_snapshot_id() const { return can_inherit_snapshot_id_; }
232 const std::string& commit_uuid() const { return commit_uuid_; }
233 int32_t manifest_count() const {
234 return manifest_count_.load(std::memory_order_relaxed);
235 }
236 int32_t attempt() const { return attempt_.load(std::memory_order_relaxed); }
237 int64_t target_manifest_size_bytes() const { return target_manifest_size_bytes_; }
238
249 virtual Status CleanUncommitted(const std::unordered_set<std::string>& committed) = 0;
250
254 virtual std::string operation() = 0;
255
262 virtual Status Validate(const TableMetadata& current_metadata,
263 const std::shared_ptr<Snapshot>& snapshot) {
264 return {};
265 };
266
273 const TableMetadata& metadata_to_update,
274 const std::shared_ptr<Snapshot>& snapshot) = 0;
275
279 virtual std::unordered_map<std::string, std::string> Summary() = 0;
280
285 virtual void SetSummaryProperty(const std::string& property, const std::string& value);
286
288 int64_t SnapshotId();
289
291 Status DeleteFile(const std::string& path) noexcept;
292 void RegisterStagedFile(const std::string& path);
294 void UnregisterStagedFile(const std::string& path);
295
296 std::string ManifestPath();
297 std::string ManifestListPath();
298 OptionalExecutor plan_executor() const { return plan_executor_; }
299 SnapshotSummaryBuilder& summary_builder() { return summary_; }
300 SnapshotSummaryBuilder BuildManifestCountSummary(
301 std::span<const ManifestFile> manifests, int32_t replaced_manifests_count);
302
303 private:
305 Result<std::unordered_map<std::string, std::string>> ComputeSummary(
306 const TableMetadata& previous);
307
308 Status ReportCommit() const;
309
310 protected:
311 SnapshotSummaryBuilder summary_;
312
313 private:
314 void SetReporter(std::shared_ptr<MetricsReporter> reporter) {
315 reporter_ = std::move(reporter);
316 }
317
318 void SetDeleteFunction(std::function<Status(const std::string&)> delete_func) {
319 if (delete_func_) {
320 AddError(ErrorKind::kInvalidArgument, "Cannot set delete callback more than once");
321 return;
322 }
323 delete_func_ = std::move(delete_func);
324 }
325
326 void SetStageOnly() { stage_only_ = true; }
327
328 void SetPlanExecutor(Executor& executor) { plan_executor_ = std::ref(executor); }
329
330 void SetTargetBranch(const std::string& branch) {
331 if (branch.empty()) [[unlikely]] {
332 AddError(ErrorKind::kInvalidArgument, "Branch name cannot be empty");
333 return;
334 }
335
336 if (auto ref_it = base().refs.find(branch); ref_it != base().refs.end()) {
337 if (ref_it->second->type() != SnapshotRefType::kBranch) {
338 AddError(ErrorKind::kInvalidArgument,
339 "{} is a tag, not a branch. Tags cannot be targets for "
340 "producing snapshots",
341 branch);
342 return;
343 }
344 }
345
346 target_branch_ = branch;
347 }
348
349 void SetManifestWriter(Executor& executor, int32_t parallelism) {
350 if (parallelism <= 0) [[unlikely]] {
351 AddError(ErrorKind::kInvalidArgument,
352 "Manifest write parallelism must be greater than 0, but was: {}",
353 parallelism);
354 return;
355 }
356
357 write_manifest_executor_ = std::ref(executor);
358 write_manifest_parallelism_ = parallelism;
359 }
360
361 const bool can_inherit_snapshot_id_{true};
362 const std::string commit_uuid_;
363 OptionalExecutor write_manifest_executor_;
364 int32_t write_manifest_parallelism_{1};
365 std::atomic<int32_t> manifest_count_{0};
366 std::atomic<int32_t> attempt_{0};
367 // All paths are registered before writes, including partial/failed writes.
368 std::mutex staging_mutex_;
369 std::unordered_set<std::string> staged_files_;
370 const int64_t target_manifest_size_bytes_;
371 std::optional<int64_t> snapshot_id_;
372 OptionalExecutor plan_executor_;
373 bool stage_only_{false};
374 std::function<Status(const std::string&)> delete_func_;
375 std::string target_branch_{SnapshotRef::kMainBranch};
376 std::shared_ptr<Snapshot> staged_snapshot_;
377 std::unique_ptr<CommitMetrics> commit_metrics_;
378 std::shared_ptr<MetricsReporter> reporter_;
379};
380
381} // namespace iceberg
Schedules iceberg-cpp tasks.
Definition executor.h:46
Base class for all kinds of table metadata updates.
Definition pending_update.h:48
Helper class for building snapshot summaries.
Definition snapshot.h:266
API for table changes that produce snapshots.
Definition snapshot_update.h:61
Status CleanStaged() override
Discard this generation's staging, retaining applied operation intent.
virtual Result< std::vector< ManifestFile > > Apply(const TableMetadata &metadata_to_update, const std::shared_ptr< Snapshot > &snapshot)=0
Apply the update's changes to the given metadata and snapshot.
virtual std::unordered_map< std::string, std::string > Summary()=0
Get the summary map for this operation.
auto & StageOnly(this auto &self)
Stage a snapshot in table metadata, but do not make it current.
Definition snapshot_update.h:123
virtual std::string operation()=0
A string that describes the action that produced the new snapshot.
void UnregisterStagedFile(const std::string &path)
Transfer cleanup ownership to the derived update.
virtual Status CleanUncommitted(const std::unordered_set< std::string > &committed)=0
Clean up any uncommitted manifests that were created.
bool IsRetryable() const override
Whether this update can be retried after a commit conflict.
Definition snapshot_update.h:74
auto & ToBranch(this auto &self, const std::string &branch)
Perform operations on a particular branch.
Definition snapshot_update.h:155
Status Finalize(const TableMetadata &committed) override
Complete a known successful commit. Called only by Transaction with the final committed table metadat...
virtual Status Validate(const TableMetadata &current_metadata, const std::shared_ptr< Snapshot > &snapshot)
Validate the current metadata.
Definition snapshot_update.h:262
int64_t SnapshotId()
Get or generate the snapshot ID for the new snapshot.
auto & ScanManifestsWith(this auto &self, Executor &executor)
Configure an executor for manifest planning work.
Definition snapshot_update.h:139
virtual Result< ApplyResult > Apply()
Build snapshot state for the transaction's current metadata.
auto & WriteManifestsWith(this auto &self, Executor &executor, int32_t parallelism)
Configure an executor and max writer count for writing new manifests.
Definition snapshot_update.h:194
Result< std::vector< ManifestFile > > WriteDataManifests(std::span< const std::shared_ptr< DataFile > > files, const std::shared_ptr< PartitionSpec > &spec, std::optional< int64_t > data_sequence_number=std::nullopt)
Write data manifests for the given data files.
Kind kind() const override
Return the kind of this pending update.
Definition snapshot_update.h:73
auto & Set(this auto &self, const std::string &property, const std::string &value)
Set a summary property in the snapshot produced by this update.
Definition snapshot_update.h:172
Status DeleteFile(const std::string &path) noexcept
Best-effort delete. Failed paths remain registered for later cleanup.
auto & DeleteWith(this auto &self, std::function< Status(const std::string &)> delete_func)
Set a callback to delete files instead of the table's default.
Definition snapshot_update.h:104
Status Commit() override
Apply the pending changes and commit.
auto & ReportWith(this auto &self, std::shared_ptr< MetricsReporter > reporter)
Set the metrics reporter for this snapshot update.
Definition snapshot_update.h:87
virtual void SetSummaryProperty(const std::string &property, const std::string &value)
Set a summary property.
A transaction for performing multiple updates to a table.
Definition transaction.h:53
Definition expected.h:1199
Define task executor interfaces.
Define symbol visibility macros for core Iceberg APIs.
Core Apache Iceberg C++ APIs.
Definition arrow_io_util.h:34
Define Result, Status, and error helpers.
Define snapshot metadata types.
Result of applying a snapshot update.
Definition snapshot_update.h:64
Represents the metadata for an Iceberg table.
Definition table_metadata.h:73