cs_error_t votequorum_dispatch ( votequorum_handle_t handle, cs_dispatch_flags_t dispatch_types) { int timeout = -1; cs_error_t error; int cont = 1; /* always continue do loop except when set to 0 */ struct votequorum_inst *votequorum_inst; votequorum_callbacks_t callbacks; struct qb_ipc_response_header *dispatch_data; struct res_lib_votequorum_notification *res_lib_votequorum_notification; struct res_lib_votequorum_expectedvotes_notification *res_lib_votequorum_expectedvotes_notification; char dispatch_buf[IPC_DISPATCH_SIZE]; votequorum_ring_id_t ring_id; if (dispatch_types != CS_DISPATCH_ONE && dispatch_types != CS_DISPATCH_ALL && dispatch_types != CS_DISPATCH_BLOCKING && dispatch_types != CS_DISPATCH_ONE_NONBLOCKING) { return (CS_ERR_INVALID_PARAM); } error = hdb_error_to_cs(hdb_handle_get (&votequorum_handle_t_db, handle, (void *)&votequorum_inst)); if (error != CS_OK) { return (error); } /* * Timeout instantly for CS_DISPATCH_ONE_NONBLOCKING or CS_DISPATCH_ALL and * wait indefinately for CS_DISPATCH_ONE or CS_DISPATCH_BLOCKING */ if (dispatch_types == CS_DISPATCH_ALL || dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { timeout = 0; } dispatch_data = (struct qb_ipc_response_header *)dispatch_buf; do { error = qb_to_cs_error (qb_ipcc_event_recv ( votequorum_inst->c, dispatch_buf, IPC_DISPATCH_SIZE, timeout)); if (error == CS_ERR_BAD_HANDLE) { error = CS_OK; goto error_put; } if (error == CS_ERR_TRY_AGAIN) { if (dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { /* * Don't mask error */ goto error_put; } error = CS_OK; if (dispatch_types == CS_DISPATCH_ALL) { break; /* exit do while cont is 1 loop */ } else { continue; /* next poll */ } } if (error != CS_OK) { goto error_put; } /* * Make copy of callbacks, message data, unlock instance, and call callback * A risk of this dispatch method is that the callback routines may * operate at the same time that votequorum_finalize has been called in another thread. */ memcpy (&callbacks, &votequorum_inst->callbacks, sizeof (votequorum_callbacks_t)); /* * Dispatch incoming message */ switch (dispatch_data->id) { case MESSAGE_RES_VOTEQUORUM_NOTIFICATION: if (callbacks.votequorum_notify_fn == NULL) { break; } res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)dispatch_data; marshall_from_mar_votequorum_ring_id (&ring_id, &res_lib_votequorum_notification->ring_id); callbacks.votequorum_notify_fn ( handle, res_lib_votequorum_notification->context, res_lib_votequorum_notification->quorate, ring_id, res_lib_votequorum_notification->node_list_entries, (votequorum_node_t *)res_lib_votequorum_notification->node_list ); ; break; case MESSAGE_RES_VOTEQUORUM_EXPECTEDVOTES_NOTIFICATION: if (callbacks.votequorum_expectedvotes_notify_fn == NULL) { break; } res_lib_votequorum_expectedvotes_notification = (struct res_lib_votequorum_expectedvotes_notification *)dispatch_data; callbacks.votequorum_expectedvotes_notify_fn ( handle, res_lib_votequorum_expectedvotes_notification->context, res_lib_votequorum_expectedvotes_notification->expected_votes); break; default: error = CS_ERR_LIBRARY; goto error_put; break; } if (votequorum_inst->finalize) { /* * If the finalize has been called then get out of the dispatch. */ error = CS_ERR_BAD_HANDLE; goto error_put; } /* * Determine if more messages should be processed */ if (dispatch_types == CS_DISPATCH_ONE || dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { cont = 0; } } while (cont); error_put: hdb_handle_put (&votequorum_handle_t_db, handle); return (error); }
cs_error_t quorum_initialize ( quorum_handle_t *handle, quorum_callbacks_t *callbacks, uint32_t *quorum_type) { cs_error_t error; struct quorum_inst *quorum_inst; struct iovec iov; struct qb_ipc_request_header req; struct res_lib_quorum_gettype res_lib_quorum_gettype; error = hdb_error_to_cs(hdb_handle_create (&quorum_handle_t_db, sizeof (struct quorum_inst), handle)); if (error != CS_OK) { goto error_no_destroy; } error = hdb_error_to_cs(hdb_handle_get (&quorum_handle_t_db, *handle, (void *)&quorum_inst)); if (error != CS_OK) { goto error_destroy; } error = CS_OK; quorum_inst->c = qb_ipcc_connect ("quorum", IPC_REQUEST_SIZE); if (quorum_inst->c == NULL) { error = qb_to_cs_error(-errno); goto error_put_destroy; } req.size = sizeof (req); req.id = MESSAGE_REQ_QUORUM_GETTYPE; iov.iov_base = (char *)&req; iov.iov_len = sizeof (req); error = qb_to_cs_error(qb_ipcc_sendv_recv ( quorum_inst->c, &iov, 1, &res_lib_quorum_gettype, sizeof (struct res_lib_quorum_gettype), -1)); if (error != CS_OK) { goto error_put_destroy; } error = res_lib_quorum_gettype.header.error; *quorum_type = res_lib_quorum_gettype.quorum_type; if (callbacks) memcpy(&quorum_inst->callbacks, callbacks, sizeof (*callbacks)); else memset(&quorum_inst->callbacks, 0, sizeof (*callbacks)); (void)hdb_handle_put (&quorum_handle_t_db, *handle); return (CS_OK); error_put_destroy: (void)hdb_handle_put (&quorum_handle_t_db, *handle); error_destroy: (void)hdb_handle_destroy (&quorum_handle_t_db, *handle); error_no_destroy: return (error); }
evs_error_t evs_dispatch ( evs_handle_t handle, cs_dispatch_flags_t dispatch_types) { int timeout = -1; cs_error_t error; int cont = 1; /* always continue do loop except when set to 0 */ struct evs_inst *evs_inst; struct res_evs_confchg_callback *res_evs_confchg_callback; struct res_evs_deliver_callback *res_evs_deliver_callback; evs_callbacks_t callbacks; coroipc_response_header_t *dispatch_data; error = hdb_error_to_cs(hdb_handle_get (&evs_handle_t_db, handle, (void *)&evs_inst)); if (error != CS_OK) { return (error); } /* * Timeout instantly for CS_DISPATCH_ONE or CS_DISPATCH_ALL and * wait indefinately for CS_DISPATCH_BLOCKING */ if (dispatch_types == EVS_DISPATCH_ALL) { timeout = 0; } do { error = coroipcc_dispatch_get ( evs_inst->handle, (void **)&dispatch_data, timeout); if (error == CS_ERR_BAD_HANDLE) { error = CS_OK; goto error_put; } if (error == CS_ERR_TRY_AGAIN) { error = CS_OK; if (dispatch_types == CPG_DISPATCH_ALL) { break; /* exit do while cont is 1 loop */ } else { continue; /* next poll */ } } if (error != CS_OK) { goto error_put; } /* * Make copy of callbacks, message data, unlock instance, and call callback * A risk of this dispatch method is that the callback routines may * operate at the same time that evsFinalize has been called. */ memcpy (&callbacks, &evs_inst->callbacks, sizeof (evs_callbacks_t)); /* * Dispatch incoming message */ switch (dispatch_data->id) { case MESSAGE_RES_EVS_DELIVER_CALLBACK: if (callbacks.evs_deliver_fn == NULL) { continue; } res_evs_deliver_callback = (struct res_evs_deliver_callback *)dispatch_data; callbacks.evs_deliver_fn ( handle, res_evs_deliver_callback->local_nodeid, &res_evs_deliver_callback->msg, res_evs_deliver_callback->msglen); break; case MESSAGE_RES_EVS_CONFCHG_CALLBACK: if (callbacks.evs_confchg_fn == NULL) { continue; } res_evs_confchg_callback = (struct res_evs_confchg_callback *)dispatch_data; callbacks.evs_confchg_fn ( handle, res_evs_confchg_callback->member_list, res_evs_confchg_callback->member_list_entries, res_evs_confchg_callback->left_list, res_evs_confchg_callback->left_list_entries, res_evs_confchg_callback->joined_list, res_evs_confchg_callback->joined_list_entries, NULL); break; default: coroipcc_dispatch_put (evs_inst->handle); error = CS_ERR_LIBRARY; goto error_put; break; } coroipcc_dispatch_put (evs_inst->handle); /* * Determine if more messages should be processed */ if (dispatch_types == CS_DISPATCH_ONE) { cont = 0; } } while (cont); error_put: hdb_handle_put (&evs_handle_t_db, handle); return (error); }
/* * External API */ cs_error_t coroipcc_service_connect ( const char *socket_name, unsigned int service, size_t request_size, size_t response_size, size_t dispatch_size, hdb_handle_t *handle) { int request_fd; struct sockaddr_un address; cs_error_t res; struct ipc_instance *ipc_instance; #if _POSIX_THREAD_PROCESS_SHARED < 1 key_t semkey = 0; union semun semun; #endif int sys_res; mar_req_setup_t req_setup; mar_res_setup_t res_setup; char control_map_path[PATH_MAX]; char request_map_path[PATH_MAX]; char response_map_path[PATH_MAX]; char dispatch_map_path[PATH_MAX]; res = hdb_error_to_cs (hdb_handle_create (&ipc_hdb, sizeof (struct ipc_instance), handle)); if (res != CS_OK) { return (res); } res = hdb_error_to_cs (hdb_handle_get (&ipc_hdb, *handle, (void **)&ipc_instance)); if (res != CS_OK) { return (res); } res_setup.error = CS_ERR_LIBRARY; #if defined(COROSYNC_SOLARIS) request_fd = socket (PF_UNIX, SOCK_STREAM, 0); #else request_fd = socket (PF_LOCAL, SOCK_STREAM, 0); #endif if (request_fd == -1) { return (CS_ERR_LIBRARY); } #ifdef SO_NOSIGPIPE socket_nosigpipe (request_fd); #endif memset (&address, 0, sizeof (struct sockaddr_un)); address.sun_family = AF_UNIX; #if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN) address.sun_len = SUN_LEN(&address); #endif #if defined(COROSYNC_LINUX) sprintf (address.sun_path + 1, "%s", socket_name); #else sprintf (address.sun_path, "%s/%s", SOCKETDIR, socket_name); #endif sys_res = connect (request_fd, (struct sockaddr *)&address, COROSYNC_SUN_LEN(&address)); if (sys_res == -1) { res = CS_ERR_TRY_AGAIN; goto error_connect; } sys_res = memory_map ( control_map_path, "control_buffer-XXXXXX", (void *)&ipc_instance->control_buffer, 8192); if (sys_res == -1) { res = CS_ERR_LIBRARY; goto error_connect; } sys_res = memory_map ( request_map_path, "request_buffer-XXXXXX", (void *)&ipc_instance->request_buffer, request_size); if (sys_res == -1) { res = CS_ERR_LIBRARY; goto error_request_buffer; } sys_res = memory_map ( response_map_path, "response_buffer-XXXXXX", (void *)&ipc_instance->response_buffer, response_size); if (sys_res == -1) { res = CS_ERR_LIBRARY; goto error_response_buffer; } sys_res = circular_memory_map ( dispatch_map_path, "dispatch_buffer-XXXXXX", (void *)&ipc_instance->dispatch_buffer, dispatch_size); if (sys_res == -1) { res = CS_ERR_LIBRARY; goto error_dispatch_buffer; } #if _POSIX_THREAD_PROCESS_SHARED > 0 sem_init (&ipc_instance->control_buffer->sem_request_or_flush_or_exit, 1, 0); sem_init (&ipc_instance->control_buffer->sem_request, 1, 0); sem_init (&ipc_instance->control_buffer->sem_response, 1, 0); sem_init (&ipc_instance->control_buffer->sem_dispatch, 1, 0); #else { int i; /* * Allocate a semaphore segment */ while (1) { semkey = random(); ipc_instance->euid = geteuid (); if ((ipc_instance->control_buffer->semid = semget (semkey, 4, IPC_CREAT|IPC_EXCL|0600)) != -1) { break; } /* * EACCESS can be returned as non root user when opening a different * users semaphore. * * EEXIST can happen when we are a root or nonroot user opening * an existing shared memory segment for which we have access */ if (errno != EEXIST && errno != EACCES) { res = CS_ERR_LIBRARY; goto error_exit; } } for (i = 0; i < 4; i++) { semun.val = 0; sys_res = semctl (ipc_instance->control_buffer->semid, i, SETVAL, semun); if (sys_res != 0) { res = CS_ERR_LIBRARY; goto error_exit; } } } #endif /* * Initialize IPC setup message */ req_setup.service = service; strcpy (req_setup.control_file, control_map_path); strcpy (req_setup.request_file, request_map_path); strcpy (req_setup.response_file, response_map_path); strcpy (req_setup.dispatch_file, dispatch_map_path); req_setup.control_size = 8192; req_setup.request_size = request_size; req_setup.response_size = response_size; req_setup.dispatch_size = dispatch_size; #if _POSIX_THREAD_PROCESS_SHARED < 1 req_setup.semkey = semkey; #endif res = socket_send (request_fd, &req_setup, sizeof (mar_req_setup_t)); if (res != CS_OK) { goto error_exit; } res = socket_recv (request_fd, &res_setup, sizeof (mar_res_setup_t)); if (res != CS_OK) { goto error_exit; } ipc_instance->fd = request_fd; if (res_setup.error == CS_ERR_TRY_AGAIN) { res = res_setup.error; goto error_exit; } ipc_instance->control_size = 8192; ipc_instance->request_size = request_size; ipc_instance->response_size = response_size; ipc_instance->dispatch_size = dispatch_size; pthread_mutex_init (&ipc_instance->mutex, NULL); hdb_handle_put (&ipc_hdb, *handle); return (res_setup.error); error_exit: #if _POSIX_THREAD_PROCESS_SHARED < 1 if (ipc_instance->control_buffer->semid > 0) semctl (ipc_instance->control_buffer->semid, 0, IPC_RMID); #endif memory_unmap (ipc_instance->dispatch_buffer, dispatch_size); error_dispatch_buffer: memory_unmap (ipc_instance->response_buffer, response_size); error_response_buffer: memory_unmap (ipc_instance->request_buffer, request_size); error_request_buffer: memory_unmap (ipc_instance->control_buffer, 8192); error_connect: close (request_fd); hdb_handle_destroy (&ipc_hdb, *handle); hdb_handle_put (&ipc_hdb, *handle); return (res); }
cs_error_t coroipcc_dispatch_get ( hdb_handle_t handle, void **data, int timeout) { struct pollfd ufds; int poll_events; char buf; struct ipc_instance *ipc_instance; char *data_addr; cs_error_t error = CS_OK; int res; error = hdb_error_to_cs (hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance)); if (error != CS_OK) { return (error); } if (shared_mem_dispatch_bytes_left (ipc_instance) > (ipc_instance->dispatch_size/2)) { /* * Notify coroipcs to flush any pending dispatch messages */ res = ipc_sem_post (ipc_instance->control_buffer, SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT); if (res != CS_OK) { error = CS_ERR_LIBRARY; goto error_put; } } *data = NULL; ufds.fd = ipc_instance->fd; ufds.events = POLLIN; ufds.revents = 0; poll_events = poll (&ufds, 1, timeout); if (poll_events == -1 && errno == EINTR) { error = CS_ERR_TRY_AGAIN; goto error_put; } else if (poll_events == -1) { error = CS_ERR_LIBRARY; goto error_put; } else if (poll_events == 0) { error = CS_ERR_TRY_AGAIN; goto error_put; } if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) { error = CS_ERR_LIBRARY; goto error_put; } error = socket_recv (ipc_instance->fd, &buf, 1); #if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN) /* On many OS poll() never returns POLLHUP or POLLERR. * EOF is detected when recvmsg() return 0. */ if ( error == CS_ERR_LIBRARY ) goto error_put; #endif assert (error == CS_OK); if (shared_mem_dispatch_bytes_left (ipc_instance) > (ipc_instance->dispatch_size/2)) { /* * Notify coroipcs to flush any pending dispatch messages */ res = ipc_sem_post (ipc_instance->control_buffer, SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT); if (res != CS_OK) { error = CS_ERR_LIBRARY; goto error_put; } } data_addr = ipc_instance->dispatch_buffer; data_addr = &data_addr[ipc_instance->control_buffer->read]; *data = (void *)data_addr; return (CS_OK); error_put: hdb_handle_put (&ipc_hdb, handle); return (error); }
cs_error_t coroipcc_dispatch_put (hdb_handle_t handle) { #if _POSIX_THREAD_PROCESS_SHARED < 1 struct sembuf sop; #endif coroipc_response_header_t *header; struct ipc_instance *ipc_instance; int res; char *addr; unsigned int read_idx; res = hdb_error_to_cs (hdb_handle_get_always (&ipc_hdb, handle, (void **)&ipc_instance)); if (res != CS_OK) { return (res); } #if _POSIX_THREAD_PROCESS_SHARED > 0 retry_semwait: res = sem_wait (&ipc_instance->control_buffer->sem2); if (res == -1 && errno == EINTR) { goto retry_semwait; } #else sop.sem_num = 2; sop.sem_op = -1; sop.sem_flg = 0; retry_semop: res = semop (ipc_instance->semid, &sop, 1); if (res == -1 && errno == EINTR) { res = CS_ERR_TRY_AGAIN; goto error_exit; } else if (res == -1 && errno == EACCES) { priv_change_send (ipc_instance); goto retry_semop; } else if (res == -1) { res = CS_ERR_LIBRARY; goto error_exit; } #endif addr = ipc_instance->dispatch_buffer; read_idx = ipc_instance->control_buffer->read; header = (coroipc_response_header_t *) &addr[read_idx]; ipc_instance->control_buffer->read = (read_idx + header->size) % ipc_instance->dispatch_size; /* * Put from dispatch get and also from this call's get */ res = CS_OK; #if _POSIX_THREAD_PROCESS_SHARED < 1 error_exit: #endif hdb_handle_put (&ipc_hdb, handle); hdb_handle_put (&ipc_hdb, handle); return (res); }
cs_error_t corosync_cfg_get_node_addrs ( corosync_cfg_handle_t cfg_handle, unsigned int nodeid, size_t max_addrs, int *num_addrs, corosync_cfg_node_address_t *addrs) { cs_error_t error; struct req_lib_cfg_get_node_addrs req_lib_cfg_get_node_addrs; struct res_lib_cfg_get_node_addrs *res_lib_cfg_get_node_addrs; struct cfg_inst *cfg_inst; int addrlen = 0; int i; struct iovec iov; const char *addr_buf; char response_buf[IPC_RESPONSE_SIZE]; char zeroes[sizeof(struct sockaddr_storage)]; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } memset(zeroes, 0, sizeof(zeroes)); req_lib_cfg_get_node_addrs.header.size = sizeof (req_lib_cfg_get_node_addrs); req_lib_cfg_get_node_addrs.header.id = MESSAGE_REQ_CFG_GET_NODE_ADDRS; req_lib_cfg_get_node_addrs.nodeid = nodeid; iov.iov_base = (char *)&req_lib_cfg_get_node_addrs; iov.iov_len = sizeof (req_lib_cfg_get_node_addrs); error = qb_to_cs_error (qb_ipcc_sendv_recv ( cfg_inst->c, &iov, 1, response_buf, IPC_RESPONSE_SIZE, CS_IPC_TIMEOUT_MS)); res_lib_cfg_get_node_addrs = (struct res_lib_cfg_get_node_addrs *)response_buf; if (error != CS_OK) { goto error_put; } if (res_lib_cfg_get_node_addrs->family == AF_INET) addrlen = sizeof(struct sockaddr_in); if (res_lib_cfg_get_node_addrs->family == AF_INET6) addrlen = sizeof(struct sockaddr_in6); for (i = 0, addr_buf = (char *)res_lib_cfg_get_node_addrs->addrs; i < max_addrs && i<res_lib_cfg_get_node_addrs->num_addrs; i++, addr_buf += TOTEMIP_ADDRLEN) { struct sockaddr_in *in; struct sockaddr_in6 *in6; addrs[i].address_length = addrlen; if (res_lib_cfg_get_node_addrs->family == AF_INET) { in = (struct sockaddr_in *)addrs[i].address; if (memcmp(addr_buf, zeroes, addrlen) == 0) { in->sin_family = 0; } else { in->sin_family = AF_INET; } memcpy(&in->sin_addr, addr_buf, sizeof(struct in_addr)); } if (res_lib_cfg_get_node_addrs->family == AF_INET6) { in6 = (struct sockaddr_in6 *)addrs[i].address; if (memcmp(addr_buf, zeroes, addrlen) == 0) { in6->sin6_family = 0; } else { in6->sin6_family = AF_INET6; } memcpy(&in6->sin6_addr, addr_buf, sizeof(struct in6_addr)); } /* Mark it as unused */ } *num_addrs = res_lib_cfg_get_node_addrs->num_addrs; errno = error = res_lib_cfg_get_node_addrs->header.error; error_put: hdb_handle_put (&cfg_hdb, cfg_handle); return (error); }
cs_error_t cmap_dispatch ( cmap_handle_t handle, cs_dispatch_flags_t dispatch_types) { int timeout = -1; cs_error_t error; int cont = 1; /* always continue do loop except when set to 0 */ struct cmap_inst *cmap_inst; struct qb_ipc_response_header *dispatch_data; char dispatch_buf[IPC_DISPATCH_SIZE]; struct res_lib_cmap_notify_callback *res_lib_cmap_notify_callback; struct cmap_track_inst *cmap_track_inst; struct cmap_notify_value old_val; struct cmap_notify_value new_val; error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); if (error != CS_OK) { return (error); } /* * Timeout instantly for CS_DISPATCH_ONE_NONBLOCKING or CS_DISPATCH_ALL and * wait indefinately for CS_DISPATCH_ONE or CS_DISPATCH_BLOCKING */ if (dispatch_types == CS_DISPATCH_ALL || dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { timeout = 0; } dispatch_data = (struct qb_ipc_response_header *)dispatch_buf; do { error = qb_to_cs_error(qb_ipcc_event_recv ( cmap_inst->c, dispatch_buf, IPC_DISPATCH_SIZE, timeout)); if (error == CS_ERR_BAD_HANDLE) { error = CS_OK; goto error_put; } if (error == CS_ERR_TRY_AGAIN) { if (dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { /* * Don't mask error */ goto error_put; } error = CS_OK; if (dispatch_types == CS_DISPATCH_ALL) { break; /* exit do while cont is 1 loop */ } else { continue; /* next poll */ } } if (error != CS_OK) { goto error_put; } /* * Dispatch incoming message */ switch (dispatch_data->id) { case MESSAGE_RES_CMAP_NOTIFY_CALLBACK: res_lib_cmap_notify_callback = (struct res_lib_cmap_notify_callback *)dispatch_data; error = hdb_error_to_cs(hdb_handle_get(&cmap_track_handle_t_db, res_lib_cmap_notify_callback->track_inst_handle, (void *)&cmap_track_inst)); if (error == CS_ERR_BAD_HANDLE) { /* * User deleted tracker -> ignore error */ break; } if (error != CS_OK) { goto error_put; } new_val.type = res_lib_cmap_notify_callback->new_value_type; old_val.type = res_lib_cmap_notify_callback->old_value_type; new_val.len = res_lib_cmap_notify_callback->new_value_len; old_val.len = res_lib_cmap_notify_callback->old_value_len; new_val.data = res_lib_cmap_notify_callback->new_value; old_val.data = (((const char *)res_lib_cmap_notify_callback->new_value) + new_val.len); cmap_track_inst->notify_fn(handle, cmap_track_inst->track_handle, res_lib_cmap_notify_callback->event, (char *)res_lib_cmap_notify_callback->key_name.value, new_val, old_val, cmap_track_inst->user_data); (void)hdb_handle_put(&cmap_track_handle_t_db, res_lib_cmap_notify_callback->track_inst_handle); break; default: error = CS_ERR_LIBRARY; goto error_put; break; } /* * Determine if more messages should be processed */ if (dispatch_types == CS_DISPATCH_ONE || dispatch_types == CS_DISPATCH_ONE_NONBLOCKING) { cont = 0; } } while (cont); error_put: (void)hdb_handle_put (&cmap_handle_t_db, handle); return (error); }
cs_error_t cmap_get( cmap_handle_t handle, const char *key_name, void *value, size_t *value_len, cmap_value_types_t *type) { cs_error_t error; struct cmap_inst *cmap_inst; struct iovec iov; struct req_lib_cmap_get req_lib_cmap_get; struct res_lib_cmap_get *res_lib_cmap_get; size_t res_size; if (key_name == NULL) { return (CS_ERR_INVALID_PARAM); } error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); if (error != CS_OK) { return (error); } memset(&req_lib_cmap_get, 0, sizeof(req_lib_cmap_get)); req_lib_cmap_get.header.size = sizeof(req_lib_cmap_get); req_lib_cmap_get.header.id = MESSAGE_REQ_CMAP_GET; memcpy(req_lib_cmap_get.key_name.value, key_name, strlen(key_name)); req_lib_cmap_get.key_name.length = strlen(key_name); if (value != NULL && value_len != NULL) { req_lib_cmap_get.value_len = *value_len; } else { req_lib_cmap_get.value_len = 0; } iov.iov_base = (char *)&req_lib_cmap_get; iov.iov_len = sizeof(req_lib_cmap_get); res_size = sizeof(struct res_lib_cmap_get) + req_lib_cmap_get.value_len; res_lib_cmap_get = malloc(res_size); if (res_lib_cmap_get == NULL) { return (CS_ERR_NO_MEMORY); } error = qb_to_cs_error(qb_ipcc_sendv_recv( cmap_inst->c, &iov, 1, res_lib_cmap_get, res_size, CS_IPC_TIMEOUT_MS)); if (error == CS_OK) { error = res_lib_cmap_get->header.error; } if (error == CS_OK) { if (type != NULL) { *type = res_lib_cmap_get->type; } if (value_len != NULL) { *value_len = res_lib_cmap_get->value_len; } if (value != NULL) { memcpy(value, res_lib_cmap_get->value, res_lib_cmap_get->value_len); } } free(res_lib_cmap_get); (void)hdb_handle_put (&cmap_handle_t_db, handle); return (error); }
static int object_key_create_typed( hdb_handle_t object_handle, const char *key_name, const void *value, size_t value_len, objdb_value_types_t value_type) { struct object_instance *instance; struct object_key *object_key; int res; struct list_head *list; int found = 0; int i; size_t key_len = strlen(key_name); size_t expected_size; int test_size_by_type = CS_TRUE; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } switch (value_type) { case OBJDB_VALUETYPE_INT16: expected_size = sizeof (int16_t); break; case OBJDB_VALUETYPE_UINT16: expected_size = sizeof (uint16_t); break; case OBJDB_VALUETYPE_INT32: expected_size = sizeof (int32_t); break; case OBJDB_VALUETYPE_UINT32: expected_size = sizeof (uint32_t); break; case OBJDB_VALUETYPE_INT64: expected_size = sizeof (int64_t); break; case OBJDB_VALUETYPE_UINT64: expected_size = sizeof (uint64_t); break; case OBJDB_VALUETYPE_FLOAT: expected_size = sizeof (float); break; case OBJDB_VALUETYPE_DOUBLE: expected_size = sizeof (double); break; case OBJDB_VALUETYPE_ANY: default: test_size_by_type = CS_FALSE; break; } if (test_size_by_type) { if (expected_size != value_len) { //printf ("%s exp:%d != len:%d\n", key_name, expected_size, value_len); goto error_put; } } /* * Do validation check if validation is configured for the parent object */ if (instance->object_key_valid_list_entries) { for (i = 0; i < instance->object_key_valid_list_entries; i++) { if ((key_len == instance->object_key_valid_list[i].key_len) && (memcmp (key_name, instance->object_key_valid_list[i].key_name, key_len) == 0)) { found = 1; break; } } /* * Item not found in validation list */ if (found == 0) { goto error_put; } else { if (instance->object_key_valid_list[i].validate_callback) { res = instance->object_key_valid_list[i].validate_callback ( key_name, key_len, value, value_len); if (res != 0) { goto error_put; } } } } /* See if it already exists */ found = 0; for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { free(object_key->value); } else { object_key = malloc (sizeof (struct object_key)); if (object_key == 0) { goto error_put; } object_key->key_name = malloc (key_len + 1); if (object_key->key_name == 0) { goto error_put_object; } memcpy (object_key->key_name, key_name, key_len + 1); list_init (&object_key->list); list_add_tail (&object_key->list, &instance->key_head); } object_key->value = malloc (value_len); if (object_key->value == 0) { goto error_put_key; } memcpy (object_key->value, value, value_len); object_key->key_len = key_len; object_key->value_len = value_len; object_key->value_type = value_type; object_key_changed_notification(object_handle, key_name, key_len, value, value_len, OBJECT_KEY_CREATED); hdb_handle_put (&object_instance_database, object_handle); return (0); error_put_key: free (object_key->key_name); error_put_object: free (object_key); error_put: hdb_handle_put (&object_instance_database, object_handle); error_exit: return (-1); }
/* * object db reading */ static int object_find_create ( hdb_handle_t object_handle, const void *object_name, size_t object_len, hdb_handle_t *object_find_handle) { int res; struct object_instance *iter_obj_inst; struct object_instance *object_instance; struct object_find_instance *object_find_instance; struct list_head *list; hdb_handle_t *handles_array, *handles_array_realloc; size_t ha_len; size_t ha_used; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&object_instance); if (res != 0) { goto error_exit; } res = hdb_handle_create (&object_find_instance_database, sizeof (struct object_find_instance), object_find_handle); if (res != 0) { goto error_put; } res = hdb_handle_get (&object_find_instance_database, *object_find_handle, (void *)&object_find_instance); if (res != 0) { goto error_destroy; } object_find_instance->object_name = (char *)object_name; object_find_instance->object_len = object_len; ha_len = ha_used = 0; handles_array = NULL; for (list = object_instance->child_head.next; list != &object_instance->child_head; list = list->next) { iter_obj_inst = list_entry (list, struct object_instance, child_list); if (object_find_instance->object_len == 0 || ((iter_obj_inst->object_name_len == object_find_instance->object_len) && (memcmp (iter_obj_inst->object_name, object_find_instance->object_name, object_find_instance->object_len) == 0))) { /* * Add handle to list */ if (ha_used + 1 > ha_len) { ha_len = ha_len * 2 + 1; if ((handles_array_realloc = realloc (handles_array, ha_len * sizeof (hdb_handle_t))) == NULL) { goto error_ha_free; } handles_array = handles_array_realloc; } handles_array[ha_used] = iter_obj_inst->object_handle; ha_used++; } } object_find_instance->handles_array_size = ha_used; object_find_instance->handles_array_pos = 0; object_find_instance->handles_array = handles_array; hdb_handle_put (&object_instance_database, object_handle); hdb_handle_put (&object_find_instance_database, *object_find_handle); return (0); error_ha_free: free(handles_array); error_destroy: hdb_handle_destroy (&object_instance_database, *object_find_handle); error_put: hdb_handle_put (&object_instance_database, object_handle); error_exit: return (-1); }
/* * object db create/destroy/set */ static int object_create ( hdb_handle_t parent_object_handle, hdb_handle_t *object_handle, const void *object_name, size_t object_name_len) { struct object_instance *object_instance; struct object_instance *parent_instance; int res; int found = 0; int i; res = hdb_handle_get (&object_instance_database, parent_object_handle, (void *)&parent_instance); if (res != 0) { goto error_exit; } /* * Do validation check if validation is configured for the parent object */ if (parent_instance->object_valid_list_entries) { for (i = 0; i < parent_instance->object_valid_list_entries; i++) { if ((object_name_len == parent_instance->object_valid_list[i].object_len) && (memcmp (object_name, parent_instance->object_valid_list[i].object_name, object_name_len) == 0)) { found = 1; break; } } /* * Item not found in validation list */ if (found == 0) { goto error_object_put; } } res = hdb_handle_create (&object_instance_database, sizeof (struct object_instance), object_handle); if (res != 0) { goto error_object_put; } res = hdb_handle_get (&object_instance_database, *object_handle, (void *)&object_instance); if (res != 0) { goto error_destroy; } list_init (&object_instance->key_head); list_init (&object_instance->child_head); list_init (&object_instance->child_list); list_init (&object_instance->track_head); object_instance->object_name = malloc (object_name_len); if (object_instance->object_name == 0) { goto error_put_destroy; } memcpy (object_instance->object_name, object_name, object_name_len); object_instance->object_name_len = object_name_len; list_add_tail (&object_instance->child_list, &parent_instance->child_head); object_instance->object_handle = *object_handle; object_instance->find_child_list = &object_instance->child_head; object_instance->iter_key_list = &object_instance->key_head; object_instance->iter_list = &object_instance->child_head; object_instance->priv = NULL; object_instance->object_valid_list = NULL; object_instance->object_valid_list_entries = 0; object_instance->parent_handle = parent_object_handle; hdb_handle_put (&object_instance_database, *object_handle); hdb_handle_put (&object_instance_database, parent_object_handle); object_created_notification( object_instance->parent_handle, object_instance->object_handle, object_instance->object_name, object_instance->object_name_len); return (0); error_put_destroy: hdb_handle_put (&object_instance_database, *object_handle); error_destroy: hdb_handle_destroy (&object_instance_database, *object_handle); error_object_put: hdb_handle_put (&object_instance_database, parent_object_handle); error_exit: return (-1); }
static int object_key_replace ( hdb_handle_t object_handle, const void *key_name, size_t key_len, const void *new_value, size_t new_value_len) { int res; int ret = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; int value_changed = 0; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { int i; int found_validator = 0; /* * Do validation check if validation is configured for the parent object */ if (instance->object_key_valid_list_entries) { for (i = 0; i < instance->object_key_valid_list_entries; i++) { if ((key_len == instance->object_key_valid_list[i].key_len) && (memcmp (key_name, instance->object_key_valid_list[i].key_name, key_len) == 0)) { found_validator = 1; break; } } /* * Item not found in validation list */ if (found_validator == 0) { goto error_put; } else { if (instance->object_key_valid_list[i].validate_callback) { res = instance->object_key_valid_list[i].validate_callback ( key_name, key_len, new_value, new_value_len); if (res != 0) { goto error_put; } } } } if (new_value_len != object_key->value_len) { void *replacement_value; replacement_value = malloc(new_value_len); if (!replacement_value) goto error_exit; free(object_key->value); object_key->value = replacement_value; memset (object_key->value, 0, new_value_len); object_key->value_len = new_value_len; } if (memcmp (object_key->value, new_value, new_value_len) == 0) { value_changed = 0; } else { memcpy(object_key->value, new_value, new_value_len); object_key->value_len = new_value_len; value_changed = 1; } } else { ret = -1; errno = ENOENT; } hdb_handle_put (&object_instance_database, object_handle); if (ret == 0 && value_changed) { object_key_changed_notification (object_handle, key_name, key_len, new_value, new_value_len, OBJECT_KEY_REPLACED); } return (ret); error_put: hdb_handle_put (&object_instance_database, object_handle); error_exit: return (-1); }
static int object_key_decrement ( hdb_handle_t object_handle, const void *key_name, size_t key_len, unsigned int *value) { int res = 0; struct object_instance *instance; struct object_key *object_key = NULL; struct list_head *list; int found = 0; res = hdb_handle_get (&object_instance_database, object_handle, (void *)&instance); if (res != 0) { goto error_exit; } for (list = instance->key_head.next; list != &instance->key_head; list = list->next) { object_key = list_entry (list, struct object_key, list); if ((object_key->key_len == key_len) && (memcmp (object_key->key_name, key_name, key_len) == 0)) { found = 1; break; } } if (found) { switch (object_key->value_type) { case OBJDB_VALUETYPE_INT16: (*(int16_t *)object_key->value)--; break; case OBJDB_VALUETYPE_UINT16: (*(uint16_t *)object_key->value)--; break; case OBJDB_VALUETYPE_INT32: (*(int32_t *)object_key->value)--; break; case OBJDB_VALUETYPE_UINT32: (*(uint32_t *)object_key->value)--; break; case OBJDB_VALUETYPE_INT64: (*(int64_t *)object_key->value)--; break; case OBJDB_VALUETYPE_UINT64: (*(uint64_t *)object_key->value)--; break; case OBJDB_VALUETYPE_ANY: /* for backwards compatibilty */ if (object_key->value_len == sizeof(int)) { (*(int *)object_key->value)--; } else { res = -1; } break; default: res = -1; break; } if (res == 0) { /* nasty, not sure why we need to return this typed * instead of void* */ *value = *(int *)object_key->value; } } else { res = -1; } hdb_handle_put (&object_instance_database, object_handle); if (res == 0) { object_key_changed_notification (object_handle, key_name, key_len, object_key->value, object_key->value_len, OBJECT_KEY_REPLACED); } return (res); error_exit: return (-1); }
cs_error_t corosync_cfg_dispatch ( corosync_cfg_handle_t cfg_handle, cs_dispatch_flags_t dispatch_flags) { int timeout = -1; cs_error_t error; int cont = 1; /* always continue do loop except when set to 0 */ struct cfg_inst *cfg_inst; struct res_lib_cfg_testshutdown *res_lib_cfg_testshutdown; corosync_cfg_callbacks_t callbacks; struct qb_ipc_response_header *dispatch_data; char dispatch_buf[IPC_DISPATCH_SIZE]; error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } /* * Timeout instantly for CS_DISPATCH_ONE_NONBLOCKING or CS_DISPATCH_ALL and * wait indefinately for CS_DISPATCH_ONE or CS_DISPATCH_BLOCKING */ if (dispatch_flags == CS_DISPATCH_ALL || dispatch_flags == CS_DISPATCH_ONE_NONBLOCKING) { timeout = 0; } dispatch_data = (struct qb_ipc_response_header *)dispatch_buf; do { error = qb_to_cs_error (qb_ipcc_event_recv ( cfg_inst->c, dispatch_buf, IPC_DISPATCH_SIZE, timeout)); if (error == CS_ERR_BAD_HANDLE) { error = CS_OK; goto error_put; } if (error == CS_ERR_TRY_AGAIN) { if (dispatch_flags == CS_DISPATCH_ONE_NONBLOCKING) { /* * Don't mask error */ goto error_put; } error = CS_OK; if (dispatch_flags == CS_DISPATCH_ALL) { break; /* exit do while cont is 1 loop */ } else { continue; /* next poll */ } } if (error != CS_OK) { goto error_put; } /* * Make copy of callbacks, message data, unlock instance, and call callback * A risk of this dispatch method is that the callback routines may * operate at the same time that cfgFinalize has been called in another thread. */ memcpy (&callbacks, &cfg_inst->callbacks, sizeof (corosync_cfg_callbacks_t)); /* * Dispatch incoming response */ switch (dispatch_data->id) { case MESSAGE_RES_CFG_TESTSHUTDOWN: if (callbacks.corosync_cfg_shutdown_callback == NULL) { break; } res_lib_cfg_testshutdown = (struct res_lib_cfg_testshutdown *)dispatch_data; callbacks.corosync_cfg_shutdown_callback(cfg_handle, res_lib_cfg_testshutdown->flags); break; default: error = CS_ERR_LIBRARY; goto error_nounlock; break; } if (cfg_inst->finalize) { /* * If the finalize has been called then get out of the dispatch. */ error = CS_ERR_BAD_HANDLE; goto error_put; } /* * Determine if more messages should be processed */ if (dispatch_flags == CS_DISPATCH_ONE || dispatch_flags == CS_DISPATCH_ONE_NONBLOCKING) { cont = 0; } } while (cont); error_put: (void)hdb_handle_put (&cfg_hdb, cfg_handle); error_nounlock: return (error); }
cs_error_t cmap_track_add( cmap_handle_t handle, const char *key_name, int32_t track_type, cmap_notify_fn_t notify_fn, void *user_data, cmap_track_handle_t *cmap_track_handle) { cs_error_t error; struct iovec iov; struct cmap_inst *cmap_inst; struct req_lib_cmap_track_add req_lib_cmap_track_add; struct res_lib_cmap_track_add res_lib_cmap_track_add; struct cmap_track_inst *cmap_track_inst; cmap_track_handle_t cmap_track_inst_handle; error = hdb_error_to_cs(hdb_handle_get (&cmap_handle_t_db, handle, (void *)&cmap_inst)); if (error != CS_OK) { return (error); } error = hdb_error_to_cs(hdb_handle_create(&cmap_track_handle_t_db, sizeof(*cmap_track_inst), &cmap_track_inst_handle)); if (error != CS_OK) { goto error_put; } error = hdb_error_to_cs(hdb_handle_get(&cmap_track_handle_t_db, cmap_track_inst_handle, (void *)&cmap_track_inst)); if (error != CS_OK) { goto error_put_destroy; } cmap_track_inst->user_data = user_data; cmap_track_inst->notify_fn = notify_fn; cmap_track_inst->c = cmap_inst->c; memset(&req_lib_cmap_track_add, 0, sizeof(req_lib_cmap_track_add)); req_lib_cmap_track_add.header.size = sizeof(req_lib_cmap_track_add); req_lib_cmap_track_add.header.id = MESSAGE_REQ_CMAP_TRACK_ADD; if (key_name) { memcpy(req_lib_cmap_track_add.key_name.value, key_name, strlen(key_name)); req_lib_cmap_track_add.key_name.length = strlen(key_name); } req_lib_cmap_track_add.track_type = track_type; req_lib_cmap_track_add.track_inst_handle = cmap_track_inst_handle; iov.iov_base = (char *)&req_lib_cmap_track_add; iov.iov_len = sizeof(req_lib_cmap_track_add); error = qb_to_cs_error(qb_ipcc_sendv_recv( cmap_inst->c, &iov, 1, &res_lib_cmap_track_add, sizeof (struct res_lib_cmap_track_add), CS_IPC_TIMEOUT_MS)); if (error == CS_OK) { error = res_lib_cmap_track_add.header.error; } if (error == CS_OK) { *cmap_track_handle = res_lib_cmap_track_add.track_handle; cmap_track_inst->track_handle = *cmap_track_handle; } (void)hdb_handle_put (&cmap_track_handle_t_db, cmap_track_inst_handle); (void)hdb_handle_put (&cmap_handle_t_db, handle); return (error); error_put_destroy: (void)hdb_handle_put (&cmap_track_handle_t_db, cmap_track_inst_handle); (void)hdb_handle_destroy (&cmap_track_handle_t_db, cmap_track_inst_handle); error_put: (void)hdb_handle_put (&cmap_handle_t_db, handle); return (error); }
cs_error_t corosync_cfg_ring_status_get ( corosync_cfg_handle_t cfg_handle, char ***interface_names, char ***status, unsigned int *interface_count) { struct cfg_inst *cfg_inst; struct req_lib_cfg_ringstatusget req_lib_cfg_ringstatusget; struct res_lib_cfg_ringstatusget res_lib_cfg_ringstatusget; unsigned int i, j; cs_error_t error; struct iovec iov; error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst)); if (error != CS_OK) { return (error); } req_lib_cfg_ringstatusget.header.size = sizeof (struct req_lib_cfg_ringstatusget); req_lib_cfg_ringstatusget.header.id = MESSAGE_REQ_CFG_RINGSTATUSGET; iov.iov_base = (void *)&req_lib_cfg_ringstatusget, iov.iov_len = sizeof (struct req_lib_cfg_ringstatusget), error = qb_to_cs_error (qb_ipcc_sendv_recv(cfg_inst->c, &iov, 1, &res_lib_cfg_ringstatusget, sizeof (struct res_lib_cfg_ringstatusget), CS_IPC_TIMEOUT_MS)); if (error != CS_OK) { goto exit_handle_put; } *interface_count = res_lib_cfg_ringstatusget.interface_count; *interface_names = malloc (sizeof (char *) * *interface_count); if (*interface_names == NULL) { return (CS_ERR_NO_MEMORY); } memset (*interface_names, 0, sizeof (char *) * *interface_count); *status = malloc (sizeof (char *) * *interface_count); if (*status == NULL) { error = CS_ERR_NO_MEMORY; goto error_free_interface_names_array; } memset (*status, 0, sizeof (char *) * *interface_count); for (i = 0; i < res_lib_cfg_ringstatusget.interface_count; i++) { (*(interface_names))[i] = strdup (res_lib_cfg_ringstatusget.interface_name[i]); if ((*(interface_names))[i] == NULL) { error = CS_ERR_NO_MEMORY; goto error_free_interface_names; } } for (i = 0; i < res_lib_cfg_ringstatusget.interface_count; i++) { (*(status))[i] = strdup (res_lib_cfg_ringstatusget.interface_status[i]); if ((*(status))[i] == NULL) { error = CS_ERR_NO_MEMORY; goto error_free_status; } } goto exit_handle_put; error_free_status: for (j = 0; j < i; j++) { free ((*(status))[j]); } i = *interface_count; error_free_interface_names: for (j = 0; j < i; j++) { free ((*(interface_names))[j]); } free (*status); error_free_interface_names_array: free (*interface_names); exit_handle_put: (void)hdb_handle_put (&cfg_hdb, cfg_handle); return (error); }
cs_error_t coroipcc_dispatch_get ( hdb_handle_t handle, void **data, int timeout) { struct pollfd ufds; int poll_events; char buf; struct ipc_instance *ipc_instance; int res; char buf_two = 1; char *data_addr; cs_error_t error = CS_OK; error = hdb_error_to_cs (hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance)); if (error != CS_OK) { return (error); } *data = NULL; ufds.fd = ipc_instance->fd; ufds.events = POLLIN; ufds.revents = 0; poll_events = poll (&ufds, 1, timeout); if (poll_events == -1 && errno == EINTR) { error = CS_ERR_TRY_AGAIN; goto error_put; } else if (poll_events == -1) { error = CS_ERR_LIBRARY; goto error_put; } else if (poll_events == 0) { error = CS_ERR_TRY_AGAIN; goto error_put; } if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) { error = CS_ERR_LIBRARY; goto error_put; } res = recv (ipc_instance->fd, &buf, 1, 0); if (res == -1 && errno == EINTR) { error = CS_ERR_TRY_AGAIN; goto error_put; } else if (res == -1) { error = CS_ERR_LIBRARY; goto error_put; } else if (res == 0) { /* Means that the peer closed cleanly the socket. However, it should * happen only on BSD and Darwing systems since poll() returns a * POLLHUP event on other systems. */ error = CS_ERR_LIBRARY; goto error_put; } ipc_instance->flow_control_state = 0; if (buf == MESSAGE_RES_OUTQ_NOT_EMPTY || buf == MESSAGE_RES_ENABLE_FLOWCONTROL) { ipc_instance->flow_control_state = 1; } /* * Notify executive to flush any pending dispatch messages */ if (ipc_instance->flow_control_state) { buf_two = MESSAGE_REQ_OUTQ_FLUSH; res = socket_send (ipc_instance->fd, &buf_two, 1); assert (res == CS_OK); /* TODO */ } /* * This is just a notification of flow control starting at the addition * of a new pending message, not a message to dispatch */ if (buf == MESSAGE_RES_ENABLE_FLOWCONTROL) { error = CS_ERR_TRY_AGAIN; goto error_put; } if (buf == MESSAGE_RES_OUTQ_FLUSH_NR) { error = CS_ERR_TRY_AGAIN; goto error_put; } data_addr = ipc_instance->dispatch_buffer; data_addr = &data_addr[ipc_instance->control_buffer->read]; *data = (void *)data_addr; return (CS_OK); error_put: hdb_handle_put (&ipc_hdb, handle); return (error); }