void
rspamd_redis_pool_release_connection (struct rspamd_redis_pool *pool,
- struct redisAsyncContext *ctx, gboolean is_fatal)
+ struct redisAsyncContext *ctx, enum rspamd_redis_pool_release_type how)
{
struct rspamd_redis_pool_connection *conn;
if (conn != NULL) {
g_assert (conn->active);
- if (is_fatal || ctx->err != REDIS_OK) {
+ if (ctx->err != REDIS_OK) {
/* We need to terminate connection forcefully */
- msg_debug_rpool ("closed connection %p forcefully", conn->ctx);
+ msg_debug_rpool ("closed connection %p due to an error", conn->ctx);
REF_RELEASE (conn);
}
else {
- /* Ensure that there are no callbacks attached to this conn */
- if (ctx->replies.head == NULL) {
- /* Just move it to the inactive queue */
- g_queue_unlink (conn->elt->active, conn->entry);
- g_queue_push_head_link (conn->elt->inactive, conn->entry);
- conn->active = FALSE;
- rspamd_redis_pool_schedule_timeout (conn);
- msg_debug_rpool ("mark connection %p inactive", conn->ctx);
+ if (how == RSPAMD_REDIS_RELEASE_DEFAULT) {
+ /* Ensure that there are no callbacks attached to this conn */
+ if (ctx->replies.head == NULL) {
+ /* Just move it to the inactive queue */
+ g_queue_unlink (conn->elt->active, conn->entry);
+ g_queue_push_head_link (conn->elt->inactive, conn->entry);
+ conn->active = FALSE;
+ rspamd_redis_pool_schedule_timeout (conn);
+ msg_debug_rpool ("mark connection %p inactive", conn->ctx);
+ }
+ else {
+ msg_debug_rpool ("closed connection %p due to callbacks left",
+ conn->ctx);
+ REF_RELEASE (conn);
+ }
}
else {
- msg_debug_rpool ("closed connection %p due to callbacks left",
- conn->ctx);
+ if (how == RSPAMD_REDIS_RELEASE_FATAL) {
+ msg_debug_rpool ("closed connection %p due to an fatal termination",
+ conn->ctx);
+ }
+ else {
+ msg_debug_rpool ("closed connection %p due to explicit termination",
+ conn->ctx);
+ }
+
REF_RELEASE (conn);
}
}
const gchar *db, const gchar *password,
const char *ip, int port);
+enum rspamd_redis_pool_release_type {
+ RSPAMD_REDIS_RELEASE_DEFAULT = 0,
+ RSPAMD_REDIS_RELEASE_FATAL = 1,
+ RSPAMD_REDIS_RELEASE_ENFORCE
+};
+
/**
* Release a connection to the pool
* @param pool
* @param ctx
*/
void rspamd_redis_pool_release_connection (struct rspamd_redis_pool *pool,
- struct redisAsyncContext *ctx, gboolean is_fatal);
+ struct redisAsyncContext *ctx, enum rspamd_redis_pool_release_type how);
/**
* Stops redis pool and destroys it
#define LUA_REDIS_ASYNC (1 << 0)
#define LUA_REDIS_TEXTDATA (1 << 1)
#define LUA_REDIS_TERMINATED (1 << 2)
+#define LUA_REDIS_NO_POOL (1 << 3)
#define IS_ASYNC(ctx) ((ctx)->flags & LUA_REDIS_ASYNC)
struct lua_redis_request_specific_userdata {
ud->terminated = 1;
ac = ud->ctx;
ud->ctx = NULL;
- rspamd_redis_pool_release_connection (ud->pool, ac, !is_successful);
+
+ if (!is_successful) {
+ rspamd_redis_pool_release_connection (ud->pool, ac,
+ RSPAMD_REDIS_RELEASE_FATAL);
+ }
+ else {
+ rspamd_redis_pool_release_connection (ud->pool, ac,
+ (ctx->flags & LUA_REDIS_NO_POOL) ?
+ RSPAMD_REDIS_RELEASE_ENFORCE : RSPAMD_REDIS_RELEASE_DEFAULT);
+ }
+
}
LL_FOREACH_SAFE (ud->specific, cur, tmp) {
ud->ctx = NULL;
if (ac) {
- rspamd_redis_pool_release_connection (ud->pool, ac, FALSE);
+ rspamd_redis_pool_release_connection (ud->pool, ac,
+ (ctx->flags & LUA_REDIS_NO_POOL) ?
+ RSPAMD_REDIS_RELEASE_ENFORCE : RSPAMD_REDIS_RELEASE_DEFAULT);
}
}
* This will call all callbacks pending so the entire context
* will be destructed
*/
- rspamd_redis_pool_release_connection (sp_ud->c->pool, ac, TRUE);
+ rspamd_redis_pool_release_connection (sp_ud->c->pool, ac,
+ RSPAMD_REDIS_RELEASE_FATAL);
}
result->result_ref = luaL_ref (L, LUA_REGISTRYINDEX);
* This will call all callbacks pending so the entire context
* will be destructed
*/
- rspamd_redis_pool_release_connection (sp_ud->c->pool, ac, TRUE);
+ rspamd_redis_pool_release_connection (sp_ud->c->pool, ac,
+ RSPAMD_REDIS_RELEASE_FATAL);
}
}
* This will call all callbacks pending so the entire context
* will be destructed
*/
- rspamd_redis_pool_release_connection (sp_ud->c->pool, ac, TRUE);
+ rspamd_redis_pool_release_connection (sp_ud->c->pool, ac,
+ RSPAMD_REDIS_RELEASE_FATAL);
}
REDIS_RELEASE (ctx);
}
lua_pop (L, 1);
+ lua_pushstring (L, "no_pool");
+ lua_gettable (L, -2);
+ if (!!lua_toboolean (L, -1)) {
+ flags |= LUA_REDIS_NO_POOL;
+ }
+ lua_pop (L, 1);
+
lua_pop (L, 1); /* table */
if (session && rspamd_session_blocked (session)) {
if (ud->ctx) {
msg_err_task_check ("cannot connect to redis: %s",
ud->ctx->errstr);
- rspamd_redis_pool_release_connection (ud->pool, ud->ctx, TRUE);
+ rspamd_redis_pool_release_connection (ud->pool, ud->ctx,
+ RSPAMD_REDIS_RELEASE_FATAL);
ud->ctx = NULL;
}
else {
}
else {
msg_info ("call to redis failed: %s", ud->ctx->errstr);
- rspamd_redis_pool_release_connection (ud->pool, ud->ctx, TRUE);
+ rspamd_redis_pool_release_connection (ud->pool, ud->ctx,
+ RSPAMD_REDIS_RELEASE_FATAL);
ud->ctx = NULL;
REDIS_RELEASE (ctx);
ret = FALSE;