static int q_lib_init(void)
{
	votequorum_callbacks_t vq_callbacks;
	quorum_callbacks_t q_callbacks;
	int ret = 0;
	int retry = 3;
	int fd;

	if (vq_handle == 0) {
		qb_log (LOG_INFO, "votequorum_initialize");
		vq_callbacks.votequorum_notify_fn = votequorum_notification_fn;
		vq_callbacks.votequorum_expectedvotes_notify_fn = NULL;
		ret = CS_ERR_NOT_EXIST;
		while (ret == CS_ERR_NOT_EXIST && retry > 0) {
			ret = votequorum_initialize (&vq_handle, &vq_callbacks);
			if (ret == CS_ERR_NOT_EXIST) {
				sleep (1);
				retry--;
			}
		}
		if (ret != CS_OK) {
			qb_log (LOG_ERR, "votequorum_initialize FAILED: %d", ret);
			vq_handle = 0;
		}
		else {
			ret = votequorum_trackstart (vq_handle, vq_handle, CS_TRACK_CHANGES);
			if (ret != CS_OK) {
				qb_log (LOG_ERR, "votequorum_trackstart FAILED: %d", ret);
			}

			votequorum_fd_get (vq_handle, &fd);
			qb_loop_poll_add (ta_poll_handle_get(), QB_LOOP_MED, fd,
				POLLIN|POLLNVAL, NULL, vq_dispatch_wrapper_fn);
		}
	}
	if (q_handle == 0) {
		uint32_t q_type;
		qb_log (LOG_INFO, "quorum_initialize");
		q_callbacks.quorum_notify_fn = quorum_notification_fn;
		ret = quorum_initialize (&q_handle, &q_callbacks, &q_type);
		if (ret != CS_OK) {
			qb_log (LOG_ERR, "quorum_initialize FAILED: %d", ret);
			q_handle = 0;
		}
		else {
			ret = quorum_trackstart (q_handle, CS_TRACK_CHANGES);
			if (ret != CS_OK) {
				qb_log (LOG_ERR, "quorum_trackstart FAILED: %d", ret);
			}
			quorum_fd_get (q_handle, &fd);
			qb_loop_poll_add (ta_poll_handle_get(), QB_LOOP_MED, fd,
				POLLIN|POLLNVAL, NULL, q_dispatch_wrapper_fn);
		}
	}
	return ret;
}
static void
_cs_quorum_init(void)
{
	cs_error_t rc;
	uint32_t quorum_type;
	int fd;

	quorum_callbacks_t quorum_callbacks = {
		.quorum_notify_fn = _cs_quorum_notification,
	};

	rc = quorum_initialize (&quorum_handle, &quorum_callbacks,
			        &quorum_type);
	if (rc != CS_OK) {
		qb_log(LOG_ERR, "Could not connect to corosync(quorum)");
		return;
	}
	quorum_fd_get(quorum_handle, &fd);
	qb_loop_poll_add(main_loop, QB_LOOP_MED, fd, POLLIN|POLLNVAL, NULL,
		_cs_quorum_dispatch);
	rc = quorum_trackstart(quorum_handle, CS_TRACK_CHANGES);
	if (rc != CS_OK) {
		qb_log(LOG_ERR, "Could not start tracking");
		return;
	}
}
Exemple #3
0
 IPCClientPrivate::IPCClientPrivate(IPCClient& p_instance)
   : _p_instance(p_instance),
     _thread(this, &IPCClientPrivate::thread)
 {
   _qb_conn = nullptr;
   _qb_conn_fd = -1;
   _eventfd = eventfd(0, 0);
   _qb_loop = qb_loop_create();
   qb_loop_poll_add(_qb_loop, QB_LOOP_HIGH, _eventfd, POLLIN, NULL, qbPollEventFn);
   _thread.start();
   return;
 }
Exemple #4
0
int cs_poll_dispatch_add (qb_loop_t * handle,
		int fd,
		int events,
		void *data,

		int (*dispatch_fn) (int fd,
			int revents,
			void *data))
{
	return qb_loop_poll_add(handle, QB_LOOP_MED, fd, events, data,
				dispatch_fn);
}
static void
_cs_cmap_init(void)
{
	cs_error_t rc;
	int cmap_fd = 0;
	cmap_track_handle_t track_handle;

	rc = cmap_initialize (&cmap_handle);
	if (rc != CS_OK) {
		qb_log(LOG_ERR, "Failed to initialize the cmap API. Error %d", rc);
		exit (EXIT_FAILURE);
	}
	cmap_fd_get(cmap_handle, &cmap_fd);

	qb_loop_poll_add(main_loop, QB_LOOP_MED, cmap_fd, POLLIN|POLLNVAL, NULL,
		_cs_cmap_dispatch);

	rc = cmap_track_add(cmap_handle, "runtime.connections.",
			CMAP_TRACK_ADD | CMAP_TRACK_DELETE | CMAP_TRACK_PREFIX,
			_cs_cmap_connections_key_changed,
			NULL,
			&track_handle);
	if (rc != CS_OK) {
		qb_log(LOG_ERR,
			"Failed to track the connections key. Error %d", rc);
		exit (EXIT_FAILURE);
	}

	rc = cmap_track_add(cmap_handle, "runtime.totem.pg.mrp.srp.members.",
			CMAP_TRACK_ADD | CMAP_TRACK_MODIFY | CMAP_TRACK_PREFIX,
			_cs_cmap_members_key_changed,
			NULL,
			&track_handle);
	if (rc != CS_OK) {
		qb_log(LOG_ERR,
			"Failed to track the members key. Error %d", rc);
		exit (EXIT_FAILURE);
	}
	rc = cmap_track_add(cmap_handle, "runtime.totem.pg.mrp.rrp.",
			CMAP_TRACK_ADD | CMAP_TRACK_MODIFY | CMAP_TRACK_PREFIX,
			_cs_cmap_rrp_faulty_key_changed,
			NULL,
			&track_handle);
	if (rc != CS_OK) {
		qb_log(LOG_ERR,
			"Failed to track the rrp key. Error %d", rc);
		exit (EXIT_FAILURE);
	}
}
Exemple #6
0
int
main(int argc, char *argv[])
{
	int sock;
	int true_opt = 1;
	struct sockaddr_in server_addr;
	qb_loop_t *ml = qb_loop_create();

	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror("Socket");
		exit(1);
	}

	if (setsockopt(sock,
		       SOL_SOCKET,
		       SO_REUSEADDR, &true_opt, sizeof(int)) == -1) {
		perror("Setsockopt");
		exit(1);
	}

	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(5000);
	server_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(server_addr.sin_zero), 8);

	printf("TCPServer binding to port 5000\n");
	if (bind(sock,
		 (struct sockaddr *)&server_addr,
		 sizeof(struct sockaddr)) == -1) {
		perror("Unable to bind");
		exit(1);
	}

	printf("TCPServer Waiting for client on port 5000\n");

	if (listen(sock, 5) == -1) {
		perror("Listen");
		exit(1);
	}

	qb_loop_poll_add(ml, QB_LOOP_MED, sock, POLLIN, ml, sock_accept_fn);

	qb_loop_signal_add(ml, QB_LOOP_HIGH, SIGINT, ml, please_exit_fn, NULL);
	qb_loop_run(ml);

	close(sock);
	return 0;
}
Exemple #7
0
/* Return pipe FDs & child PID if sucessful */
int fork_new_instance(int nodeid, int *vq_sock, pid_t *childpid)
{
	int pipes[2];
	pid_t pid;

	if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, pipes)) {
		return -1;
	}
	parent_socket = pipes[0];

	switch ( (pid=fork()) ) {
	case -1:
		perror("fork failed");
		return -1;
	case 0:
		/* child process - continue below */
		break;
	default:
		/* parent process */
		*vq_sock = pipes[1];
		*childpid = pid;
		return 0;
	}

	our_nodeid = nodeid;
	poll_loop = qb_loop_create();

	if (icmap_get_uint32("quorum.device.timeout", &qdevice_timeout) != CS_OK) {
		qdevice_timeout = VOTEQUORUM_QDEVICE_DEFAULT_TIMEOUT;
	}

	set_local_node_pos(&corosync_api);
	load_quorum_instance(&corosync_api);

	qb_loop_poll_add(poll_loop,
			 QB_LOOP_MED,
			 parent_socket,
			 POLLIN,
			 NULL,
			 parent_pipe_read_fn);

	/* Start it up! */
	initial_sync(nodeid);
	qb_loop_run(poll_loop);

	return 0;
}
Exemple #8
0
static int32_t
sock_accept_fn(int32_t fd, int32_t revents, void *data)
{
	struct sockaddr_in client_addr;
	qb_loop_t *ml = (qb_loop_t *) data;
	socklen_t sin_size = sizeof(struct sockaddr_in);
	int connected = accept(fd, (struct sockaddr *)&client_addr, &sin_size);

	if (connected < 0) {
		perror("accept");
		return QB_TRUE;
	}
	printf("I got a connection from (%s , %d)\n",
	       inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

	qb_loop_poll_add(ml, QB_LOOP_MED, connected, POLLIN, ml, sock_read_fn);

	return QB_TRUE;
}
Exemple #9
0
  void IPCClientPrivate::connect()
  {
    _qb_conn = qb_ipcc_connect("usbguard", 1<<20);

    if (_qb_conn == nullptr) {
      throw IPCException(IPCException::ConnectionError, "IPC Connection not established");
    }

    qb_ipcc_fd_get(_qb_conn, &_qb_conn_fd);

    if (_qb_conn_fd < 0) {
      qb_ipcc_disconnect(_qb_conn);
      _qb_conn = nullptr;
      _qb_conn_fd = -1;
      throw IPCException(IPCException::ConnectionError, "Bad file descriptor");
    }

    qb_loop_poll_add(_qb_loop, QB_LOOP_HIGH, _qb_conn_fd, POLLIN, this, qbIPCMessageProcessFn);
    _p_instance.IPCConnected();
    return;
  }
Exemple #10
0
static int32_t
my_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
		void *data, qb_ipcs_dispatch_fn_t fn)
{
	return qb_loop_poll_add(bms_loop, p, fd, evts, data, fn);
}
Exemple #11
0
static void do_command (int sock, char* func, char*args[], int num_args)
{
	int result;
	char response[100];
	struct cpg_name group_name;
	ssize_t rc;
	size_t send_len;

	qb_log (LOG_TRACE, "RPC:%s() called.", func);

	if (strcmp ("cpg_mcast_joined",func) == 0) {
		struct iovec iov[5];
		int a;

		for (a = 0; a < num_args; a++) {
			iov[a].iov_base = args[a];
			iov[a].iov_len = strlen(args[a])+1;
		}
		cpg_mcast_joined (cpg_handle, CPG_TYPE_AGREED, iov, num_args);

	} else if (strcmp ("cpg_join",func) == 0) {
		if (strlen(args[0]) >= CPG_MAX_NAME_LENGTH) {
			qb_log (LOG_ERR, "Invalid group name");
			exit (1);
		}
		strcpy (group_name.value, args[0]);
		group_name.length = strlen(args[0]);
		result = cpg_join (cpg_handle, &group_name);
		if (result != CS_OK) {
			qb_log (LOG_ERR,
				"Could not join process group, error %d", result);
			exit (1);
		}
		qb_log (LOG_INFO, "called cpg_join(%s)!", group_name.value);

	} else if (strcmp ("cpg_leave",func) == 0) {

		strcpy (group_name.value, args[0]);
		group_name.length = strlen(args[0]);

		result = cpg_leave (cpg_handle, &group_name);
		if (result != CS_OK) {
			qb_log (LOG_ERR,
				"Could not leave process group, error %d", result);
			exit (1);
		}
		qb_log (LOG_INFO, "called cpg_leave(%s)!", group_name.value);

	} else if (strcmp ("cpg_initialize",func) == 0) {
		int retry_count = 0;

		result = cpg_initialize (&cpg_handle, &callbacks);
		while (result != CS_OK) {
			qb_log (LOG_ERR,
				"cpg_initialize error %d (attempt %d)",
				result, retry_count);
			if (retry_count >= 3) {
				exit (1);
			}
			sleep(1);
			retry_count++;
			result = cpg_initialize (&cpg_handle, &callbacks);
		}

		cpg_fd_get (cpg_handle, &cpg_fd);
		qb_loop_poll_add (ta_poll_handle_get(),
			QB_LOOP_MED,
			cpg_fd,
			POLLIN|POLLNVAL,
			NULL,
			cpg_dispatch_wrapper_fn);

	} else if (strcmp ("cpg_local_get", func) == 0) {
		unsigned int local_nodeid;

		cpg_local_get (cpg_handle, &local_nodeid);
		snprintf (response, 100, "%u",local_nodeid);
		send_len = strlen (response);
		rc = send (sock, response, send_len, 0);
		assert(rc == send_len);
	} else if (strcmp ("cpg_finalize", func) == 0) {

		if (cpg_handle > 0) {
			cpg_finalize (cpg_handle);
			cpg_handle = 0;
		}

	} else if (strcmp ("record_config_events", func) == 0) {
		record_config_events (sock);
	} else if (strcmp ("record_messages", func) == 0) {
		record_messages ();
	} else if (strcmp ("read_config_event", func) == 0) {
		read_config_event (sock);
	} else if (strcmp ("read_messages", func) == 0) {
		read_messages (sock, args[0]);
	} else if (strcmp ("msg_blaster_zcb", func) == 0) {
		msg_blaster_zcb (sock, args[0]);
	} else if (strcmp ("pcmk_test", func) == 0) {
		pcmk_test = 1;
	} else if (strcmp ("msg_blaster", func) == 0) {
		msg_blaster (sock, args[0]);
	} else if (strcmp ("context_test", func) == 0) {
		context_test (sock);
	} else if (strcmp ("are_you_ok_dude", func) == 0) {
		snprintf (response, 100, "%s", OK_STR);
		send_len = strlen (response);
		rc = send (sock, response, strlen (response), 0);
		assert(rc == send_len);
	} else if (strcmp ("cfg_shutdown", func) == 0) {

		qb_log (LOG_INFO, "calling %s() called!", func);
		result = corosync_cfg_try_shutdown (cfg_handle, COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST);
		qb_log (LOG_INFO,"%s() returned %d!", func, result);

	} else if (strcmp ("cfg_initialize",func) == 0) {
		int retry_count = 0;

		qb_log (LOG_INFO,"%s() called!", func);
		result = corosync_cfg_initialize (&cfg_handle, &cfg_callbacks);
		while (result != CS_OK) {
			qb_log (LOG_ERR,
				"cfg_initialize error %d (attempt %d)",
				result, retry_count);
			if (retry_count >= 3) {
				exit (1);
			}
			sleep(1);
			retry_count++;
			result = corosync_cfg_initialize (&cfg_handle, &cfg_callbacks);
		}
		qb_log (LOG_INFO,"corosync_cfg_initialize() == %d", result);

		result = corosync_cfg_fd_get (cfg_handle, &cfg_fd);
		qb_log (LOG_INFO,"corosync_cfg_fd_get() == %d", result);

		qb_loop_poll_add (ta_poll_handle_get(),
			QB_LOOP_MED,
			cfg_fd,
			POLLIN|POLLNVAL,
			NULL,
			cfg_dispatch_wrapper_fn);
	} else {
		qb_log(LOG_ERR, "RPC:%s not supported!", func);
	}
}
Exemple #12
0
/*
 * Create an instance
 */
int totemknet_initialize (
	qb_loop_t *poll_handle,
	void **knet_context,
	struct totem_config *totem_config,
	totemsrp_stats_t *stats,
	void *context,

	void (*deliver_fn) (
		void *context,
		const void *msg,
		unsigned int msg_len),

	void (*iface_change_fn) (
		void *context,
		const struct totem_ip_address *iface_address,
		unsigned int link_no),

	void (*mtu_changed) (
		void *context,
		int net_mtu),

	void (*target_set_completed) (
		void *context))
{
	struct totemknet_instance *instance;
	int8_t channel=0;
	int res;
	int i;

	instance = malloc (sizeof (struct totemknet_instance));
	if (instance == NULL) {
		return (-1);
	}

	totemknet_instance_initialize (instance);

	instance->totem_config = totem_config;
	instance->stats = stats;

	/*
	* Configure logging
	*/
	instance->totemknet_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
	instance->totemknet_log_level_error = totem_config->totem_logging_configuration.log_level_error;
	instance->totemknet_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
	instance->totemknet_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
	instance->totemknet_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
	instance->totemknet_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
	instance->totemknet_log_printf = totem_config->totem_logging_configuration.log_printf;

	instance->knet_subsys_id = _logsys_subsys_create("KNET", "libknet.h");

	/*
	 * Initialize local variables for totemknet
	 */

	instance->our_nodeid = instance->totem_config->node_id;

	for (i=0; i< instance->totem_config->interface_count; i++) {
		totemip_copy(&instance->my_ids[i], &totem_config->interfaces[i].bindnet);
		instance->my_ids[i].nodeid = instance->our_nodeid;
		instance->ip_port[i] = totem_config->interfaces[i].ip_port;

		/* Needed for totemsrp */
		totem_config->interfaces[i].boundto.nodeid = instance->our_nodeid;
	}

	instance->poll_handle = poll_handle;

	instance->context = context;
	instance->totemknet_deliver_fn = deliver_fn;

	instance->totemknet_iface_change_fn = iface_change_fn;

	instance->totemknet_mtu_changed = mtu_changed;

	instance->totemknet_target_set_completed = target_set_completed;

	pipe(instance->logpipes);
	fcntl(instance->logpipes[0], F_SETFL, O_NONBLOCK);
	fcntl(instance->logpipes[1], F_SETFL, O_NONBLOCK);

	instance->knet_handle = knet_handle_new(instance->totem_config->node_id, instance->logpipes[1], KNET_LOG_DEBUG);

	if (!instance->knet_handle) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_CRIT, "knet_handle_new failed");
		return (-1);
	}
	res = knet_handle_pmtud_setfreq(instance->knet_handle, instance->totem_config->knet_pmtud_interval);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_pmtud_setfreq failed");
	}
	res = knet_handle_enable_filter(instance->knet_handle, instance, dst_host_filter_callback_fn);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_filter failed");
	}
	res = knet_handle_enable_sock_notify(instance->knet_handle, instance, socket_error_callback_fn);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_sock_notify failed");
	}
	res = knet_host_enable_status_change_notify(instance->knet_handle, instance, host_change_callback_fn);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_host_enable_status_change_notify failed");
	}
	res = knet_handle_enable_pmtud_notify(instance->knet_handle, instance, pmtu_change_callback_fn);
	if (res) {
		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_pmtud_notify failed");
	}

	/* Get an fd into knet */
	instance->knet_fd = 0;
	res = knet_handle_add_datafd(instance->knet_handle, &instance->knet_fd, &channel);
	if (res) {
		knet_log_printf(LOG_DEBUG, "knet_handle_add_datafd failed: %s", strerror(errno));
		return -1;
	}

	/* Enable crypto if requested */
	if (strcmp(instance->totem_config->crypto_cipher_type, "none") != 0) {
		struct knet_handle_crypto_cfg crypto_cfg;

		strcpy(crypto_cfg.crypto_model, "nss");
		strcpy(crypto_cfg.crypto_cipher_type, instance->totem_config->crypto_cipher_type);
		strcpy(crypto_cfg.crypto_hash_type, instance->totem_config->crypto_hash_type);
		memcpy(crypto_cfg.private_key, instance->totem_config->private_key, instance->totem_config->private_key_len);
		crypto_cfg.private_key_len = instance->totem_config->private_key_len;

		res = knet_handle_crypto(instance->knet_handle, &crypto_cfg);
		if (res == -1) {
			knet_log_printf(LOG_ERR, "knet_handle_crypto failed: %s", strerror(errno));
			return -1;
		}
		if (res == -2) {
			knet_log_printf(LOG_ERR, "knet_handle_crypto failed: -2");
			return -1;
		}
		knet_log_printf(LOG_INFO, "kronosnet crypto initialized: %s/%s", crypto_cfg.crypto_cipher_type, crypto_cfg.crypto_hash_type);
	}
	knet_handle_setfwd(instance->knet_handle, 1);

	instance->link_mode = KNET_LINK_POLICY_PASSIVE;
	if (strcmp(instance->totem_config->link_mode, "active")==0) {
		instance->link_mode = KNET_LINK_POLICY_ACTIVE;
	}
	if (strcmp(instance->totem_config->link_mode, "rr")==0) {
		instance->link_mode = KNET_LINK_POLICY_RR;
	}

	for (i=0; i<INTERFACE_MAX; i++) {
		instance->link_status[i] = malloc(CFG_INTERFACE_STATUS_MAX_LEN);
		if (!instance->link_status[i]) {
			return -1;
		}
	}

	qb_loop_poll_add (instance->poll_handle,
		QB_LOOP_MED,
		instance->logpipes[0],
		POLLIN, instance, log_deliver_fn);

	qb_loop_poll_add (instance->poll_handle,
		QB_LOOP_HIGH,
		instance->knet_fd,
		POLLIN, instance, data_deliver_fn);

	/*
	 * Upper layer isn't ready to receive message because it hasn't
	 * initialized yet.  Add short timer to check the interfaces.
	 */
	qb_loop_timer_add (instance->poll_handle,
		QB_LOOP_MED,
		100*QB_TIME_NS_IN_MSEC,
		(void *)instance,
		timer_function_netif_check_timeout,
		&instance->timer_netif_check_timeout);

	totemknet_start_merge_detect_timeout(instance);

	/* Start listening for config changes */
	totemknet_add_config_notifications(instance);

	knet_log_printf (LOGSYS_LEVEL_INFO, "totemknet initialized");
	*knet_context = instance;
	return (0);
}
Exemple #13
0
static void
_cs_cmap_init(void)
{
	cs_error_t rc = CS_OK;
	int cmap_fd = 0;
	int stats_fd = 0;
	cmap_track_handle_t track_handle;

	tracker_map = qb_trie_create();
	if (!tracker_map) {
		qb_log(LOG_ERR, "Failed to initialize the track map. Error %d", rc);
		exit (EXIT_FAILURE);
	}

	rc = cmap_initialize_map (&cmap_handle, CMAP_MAP_ICMAP);
	if (rc != CS_OK) {
		qb_log(LOG_ERR, "Failed to initialize the cmap API. Error %d", rc);
		exit (EXIT_FAILURE);
	}
	cmap_fd_get(cmap_handle, &cmap_fd);

	qb_loop_poll_add(main_loop, QB_LOOP_MED, cmap_fd, POLLIN|POLLNVAL, (void*)&cmap_handle,
		_cs_cmap_dispatch);


	rc = cmap_initialize_map (&stats_handle, CMAP_MAP_STATS);
	if (rc != CS_OK) {
		qb_log(LOG_ERR, "Failed to initialize the cmap stats API. Error %d", rc);
		exit (EXIT_FAILURE);
	}
	cmap_fd_get(stats_handle, &stats_fd);

	qb_loop_poll_add(main_loop, QB_LOOP_MED, stats_fd, POLLIN|POLLNVAL, (void*)&stats_handle,
		_cs_cmap_dispatch);


	rc = cmap_track_add(cmap_handle, "runtime.members.",
			CMAP_TRACK_ADD | CMAP_TRACK_MODIFY | CMAP_TRACK_PREFIX,
			_cs_cmap_members_key_changed,
			NULL,
			&track_handle);
	if (rc != CS_OK) {
		qb_log(LOG_ERR,
			"Failed to track the members key. Error %d", rc);
		exit (EXIT_FAILURE);
	}

	rc = cmap_track_add(stats_handle, "stats.ipcs.",
			CMAP_TRACK_ADD | CMAP_TRACK_DELETE | CMAP_TRACK_PREFIX,
			_cs_cmap_connections_key_changed,
			NULL,
			&track_handle);
	if (rc != CS_OK) {
		qb_log(LOG_ERR,
			"Failed to track the connections key. Error %d", rc);
		exit (EXIT_FAILURE);
	}

	rc = cmap_track_add(stats_handle, "stats.knet.",
			CMAP_TRACK_ADD | CMAP_TRACK_DELETE | CMAP_TRACK_PREFIX,
			_cs_cmap_link_added_removed,
			NULL,
			&track_handle);
	if (rc != CS_OK) {
		qb_log(LOG_ERR,
			"Failed to track the knet link status key. Error %d", rc);
		exit (EXIT_FAILURE);
	}
	track_link_updown_events();

}