void cleanup(void) { if(db) { redisAsyncFree(db); db = NULL; } sspCleanup(); }
redisAsyncContext * redis_nginx_open_context(u_char *host, int port, int database, u_char *password, redisAsyncContext **context) { redisAsyncContext *ac = NULL; if ((context == NULL) || (*context == NULL) || (*context)->err) { ac = redisAsyncConnect((const char *)host, port); if (ac == NULL) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "redis_nginx_adapter: could not allocate the redis context for %s:%d", host, port); return NULL; } if (ac->err) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "redis_nginx_adapter: could not create the redis context for %s:%d - %s", host, port, ac->errstr); redisAsyncFree(ac); return NULL; } redis_nginx_event_attach(ac); if (context != NULL) { *context = ac; } if(password) { redisAsyncCommand(ac, redis_nginx_auth_callback, context, AUTH_COMMAND, password); } redisAsyncCommand(ac, redis_nginx_select_callback, context, SELECT_DATABASE_COMMAND, database); } else { ac = *context; } return ac; }
RedisProxy::~RedisProxy() { /* if (_connected && nullptr != _context) { redisAsyncDisconnect(_context); }*/ if (nullptr != _context) { redisAsyncFree(_context); _context = nullptr; } }
static void dispatch_conn_context_deinit(conn_context *cc) { if (cc->ctx) { redisFree(cc->ctx); cc->ctx == NULL; } if (cc->actx) { redisAsyncFree(cc->actx); cc->actx == NULL; } }
void redis_nginx_auth_callback(redisAsyncContext *ac, void *rep, void *privdata) { redisAsyncContext **context = privdata; redisReply *reply = rep; if ((reply == NULL) || (reply->type == REDIS_REPLY_ERROR)) { if (context != NULL) { *context = NULL; } ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "redis_nginx_adapter: AUTH command failed, probably because the password is incorrect"); redisAsyncFree(ac); } }
void redis_nginx_select_callback(redisAsyncContext *ac, void *rep, void *privdata) { //redisAsyncContext **context = privdata; redisReply *reply = rep; if ((reply == NULL) || (reply->type == REDIS_REPLY_ERROR)) { /*if (context != NULL) { *context = NULL; }*/ ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "redis_nginx_adapter: could not select redis database"); redisAsyncFree(ac); } }
static void lua_redis_fin (void *arg) { struct lua_redis_userdata *ud = arg; if (ud->ctx) { ud->terminated = 1; redisAsyncFree (ud->ctx); lua_redis_free_args (ud); event_del (&ud->timeout); luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref); } }
/** * Detect disconnection of a pub/sub client. We need to clean up the command. */ void on_http_disconnect(struct evhttp_connection *evcon, void *ctx) { struct pubsub_client *ps = ctx; (void)evcon; /* clean up redis object */ redisAsyncFree(ps->s->ac); /* clean up command object */ if(ps->cmd) { cmd_free(ps->cmd); } free(ps); }
/** \brief QUIT command * Emits and awaits response for an async QUIT command. * It's used to disconnect with redis * \param ctx redis context */ static void SCLogAsyncRedisSendQuit(SCLogRedisContext * ctx) { if (ctx->connected) { redisAsyncCommand(ctx->async, SCRedisAsyncQuitCommandCallback, ctx, "QUIT"); SCLogInfo("QUIT Command sent to redis. Connection will terminate!"); } redisAsyncFree(ctx->async); event_base_dispatch(ctx->ev_base); ctx->async = NULL; event_base_free(ctx->ev_base); ctx->ev_base = NULL; ctx->connected = 0; }
void RedisProxy::connect() { if(_connected) { return; } SLOG(DEBUG) << "redis connect begin..."; _context = redisAsyncConnect(_ip.c_str(), _port); if(!_context) { SLOG(WARNING) << "allocate redis async connection fail!"; return; } if(_context->err != 0) { SLOG(WARNING) << "connect fail[" << _context->err << "]"; redisAsyncFree(_context); _context = nullptr; return; } _context->data = this; _context->ev.data = this; _context->ev.addRead = RedisProxy::redis_add_read; _context->ev.delRead = RedisProxy::redis_del_read; _context->ev.addWrite = RedisProxy::redis_add_write; _context->ev.delWrite = RedisProxy::redis_del_write; _context->ev.cleanup = RedisProxy::redis_cleanup; _read_io = std::make_shared<IO>(_context->c.fd, EV_READ, false);//FIXME:add EV_ET in future _read_io->on_read([this]() { LOG(INFO) << "on read"; redisAsyncHandleRead(_context); }); _write_io = std::make_shared<IO>(_context->c.fd, EV_WRITE, false);//FIXME:add EV_ET in future LOG(INFO) << "redis fd:" << _context->c.fd; _write_io->on_write([this]() { LOG(INFO) << "on write"; redisAsyncHandleWrite(_context); }); _connected = get_local_loop()->add_io(_read_io, false) && get_local_loop()->add_io(_write_io, false); redisAsyncSetConnectCallback(_context, RedisProxy::handle_connect); redisAsyncSetDisconnectCallback(_context, RedisProxy::handle_disconnect); }
int RedisConnectionAsync::asyncConnect() { _ac = redisAsyncConnect(_host.c_str(), _port); if (_ac == nullptr) return -1; _ac->data = (void*)this; if (_ac->err) { redisAsyncFree(_ac); _ac = nullptr; return -1; // throw RedisException((std::string)"RedisAsyncConnect: "+_ac->errstr); } if (redisAsyncSetConnectCallback(_ac, &connected)!=REDIS_OK || redisAsyncSetDisconnectCallback(_ac, &disconnected)!=REDIS_OK) { redisAsyncFree(_ac); _ac = nullptr; return -1; // throw RedisException("RedisAsyncConnect: Can't register callbacks"); } #if HIREDISPP_USE_LIBEVENT if (redisLibeventAttach(_ac, (struct event_base *)_loopbase)!=REDIS_OK) { redisAsyncFree(_ac); _ac = nullptr; return -1; // throw RedisException("redisLibeventAttach: nothing should be attached when something is already attached"); } // Send PING command, so libevent start working redisAsyncCommand(_ac, nullptr, nullptr, "PING"); #else // actually start io proccess ev_io_start(EV_DEFAULT, &((((redisLibevEvents*)(_ac->ev.data)))->rev)); ev_io_start(EV_DEFAULT, &((((redisLibevEvents*)(_ac->ev.data)))->wev)); #endif return 0; }
/** * @brief Stop eredis and free all ressources allocated * * @param e eredis */ void eredis_free( eredis_t *e ) { int i; char *s; eredis_reader_t *r; /* Flag for shutdown */ SET_SHUTDOWN(e); /* Loop trash */ if (e->loop) { if (IS_INTHR( e )) /* Thread - wait to EVBREAK_ALL */ pthread_join( e->async_thr, NULL ); else /* Re-run loop until EVBREAK_ALL */ eredis_run( e ); ev_loop_destroy( e->loop ); e->loop = NULL; } /* Shutdown what's left */ for (i=0; i<e->hosts_nb; i++) { host_t *h = &e->hosts[i]; if (h->async_ctx) redisAsyncFree( h->async_ctx ); free(h->target); } free(e->hosts); /* Clear rqueue */ while ((r = _eredis_rqueue_shift( e ))) { if (r->free) _eredis_reader_free( r ); else fprintf(stderr,"eredis: eredis_free: reader not in 'free' state!?\n"); } /* Clear wqueue */ while ((s = _eredis_wqueue_shift( e, NULL ))) free(s); pthread_mutex_destroy( &e->async_lock ); pthread_mutex_destroy( &e->reader_lock ); pthread_cond_destroy( &e->reader_cond ); free(e); }
void rspamd_redis_finalize_learn (struct rspamd_task *task, gpointer runtime, gpointer ctx) { struct redis_stat_runtime *rt = REDIS_RUNTIME (runtime); redisAsyncContext *redis; if (event_get_base (&rt->timeout_event)) { event_del (&rt->timeout_event); } if (rt->redis) { redis = rt->redis; rt->redis = NULL; redisAsyncFree (redis); } }
/* Called on connection termination */ static void rspamd_redis_cache_fin (gpointer data) { struct rspamd_redis_cache_runtime *rt = data; redisAsyncContext *redis; rt->has_event = FALSE; if (event_get_base (&rt->timeout_event)) { event_del (&rt->timeout_event); } if (rt->redis) { redis = rt->redis; rt->redis = NULL; /* This calls for all callbacks pending */ redisAsyncFree (redis); } }
/** \brief SCConfLogReopenAsyncRedis() Open or re-opens connection to redis for logging. * \param log_ctx Log file context allocated by caller */ static int SCConfLogReopenAsyncRedis(LogFileCtx *log_ctx) { SCLogRedisContext * ctx = log_ctx->redis; const char *redis_server = log_ctx->redis_setup.server; int redis_port = log_ctx->redis_setup.port; /* only try to reconnect once per second */ if (ctx->tried >= time(NULL)) { return -1; } ctx->async = redisAsyncConnect(redis_server, redis_port); if (ctx->ev_base != NULL) { event_base_free(ctx->ev_base); } if (ctx->async == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Error allocate redis async."); ctx->tried = time(NULL); return -1; } if (ctx->async != NULL && ctx->async->err) { SCLogError(SC_ERR_SOCKET, "Error setting to redis async: [%s].", ctx->async->errstr); ctx->tried = time(NULL); return -1; } ctx->ev_base = event_base_new(); if (ctx->ev_base == NULL) { ctx->tried = time(NULL); redisAsyncFree(ctx->async); ctx->async = NULL; return -1; } redisLibeventAttach(ctx->async, ctx->ev_base); log_ctx->redis = ctx; log_ctx->Close = SCLogFileCloseRedis; return 0; }
static void rspamd_redis_fin_learn (gpointer data) { struct redis_stat_runtime *rt = REDIS_RUNTIME (data); redisAsyncContext *redis; rt->has_event = FALSE; /* Stop timeout */ if (event_get_base (&rt->timeout_event)) { event_del (&rt->timeout_event); } if (rt->redis) { redis = rt->redis; rt->redis = NULL; /* This calls for all callbacks pending */ redisAsyncFree (redis); } }
static void rspamd_redis_async_cbdata_cleanup (struct rspamd_redis_stat_cbdata *cbdata) { guint i; gchar *k; if (cbdata && !cbdata->wanna_die) { /* Avoid double frees */ cbdata->wanna_die = TRUE; redisAsyncFree (cbdata->redis); for (i = 0; i < cbdata->cur_keys->len; i ++) { k = g_ptr_array_index (cbdata->cur_keys, i); g_free (k); } g_ptr_array_free (cbdata->cur_keys, TRUE); if (cbdata->elt) { cbdata->elt->cbdata = NULL; /* Re-enable parent event */ cbdata->elt->async->enabled = TRUE; /* Replace ucl object */ if (cbdata->cur) { if (cbdata->elt->stat) { ucl_object_unref (cbdata->elt->stat); } cbdata->elt->stat = cbdata->cur; cbdata->cur = NULL; } } if (cbdata->cur) { ucl_object_unref (cbdata->cur); } g_slice_free1 (sizeof (*cbdata), cbdata); } }
static void rspamd_redis_timeout (gint fd, short what, gpointer d) { struct redis_stat_runtime *rt = REDIS_RUNTIME (d); struct rspamd_task *task; redisAsyncContext *redis; task = rt->task; msg_err_task_check ("connection to redis server %s timed out", rspamd_upstream_name (rt->selected)); rspamd_upstream_fail (rt->selected); if (rt->redis) { redis = rt->redis; rt->redis = NULL; /* This calls for all callbacks pending */ redisAsyncFree (redis); } }
static int lua_create_client(lua_State *L) { lua_redis_client_t *lua_redis_client = NULL; redisAsyncContext *redis_async_context = NULL; luv_ref_t *ref; const char *host = luaL_checkstring(L, 1); int port = luaL_checkint(L, 2); redis_async_context = redisAsyncConnect(host, port); if(redis_async_context->err) { redisAsyncFree(redis_async_context); return luaL_error(L, redis_async_context->errstr); } redisLibevAttach(EV_DEFAULT_ redis_async_context); lua_redis_client = (lua_redis_client_t *)lua_newuserdata( L, sizeof(lua_redis_client_t)); lua_redis_client->redis_async_context = redis_async_context; luaL_getmetatable(L, LUA_REDIS_CLIENT_MT); lua_setmetatable(L, -2); lua_newtable(L); lua_setfenv(L, -2); ref = ref_alloc(); ref->L = L; lua_pushvalue(L, -1); ref->r = luaL_ref(L, LUA_REGISTRYINDEX); redis_async_context->data = ref; return 1; }
void _redis_close() { int outstanding = 0; if (handle) { if (handle->conn) { redisFree(handle->conn); } if (handle->async) { redisAsyncFree(handle->async); } if (handle->event_base){ event_base_loopbreak(handle->event_base); } if (handle->redis_thread){ pthread_cancel(handle->redis_thread); } g_mutex_free(handle->lock); g_free(handle->redis_ip); free(handle); handle = NULL; } }
ucl_object_t * rspamd_redis_get_stat (gpointer runtime, gpointer ctx) { struct redis_stat_runtime *rt = REDIS_RUNTIME (runtime); struct rspamd_redis_stat_elt *st; redisAsyncContext *redis; if (rt->ctx->stat_elt) { st = rt->ctx->stat_elt->ud; if (rt->redis) { redis = rt->redis; rt->redis = NULL; redisAsyncFree (redis); } if (st->stat) { return ucl_object_ref (st->stat); } } return NULL; }
/* Internal host connect - Sync or Async */ static int _host_connect( host_t *h, eredis_reader_t *r ) { redisContext *c; if (r) { /* Sync - not in EV context */ c = (h->port) ? redisConnect( h->target, h->port ) : redisConnectUnix( h->target ); if (! c) { fprintf(stderr, "eredis: error: connect sync %s NULL\n", h->target); return 0; } if (c->err) { #if EREDIS_VERBOSE>0 printf( "eredis: error: connect sync %s %d\n", h->target, c->err); #endif redisFree( c ); return 0; } r->ctx = c; r->host = h; } else { redisAsyncContext *ac; /* ASync - in EV context */ ac = (h->port) ? redisAsyncConnect( h->target, h->port ) : redisAsyncConnectUnix( h->target ); if (! ac) { printf( "eredis: error: connect async %s undef\n", h->target); return 0; } if (ac->err) { #if EREDIS_VERBOSE>0 printf( "eredis: error: connect async %s %d\n", h->target, ac->err); #endif redisAsyncFree( ac ); return 0; } h->async_ctx = ac; /* data for _redis_*_cb */ ac->data = h; /* Order is important here */ /* attach */ redisLibevAttach( h->e->loop, ac ); /* set callbacks */ redisAsyncSetDisconnectCallback( ac, _redis_disconnect_cb ); redisAsyncSetConnectCallback( ac, _redis_connect_cb ); c = (redisContext*) ac; } /* Apply keep-alive */ #ifdef HOST_TCP_KEEPALIVE if (h->port) { redisEnableKeepAlive( c ); if (r && (h->e->sync_to.tv_sec||h->e->sync_to.tv_usec)) { redisSetTimeout( c, h->e->sync_to ); } } #endif /* Override the maxbuf */ c->reader->maxbuf = EREDIS_READER_MAX_BUF; return 1; }
/*** * @function rspamd_redis.make_request({params}) * Make request to redis server, params is a table of key=value arguments in any order * @param {task} task worker task object * @param {ip} host server address * @param {function} callback callback to be called in form `function (task, err, data)` * @param {string} cmd command to be sent to redis * @param {table} args numeric array of strings used as redis arguments * @param {number} timeout timeout in seconds for request (1.0 by default) * @return {boolean} `true` if a request has been scheduled */ static int lua_redis_make_request (lua_State *L) { struct lua_redis_userdata *ud; struct rspamd_lua_ip *addr = NULL; struct rspamd_task *task = NULL; const gchar *cmd = NULL; gint top, cbref = -1; struct timeval tv; gboolean ret = FALSE; gdouble timeout = REDIS_DEFAULT_TIMEOUT; if (lua_istable (L, 1)) { /* Table version */ lua_pushstring (L, "task"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TUSERDATA) { task = lua_check_task (L, -1); } lua_pop (L, 1); lua_pushstring (L, "callback"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TFUNCTION) { /* This also pops function from the stack */ cbref = luaL_ref (L, LUA_REGISTRYINDEX); } else { msg_err ("bad callback argument for lua redis"); lua_pop (L, 1); } lua_pushstring (L, "cmd"); lua_gettable (L, -2); cmd = lua_tostring (L, -1); lua_pop (L, 1); lua_pushstring (L, "host"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TUSERDATA) { addr = lua_check_ip (L, -1); } lua_pop (L, 1); lua_pushstring (L, "timeout"); lua_gettable (L, -2); timeout = lua_tonumber (L, -1); lua_pop (L, 1); if (task != NULL && addr != NULL && cbref != -1 && cmd != NULL) { ud = rspamd_mempool_alloc (task->task_pool, sizeof (struct lua_redis_userdata)); ud->task = task; ud->L = L; ud->cbref = cbref; lua_pushstring (L, "args"); lua_redis_parse_args (L, -1, cmd, ud); ret = TRUE; } else { if (cbref != -1) { luaL_unref (L, LUA_REGISTRYINDEX, cbref); } msg_err ("incorrect function invocation"); } } else if ((task = lua_check_task (L, 1)) != NULL) { addr = lua_check_ip (L, 2); top = lua_gettop (L); /* Now get callback */ if (lua_isfunction (L, 3) && addr != NULL && addr->addr && top >= 4) { /* Create userdata */ ud = rspamd_mempool_alloc (task->task_pool, sizeof (struct lua_redis_userdata)); ud->task = task; ud->L = L; /* Pop other arguments */ lua_pushvalue (L, 3); /* Get a reference */ ud->cbref = luaL_ref (L, LUA_REGISTRYINDEX); cmd = luaL_checkstring (L, 4); if (top > 4) { lua_redis_parse_args (L, 5, cmd, ud); } else { lua_redis_parse_args (L, 0, cmd, ud); } ret = TRUE; } else { msg_err ("incorrect function invocation"); } } if (ret) { ud->terminated = 0; ud->ctx = redisAsyncConnect (rspamd_inet_address_to_string (addr->addr), rspamd_inet_address_get_port (addr->addr)); redisAsyncSetConnectCallback (ud->ctx, lua_redis_connect_cb); if (ud->ctx == NULL || ud->ctx->err) { ud->terminated = 1; redisAsyncFree (ud->ctx); lua_redis_free_args (ud); luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref); lua_pushboolean (L, FALSE); return 1; } redisLibeventAttach (ud->ctx, ud->task->ev_base); ret = redisAsyncCommandArgv (ud->ctx, lua_redis_callback, ud, ud->nargs, (const gchar **)ud->args, NULL); if (ret == REDIS_OK) { rspamd_session_add_event (ud->task->s, lua_redis_fin, ud, g_quark_from_static_string ("lua redis")); double_to_tv (timeout, &tv); event_set (&ud->timeout, -1, EV_TIMEOUT, lua_redis_timeout, ud); event_base_set (ud->task->ev_base, &ud->timeout); event_add (&ud->timeout, &tv); } else { msg_info ("call to redis failed: %s", ud->ctx->errstr); ud->terminated = 1; lua_redis_free_args (ud); redisAsyncFree (ud->ctx); luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref); } } lua_pushboolean (L, ret); return 1; }
void destroyRedis(redisAsyncContext *ctx) { redisAsyncDisconnect(ctx); redisAsyncFree(ctx); }