odyssey/sources/client_pool.h

149 lines
3.0 KiB
C

#ifndef ODYSSEY_CLIENT_POOL_H
#define ODYSSEY_CLIENT_POOL_H
/*
* Odyssey.
*
* Scalable PostgreSQL connection pooler.
*/
typedef struct od_client_pool od_client_pool_t;
typedef int (*od_client_pool_cb_t)(od_client_t*, void**);
struct od_client_pool
{
od_list_t active;
od_list_t queue;
od_list_t pending;
int count_active;
int count_queue;
int count_pending;
};
static inline void
od_client_pool_init(od_client_pool_t *pool)
{
pool->count_active = 0;
pool->count_queue = 0;
pool->count_pending = 0;
od_list_init(&pool->active);
od_list_init(&pool->queue);
od_list_init(&pool->pending);
}
static inline void
od_client_pool_set(od_client_pool_t *pool, od_client_t *client,
od_client_state_t state)
{
if (client->state == state)
return;
switch (client->state) {
case OD_CLIENT_UNDEF:
break;
case OD_CLIENT_ACTIVE:
pool->count_active--;
break;
case OD_CLIENT_QUEUE:
pool->count_queue--;
break;
case OD_CLIENT_PENDING:
pool->count_pending--;
break;
}
od_list_t *target = NULL;
switch (state) {
case OD_CLIENT_UNDEF:
break;
case OD_CLIENT_ACTIVE:
target = &pool->active;
pool->count_active++;
break;
case OD_CLIENT_QUEUE:
target = &pool->queue;
pool->count_queue++;
break;
case OD_CLIENT_PENDING:
target = &pool->pending;
pool->count_pending++;
break;
}
od_list_unlink(&client->link_pool);
od_list_init(&client->link_pool);
if (target)
od_list_append(target, &client->link_pool);
client->state = state;
}
static inline od_client_t*
od_client_pool_next(od_client_pool_t *pool, od_client_state_t state)
{
int target_count = 0;
od_list_t *target = NULL;
switch (state) {
case OD_CLIENT_ACTIVE:
target = &pool->active;
target_count = pool->count_active;
break;
case OD_CLIENT_QUEUE:
target = &pool->queue;
target_count = pool->count_queue;
break;
case OD_CLIENT_PENDING:
target = &pool->pending;
target_count = pool->count_pending;
break;
case OD_CLIENT_UNDEF:
assert(0);
break;
}
if (target_count == 0)
return NULL;
od_client_t *client;
client = od_container_of(target->next, od_client_t, link_pool);
return client;
}
static inline od_client_t*
od_client_pool_foreach(od_client_pool_t *pool,
od_client_state_t state,
od_client_pool_cb_t callback,
void **argv)
{
od_list_t *target = NULL;
switch (state) {
case OD_CLIENT_ACTIVE:
target = &pool->active;
break;
case OD_CLIENT_QUEUE:
target = &pool->queue;
break;
case OD_CLIENT_PENDING:
target = &pool->pending;
break;
case OD_CLIENT_UNDEF:
assert(0);
break;
}
od_client_t *client;
od_list_t *i, *n;
od_list_foreach_safe(target, i, n) {
client = od_container_of(i, od_client_t, link_pool);
int rc;
rc = callback(client, argv);
if (rc) {
return client;
}
}
return NULL;
}
static inline int
od_client_pool_total(od_client_pool_t *pool)
{
return pool->count_active + pool->count_queue +
pool->count_pending;
}
#endif /* ODYSSEY_CLIENT_POOL_H */