#if !defined(_ZARRAY_H_) #define _ZARRAY_H_ 1 #include #include #include "mylock.h" #include "xlist.h" typedef void (*zarray_item_killer_t)(void*); typedef int (*zarray_iter_fn_t)(void*, void*); typedef int (*zarray_iter_skip_fn_t)(void*); typedef int (*zarray_find_cond_fn_t)(void*, va_list); typedef struct { mylock_t lock; int count; int pos; int caps; int delta; zarray_item_killer_t killer; void** data; } zarray_t; extern int zarray_init(zarray_t*, int, zarray_item_killer_t); extern int zarray_store(zarray_t*, void*); extern int zarray_clear(zarray_t*, int); extern int zarray_iter_ex(zarray_t*, zarray_iter_skip_fn_t, xlist_t*, void*); extern int zarray_iter(zarray_t*, zarray_iter_fn_t, void*); extern int zarray_del(zarray_t*, int); extern int zarray_put(zarray_t*, int, void*); extern int zarray_put_ex(zarray_t*, int, int*, void**); extern int zarray_get_ex(zarray_t*, int, int*, void**); extern void* zarray_get(zarray_t*, int); extern void* zarray_find(zarray_t*, zarray_find_cond_fn_t, ...); extern void zarray_fini(zarray_t*); typedef struct { int delta; destroy_fn_t datakiller; } xzarray_params_t; extern typeinfo_t xzarray_type; /* job-array-single-wal-record task 7.1 (bug-1443): pre-grows an xzarray_type * instance's backing value store for `n` additional entries, by calling the * existing, unmodified xzarray_ensure_items(a, a->count + n) internally -- * zero changes to xzarray_ensure_items or any other existing function in * this file. This is the primitive kvmgr_reserve() (kvmgr.c/kvmgr.h) uses to * pre-grow c->jobmgr's backing xzarray_type instance (kvm->data) before a * bulk-insert pass, closing the DOMINANT, N-scaling failure mode for that * pass (the large realloc() reachable through vstore -> * xzarray_ensure_items). It does NOT make every subsequent vstore() call * unconditionally infallible: this only covers the value-store side -- * xkvmgr_type's separate kvtab key->index table (kv.c) has its own, * independent, much smaller, non-N-scaling per-entry allocation that this * function does not and cannot pre-reserve. * * Caller MUST hold the same write lock the subsequent bulk vstore()/ * key_add() calls will be made under, for the full duration of this call -- * identical contract to kvmgr_capture_keys() (kvmgr.h). * * Returns 1 on success (capacity already sufficient, or successfully * grown). Returns -EINVAL for a NULL array or negative n. Returns -ENOMEM if * the underlying growth allocation fails. */ extern int xzarray_reserve(var array, int n); #ifdef XCE_TESTING /* Test-only fault injection for xzarray_reserve() (job-array-single-wal- * record task 7.1 / bug-1443). When engaged, EVERY subsequent * xzarray_reserve() call -- across any xzarray_type instance, including one * wrapped inside an xkvmgr_type via kvmgr_reserve() -- reports a simulated * allocation failure (-ENOMEM) without touching the real array. File-scope, * not per-instance: mirrors job.c's own * job_array_apply_test_set_bulk_insert_force_fail_at() convention (this * feature's own established #ifdef XCE_TESTING test-only-symbol style). * * NOTE on why these declarations, unlike job.c's own #ifdef XCE_TESTING * seams, are guarded here but their DEFINITIONS (zarray.c) are NOT: zarray.c * is compiled exactly once, as part of the shared `libxce` static_library() * target (src/lib/meson.build), without -DXCE_TESTING -- unlike job.c, which * every consumer (including test binaries) recompiles from source with its * own c_args. Guarding the .c definitions the same way would silently drop * them from libxce.a in every build, including test builds that need them * (confirmed empirically). So the underlying symbols are unconditionally * present in the compiled library; only these DECLARATIONS are gated, which * keeps them un-prototyped (hence uncallable without a compiler error) from * any translation unit that does not itself define XCE_TESTING -- i.e. every * production source file. */ extern void xzarray_reserve_test_set_force_fail(void); extern void xzarray_reserve_test_clear_force_fail(void); /* Test-only introspection: returns the CURRENT backing-store capacity (item * slots, not bytes) of an xzarray_type instance. xzarray_t is fully opaque * outside zarray.c, so this is the only way a test can observe whether a * reservation actually grew capacity ahead of need, as opposed to deferring * growth to the next vstore() call. Returns -EINVAL for a NULL array. See * the NOTE above -- declaration-gated, not definition-gated, for the same * shared-library build reason. */ extern int xzarray_test_get_caps(var array); #endif #endif