예제 #1
0
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);
}
예제 #2
0
파일: quorum.c 프로젝트: ip1981/corosync
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);
}
예제 #3
0
파일: evs.c 프로젝트: ystk/debian-corosync
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);
}
예제 #4
0
파일: coroipcc.c 프로젝트: emrehe/corosync
/*
 * 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);
}
예제 #5
0
파일: coroipcc.c 프로젝트: emrehe/corosync
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);
}
예제 #6
0
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);
}
예제 #7
0
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);
}
예제 #8
0
파일: cmap.c 프로젝트: ip1981/corosync
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);
}
예제 #9
0
파일: cmap.c 프로젝트: ip1981/corosync
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);
}
예제 #10
0
파일: objdb.c 프로젝트: danfrincu/corosync
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);
}
예제 #11
0
파일: objdb.c 프로젝트: danfrincu/corosync
/*
 * 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);
}
예제 #12
0
파일: objdb.c 프로젝트: danfrincu/corosync
/*
 * 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);
}
예제 #13
0
파일: objdb.c 프로젝트: danfrincu/corosync
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);
}
예제 #14
0
파일: objdb.c 프로젝트: danfrincu/corosync
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);
}
예제 #15
0
파일: cfg.c 프로젝트: credativ/corosync
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);
}
예제 #16
0
파일: cmap.c 프로젝트: ip1981/corosync
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);
}
예제 #17
0
파일: cfg.c 프로젝트: credativ/corosync
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);
}
예제 #18
0
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);
}