clickhouse-posix-io.h

chc_io backend over blocking read(2) / write(2). EINTR is looped internally. write loops until all bytes are flushed; read may short-read & lets chc_block_read / the TCP loop’s buffered input layer handle assembly.

Exactly one TU defines CHC_IMPLEMENTATION before including. Depends on clickhouse.h.

typedef struct chc_posix_io {
    int      fd;
    bool   (*check_cancel)(void *ud);
    void    *cancel_ud;
    int64_t  deadline_us;   /* absolute CLOCK_MONOTONIC us; 0 disables */
} chc_posix_io;

void chc_posix_io_init(chc_posix_io *state, chc_io *out_io, int fd,
                       bool (*check_cancel)(void *), void *cancel_ud);

void chc_posix_io_set_deadline(chc_posix_io *state, int64_t deadline_us);

state is caller-owned (typically stack); the filled chc_io references it via ud, so state must outlive out_io. Library never closes fd.

check_cancel is optional. When non-NULL, it’s wrapped into the chc_io check_cancel slot — polled between reads, non-zero aborts the current operation with CHC_ERR_CANCELLED. PG callers wire this to QueryCancelPending || ProcDiePending.

Caller is responsible for socket(), connect(), setsockopt, timeouts, non-blocking mode, etc. — same posture as clickhouse-openssl.h. For non-blocking sockets, callers wanting WaitLatchOrSocket/epoll should roll their own chc_io rather than use this header.

Read deadline

chc_posix_io_set_deadline bounds later reads by an absolute CLOCK_MONOTONIC microsecond timestamp; 0 (the init default) disables it. Before each blocking read(2) the backend poll(2)s the fd until readable or the deadline passes; on expiry the read fails with CHC_ERR_IO & a read timeout message. EINTR during the wait is looped; write is not bounded.

Deadline is absolute & shared across reads until changed. Set before each logical operation (e.g. a packet read).