diff --git a/configure.ac b/configure.ac index 0003c33..24d1659 100644 --- a/configure.ac +++ b/configure.ac @@ -241,7 +241,6 @@ case "$host_os" in *linux*) AC_DEFINE_UNQUOTED([QB_LINUX], [1], [Compiling for Linux platform]) - LINT_FLAGS+=" -expect 21" ;; darwin*) AC_DEFINE_UNQUOTED([QB_DARWIN], [1], @@ -269,7 +268,6 @@ case "$host_os" in [Compiling for FreeBSD >= 8 platform]) ;; esac - LINT_FLAGS="$LINT_FLAGS -expect 22" ;; *solaris*) AC_DEFINE_UNQUOTED([QB_SOLARIS], [1], diff --git a/include/qb/qbipcs.h b/include/qb/qbipcs.h index 9e23ae7..7d14ef5 100644 --- a/include/qb/qbipcs.h +++ b/include/qb/qbipcs.h @@ -44,7 +44,8 @@ enum qb_ipcs_rate_limit { struct qb_ipcs_connection; typedef struct qb_ipcs_connection qb_ipcs_connection_t; -typedef qb_handle_t qb_ipcs_service_pt; +struct qb_ipcs_service; +typedef struct qb_ipcs_service qb_ipcs_service_t; struct qb_ipcs_stats { uint32_t active_connections; @@ -125,17 +126,38 @@ struct qb_ipcs_service_handlers { /** * Create a new IPC server. + * + * @param name for clients to connect to. + * @param service_id an integer to associate with the service + * @param type transport type. + * @param handlers callbacks. + * @return the new service instance. */ -qb_ipcs_service_pt qb_ipcs_create(const char *name, +qb_ipcs_service_t* qb_ipcs_create(const char *name, int32_t service_id, enum qb_ipc_type type, struct qb_ipcs_service_handlers *handlers); + +/** + * Increase the reference counter on the service object. + * + * @param s service instance + */ +void qb_ipcs_ref(qb_ipcs_service_t *s); + +/** + * Decrease the reference counter on the service object. + * + * @param s service instance + */ +void qb_ipcs_unref(qb_ipcs_service_t *s); + /** * Set your poll callbacks. * @param s service instance */ -void qb_ipcs_poll_handlers_set(qb_ipcs_service_pt s, +void qb_ipcs_poll_handlers_set(qb_ipcs_service_t* s, struct qb_ipcs_poll_handlers *handlers); /** @@ -143,19 +165,19 @@ void qb_ipcs_poll_handlers_set(qb_ipcs_service_pt s, * @param s service instance * @return 0 == ok; -errno to indicate a failure */ -int32_t qb_ipcs_run(qb_ipcs_service_pt s); +int32_t qb_ipcs_run(qb_ipcs_service_t* s); /** * Destroy the IPC server. * @param s service instance */ -void qb_ipcs_destroy(qb_ipcs_service_pt s); +void qb_ipcs_destroy(qb_ipcs_service_t* s); /** * * @param s service instance */ -void qb_ipcs_request_rate_limit(qb_ipcs_service_pt pt, enum qb_ipcs_rate_limit rl); +void qb_ipcs_request_rate_limit(qb_ipcs_service_t* pt, enum qb_ipcs_rate_limit rl); /** * send a response to a incomming request. @@ -232,7 +254,7 @@ int32_t qb_ipcs_connection_stats_get(qb_ipcs_connection_t *c, * @param pt service instance * @return 0 == ok; -errno to indicate a failure */ -int32_t qb_ipcs_stats_get(qb_ipcs_service_pt pt, +int32_t qb_ipcs_stats_get(qb_ipcs_service_t* pt, struct qb_ipcs_stats* stats, int32_t clear_after_read); @@ -244,7 +266,7 @@ int32_t qb_ipcs_stats_get(qb_ipcs_service_pt pt, * @param pt service instance * @return first connection */ -qb_ipcs_connection_t * qb_ipcs_connection_first_get(qb_ipcs_service_pt pt); +qb_ipcs_connection_t * qb_ipcs_connection_first_get(qb_ipcs_service_t* pt); /** * Get the next connection. @@ -255,7 +277,7 @@ qb_ipcs_connection_t * qb_ipcs_connection_first_get(qb_ipcs_service_pt pt); * @param current current connection * @return next connection */ -qb_ipcs_connection_t * qb_ipcs_connection_next_get(qb_ipcs_service_pt pt, +qb_ipcs_connection_t * qb_ipcs_connection_next_get(qb_ipcs_service_t* pt, qb_ipcs_connection_t *current); /* *INDENT-OFF* */ diff --git a/lib/ipc_int.h b/lib/ipc_int.h index 70290be..01f9ead 100644 --- a/lib/ipc_int.h +++ b/lib/ipc_int.h @@ -142,6 +142,7 @@ struct qb_ipcs_service { enum qb_ipc_type type; char name[NAME_MAX]; int32_t service_id; + int32_t ref_count; pid_t pid; int32_t needs_sock_for_poll; int32_t server_sock; @@ -152,6 +153,7 @@ struct qb_ipcs_service { enum qb_loop_priority poll_priority; struct qb_list_head connections; + struct qb_list_head list; struct qb_ipcs_stats stats; }; diff --git a/lib/ipcs.c b/lib/ipcs.c index 5d47d49..0b1d3d9 100644 --- a/lib/ipcs.c +++ b/lib/ipcs.c @@ -26,28 +26,25 @@ #include #include -static void qb_ipcs_destroy_internal(void *data); static void qb_ipcs_flowcontrol_set(struct qb_ipcs_connection *c, int32_t fc_enable); -QB_HDB_DECLARE(qb_ipc_services, qb_ipcs_destroy_internal); +static QB_LIST_DECLARE(qb_ipc_services); -qb_ipcs_service_pt qb_ipcs_create(const char *name, +qb_ipcs_service_t* qb_ipcs_create(const char *name, int32_t service_id, enum qb_ipc_type type, struct qb_ipcs_service_handlers *handlers) { struct qb_ipcs_service *s; - qb_ipcs_service_pt h; - qb_hdb_handle_create(&qb_ipc_services, - sizeof(struct qb_ipcs_service), &h); - qb_hdb_handle_get(&qb_ipc_services, h, (void **)&s); + s = calloc(1, sizeof(struct qb_ipcs_service)); s->pid = getpid(); s->type = type; s->needs_sock_for_poll = QB_FALSE; s->poll_priority = QB_LOOP_MED; + s->ref_count = 1; s->service_id = service_id; strncpy(s->name, name, NAME_MAX); @@ -58,33 +55,24 @@ qb_ipcs_service_pt qb_ipcs_create(const char *name, s->serv_fns.connection_destroyed = handlers->connection_destroyed; qb_list_init(&s->connections); + qb_list_init(&s->list); + qb_list_add(&s->list, &qb_ipc_services); - qb_hdb_handle_put(&qb_ipc_services, h); - - return h; + return s; } -void qb_ipcs_poll_handlers_set(qb_ipcs_service_pt pt, +void qb_ipcs_poll_handlers_set(struct qb_ipcs_service* s, struct qb_ipcs_poll_handlers *handlers) { - struct qb_ipcs_service *s; - - qb_hdb_handle_get(&qb_ipc_services, pt, (void **)&s); - s->poll_fns.job_add = handlers->job_add; s->poll_fns.dispatch_add = handlers->dispatch_add; s->poll_fns.dispatch_mod = handlers->dispatch_mod; s->poll_fns.dispatch_del = handlers->dispatch_del; - - qb_hdb_handle_put(&qb_ipc_services, pt); } -int32_t qb_ipcs_run(qb_ipcs_service_pt pt) +int32_t qb_ipcs_run(struct qb_ipcs_service* s) { int32_t res; - struct qb_ipcs_service *s; - - qb_hdb_handle_get(&qb_ipc_services, pt, (void **)&s); switch (s->type) { case QB_IPC_SOCKET: @@ -105,21 +93,19 @@ int32_t qb_ipcs_run(qb_ipcs_service_pt pt) } res = qb_ipcs_us_publish(s); if (res < 0) { - qb_hdb_handle_put(&qb_ipc_services, pt); + qb_ipcs_unref(s); return res; } if (res < 0) { - qb_ipcs_us_withdraw(s); + (void)qb_ipcs_us_withdraw(s); } - qb_hdb_handle_put(&qb_ipc_services, pt); return res; } -void qb_ipcs_request_rate_limit(qb_ipcs_service_pt pt, enum qb_ipcs_rate_limit rl) +void qb_ipcs_request_rate_limit(struct qb_ipcs_service* s, enum qb_ipcs_rate_limit rl) { - struct qb_ipcs_service *s; struct qb_ipcs_connection *c; enum qb_loop_priority p; @@ -137,8 +123,6 @@ void qb_ipcs_request_rate_limit(qb_ipcs_service_pt pt, enum qb_ipcs_rate_limit r break; } - qb_hdb_handle_get(&qb_ipc_services, pt, (void**)&s); - qb_list_for_each_entry(c, &s->connections, list) { qb_ipcs_connection_ref_inc(c); @@ -166,33 +150,40 @@ void qb_ipcs_request_rate_limit(qb_ipcs_service_pt pt, enum qb_ipcs_rate_limit r qb_ipcs_connection_ref_dec(c); } s->poll_priority = p; - qb_hdb_handle_put(&qb_ipc_services, pt); } -void qb_ipcs_destroy(qb_ipcs_service_pt pt) +void qb_ipcs_ref(struct qb_ipcs_service *s) { - qb_hdb_handle_put(&qb_ipc_services, pt); - qb_hdb_handle_destroy(&qb_ipc_services, pt); + qb_atomic_int_inc(&s->ref_count); } -static void qb_ipcs_destroy_internal(void *data) +void qb_ipcs_unref(struct qb_ipcs_service *s) { - struct qb_ipcs_service *s = (struct qb_ipcs_service *)data; + int32_t free_it; struct qb_ipcs_connection *c = NULL; struct qb_list_head *iter; struct qb_list_head *iter_next; - qb_util_log(LOG_DEBUG, "%s\n", __func__); - - qb_list_for_each_safe(iter, iter_next, &s->connections) { - c = qb_list_entry(iter, struct qb_ipcs_connection, list); - if (c == NULL) { - continue; + assert(s->ref_count > 0); + free_it = qb_atomic_int_dec_and_test(&s->ref_count); + if (free_it) { + qb_util_log(LOG_DEBUG, "%s() - destorying\n", __func__); + qb_list_for_each_safe(iter, iter_next, &s->connections) { + c = qb_list_entry(iter, struct qb_ipcs_connection, list); + if (c == NULL) { + continue; + } + qb_ipcs_disconnect(c); } - qb_ipcs_disconnect(c); + free(s); } } +void qb_ipcs_destroy(struct qb_ipcs_service* s) +{ + qb_ipcs_unref(s); +} + /* * connection API */ @@ -299,44 +290,36 @@ ssize_t qb_ipcs_event_sendv(struct qb_ipcs_connection *c, const struct iovec * i return res; } -qb_ipcs_connection_t * qb_ipcs_connection_first_get(qb_ipcs_service_pt pt) +qb_ipcs_connection_t * qb_ipcs_connection_first_get(struct qb_ipcs_service* s) { - struct qb_ipcs_service *s; struct qb_ipcs_connection *c; struct qb_list_head *iter; - qb_hdb_handle_get(&qb_ipc_services, pt, (void **)&s); - if (qb_list_empty(&s->connections)) { - qb_hdb_handle_put(&qb_ipc_services, pt); return NULL; } iter = s->connections.next; c = qb_list_entry(iter, struct qb_ipcs_connection, list); qb_ipcs_connection_ref_inc(c); - qb_hdb_handle_put(&qb_ipc_services, pt); + return c; } -qb_ipcs_connection_t * qb_ipcs_connection_next_get(qb_ipcs_service_pt pt, +qb_ipcs_connection_t * qb_ipcs_connection_next_get(struct qb_ipcs_service* s, struct qb_ipcs_connection *current) { - struct qb_ipcs_service *s; struct qb_ipcs_connection *c; struct qb_list_head *iter; - qb_hdb_handle_get(&qb_ipc_services, pt, (void **)&s); - if (current->list.next == &s->connections) { - qb_hdb_handle_put(&qb_ipc_services, pt); return NULL; } iter = current->list.next; c = qb_list_entry(iter, struct qb_ipcs_connection, list); qb_ipcs_connection_ref_inc(c); - qb_hdb_handle_put(&qb_ipc_services, pt); + return c; } @@ -588,18 +571,14 @@ int32_t qb_ipcs_connection_stats_get(qb_ipcs_connection_t *c, return 0; } -int32_t qb_ipcs_stats_get(qb_ipcs_service_pt pt, +int32_t qb_ipcs_stats_get(struct qb_ipcs_service* s, struct qb_ipcs_stats* stats, int32_t clear_after_read) { - struct qb_ipcs_service *s; - - qb_hdb_handle_get(&qb_ipc_services, pt, (void **)&s); memcpy(stats, &s->stats, sizeof(struct qb_ipcs_stats)); if (clear_after_read) { memset(&s->stats, 0, sizeof(struct qb_ipcs_stats)); } - qb_hdb_handle_put(&qb_ipc_services, pt); return 0; } diff --git a/tests/bms.c b/tests/bms.c index 80d3561..65010dc 100644 --- a/tests/bms.c +++ b/tests/bms.c @@ -39,7 +39,7 @@ static qb_loop_t *bms_loop; static GMainLoop *glib_loop; static qb_array_t *gio_map; #endif -static qb_ipcs_service_pt s1; +static qb_ipcs_service_t* s1; static int32_t s1_connection_accept_fn(qb_ipcs_connection_t *c, uid_t uid, gid_t gid) { diff --git a/tests/check_ipc.c b/tests/check_ipc.c index b97e91c..ca20239 100644 --- a/tests/check_ipc.c +++ b/tests/check_ipc.c @@ -68,7 +68,7 @@ enum my_msg_ids { * 8) multiple services */ static qb_loop_t *my_loop; -static qb_ipcs_service_pt s1; +static qb_ipcs_service_t* s1; static int32_t turn_on_fc = QB_FALSE; static int32_t fc_enabled = 89;