odyssey/sources/server_pool.h

174 lines
6.4 KiB
C

#ifndef ODYSSEY_SERVER_POOL_H
#define ODYSSEY_SERVER_POOL_H
/*
* Odyssey.
*
* Scalable PostgreSQL connection pooler.
*/
typedef struct od_server_pool od_server_pool_t;
typedef int (*od_server_pool_cb_t)(od_server_t *, void **);
struct od_server_pool {
od_list_t active;
od_list_t idle;
int count_active;
int count_idle;
};
static inline void od_server_pool_init(od_server_pool_t *pool)
{
pool->count_active = 0;
pool->count_idle = 0;
od_list_init(&pool->idle);
od_list_init(&pool->active);
}
#define OD_SERVER_POOL_FREE_DECLARE(name, type, server_free_cb) \
static inline void od_##name##_server_pool_free( \
od_server_pool_t *pool) \
{ \
type *server; \
od_list_t *i, *n; \
\
od_list_foreach_safe(&pool->idle, i, n) \
{ \
server = od_container_of(i, type, link); \
server_free_cb(server); \
} \
\
od_list_foreach_safe(&pool->active, i, n) \
{ \
server = od_container_of(i, type, link); \
server_free_cb(server); \
} \
}
OD_SERVER_POOL_FREE_DECLARE(pg, od_server_t, od_server_free)
#ifdef LDAP_FOUND
OD_SERVER_POOL_FREE_DECLARE(ldap, od_ldap_server_t, od_ldap_server_free)
#endif
#define OD_SERVER_POOL_SET_DECLARE(name, type) \
static inline void od_##name##_server_pool_set( \
od_server_pool_t *pool, type *server, od_server_state_t state) \
{ \
if (server->state == state) \
return; \
switch (server->state) { \
case OD_SERVER_UNDEF: \
break; \
case OD_SERVER_IDLE: \
pool->count_idle--; \
break; \
case OD_SERVER_ACTIVE: \
pool->count_active--; \
break; \
} \
\
od_list_t *target = NULL; \
switch (state) { \
case OD_SERVER_UNDEF: \
break; \
case OD_SERVER_IDLE: \
target = &pool->idle; \
pool->count_idle++; \
break; \
case OD_SERVER_ACTIVE: \
target = &pool->active; \
pool->count_active++; \
break; \
} \
\
od_list_unlink(&server->link); \
od_list_init(&server->link); \
if (target) { \
od_list_push(target, &server->link); \
} \
server->state = state; \
}
OD_SERVER_POOL_SET_DECLARE(pg, od_server_t)
#ifdef LDAP_FOUND
OD_SERVER_POOL_SET_DECLARE(ldap, od_ldap_server_t)
#endif
#define OD_SERVER_POOL_NEXT_DECLARE(name, type) \
static inline type *od_##name##_server_pool_next( \
od_server_pool_t *pool, od_server_state_t state) \
{ \
int target_count = 0; \
od_list_t *target = NULL; \
switch (state) { \
case OD_SERVER_IDLE: \
target_count = pool->count_idle; \
target = &pool->idle; \
break; \
case OD_SERVER_ACTIVE: \
target_count = pool->count_active; \
target = &pool->active; \
break; \
case OD_SERVER_UNDEF: \
assert(0); \
break; \
} \
if (target_count == 0) \
return NULL; \
type *server; \
server = od_container_of(target->next, type, link); \
return server; \
}
OD_SERVER_POOL_NEXT_DECLARE(pg, od_server_t)
#ifdef LDAP_FOUND
OD_SERVER_POOL_NEXT_DECLARE(ldap, od_ldap_server_t)
#endif
static inline od_server_t *od_server_pool_foreach(od_server_pool_t *pool,
od_server_state_t state,
od_server_pool_cb_t callback,
void **argv)
{
od_list_t *target = NULL;
switch (state) {
case OD_SERVER_IDLE:
target = &pool->idle;
break;
case OD_SERVER_ACTIVE:
target = &pool->active;
break;
case OD_SERVER_UNDEF:
assert(0);
break;
}
od_server_t *server;
od_list_t *i, *n;
od_list_foreach_safe(target, i, n)
{
server = od_container_of(i, od_server_t, link);
int rc;
rc = callback(server, argv);
if (rc) {
return server;
}
}
return NULL;
}
static inline int od_server_pool_active(od_server_pool_t *pool)
{
return pool->count_active;
}
static inline int od_server_pool_total(od_server_pool_t *pool)
{
return pool->count_active + pool->count_idle;
}
#endif /* ODYSSEY_SERVER_POOL_H */