Skip to content

HDDS-15946. [Ozone versioning] [T2] VersionId generation strategy framework - #10845

Open
symious wants to merge 11 commits into
apache:HDDS-15728from
symious:HDDS-15946
Open

HDDS-15946. [Ozone versioning] [T2] VersionId generation strategy framework#10845
symious wants to merge 11 commits into
apache:HDDS-15728from
symious:HDDS-15946

Conversation

@symious

@symious symious commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

First 6 commits belong to HDDS-15879, can ignore them.

This ticket includes the follows tasks:

Sub-task Scope Acceptance
T2.1 interface + default generator VersionIdGenerator interface; TransactionIndexVersionIdGenerator; the ozone.om.versioning.version-id-generator class-name config, loaded reflectively shared contract test (strictly increasing / frozen / reserved ids) run against every generator; unknown class and class not implementing the interface both rejected; default generator carries no allocator state
T2.2 commit-time ordering check VersionIdAllocator: refuse a commit whose id does not come after the key's current version; fall back to a versionedKeyTable lookup for records predating versioning increasing id accepted; id at or below the current one rejected with INVALID_REQUEST; taken id on a pre-versioning record rejected with KEY_ALREADY_EXISTS; steady state performs no lookup (unit test asserts versionedKeyTable is never touched)
T2.3 pinned-first generator PinnedFirstVersionIdGenerator: first-version detection (no current in keyTable) + FIRST_VERSION_ID = 1 sentinel first PUT gets the sentinel, later PUTs get transaction indexes; sentinel sorts before every transaction index; sentinel does not collide with the null slot; selectable by configuration

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-15946

How was this patch tested?

Unit test

@symious symious changed the title Hdds 15946 HDDS-15946. [Ozone versioning] VersionId generation strategy framework Jul 23, 2026
@symious symious changed the title HDDS-15946. [Ozone versioning] VersionId generation strategy framework HDDS-15946. [Ozone versioning] [T2] VersionId generation strategy framework Jul 31, 2026
symious and others added 8 commits August 18, 2026 10:28
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…equest

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Key names in OBJECT_STORE buckets contain '/' verbatim, so a '/' separator
interleaves a key's versions with those of keys nested under it, breaking
the single-seek promotion and the merged ListObjectVersions order.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@symious
symious force-pushed the HDDS-15946 branch 2 times, most recently from 7358ce5 to 82a79e7 Compare August 20, 2026 01:52
Adds VersionIdGenerator, the pluggable source of the id an object version
is numbered with, and UniqueIdVersionIdGenerator as the cluster default.

The id is proposed on the OM that received the request, in preExecute, so
it travels in the replicated request and every OM applies a version that
is already numbered. Nothing about it depends on the transaction carrying
the write, or on OM being replicated by Ratis.

The default numbers a version with the time it was written, through the
scheme Ozone already uses for block local IDs: currentTimeMillis << 16
with a 16-bit counter separating ids proposed inside one millisecond. It
needs no allocator state and no coordination, which is what makes it safe
to read on any OM.

The interface has one abstract method, generateVersionId(), plus a default
versionIdFor(proposed, hasCurrentVersion) that lets a generator number
some versions specially at apply time. The implementation is selected
cluster-wide by ozone.om.versioning.version-id-generator.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
symious and others added 2 commits August 20, 2026 10:25
Adds VersionIdAllocator, which turns the id proposed for a version into
the id it is applied with.

versionedKeyTable orders a key's versions by Long.MAX_VALUE - versionId,
so the ids of one key have to increase in the order the versions were
written. A proposal is a clock reading and cannot promise that: ids
proposed inside one millisecond can exhaust the counter separating them,
and a leader change onto a lagging clock proposes a lower value.

So a proposal is a floor. The applied id is the later of it and the id
after the key's current version, which the write path already holds - no
read of its own, no global state, and identical on every OM. Under a clock
regression an affected key's ids climb by one until proposals overtake
them again: the versions stay ordered and only the id's reading as a time
degrades.

propose() runs in preExecute on the OM that received the request;
allocate() runs under the write's lock on every OM.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds PinnedFirstVersionIdGenerator, which numbers versions like the
default except that a key's first version takes FIRST_VERSION_ID, so it
can be referenced without listing the key's versions first.

Whether the key already has a version is not known when the id is
proposed, so the generator decides it in versionIdFor, under the write's
lock, from the current version the allocator was handed.

The sentinel is 1: below every proposed id, so a pinned version sorts at
the old end of the key in versionedKeyTable, and above the unset value a
pre-versioning record carries. It says nothing about the null version,
which carries a proposed id like any other and is marked by isNullVersion.

Known trade-off: once every version of a key has been permanently deleted,
a recreated key takes the sentinel again, so an external reference to the
first version resolves to the new content. The generator is off by default
and selected by ozone.om.versioning.version-id-generator.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant