Hi This is the same patch with Steve's requested changes.
-Angus Signed-off-by: Angus Salkeld <[email protected]> --- exec/coroipcs.c | 107 +++++++++++++++++++++++++++++++-- exec/main.c | 140 +++++++++++++++++++++++++++++++++++++++++++ include/corosync/coroipcs.h | 12 ++++ 3 files changed, 254 insertions(+), 5 deletions(-) diff --git a/exec/coroipcs.c b/exec/coroipcs.c index ab7be0b..9186f25 100644 --- a/exec/coroipcs.c +++ b/exec/coroipcs.c @@ -72,6 +72,7 @@ #include <corosync/list.h> #include <corosync/coroipc_types.h> +#include <corosync/hdb.h> #include <corosync/coroipcs.h> #include <corosync/coroipc_ipc.h> @@ -91,6 +92,7 @@ #define MSG_SEND_UNLOCKED 1 static struct coroipcs_init_state *api; +static struct coroipcs_init_stats_state *stats_api; DECLARE_LIST_INIT (conn_info_list_head); @@ -130,11 +132,13 @@ enum conn_state { struct conn_info { int fd; pthread_t thread; + pid_t client_pid; pthread_attr_t thread_attr; unsigned int service; enum conn_state state; int notify_flow_control_enabled; int refcount; + hdb_handle_t stats_handle; #if _POSIX_THREAD_PROCESS_SHARED < 1 key_t semkey; int semid; @@ -180,6 +184,7 @@ static void sem_post_exit_thread (struct conn_info *conn_info) retry_semop: res = sem_post (&conn_info->control_buffer->sem0); if (res == -1 && errno == EINTR) { + stats_api->stats_increment_value (conn_info->stats_handle, "sem_retry_count"); goto retry_semop; } #else @@ -190,6 +195,7 @@ retry_semop: retry_semop: res = semop (conn_info->semid, &sop, 1); if ((res == -1) && (errno == EINTR || errno == EAGAIN)) { + stats_api->stats_increment_value (conn_info->stats_handle, "sem_retry_count"); goto retry_semop; } #endif @@ -437,6 +443,7 @@ static inline int conn_info_destroy (struct conn_info *conn_info) * Retry library exit function if busy */ if (conn_info->state == CONN_STATE_THREAD_DESTROYED) { + stats_api->stats_destroy_connection (conn_info->stats_handle); res = api->exit_fn_get (conn_info->service) (conn_info); if (res == -1) { api->serialize_unlock (); @@ -588,6 +595,7 @@ retry_semwait: pthread_exit (0); } if ((res == -1) && (errno == EINTR)) { + stats_api->stats_increment_value (conn_info->stats_handle, "sem_retry_count"); goto retry_semwait; } #else @@ -602,6 +610,7 @@ retry_semop: } res = semop (conn_info->semid, &sop, 1); if ((res == -1) && (errno == EINTR || errno == EAGAIN)) { + stats_api->stats_increment_value (conn_info->stats_handle, "sem_retry_count"); goto retry_semop; } else if ((res == -1) && (errno == EINVAL || errno == EIDRM)) { @@ -639,12 +648,14 @@ retry_semop: } else if (send_ok) { api->serialize_lock(); + stats_api->stats_increment_value (conn_info->stats_handle, "requests"); api->handler_fn_get (conn_info->service, header->id) (conn_info, header); api->serialize_unlock(); } else { /* * Overload, tell library to retry */ + stats_api->stats_increment_value (conn_info->stats_handle, "sem_retry_count"); coroipc_response_header.size = sizeof (coroipc_response_header_t); coroipc_response_header.id = 0; coroipc_response_header.error = CS_ERR_TRY_AGAIN; @@ -672,9 +683,11 @@ req_setup_send ( retry_send: res = send (conn_info->fd, &res_setup, sizeof (mar_res_setup_t), MSG_WAITALL); if (res == -1 && errno == EINTR) { + stats_api->stats_increment_value (conn_info->stats_handle, "send_retry_count"); goto retry_send; } else if (res == -1 && errno == EAGAIN) { + stats_api->stats_increment_value (conn_info->stats_handle, "send_retry_count"); goto retry_send; } return (0); @@ -719,6 +732,7 @@ req_setup_recv ( retry_recv: res = recvmsg (conn_info->fd, &msg_recv, MSG_NOSIGNAL); if (res == -1 && errno == EINTR) { + stats_api->stats_increment_value (conn_info->stats_handle, "recv_retry_count"); goto retry_recv; } else if (res == -1 && errno != EAGAIN) { @@ -753,6 +767,7 @@ retry_recv: if (getpeerucred (conn_info->fd, &uc) == 0) { euid = ucred_geteuid (uc); egid = ucred_getegid (uc); + conn_info->client_pid = ucred_getpid (uc); if (api->security_valid (euid, egid)) { authenticated = 1; } @@ -768,6 +783,10 @@ retry_recv: uid_t euid; gid_t egid; + /* + * TODO get the peer's pid. + * conn_info->client_pid = ?; + */ euid = -1; egid = -1; if (getpeereid (conn_info->fd, &euid, &egid) == 0) { @@ -785,6 +804,7 @@ retry_recv: assert (cmsg); cred = (struct ucred *)CMSG_DATA (cmsg); if (cred) { + conn_info->client_pid = cred->pid; if (api->security_valid (cred->uid, cred->gid)) { authenticated = 1; } @@ -838,6 +858,7 @@ static int conn_info_create (int fd) memset (conn_info, 0, sizeof (struct conn_info)); conn_info->fd = fd; + conn_info->client_pid = 0; conn_info->service = SOCKET_SERVICE_INIT; conn_info->state = CONN_STATE_THREAD_INACTIVE; list_init (&conn_info->outq_head); @@ -845,7 +866,7 @@ static int conn_info_create (int fd) list_init (&conn_info->zcb_mapped_list_head); list_add (&conn_info->list, &conn_info_list_head); - api->poll_dispatch_add (fd, conn_info); + api->poll_dispatch_add (fd, conn_info); return (0); } @@ -926,10 +947,16 @@ extern void coroipcs_ipc_init ( #endif listen (server_fd, SERVER_BACKLOG); - /* - * Setup connection dispatch routine - */ - api->poll_accept_add (server_fd); + /* + * Setup connection dispatch routine + */ + api->poll_accept_add (server_fd); +} + +extern void coroipcs_ipc_stats_init ( + struct coroipcs_init_stats_state *init_stats_state) +{ + stats_api = init_stats_state; } void coroipcs_ipc_exit (void) @@ -1006,6 +1033,7 @@ retry_semop: return (0); } #endif + stats_api->stats_increment_value (conn_info->stats_handle, "responses"); return (0); } @@ -1121,6 +1149,7 @@ retry_semop: return; } #endif + stats_api->stats_increment_value (conn_info->stats_handle, "dispatched"); } static void outq_flush (struct conn_info *conn_info) { @@ -1173,9 +1202,11 @@ retry_recv: sizeof (mar_req_priv_change), MSG_NOSIGNAL); if (res == -1 && errno == EINTR) { + stats_api->stats_increment_value (conn_info->stats_handle, "recv_retry_count"); goto retry_recv; } if (res == -1 && errno == EAGAIN) { + stats_api->stats_increment_value (conn_info->stats_handle, "recv_retry_count"); goto retry_recv; } if (res == -1 && errno != EAGAIN) { @@ -1346,6 +1377,69 @@ retry_accept: return (0); } +static char * pid_to_name (pid_t pid, char* out_name, size_t name_len) +{ + char *name; + char *rest; + FILE *fp; + char fname[32]; + char buf[256]; + + snprintf (fname, 32, "/proc/%d/stat", pid); + fp = fopen (fname, "r"); + if (!fp) { + return NULL; + } + + if (fgets (buf, sizeof (buf), fp) == NULL) { + fclose (fp); + return NULL; + } + fclose (fp); + + name = strrchr (buf, '('); + if (!name) { + return NULL; + } + + /* move past the bracket */ + name++; + + rest = strrchr (buf, ')'); + + if (rest == NULL || rest[1] != ' ') { + return NULL; + } + + *rest = '\0'; + /* move past the NULL and space */ + rest += 2; + + /* copy the name */ + strncpy (out_name, name, name_len); + out_name[name_len] = '\0'; + return out_name; +} + +static void coroipcs_init_conn_stats ( + struct conn_info * conn) +{ + char conn_name[42]; + char proc_name[32]; + + if (conn->client_pid > 0) { + if (pid_to_name (conn->client_pid, proc_name, sizeof(proc_name))) + snprintf (conn_name, sizeof(conn_name), "%s:%d:%d", proc_name, conn->client_pid, conn->fd); + else + snprintf (conn_name, sizeof(conn_name), "%d:%d", conn->client_pid, conn->fd); + } else + snprintf (conn_name, sizeof(conn_name), "%d", conn->fd); + + conn->stats_handle = stats_api->stats_create_connection (conn_name, conn->client_pid, conn->fd); + stats_api->stats_update_value (conn->stats_handle, "service_id", + &conn->service, sizeof(conn->service)); +} + int coroipcs_handler_dispatch ( int fd, int revent, @@ -1447,6 +1541,9 @@ int coroipcs_handler_dispatch ( api->init_fn_get (conn_info->service) (conn_info); + /* create stats objects */ + coroipcs_init_conn_stats (conn_info); + pthread_attr_init (&conn_info->thread_attr); /* * IA64 needs more stack space then other arches diff --git a/exec/main.c b/exec/main.c index ede12dd..76ffffd 100644 --- a/exec/main.c +++ b/exec/main.c @@ -129,6 +129,8 @@ static hdb_handle_t corosync_poll_handle; struct sched_param global_sched_param; +static hdb_handle_t object_connection_handle; + hdb_handle_t corosync_poll_handle_get (void) { return (corosync_poll_handle); @@ -669,6 +671,100 @@ static void corosync_poll_dispatch_modify ( corosync_poll_handler_dispatch); } + +static hdb_handle_t corosync_stats_create_connection (const char* name, + const pid_t pid, const int fd) +{ + uint32_t zero_32 = 0; + uint64_t zero_64 = 0; + unsigned int key_incr_dummy; + hdb_handle_t object_handle; + + objdb->object_key_increment (object_connection_handle, + "active", strlen("active"), + &key_incr_dummy); + + objdb->object_create (object_connection_handle, + &object_handle, + name, + strlen (name)); + + objdb->object_key_create_typed (object_handle, + "service_id", + &zero_32, sizeof (zero_32), + OBJDB_VALUETYPE_UINT32); + + objdb->object_key_create_typed (object_handle, + "client_pid", + &pid, sizeof (pid), + OBJDB_VALUETYPE_INT32); + + objdb->object_key_create_typed (object_handle, + "responses", + &zero_64, sizeof (zero_64), + OBJDB_VALUETYPE_UINT64); + + objdb->object_key_create_typed (object_handle, + "dispatched", + &zero_64, sizeof (zero_64), + OBJDB_VALUETYPE_UINT64); + + objdb->object_key_create_typed (object_handle, + "requests", + &zero_64, sizeof (zero_64), + OBJDB_VALUETYPE_INT64); + + objdb->object_key_create_typed (object_handle, + "sem_retry_count", + &zero_64, sizeof (zero_64), + OBJDB_VALUETYPE_UINT64); + + objdb->object_key_create_typed (object_handle, + "send_retry_count", + &zero_64, sizeof (zero_64), + OBJDB_VALUETYPE_UINT64); + + objdb->object_key_create_typed (object_handle, + "recv_retry_count", + &zero_64, sizeof (zero_64), + OBJDB_VALUETYPE_UINT64); + + return object_handle; +} + +static void corosync_stats_destroy_connection (hdb_handle_t handle) +{ + unsigned int key_incr_dummy; + + objdb->object_destroy (handle); + + objdb->object_key_increment (object_connection_handle, + "closed", strlen("closed"), + &key_incr_dummy); + objdb->object_key_decrement (object_connection_handle, + "active", strlen("active"), + &key_incr_dummy); +} + +static void corosync_stats_update_value (hdb_handle_t handle, + const char *name, const void *value, + const size_t value_len) +{ + objdb->object_key_replace (handle, + name, strlen(name), + value, value_len); +} + +static void corosync_stats_increment_value (hdb_handle_t handle, + const char* name) +{ + unsigned int key_incr_dummy; + + objdb->object_key_increment (handle, + name, strlen(name), + &key_incr_dummy); +} + static struct coroipcs_init_state ipc_init_state = { .socket_name = COROSYNC_SOCKET_NAME, .sched_policy = SCHED_OTHER, @@ -692,6 +788,13 @@ static struct coroipcs_init_state ipc_init_state = { .handler_fn_get = corosync_handler_fn_get }; +static struct coroipcs_init_stats_state ipc_init_stats_state = { + .stats_create_connection = corosync_stats_create_connection, + .stats_destroy_connection = corosync_stats_destroy_connection, + .stats_update_value = corosync_stats_update_value, + .stats_increment_value = corosync_stats_increment_value +}; + static void corosync_setscheduler (void) { #if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX) && defined(HAVE_SCHED_SETSCHEDULER) @@ -734,6 +837,35 @@ static void corosync_setscheduler (void) #endif } +static void corosync_stats_init (void) +{ + hdb_handle_t object_find_handle; + hdb_handle_t object_runtime_handle; + uint64_t zero_64 = 0; + + objdb->object_find_create (OBJECT_PARENT_HANDLE, + "runtime", strlen ("runtime"), + &object_find_handle); + + if (objdb->object_find_next (object_find_handle, + &object_runtime_handle) != 0) { + return; + } + + /* Connection objects */ + objdb->object_create (object_runtime_handle, + &object_connection_handle, + "connections", strlen ("connections")); + + objdb->object_key_create_typed (object_connection_handle, + "active", &zero_64, sizeof (zero_64), + OBJDB_VALUETYPE_UINT64); + objdb->object_key_create_typed (object_connection_handle, + "closed", &zero_64, sizeof (zero_64), + OBJDB_VALUETYPE_UINT64); +} + + static void main_service_ready (void) { int res; @@ -746,6 +878,7 @@ static void main_service_ready (void) corosync_exit_error (AIS_DONE_INIT_SERVICES); } evil_init (api); + corosync_stats_init (); } int main (int argc, char **argv) @@ -765,6 +898,7 @@ int main (int argc, char **argv) int background, setprio; struct stat stat_out; char corosync_lib_dir[PATH_MAX]; + hdb_handle_t object_runtime_handle; #if defined(HAVE_PTHREAD_SPIN_LOCK) pthread_spin_init (&serialize_spin, 0); @@ -977,6 +1111,11 @@ int main (int argc, char **argv) corosync_exit_error (AIS_DONE_MAINCONFIGREAD); } + /* create the main runtime object */ + objdb->object_create (OBJECT_PARENT_HANDLE, + &object_runtime_handle, + "runtime", strlen ("runtime")); + /* * Now we are fully initialized. */ @@ -1062,6 +1201,7 @@ int main (int argc, char **argv) } coroipcs_ipc_init (&ipc_init_state); + coroipcs_ipc_stats_init (&ipc_init_stats_state); /* * Start main processing loop diff --git a/include/corosync/coroipcs.h b/include/corosync/coroipcs.h index 946b66d..0756a96 100644 --- a/include/corosync/coroipcs.h +++ b/include/corosync/coroipcs.h @@ -74,9 +74,21 @@ struct coroipcs_init_state { coroipcs_handler_fn_lvalue (*handler_fn_get)(unsigned int service, unsigned int id); }; +struct coroipcs_init_stats_state { + hdb_handle_t (*stats_create_connection) (const char* name, + const pid_t pid, const int fd); + void (*stats_destroy_connection) (hdb_handle_t handle); + void (*stats_update_value) (hdb_handle_t handle, + const char* name, const void* value, const size_t value_len); + void (*stats_increment_value) (hdb_handle_t handle, const char* name); +}; + extern void coroipcs_ipc_init ( struct coroipcs_init_state *init_state); +extern void coroipcs_ipc_stats_init ( + struct coroipcs_init_stats_state *init_stats_state); + extern void *coroipcs_private_data_get (void *conn); extern int coroipcs_response_send ( -- 1.6.3.4 _______________________________________________ Openais mailing list [email protected] https://lists.linux-foundation.org/mailman/listinfo/openais
