2013-06-04 13:06:43 +00:00
|
|
|
#ifndef __HIREDIS_LIBUV_H__
|
|
|
|
#define __HIREDIS_LIBUV_H__
|
2014-07-09 20:38:50 +00:00
|
|
|
#include <stdlib.h>
|
2013-06-04 13:06:43 +00:00
|
|
|
#include <uv.h>
|
|
|
|
#include "../hiredis.h"
|
|
|
|
#include "../async.h"
|
2013-09-10 20:18:16 +00:00
|
|
|
#include <string.h>
|
2013-06-04 13:06:43 +00:00
|
|
|
|
|
|
|
typedef struct redisLibuvEvents {
|
|
|
|
redisAsyncContext* context;
|
|
|
|
uv_poll_t handle;
|
|
|
|
int events;
|
|
|
|
} redisLibuvEvents;
|
|
|
|
|
|
|
|
|
|
|
|
static void redisLibuvPoll(uv_poll_t* handle, int status, int events) {
|
|
|
|
redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
|
|
|
|
|
|
|
|
if (status != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-09-19 01:48:54 +00:00
|
|
|
if (p->context != NULL && (events & UV_READABLE)) {
|
2013-06-04 13:06:43 +00:00
|
|
|
redisAsyncHandleRead(p->context);
|
|
|
|
}
|
2016-09-19 01:48:54 +00:00
|
|
|
if (p->context != NULL && (events & UV_WRITABLE)) {
|
2013-06-04 13:06:43 +00:00
|
|
|
redisAsyncHandleWrite(p->context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void redisLibuvAddRead(void *privdata) {
|
|
|
|
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
|
|
|
|
|
|
|
p->events |= UV_READABLE;
|
|
|
|
|
|
|
|
uv_poll_start(&p->handle, p->events, redisLibuvPoll);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void redisLibuvDelRead(void *privdata) {
|
|
|
|
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
|
|
|
|
|
|
|
p->events &= ~UV_READABLE;
|
|
|
|
|
|
|
|
if (p->events) {
|
|
|
|
uv_poll_start(&p->handle, p->events, redisLibuvPoll);
|
|
|
|
} else {
|
|
|
|
uv_poll_stop(&p->handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void redisLibuvAddWrite(void *privdata) {
|
|
|
|
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
|
|
|
|
|
|
|
p->events |= UV_WRITABLE;
|
|
|
|
|
|
|
|
uv_poll_start(&p->handle, p->events, redisLibuvPoll);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void redisLibuvDelWrite(void *privdata) {
|
|
|
|
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
|
|
|
|
|
|
|
p->events &= ~UV_WRITABLE;
|
|
|
|
|
|
|
|
if (p->events) {
|
|
|
|
uv_poll_start(&p->handle, p->events, redisLibuvPoll);
|
|
|
|
} else {
|
|
|
|
uv_poll_stop(&p->handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void on_close(uv_handle_t* handle) {
|
|
|
|
redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
|
|
|
|
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void redisLibuvCleanup(void *privdata) {
|
|
|
|
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
|
|
|
|
2016-09-19 01:48:54 +00:00
|
|
|
p->context = NULL; // indicate that context might no longer exist
|
2013-06-04 13:06:43 +00:00
|
|
|
uv_close((uv_handle_t*)&p->handle, on_close);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-06 03:00:10 +00:00
|
|
|
static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {
|
2013-06-04 13:06:43 +00:00
|
|
|
redisContext *c = &(ac->c);
|
|
|
|
|
|
|
|
if (ac->ev.data != NULL) {
|
|
|
|
return REDIS_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ac->ev.addRead = redisLibuvAddRead;
|
|
|
|
ac->ev.delRead = redisLibuvDelRead;
|
|
|
|
ac->ev.addWrite = redisLibuvAddWrite;
|
|
|
|
ac->ev.delWrite = redisLibuvDelWrite;
|
|
|
|
ac->ev.cleanup = redisLibuvCleanup;
|
|
|
|
|
2013-09-10 20:18:16 +00:00
|
|
|
redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p));
|
2013-06-04 13:06:43 +00:00
|
|
|
|
|
|
|
if (!p) {
|
|
|
|
return REDIS_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
|
|
|
|
if (uv_poll_init(loop, &p->handle, c->fd) != 0) {
|
|
|
|
return REDIS_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ac->ev.data = p;
|
|
|
|
p->handle.data = p;
|
|
|
|
p->context = ac;
|
|
|
|
|
|
|
|
return REDIS_OK;
|
|
|
|
}
|
|
|
|
#endif
|