diff --git a/sources/atomic.h b/sources/atomic.h index 1f15b09d..f03dcece 100644 --- a/sources/atomic.h +++ b/sources/atomic.h @@ -16,70 +16,70 @@ od_atomic_u32_of(od_atomic_u32_t *atomic) return __sync_fetch_and_add(atomic, 0); } -static inline void +static inline uint32_t od_atomic_u32_inc(od_atomic_u32_t *atomic) { - __sync_fetch_and_add(atomic, 1); -} - -static inline void -od_atomic_u32_dec(od_atomic_u32_t *atomic) -{ - __sync_fetch_and_sub(atomic, 1); -} - -static inline void -od_atomic_u32_add(od_atomic_u32_t *atomic, uint32_t value) -{ - __sync_add_and_fetch(atomic, value); -} - -static inline void -od_atomic_u32_sub(od_atomic_u32_t *atomic, uint32_t value) -{ - __sync_sub_and_fetch(atomic, value); -} - -static inline void -od_atomic_u32_or(od_atomic_u32_t *atomic, uint32_t value) -{ - __sync_or_and_fetch(atomic, value); -} - -static inline void -od_atomic_u32_xor(od_atomic_u32_t *atomic, uint32_t value) -{ - __sync_xor_and_fetch(atomic, value); + return __sync_fetch_and_add(atomic, 1); } static inline uint32_t +od_atomic_u32_dec(od_atomic_u32_t *atomic) +{ + return __sync_fetch_and_sub(atomic, 1); +} + +static inline uint32_t +od_atomic_u32_add(od_atomic_u32_t *atomic, uint32_t value) +{ + return __sync_add_and_fetch(atomic, value); +} + +static inline uint32_t +od_atomic_u32_sub(od_atomic_u32_t *atomic, uint32_t value) +{ + return __sync_sub_and_fetch(atomic, value); +} + +static inline uint32_t +od_atomic_u32_or(od_atomic_u32_t *atomic, uint32_t value) +{ + return __sync_or_and_fetch(atomic, value); +} + +static inline uint32_t +od_atomic_u32_xor(od_atomic_u32_t *atomic, uint32_t value) +{ + return __sync_xor_and_fetch(atomic, value); +} + +static inline uint64_t od_atomic_u64_of(od_atomic_u64_t *atomic) { return __sync_fetch_and_add(atomic, 0); } -static inline void +static inline uint64_t od_atomic_u64_inc(od_atomic_u64_t *atomic) { - __sync_fetch_and_add(atomic, 1); + return __sync_fetch_and_add(atomic, 1); } -static inline void +static inline uint64_t od_atomic_u64_dec(od_atomic_u64_t *atomic) { - __sync_fetch_and_sub(atomic, 1); + return __sync_fetch_and_sub(atomic, 1); } -static inline void +static inline uint64_t od_atomic_u64_add(od_atomic_u64_t *atomic, uint64_t value) { - __sync_add_and_fetch(atomic, value); + return __sync_add_and_fetch(atomic, value); } -static inline void +static inline uint64_t od_atomic_u64_sub(od_atomic_u64_t *atomic, uint64_t value) { - __sync_sub_and_fetch(atomic, value); + return __sync_sub_and_fetch(atomic, value); } #endif /* ODYSSEY_ATOMIC_H */ diff --git a/sources/console.c b/sources/console.c index aeb616f4..5a4ef0b3 100644 --- a/sources/console.c +++ b/sources/console.c @@ -665,7 +665,7 @@ od_console_show_lists(od_client_t *client, machine_msg_t *stream) int router_used_servers = 0; int router_pools = router->route_pool.count; - int router_clients = router->clients; + int router_clients = od_atomic_u32_of(&router->clients); void *argv[] = { &router_used_servers }; od_route_pool_foreach(&router->route_pool, od_console_show_lists_cb, argv); diff --git a/sources/cron.c b/sources/cron.c index 2e545d65..7ee318e2 100644 --- a/sources/cron.c +++ b/sources/cron.c @@ -138,7 +138,7 @@ od_cron_stat(od_cron_t *cron) } od_log(&instance->logger, "stats", NULL, NULL, - "clients %d", router->clients); + "clients %d", od_atomic_u32_of(&router->clients)); } /* update stats per route and print info */ diff --git a/sources/frontend.c b/sources/frontend.c index d3256aa2..6ba9f8c6 100644 --- a/sources/frontend.c +++ b/sources/frontend.c @@ -23,6 +23,10 @@ od_frontend_close(od_client_t *client) { assert(client->route == NULL); assert(client->server == NULL); + + od_router_t *router = client->global->router; + od_atomic_u32_dec(&router->clients); + od_io_close(&client->io); if (client->notify_io) { machine_close(client->notify_io); @@ -874,6 +878,15 @@ od_frontend(void *arg) return; } + /* ensure global client_max limit */ + uint32_t clients = od_atomic_u32_inc(&router->clients); + if (instance->config.client_max_set && clients >= (uint32_t)instance->config.client_max) { + od_frontend_error(client, KIWI_TOO_MANY_CONNECTIONS, + "too many connections"); + od_frontend_close(client); + return; + } + /* handle startup */ rc = od_frontend_startup(client); if (rc == -1) { diff --git a/sources/router.c b/sources/router.c index b6795aa9..2011ecc2 100644 --- a/sources/router.c +++ b/sources/router.c @@ -254,12 +254,6 @@ od_router_route(od_router_t *router, od_config_t *config, od_client_t *client) } } - /* ensure global client_max limit */ - if (config->client_max_set && router->clients >= config->client_max) { - od_router_unlock(router); - return OD_ROUTER_ERROR_LIMIT; - } - /* match or create dynamic route */ od_route_t *route; route = od_route_pool_match(&router->route_pool, &id, rule); @@ -272,7 +266,6 @@ od_router_route(od_router_t *router, od_config_t *config, od_client_t *client) return OD_ROUTER_ERROR; } } - router->clients++; od_rules_ref(rule); od_route_lock(route); @@ -301,15 +294,11 @@ od_router_route(od_router_t *router, od_config_t *config, od_client_t *client) void od_router_unroute(od_router_t *router, od_client_t *client) { + (void)router; /* detach client from route */ assert(client->route); assert(client->server == NULL); - od_router_lock(router); - assert(router->clients > 0); - router->clients--; - od_router_unlock(router); - od_route_t *route = client->route; od_route_lock(route); od_client_pool_set(&route->client_pool, client, OD_CLIENT_UNDEF); diff --git a/sources/router.h b/sources/router.h index f74ade0b..ef5f7f1c 100644 --- a/sources/router.h +++ b/sources/router.h @@ -24,7 +24,7 @@ struct od_router pthread_mutex_t lock; od_rules_t rules; od_route_pool_t route_pool; - int clients; + od_atomic_u32_t clients; }; static inline void