Repository: valkey-io/valkey
File: src/cluster_legacy.c (C)

Code before:
    node->is_node_healthy = 0;
    return node;
}

/* 8 bytes mstime + 8 bytes cluster node */
#define FAILURE_REPORT_ST_KEYLEN 16

/* The expiry time is rounded up (ceiled) to the nearest second in order to bucket
 * timestamps and keep the radix‐tree keys compact.  The resulting timestamp is stored
 * in big‑endian format, followed by the pointer to the clusterNode. */
static void encodeFailureReportKey(unsigned char *buf, mstime_t expiry, clusterNode *node) {
    mstime_t bt = ((expiry + 999) / 1000) * 1000;
    uint64_t be = htonu64((uint64_t)bt);
    memcpy(buf, &be, 8);
    memcpy(buf + 8, &node, sizeof(node));
    if (sizeof(node) == 4) memset(buf + 12, 0, 4);
}

/* Reverses the operation of encodeFailureReportKey, reading back a timestamp
 * and the pointer to the associated clusterNode. */
static void decodeFailureReportKey(unsigned char *buf, mstime_t *expiry_ptr, clusterNode **node_ptr) {
    uint64_t be;
    memcpy(&be, buf, 8);
    *expiry_ptr = (mstime_t)ntohu64(be);
    memcpy(node_ptr, buf + 8, sizeof(*node_ptr));
}

/* This function is called every time we get a failure report from a node.
 * We maintain fail_reports as a radix tree keyed by bucketed expiry timestamp
 * (ceiled to the next second) and the sender pointer, which naturally orders
 * entries by expiry time.
 *
 * 'failing' is the node that is in failure state according to the
 * 'sender' node.
 *
 * The function returns 0 if it just updates a timestamp of an existing
 * failure report from the same sender. 1 is returned if a new failure
 * report is created. */
int clusterNodeAddFailureReport(clusterNode *failing, clusterNode *sender) {
    unsigned char buf[FAILURE_REPORT_ST_KEYLEN];
    mstime_t now = mstime();
    int is_new = 1;

    /* Look for any existing entry from this sender and remove it */
    raxIterator ri;
    raxStart(&ri, failing->fail_reports);
    raxSeek(&ri, "^", NULL, 0);
    while (raxNext(&ri)) {
        mstime_t stored_ts;
        clusterNode *stored_sender;
        decodeFailureReportKey(ri.key, &stored_ts, &stored_sender);

Review comment (suggestion):
Let's not use magic number like `8` here rather depend on sizeof to determine the bytes to copy or seek.

Code after:
    node->is_node_healthy = 0;
    return node;
}

/* 8 bytes mstime + 8 bytes cluster node pointer (padded with zeros on 32-bit systems). */
#define FAILURE_REPORT_KEYLEN 16
#define SEC_IN_MS 1000ULL
#define CEIL_OFFSET_MS (SEC_IN_MS - 1)

/* The report time is rounded up (ceiled) to the nearest second in order to bucket
 * timestamps and keep the radix‐tree keys compact.  The resulting timestamp is stored
 * in big‑endian format, followed by the pointer to the clusterNode. */
static void encodeFailureReportKey(clusterNode *node, mstime_t report_time, unsigned char *buf_out) {
    const size_t node_ptr_pad_bytes = (sizeof(clusterNode *) == 4) ? 4 : 0; // pad on 32-bit

    /* Round up to the next second for fewer key splits and quorum grace */
    mstime_t bucketed_time = (report_time / SEC_IN_MS) * SEC_IN_MS + SEC_IN_MS;

    /* Big endian timestamp for numeric time order in rax */
    uint64_t big_endian_time = htonu64((uint64_t)bucketed_time);
    memcpy(buf_out, &big_endian_time, sizeof(uint64_t));

    /* Append the node pointer, plus padding if necessary */
    memcpy(buf_out + sizeof(uint64_t), &node, sizeof(node));
    if (node_ptr_pad_bytes) memset(buf_out + sizeof(uint64_t) + sizeof(node), 0, node_ptr_pad_bytes);
}

/* Reverses the operation of encodeFailureReportKey, reading back a timestamp
 * and the pointer to the associated clusterNode. */
static void decodeFailureReportKey(unsigned char *buf, mstime_t *report_time, clusterNode **node_ptr) {
    uint64_t big_endian_time;
    memcpy(&big_endian_time, buf, sizeof(uint64_t));
    *report_time = (mstime_t)ntohu64(big_endian_time);
    memcpy(node_ptr, buf + sizeof(uint64_t), sizeof(*node_ptr));
}

/* This function is called every time we get a failure report from a node.
 * We maintain fail_reports as a radix tree keyed by bucketed timestamp
 * (ceiled to the next second) and the sender pointer, which naturally orders
 * entries by time.
 *
 * 'failing' is the node that is in failure state according to the
 * 'sender' node.
 *
 * The function returns 0 if it early‐exits (same sender & time bucket)
 * or updates a timestamp of an existing failure report from the same sender.
 * 1 is returned if a new failure report is created. */
int clusterNodeAddFailureReport(clusterNode *failing, clusterNode *sender) {
    unsigned char buf[FAILURE_REPORT_KEYLEN];
    mstime_t now = mstime();
    const mstime_t bucketed_time = (now / SEC_IN_MS) * SEC_IN_MS + SEC_IN_MS;