peterxcli opened a new pull request, #11140:
URL: https://github.com/apache/ozone/pull/11140
## What changes were proposed in this pull request?
S3 `CopyObject` in Ozone streams every byte of the source key from the
datanodes
through the S3 Gateway and writes it back as a new key, so copy latency is
proportional to object size. There is no server side copy RPC in OM, which is
why `ozone sh key cp` is a client side stream copy for the same reason.
This adds an OM `CopyKey` request that creates the destination key from the
source key's committed block list, so a copy moves no data at all.
### Why this is not just a new request
Committed blocks are owned by exactly one key and there is no reference
counting in OM or SCM. Deleting or overwriting either key would move the
shared
blocks to `deletedTable`, `KeyDeletingService` would hand them to SCM, and
the
surviving key would silently stop being readable, because a datanode asked to
delete an already deleted block succeeds quietly. The one existing
protection,
`OMKeyRequest.filterOutBlocksStillInUse`, only compares against the new
version
of the *same* key.
### Approach
* an optional `sharedBlockGroupId` on `KeyInfo` (field 23). Zero, the default
for every existing key, means the key owns its blocks exclusively, so no
database needs backfilling. A non-zero value is the `objectID` of the
lineage
root, and copies of copies join the group their source already belongs to.
* a `sharedBlockGroupTable` column family holding **one sharer count per copy
lineage, not one row per block**: copying a key with ten thousand blocks
costs
a single row.
* `KeyDeletingService` consults that count at the single point where
`deletedTable` entries become SCM block deletions. While a sharer outside
the
batch is alive, the blocks are withheld from the SCM call and the entry
gets a
synthetic success, exactly as empty keys already do, so the metadata is
purged
and the blocks are not. When the whole group dies together, one member
releases the blocks and the rest are withheld so SCM is told once.
* the count drop rides the same Ratis transaction as the purge, carried by
the
final `PurgeKeysRequest` batch on purpose: losing that batch after the rows
were purged leaks blocks, which an audit can reclaim, whereas decrementing
first and then failing to purge would let a retry decrement twice and
release
blocks a live key still uses.
**No block release producer changes**, because the tag travels with
`OmKeyInfo`
into `deletedTable` through `OmUtils.prepareKeyForDelete`. Every failure
direction degrades to a leak rather than to data loss, which is the main
reason
for preferring this over a per-block reference count that plain delete, bulk
delete, commit overwrite, multipart complete, FSO directory purge and open
key
cleanup would each have to maintain correctly.
A copy still falls back to reading and rewriting the data when the source is
encrypted (block data is ciphertext under the source key's own DEK and IV),
GDPR
enforced (erasure destroys the key's own secret), or hsync active, when the
replication config would change (the read path picks the EC or Ratis stream
from
the key's own config), and for `UploadPartCopy`, which cannot express a byte
range as whole object sharing.
Design doc: `hadoop-hdds/docs/content/design/server-side-copy-key.md`
### Scope, and what is deliberately missing
This is a **proof of concept**, opened as a draft for design feedback rather
than for merge. It covers `OBJECT_STORE` buckets, same bucket, no destination
overwrite.
Required before it could merge, and not done here:
* **`OMLayoutFeature` gating.** This is the load-bearing guard: an older OM
treats the tag as an unknown proto field and would reclaim shared blocks
normally, which is silent data loss. Finalization is the only thing that
can
prevent a downgrade from doing that.
* cross-bucket copy (needs ordered multi-bucket locking), destination
overwrite,
FSO buckets, `OzoneManagerVersion` negotiation, an `ozone repair om` audit
that
rebuilds counts by scanning for tags, Recon awareness, and S3 Gateway
wiring
with fallback.
### Relation to HDDS-569
[HDDS-569](https://issues.apache.org/jira/browse/HDDS-569) proposed the same
thing in 2018 and states the copy "in ozone world, this is just a metadata
change", but its two attached patches define proto messages only, and the
block
reclaim problem above was never addressed. Its proto predates
Ratis-replicated
OM requests, FSO and snapshots, so nothing there is reusable today.
## What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-16319
## How was this patch tested?
* New integration test in the existing `TestKeyPurging` suite,
`testCopiedKeyKeepsBlocksUntilLastSharerIsDeleted`: copies a key, asserts
both
keys name the same blocks with different `objectID`s and a shared group id
with a sharer count of two, deletes the source, waits for the count row to
disappear, and asserts the copy still reads back the original bytes before
deleting it too. The existing test in that class still passes.
* `BenchmarkCopyKey` compares both copy paths on a three-datanode
`MiniOzoneCluster` and separately verifies that source and copy have
identical
MD5 digests. It is named `Benchmark` rather than `Test` so surefire does
not
pick it up in CI.
| object size | read-and-rewrite copy | CopyKey | ratio |
|-------------|----------------------|---------|-------|
| 1 MiB | 117 ms | 7.5 ms | 16x |
| 16 MiB | 889 ms | 8.2 ms | 108x |
| 64 MiB | 2 983 ms | 6.7 ms | 446x |
| 256 MiB | 11 100 ms | 9.2 ms | 1204x |
The shape is the result rather than the ratios: `CopyKey` shows no trend
across a 256-fold size range because it is one OM Ratis transaction
whatever
the key holds. The ratios overstate a real cluster, where the byte copy
beats
the 18 to 23 MiB/s a single host manages; projecting from a realistic
100 MiB/s gives roughly 320x at 256 MiB and 1280x at 1 GiB.
* `TestOmMetadataManager`, `TestBucketLayoutAwareOMKeyFactory`,
`TestOMKeyPurgeRequestAndResponse` and `TestSnapshotDiffValueParser` pass
with
the updated expectations.
* `checkstyle.sh` clean; `rat.sh` reports nothing for the new files.
Generated-by: Claude Code (claude-fable-5)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]