Skip to content

Commit dcfa3b8

Browse files
somfornotclaude
andauthored
feat(c-sdk): optional version/size fast-path and concurrent block reads (#564)
talon_read_async gains a version (const char*) and object_size (const uint64_t*) parameter pair, each independently nullable. NULL means the caller does not have that value. The read skips the StatObject control round trip only when BOTH are non-NULL, using the caller-supplied version and size; if either is NULL the SDK resolves both with a stat and ignores any lone value, since a read cannot skip the stat without both halves. Making object_size a pointer lets a caller that has a version but no valid size say so (NULL) instead of guessing, and disambiguates a real empty object (points to 0 -> zero-byte read, no stat) from "unknown" (NULL). When used, *object_size bounds the read at EOF: smaller than the range is a POSIX short read, larger surfaces as a clear worker error rather than fabricated bytes. The per-block fetches a multi-block read spans now run concurrently on the runtime (JoinSet over disjoint 'static sub-slices of the caller buffer) instead of a serial await loop, so a large read no longer pays one worker RTT per block in series. Header, smoke test, example, and the MinIO e2e are updated to the new signature; the e2e also adds a fast-path case that reuses the version and size from its stat. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent d7fad09 commit dcfa3b8

5 files changed

Lines changed: 390 additions & 32 deletions

File tree

clients/c/examples/async_read.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ int main(void) {
4747
pthread_cond_init(&ctx->cond, NULL);
4848

4949
uint64_t request_id = 0;
50+
/* version = NULL, object_size = NULL → the SDK resolves both with a stat. */
5051
int status = talon_read_async(
5152
client,
5253
"s3://bucket/path/object.bin",
5354
0,
5455
ctx->buffer,
5556
4096,
57+
NULL,
58+
NULL,
5659
on_read,
5760
ctx,
5861
&request_id);

clients/c/include/talon.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,30 @@ void talon_client_free(talon_client *client);
6767
* [dst, dst + dst_len) is exclusively owned by the SDK until the callback runs:
6868
* callers must not read, write, free, or reuse overlapping storage for another
6969
* operation during that interval. A zero-length read may pass NULL for dst.
70+
*
71+
* version and object_size are each optional and independently nullable; NULL
72+
* means the caller does not have that value. The read skips the StatObject round
73+
* trip only when BOTH are non-NULL, using the caller-supplied version and size
74+
* (the caller owns keeping them current for the object generation being read).
75+
* If either is NULL the SDK resolves both with a StatObject first and any lone
76+
* value supplied is ignored, since a read cannot skip the stat without both.
77+
*
78+
* When used, *object_size is the object's total byte length and bounds the read
79+
* at EOF (a POSIX short read): a value smaller than offset + dst_len yields a
80+
* short read, 0 denotes a genuinely empty object (an unambiguous zero-byte
81+
* read), and a value larger than the object surfaces as a read error rather than
82+
* fabricated bytes. A caller with no valid size passes NULL.
83+
*
84+
* Blocks spanned by the read are fetched concurrently.
7085
*/
7186
int talon_read_async(
7287
talon_client *client,
7388
const char *uri,
7489
uint64_t offset,
7590
uint8_t *dst,
7691
size_t dst_len,
92+
const char *version,
93+
const uint64_t *object_size,
7794
talon_callback callback,
7895
void *user_data,
7996
uint64_t *request_id_out);

0 commit comments

Comments
 (0)