synology_apm_repo.sdk.format.addressing module¶
Chunk addressing and the two path-layering schemes that key off it (FORMAT-SPEC.md §3, its composition-splitting section).
Directory-name constants (Pool, Composition, …) are not decided
here — those are repository-root layout constants that belong to the Dedup
Layer’s repository.py (FORMAT-SPEC.md: repo-root-layout’s repository-root layout).
This module only computes the id-layering fragment relative to whichever
root the caller prepends.
- class synology_apm_repo.sdk.format.addressing.ChunkAddress(stream_id, bucket_id, chunk_idx)¶
Bases:
NamedTupleA single
uint64chunk address:streamID(8b) | bucketID(40b) | chunkIdx(16b)(FORMAT-SPEC.md: ChunkAddress).Trusts its fields — neither construction nor
from_intrange-checks them. An out-of-range field either surfaces naturally downstream (an over-capacitychunk_idxraisesIndexError; a bogusbucket_idresolves to a missing path and raisesNotFoundError) or is the job ofunits/verify_reachable.py’s dedicated checks (chunk-mapmapCrc, per-chunk fingerprint), which are already verify-only and never run on the ordinary read/export path. This matters at scale:advanceruns once per real chunk in an export — millions of times for a large disk — reconstructing a value that is, by construction, already correct.Same deliberate
NamedTuple-not-@dataclass(frozen=True)exception asSizeStoreEntry— see there for the reasoning.- classmethod from_int(data)¶
Unpack a raw
uint64chunk address — doesn’t range-check the result, same as construction (see the class docstring).
- to_int()¶
- advance(k)¶
Advance by
kchunks, carrying intobucket_idwhenchunk_idxwould reachBUCKET_MAX_CHUNK_NUM(8192). This is the semantics needed to expand aChunkMapKind.MAPPINGchunk-map entry’smap_num * (1 + repeat)run of chunks starting from this address; it must never be approximated as “add k to the raw 64-bit integer”, which would misplace the carry at the packed field’s 16-bit boundary instead of the bucket’s real 8192-chunk capacity.
- synology_apm_repo.sdk.format.addressing.pool_layer_path(stream_id, bucket_id)¶
Relative path (no
Pool/prefix, no.buk/.inf/… suffix) forbucket_idwithinstream_id’s pool:<streamID>/[ancestor layers.../]<bucketID>(FORMAT-SPEC.md: pool-path-layering).For a
.inf/.fgp/.refgroup path, pass the group’s starting bucket id (bucket_id & ~(GROUP_BUCKET_NUM - 1)), not an individual bucket’s own id.
- synology_apm_repo.sdk.format.addressing.composition_session_dir(stream_id, session_id)¶
Relative path (no
Composition/prefix) to a session’s directory:<streamID>/[ancestor layers.../]<sessionID>.com(FORMAT-SPEC.md: composition-splitting) — the leaf component carries the.comsuffix rather than being a bare decimal number, unlike the Pool leaf.
- synology_apm_repo.sdk.format.addressing.composition_path(stream_id, session_id, sub_id)¶
Full relative path (no
Composition/prefix, no sequence-id suffix) to a composition sub-file:<sessionDir>/[ancestor layers.../]c<subID>(FORMAT-SPEC.md: composition-splitting).
- synology_apm_repo.sdk.format.addressing.split_layer_leaf(layer_path)¶
Split a
pool_layer_path()/composition_path()result into(dir_part, leaf)— the ancestor-layer directory and the final path component, which every caller resolving a physical file under it needs separately (a leaf-only suffix to append, a directory to generation-resolve within).dir_partis""whenlayer_pathhas no ancestor layers (id fits in one layer); pass it tojoin_pathrather than concatenating with"/"directly, since that tolerates the empty case.
- synology_apm_repo.sdk.format.addressing.split_composition_offset(global_offset)¶
Split a composition-record global offset into
(sub_id, offset_within_subfile)—sub_id = off >> 24,sub_off = off & (16MiB - 1)(FORMAT-SPEC.md: composition-splitting).
- synology_apm_repo.sdk.format.addressing.group_start_bucket_id(bucket_id)¶
The starting bucket id of the 1024-bucket group
bucket_idbelongs to:bucket_id & ~(GROUP_BUCKET_NUM - 1).