|
19 | 19 | #include "iceberg/transaction.h" |
20 | 20 |
|
21 | 21 | #include <format> |
| 22 | +#include <iterator> |
22 | 23 | #include <memory> |
23 | 24 | #include <string> |
24 | 25 |
|
@@ -400,9 +401,6 @@ Status Transaction::ApplyUpdatePartitionStatistics(UpdatePartitionStatistics& up |
400 | 401 | Result<std::shared_ptr<Table>> Transaction::Commit() { |
401 | 402 | ICEBERG_RETURN_UNEXPECTED(CheckReady()); |
402 | 403 | Result<std::shared_ptr<Table>> commit_result = ctx_->table; |
403 | | - // Snapshot id before the commit, to detect whether this commit advanced it (a |
404 | | - // data commit) versus a metadata-only commit that adds no snapshot. |
405 | | - const int64_t base_current_snapshot_id = ctx_->table->metadata()->current_snapshot_id; |
406 | 404 | int32_t attempt = 0; |
407 | 405 | std::string last_error; |
408 | 406 | try { |
@@ -444,27 +442,42 @@ Result<std::shared_ptr<Table>> Transaction::Commit() { |
444 | 442 | } |
445 | 443 |
|
446 | 444 | if (commit_result) { |
447 | | - // Name the resulting snapshot only when this commit produced one (current |
448 | | - // snapshot advanced); metadata-only commits report a plain success. |
| 445 | + // The builder contains only changes made by the successful attempt. Inspecting |
| 446 | + // AddSnapshot changes avoids attributing a concurrent writer's snapshot to this |
| 447 | + // transaction and also detects snapshots committed with StageOnly or ToBranch. |
449 | 448 | std::string detail; |
450 | | - if (auto snapshot = commit_result.value()->metadata()->Snapshot(); |
451 | | - snapshot.has_value() && |
452 | | - snapshot.value()->snapshot_id != base_current_snapshot_id) { |
453 | | - const auto& summary = snapshot.value()->summary; |
454 | | - auto op = summary.find(SnapshotSummaryFields::kOperation); |
455 | | - detail = |
456 | | - std::format(": committed snapshot {} (op={})", snapshot.value()->snapshot_id, |
457 | | - op != summary.end() ? op->second : "unknown"); |
| 449 | + const auto& changes = ctx_->metadata_builder->changes(); |
| 450 | + size_t added_snapshot_count = 0; |
| 451 | + for (const auto& change : changes) { |
| 452 | + added_snapshot_count += change->kind() == TableUpdate::Kind::kAddSnapshot; |
| 453 | + } |
| 454 | + if (added_snapshot_count > 0) { |
| 455 | + detail.reserve(32 + added_snapshot_count * 48); |
| 456 | + std::format_to(std::back_inserter(detail), ": committed snapshot{} ", |
| 457 | + added_snapshot_count == 1 ? "" : "s"); |
| 458 | + |
| 459 | + size_t appended_snapshot_count = 0; |
| 460 | + for (const auto& change : changes) { |
| 461 | + if (change->kind() != TableUpdate::Kind::kAddSnapshot) { |
| 462 | + continue; |
| 463 | + } |
| 464 | + const auto& snapshot = |
| 465 | + internal::checked_cast<const table::AddSnapshot&>(*change).snapshot(); |
| 466 | + if (appended_snapshot_count++ > 0) { |
| 467 | + detail += ", "; |
| 468 | + } |
| 469 | + const auto& summary = snapshot->summary; |
| 470 | + auto op = summary.find(SnapshotSummaryFields::kOperation); |
| 471 | + std::format_to(std::back_inserter(detail), "{} (op={})", snapshot->snapshot_id, |
| 472 | + op != summary.end() ? op->second : "unknown"); |
| 473 | + } |
458 | 474 | } |
459 | 475 | if (attempt > 1) { |
460 | 476 | ICEBERG_LOG_INFO("Transaction commit succeeded after {} attempts{}", attempt, |
461 | 477 | detail); |
462 | 478 | } else { |
463 | 479 | ICEBERG_LOG_INFO("Transaction commit succeeded{}", detail); |
464 | 480 | } |
465 | | - } else { |
466 | | - ICEBERG_LOG_ERROR("Transaction commit failed after {} attempt(s): {}", attempt, |
467 | | - commit_result.error().message); |
468 | 481 | } |
469 | 482 |
|
470 | 483 | if (!commit_result) { |
|
0 commit comments