/* * Copyright (c) 2009-2011, Salvatore Sanfilippo * * SPDX-FileCopyrightText: 2024 Hiredict Contributors * SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo * * SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: LGPL-3.0-or-later * */ #ifndef __HIREDICT_LIBHV_H__ #define __HIREDICT_LIBHV_H__ #include #include "../hiredict.h" #include "../async.h" typedef struct redictLibhvEvents { hio_t *io; htimer_t *timer; } redictLibhvEvents; static void redictLibhvHandleEvents(hio_t* io) { redictAsyncContext* context = (redictAsyncContext*)hevent_userdata(io); int events = hio_events(io); int revents = hio_revents(io); if (context && (events & HV_READ) && (revents & HV_READ)) { redictAsyncHandleRead(context); } if (context && (events & HV_WRITE) && (revents & HV_WRITE)) { redictAsyncHandleWrite(context); } } static void redictLibhvAddRead(void *privdata) { redictLibhvEvents* events = (redictLibhvEvents*)privdata; hio_add(events->io, redictLibhvHandleEvents, HV_READ); } static void redictLibhvDelRead(void *privdata) { redictLibhvEvents* events = (redictLibhvEvents*)privdata; hio_del(events->io, HV_READ); } static void redictLibhvAddWrite(void *privdata) { redictLibhvEvents* events = (redictLibhvEvents*)privdata; hio_add(events->io, redictLibhvHandleEvents, HV_WRITE); } static void redictLibhvDelWrite(void *privdata) { redictLibhvEvents* events = (redictLibhvEvents*)privdata; hio_del(events->io, HV_WRITE); } static void redictLibhvCleanup(void *privdata) { redictLibhvEvents* events = (redictLibhvEvents*)privdata; if (events->timer) htimer_del(events->timer); hio_close(events->io); hevent_set_userdata(events->io, NULL); hi_free(events); } static void redictLibhvTimeout(htimer_t* timer) { hio_t* io = (hio_t*)hevent_userdata(timer); redictAsyncHandleTimeout((redictAsyncContext*)hevent_userdata(io)); } static void redictLibhvSetTimeout(void *privdata, struct timeval tv) { redictLibhvEvents* events; uint32_t millis; hloop_t* loop; events = (redictLibhvEvents*)privdata; millis = tv.tv_sec * 1000 + tv.tv_usec / 1000; if (millis == 0) { /* Libhv disallows zero'd timers so treat this as a delete or NO OP */ if (events->timer) { htimer_del(events->timer); events->timer = NULL; } } else if (events->timer == NULL) { /* Add new timer */ loop = hevent_loop(events->io); events->timer = htimer_add(loop, redictLibhvTimeout, millis, 1); hevent_set_userdata(events->timer, events->io); } else { /* Update existing timer */ htimer_reset(events->timer, millis); } } static int redictLibhvAttach(redictAsyncContext* ac, hloop_t* loop) { redictContext *c = &(ac->c); redictLibhvEvents *events; hio_t* io = NULL; if (ac->ev.data != NULL) { return REDICT_ERR; } /* Create container struct to keep track of our io and any timer */ events = (redictLibhvEvents*)hi_malloc(sizeof(*events)); if (events == NULL) { return REDICT_ERR; } io = hio_get(loop, c->fd); if (io == NULL) { hi_free(events); return REDICT_ERR; } hevent_set_userdata(io, ac); events->io = io; events->timer = NULL; ac->ev.addRead = redictLibhvAddRead; ac->ev.delRead = redictLibhvDelRead; ac->ev.addWrite = redictLibhvAddWrite; ac->ev.delWrite = redictLibhvDelWrite; ac->ev.cleanup = redictLibhvCleanup; ac->ev.scheduleTimer = redictLibhvSetTimeout; ac->ev.data = events; return REDICT_OK; } #endif