Skip to content

Commit 5fd6698

Browse files
committed
adds index_location to sharding codec
1 parent 4990470 commit 5fd6698

File tree

1 file changed

+38
-24
lines changed

1 file changed

+38
-24
lines changed

docs/v3/codecs/sharding-indexed/v1.0.rst

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Sharding codec (version 1.0)
55
==========================================
66

7-
**Editor's draft 17 July 2023**
7+
**Editor's draft 02 November 2023**
88

99
Specification URI:
1010
https://zarr-specs.readthedocs.io/en/latest/v3/codecs/sharding-indexed/v1.0.html
@@ -25,12 +25,12 @@ is licensed under a `Creative Commons Attribution 3.0 Unported License
2525
Status of this document
2626
=======================
2727

28-
.. rst-class:: draft
28+
ZEP0002 was accepted on November 1st, 2023 via https://github.com/zarr-developers/zarr-specs/issues/254.
2929

3030
.. warning::
31-
This document is a draft for review and subject to changes.
31+
This document is subject to changes.
3232
It will become final when the `Zarr Enhancement Proposal (ZEP) 2 <https://zarr.dev/zeps/draft/ZEP0002.html>`_
33-
is approved via the `ZEP process <https://zarr.dev/zeps/active/ZEP0000.html>`_.
33+
is finalized via the `ZEP process <https://zarr.dev/zeps/active/ZEP0000.html>`_.
3434

3535

3636
Abstract
@@ -121,7 +121,8 @@ Sharding can be configured per array in the :ref:`array-metadata` as follows::
121121
}
122122
},
123123
{ "name": "crc32c" }
124-
]
124+
],
125+
"index_location": "end"
125126
}
126127
}
127128
]
@@ -155,6 +156,11 @@ Sharding can be configured per array in the :ref:`array-metadata` as follows::
155156
be used for index codecs. It is RECOMMENDED to use a little-endian codec
156157
followed by a crc32c checksum as index codecs.
157158

159+
``index_location``
160+
161+
Specifies whether the shard index is located at the beginning or end of the
162+
file. The parameter value must be either the string ``start`` or ``end``.
163+
158164
Definitions
159165
===========
160166

@@ -194,10 +200,11 @@ Empty inner chunks are interpreted as being filled with the fill value. The inde
194200
always has the full shape of all possible inner chunks per shard, even if they extend
195201
beyond the array shape.
196202

197-
The index is placed at the end of the file and encoded into binary representations
198-
using the specified index codecs. The byte size of the index is determined by the
199-
number of inner chunks in the shard ``n``, i.e. the product of chunks per shard, and
200-
the choice of index codecs.
203+
The index is either placed at the end of the file or at the beginning of the file,
204+
as configured by the ``index_location`` parameter. The index is encoded into binary
205+
representations using the specified index codecs. The byte size of the index is
206+
determined by the number of inner chunks in the shard ``n``, i.e. the product of
207+
chunks per shard, and the choice of index codecs.
201208

202209
For an example, consider a shard shape of ``[64, 64]``, an inner chunk shape of
203210
``[32, 32]`` and an index codec combination of a little-endian codec followed by
@@ -243,12 +250,13 @@ common optimizations.
243250

244251
* **Decoding**: A simple implementation to decode inner chunks in a shard would (a)
245252
read the entire value from the store into a byte buffer, (b) parse the shard
246-
index as specified above from the end of the buffer and (c) cut out the
247-
relevant bytes that belong to the requested chunk. The relevant bytes are
248-
determined by the ``offset,nbytes`` pair in the shard index. This bytestream
249-
then needs to be decoded with the inner codecs as specified in the sharding
250-
configuration applying the :ref:`decoding_procedure`. This is similar to how
251-
an implementation would access a sub-slice of a chunk.
253+
index as specified above from the beginning or end (according to the
254+
``index_location``) of the buffer and (c) cut out the relevant bytes that belong
255+
to the requested chunk. The relevant bytes are determined by the
256+
``offset,nbytes`` pair in the shard index. This bytestream then needs to be
257+
decoded with the inner codecs as specified in the sharding configuration applying
258+
the :ref:`decoding_procedure`. This is similar to how an implementation would
259+
access a sub-slice of a chunk.
252260

253261
The size of the index can be determined by applying ``c.compute_encoded_size``
254262
for each index codec recursively. The initial size is the byte size of the index
@@ -260,25 +268,31 @@ common optimizations.
260268

261269
If the underlying store supports partial reads, the decoding of single inner
262270
chunks can be optimized. In that case, the shard index can be read from the
263-
store by requesting the ``n`` last bytes, where ``n`` is the size of the index
264-
as determined by the number of inner chunks in the shard and choice of index
265-
codecs. After parsing the shard index, single inner chunks can be requested from
266-
the store by specifying the byte range. The bytestream, then, needs to be
267-
decoded as above.
271+
store by requesting the ``n`` first or last bytes (according to the
272+
``index_location``), where ``n`` is the size of the index as determined by
273+
the number of inner chunks in the shard and choice of index codecs. After
274+
parsing the shard index, single inner chunks can be requested from the store
275+
by specifying the byte range. The bytestream, then, needs to be decoded as above.
268276

269277
* **Encoding**: A simple implementation to encode a chunk in a shard would (a)
270278
encode the new chunk per :ref:`encoding_procedure` in a byte buffer using the
271279
shard's inner codecs, (b) read an existing shard from the store, (c) create a
272280
new bytestream with all encoded inner chunks of that shard including the overwritten
273-
chunk, (d) generate a new shard index that is appended to the chunk bytestream
274-
and (e) writes the shard to the store. If there was no existing shard, an
275-
empty shard is assumed. When writing entire inner chunks, reading the existing shard
276-
first may be skipped.
281+
chunk, (d) generate a new shard index that is prepended or appended (according
282+
to the ``index_location``) to the chunk bytestream and (e) writes the shard to
283+
the store. If there was no existing shard, an empty shard is assumed. When
284+
writing entire inner chunks, reading the existing shard first may be skipped.
277285

278286
When working with inner chunks that have a fixed byte size (e.g., uncompressed) and
279287
a store that supports partial writes, a optimization would be to replace the
280288
new chunk by writing to the store at the specified byte range.
281289

290+
On stores with random-write capabilities, it may be useful to (a) place the shard
291+
index at the beginning of the file, (b) write out inner chunks in
292+
application-specific order, and (c) update the shard index accordingly.
293+
Synchronization of parallelly written inner chunks needs to be handled by the
294+
application.
295+
282296
Other use case-specific optimizations may be available, e.g., for append-only
283297
workloads.
284298

0 commit comments

Comments
 (0)