#if !defined(_XCEALLOC_H_) #define _XCEALLOC_H_ 1 #include #include #include "xce/types.h" extern xce_alloc_t* make_alloc(char*, char*, uint64_t, float, int); extern xce_host_alloc_t* make_host_alloc(char*, int, xce_alloc_t**); extern xce_job_alloc_t* make_job_alloc(uint64_t, int, xce_host_alloc_t**); extern xce_alloc_t** make_allocs(int, ...); extern xce_host_alloc_t** make_host_allocs(int, ...); extern xce_job_account_t* make_job_account(xce_job_alloc_t*); extern xce_job_alloc_t* dup_job_alloc(const xce_job_alloc_t*); extern int merge_job_alloc(xce_job_alloc_t*, const xce_job_alloc_t*); /* * Allocation equality: "do these two records describe the same allocation * decision". * * alloc_eq() compares, in this order: resname, reserve, value, duration, * from. `value` is compared exactly (`==`, no floating-point tolerance): both * sides are exact copies of the same double, so any difference is real. * `from` (the reservation start time) is compared: the scheduler stamps it * with the deciding session's start, which a replay reproduces. `instid` is * NOT compared: it comes from a per-process counter (sched_get_id()) whose * value depends on how many allocations that process built before, so a * recording and its replay give the same allocation different instids * (bug-1844). * * This is not merge_job_alloc()'s slot matching. merge_job_alloc() asks * "are these the same reservation slot to add into" (resname, instid, * reserve; value ignored because merging adds values), where instid IS * significant. Neither predicate can stand in for the other. * * host_alloc_eq() compares host, then nallocs, then allocs[i] in order. * job_alloc_eq() compares jobid, nhosts, nres_shared, then allocs[i] in * order, then allocs_shared[i] in order. Lists are order-sensitive: the same * entries in a different order are not equal. * * NULL handling: identical pointers (including two NULLs) are equal; exactly * one NULL argument, list entry or string field is not equal. Precondition: * a non-zero count with a NULL entry array is a malformed record and is not * handled. Neither argument is modified. * * `why` is optional. When NULL, nothing is allocated. Otherwise *why is set * to NULL when the arguments are equal, or to a newly allocated, * NUL-terminated description of the first difference found, in comparison * order, e.g. * allocs[1](host=h1).allocs[0](resname=mem).value: 2 != 3 * allocs[0](host=h0).host: "h0" != "h2" * allocs_shared[0]: NULL != non-NULL * nhosts: 1 != 2 * job_alloc: non-NULL != NULL (a NULL top-level argument) * Path labels come from `a`, from `b` when a's entry/string is NULL, or are * `?`. The caller owns the description and releases it with free(). The value * *why holds on entry is never read or freed. If allocating the description * fails, *why is NULL and the result is unchanged. Nothing is logged. * * Returns non-zero when equal, 0 when not. */ extern int alloc_eq(const xce_alloc_t* a, const xce_alloc_t* b, char** why); extern int host_alloc_eq(const xce_host_alloc_t* a, const xce_host_alloc_t* b, char** why); extern int job_alloc_eq(const xce_job_alloc_t* a, const xce_job_alloc_t* b, char** why); #endif