Example #1
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
		struct xio_session_event_data *event_data,
		void *cb_user_context)
{
	struct server_data *server_data = cb_user_context;
	int		   i;

	printf("session event: %s. session:%p, connection:%p, reason: %s\n",
	       xio_session_event_str(event_data->event),
	       session, event_data->conn,
	       xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_session_destroy(session);
		for (i = 0; i < MAX_THREADS; i++)
			xio_context_stop_loop(server_data->tdata[i].ctx, 0);
		xio_context_stop_loop(server_data->ctx, 0);
		break;
	default:
		break;
	};

	return 0;
}
Example #2
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	/*struct xio_connection_attr	conn_attr;*/

	pr_info("session event: %s. session:%p, connection:%p, reason: %s\n",
		xio_session_event_str(event_data->event),
		session, event_data->conn,
		xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_NEW_CONNECTION_EVENT:
		if (!test_params.connection)
			test_params.connection = event_data->conn;
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		if (event_data->reason != XIO_E_SESSION_REJECTED)
			test_params.connection = NULL;
		xio_connection_destroy(event_data->conn);
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_session_destroy(session);
		if (event_data->reason != XIO_E_SESSION_REJECTED)
			xio_context_stop_loop(test_params.ctx);
		break;
	default:
		break;
	};

	return 0;
}
Example #3
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_prv_data)
{
	printf("session event: %s. session:%p, connection:%p, reason: %s\n",
	       xio_session_event_str(event_data->event),
	       session, event_data->conn,
	       xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		process_request(NULL);
		xio_session_destroy(session);
		if (test_config.finite_run)
			xio_context_stop_loop(ctx); /* exit */
		break;
	default:
		break;
	};

	return 0;
}
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
                            struct xio_session_event_data *event_data,
                            void *cb_user_context)
{
    struct ow_test_params *ow_params = cb_user_context;

    printf("session event: %s. session:%p, connection:%p, reason: %s\n",
           xio_session_event_str(event_data->event),
           session, event_data->conn,
           xio_strerror(event_data->reason));

    switch (event_data->event) {
    case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
        xio_connection_destroy(event_data->conn);
        ow_params->connection = NULL;
        break;
    case XIO_SESSION_TEARDOWN_EVENT:
        process_request(NULL);
        xio_session_destroy(session);
        xio_context_stop_loop(ow_params->ctx, 0);
        break;
    default:
        break;
    };

    return 0;
}
Example #5
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	struct server_data *server_data = cb_user_context;

	pr_info("session event: %s. reason: %s\n",
		xio_session_event_str(event_data->event),
		xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_NEW_CONNECTION_EVENT:
		server_data->connection = event_data->conn;
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		server_data->connection = NULL;
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		server_data->session = NULL;
		xio_session_destroy(session);
		if (atomic_read(&module_state) & 0x80)
			xio_context_stop_loop(server_data->ctx); /* exit */
		break;
	default:
		break;
	};

	return 0;
}
Example #6
0
/* Server run loop till shutdown */
void rdb_r_s_server_run(struct server_data *server_data)
{
    int i;

    /* default xio supplied main loop */
    if (xio_context_run_loop(server_data->ctx, XIO_INFINITE) != 0) {
        for (i = 0; i < server_data->nworkers; i++) {
            xio_context_stop_loop(server_data->wdata[i].ctx);
        }
        fprintf(stderr, "failed to run event loop for server listner. reason %d - (%s)\n",
                xio_errno(), xio_strerror(xio_errno()));
    }

    /* join the worker threads */
    for (i = 0; i < server_data->nworkers; i++) {
        pthread_join(server_data->wdata[i].thread_id, NULL);
    }

    /* free the server */
    if (server_data->server)
        xio_unbind(server_data->server);

    /* free the context */
    if (server_data->ctx)
        xio_context_destroy(server_data->ctx);

    xio_shutdown();

    if (server_data)
        free(server_data);
}
Example #7
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	struct test_params *test_params = (struct test_params *)cb_user_context;

	printf("session event: %s. reason: %s\n",
	       xio_session_event_str(event_data->event),
	       xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		printf("nsent:%lu, nrecv:%lu, " \
		       "delta:%lu\n",
		       test_params->nsent, test_params->nrecv,
		       test_params->nsent-test_params->nrecv);

		xio_connection_destroy(event_data->conn);
		break;
	case XIO_SESSION_REJECT_EVENT:
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_context_stop_loop(test_params->ctx);  /* exit */
		break;
	default:
		break;
	};

	return 0;
}
Example #8
0
static void xio_module_down(void *data)
{
	struct xio_session *tmp_session;
	struct xio_connection *tmp_connection;

	if (!g_session)
		goto stop_loop_now;

	if (!g_connection)
		goto destroy_session;

	tmp_connection = g_connection;
	g_connection = NULL;
	xio_disconnect(tmp_connection);

	return;

destroy_session:
	/* in multi thread version on need to user reference count */
	tmp_session = g_session;
	g_session = NULL;
	xio_session_destroy(tmp_session);

stop_loop_now:
	/* No session -> no XIO_SESSION_TEARDOWN_EVENT */
	xio_context_stop_loop(ctx); /* exit */
}
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
		struct xio_session_event_data *event_data,
		void *cb_user_context)
{
	struct session_data *session_data = cb_user_context;
	int		    i;


	switch (event_data->event) {
	case XIO_SESSION_CONNECTION_ERROR_EVENT:
	case XIO_SESSION_REJECT_EVENT:
	case XIO_SESSION_CONNECTION_DISCONNECTED_EVENT:
		fprintf(stderr, "%s. reason: %s\n",
			xio_session_event_str(event_data->event),
			xio_strerror(event_data->reason));

		for (i = 0; i < threads_iter; i++) {
			session_data->tdata[i].disconnect = 1;
			session_data->abort = 1;
		}
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		for (i = 0; i < threads_iter; i++)
			xio_context_stop_loop(session_data->tdata[i].ctx, 0);
		break;
	default:
		break;
	};

	return 0;
}
Example #10
0
static int gw_client_on_response(struct xio_session *session,
				 struct xio_msg *rsp,
				 int last_in_rxq,
				 void *cb_user_context)
{
	struct xio_forward_info_entry *fi_entry =
		(struct xio_forward_info_entry *)cb_user_context;
	struct xio_forward_info *fi = fi_entry->fi;

	struct xio_vmsg *pimsg = &rsp->in;
	struct xio_iovec_ex *isglist = vmsg_sglist(pimsg);

	int nents = vmsg_sglist_nents(pimsg), total = 0;

	sd_debug("response on fi_entry %p", fi_entry);

	for (int i = 0; i < nents; i++) {
		memcpy((char *)fi_entry->buf + total,
		       isglist[i].iov_base, isglist[i].iov_len);

		total += isglist[i].iov_len;
	}

	fi->nr_done++;
	if (fi->nr_done == fi->nr_send)
		xio_context_stop_loop(fi->ctx);

	return 0;
}
Example #11
0
static int server_on_request(struct xio_session *session,
			     struct xio_msg *xio_req,
			     int last_in_rxq,
			     void *cb_user_conext)
{
	struct client_info *ci = (struct client_info *)cb_user_conext;
	struct sd_req *hdr;
	struct request *req;

	struct xio_iovec_ex *sglist = vmsg_sglist(&xio_req->in);
	int nents = vmsg_sglist_nents(&xio_req->in);

	sd_debug("on request: %p, %p, nents: %d", session, xio_req, nents);
	hdr = xio_req->in.header.iov_base;

	req = alloc_request(ci, hdr->data_length);
	memcpy(&req->rq, hdr, sizeof(req->rq));

	if (hdr->data_length && hdr->flags & SD_FLAG_CMD_WRITE) {
		sd_assert(nents == 1);
		req->data = sglist[0].iov_base;
	}

	xio_req->in.header.iov_base  = NULL;
	xio_req->in.header.iov_len  = 0;
	vmsg_sglist_set_nents(&xio_req->in, 0);

	ci->xio_req = xio_req;

	queue_request(req);

	xio_context_stop_loop(xio_get_main_ctx());
	return 0;
}
Example #12
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	pr_info("session event: %s. reason: %s\n",
		xio_session_event_str(event_data->event),
		xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_CONNECTION_ESTABLISHED_EVENT:
		on_connection_established(event_data->conn);
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		break;
	case XIO_SESSION_REJECT_EVENT:
	case XIO_SESSION_TEARDOWN_EVENT:
		g_session = NULL;
		xio_session_destroy(session);
		xio_context_stop_loop(ctx);  /* exit */
		if (pool) {
			msg_pool_free(pool);
			pool = NULL;
		}
		break;
	default:
		break;
	};

	return 0;
}
Example #13
0
static int server_on_send_response_complete(struct xio_session *session,
					    struct xio_msg *msg,
					    void *cb_prv_data)
{
	xio_context_stop_loop(xio_get_main_ctx());
	return 0;
}
Example #14
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	struct session_data *session_data = (struct session_data *)
						cb_user_context;

	logit(LOG_INFO, "session event: %s. reason: %s\n",
	      xio_session_event_str(event_data->event),
	      xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_CONNECTION_DISCONNECTED_EVENT:
	case XIO_SESSION_CONNECTION_REFUSED_EVENT:
		reconnect_flag = 1;
		break;
	case XIO_SESSION_CONNECTION_ESTABLISHED_EVENT:
		on_connection_established(event_data->conn, session_data);
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		session_data->conn = NULL;
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_session_destroy(session);
		xio_context_stop_loop(session_data->ctx);  /* exit */
		break;
	default:
		break;
	};

	return 0;
}
Example #15
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	struct server_data *server_data =
		(struct server_data *)cb_user_context;

	printf("session event: %s. session:%p, connection:%p, reason: %s\n",
	       xio_session_event_str(event_data->event),
	       session, event_data->conn,
	       xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_NEW_CONNECTION_EVENT:
		server_data->connection = event_data->conn;
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		server_data->connection = NULL;
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_session_destroy(session);
		xio_context_stop_loop(server_data->ctx);  /* exit */
		break;
	default:
		break;
	};

	return 0;
}
Example #16
0
static void xio_module_down(void *data)
{
	struct test_params *params;
	struct xio_session *session;
	struct xio_connection *connection;

	params = (struct test_params *)data;

	if (!params->session)
		goto stop_loop_now;

	if (!params->connection)
		goto destroy_session;

	connection = params->connection;
	params->connection = NULL;
	xio_disconnect(connection);

	return;

destroy_session:
	/* in multi thread version on need to user reference count */
	session = params->session;
	params->session = NULL;
	xio_session_destroy(session);

stop_loop_now:
	/* No session -> no XIO_SESSION_TEARDOWN_EVENT */
	xio_context_stop_loop(params->ctx); /* exit */
}
Example #17
0
static int server_on_session_event(struct xio_session *session,
				   struct xio_session_event_data *event_data,
				   void *cb_user_context)
{
	struct client_info *ci;
	struct xio_connection_attr attr;
	struct server_data *server_data = (struct server_data *)cb_user_context;

	sd_debug("session event: %s. session:%p, connection:%p, reason: %s",
		 xio_session_event_str(event_data->event),
		 session, event_data->conn,
		 xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_NEW_CONNECTION_EVENT:
		server_data->nr_conn++;
		memset(&attr, 0, sizeof(attr));

		ci = xio_create_client(session, event_data->conn);
		list_add_tail(&ci->conn.list, &server_data->conn_list);
		attr.user_context = ci;
		xio_modify_connection(event_data->conn, &attr,
				      XIO_CONNECTION_ATTR_USER_CTX);
		xio_context_stop_loop(xio_get_main_ctx());
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		server_data->nr_conn--;
		sd_assert(0 <= server_data->nr_conn);

		xio_connection_destroy(event_data->conn);
		xio_context_stop_loop(xio_get_main_ctx());
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_session_destroy(session);
		xio_context_stop_loop(xio_get_main_ctx());
		break;
	default:
		break;
	};

	return 0;
}
Example #18
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
                            struct xio_session_event_data *event_data,
                            void *cb_user_context)
{
    struct server_data *sdata;
    struct thread_data *tdata;
    int		   i;

    sdata = (struct server_data *)cb_user_context;
    tdata = (event_data->conn_user_context == sdata) ? NULL :
            (struct thread_data *)event_data->conn_user_context;

    printf("session event: %s. session:%p, connection:%p, reason: %s\n",
           xio_session_event_str(event_data->event),
           session, event_data->conn,
           xio_strerror(event_data->reason));

    switch (event_data->event) {
    case XIO_SESSION_NEW_CONNECTION_EVENT:
        if (tdata)
            tdata->connection = event_data->conn;
        break;
    case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
        xio_connection_destroy(event_data->conn);
        if (tdata)
            tdata->connection = NULL;
        break;
    case XIO_SESSION_TEARDOWN_EVENT:
        xio_session_destroy(session);
        for (i = 0; i < sdata->tdata_nr; i++) {
            process_request(&sdata->tdata[i], NULL);
            xio_context_stop_loop(sdata->tdata[i].ctx);
        }
        xio_context_stop_loop((struct xio_context *)sdata->ctx);
        break;
    default:
        break;
    };

    return 0;
}
Example #19
0
/*---------------------------------------------------------------------------*/
static void signal_handler(int sig)
{
	if (sig == SIGHUP)
		reload_flag = 1;
	else
		exit_flag = 1;

	if (session_data.conn)
		xio_disconnect(session_data.conn);
	else
		xio_context_stop_loop(session_data.ctx);  /* exit */
}
Example #20
0
static int client_on_response(struct xio_session *session,
			      struct xio_msg *rsp,
			      int last_in_rxq,
			      void *cb_user_context)
{
	struct client_data *client_data =
			(struct client_data *)cb_user_context;

	sd_debug("response on session %p", client_data);
	xio_context_stop_loop(client_data->ctx);
	client_data->rsp = rsp;

	return 0;
}
Example #21
0
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	struct client_data *client_data =
			(struct client_data *)cb_user_context;

	switch (event_data->event) {
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		xio_context_stop_loop(client_data->ctx);  /* exit */
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_session_destroy(session);
		xio_context_stop_loop(client_data->ctx);  /* exit */
		break;
	default:
		sd_debug("other event: %d", event_data->event);
		break;
	};

	return 0;
}
Example #22
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	struct xio_connection_attr	conn_attr;
	struct test_params		*test_params = cb_user_context;

	pr_info("session event: %s. session:%p, connection:%p, reason: %s\n",
		xio_session_event_str(event_data->event),
		session, event_data->conn,
		xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_NEW_CONNECTION_EVENT:
		/* assign connection private data */
		conn_attr.user_context = cb_user_context;
		xio_modify_connection(event_data->conn, &conn_attr,
				      XIO_CONNECTION_ATTR_USER_CTX);
		if (!test_params->connection)
			test_params->connection = event_data->conn;
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		if (event_data->reason != XIO_E_SESSION_REJECTED) {
			pr_info("last recv:%llu\n",
				test_params->nrecv);
			test_params->connection = NULL;
		}
		xio_connection_destroy(event_data->conn);
		test_params->connection = NULL;
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		test_params->session = NULL;
		xio_session_destroy(session);
		if (event_data->reason != XIO_E_SESSION_REJECTED) {
			if (atomic_read(&module_state) & 0x80)
				xio_context_stop_loop(
						test_params->ctx); /* exit */
		}
		break;
	default:
		break;
	};

	return 0;
}
Example #23
0
/*---------------------------------------------------------------------------*/
void xio_context_destroy_resume(struct xio_context *ctx)
{
	if (ctx->run_private) {
		if (!--ctx->run_private) {
			switch (ctx->flags) {
			case XIO_LOOP_GIVEN_THREAD:
				xio_context_stop_loop(ctx);
				break;
			case XIO_LOOP_WORKQUEUE:
				INIT_WORK(&ctx->destroy_ctx_work.work,
					  xio_destroy_context_continue);
				schedule_work(&ctx->destroy_ctx_work.work);
				break;
			default:
				ERROR_LOG("Not supported type. %d\n", ctx->flags);
				break;
			}
		}
	}
}
Example #24
0
static int server_on_new_session(struct xio_session *session,
			  struct xio_new_session_req *req,
			  void *cb_user_context)
{
	struct xio_session_attr attr;
	struct server_data *srv = xzalloc(sizeof(*srv));

	sd_debug("on new session: %p", session);

	xio_accept(session, NULL, 0, NULL, 0);

	INIT_LIST_HEAD(&srv->conn_list);

	memset(&attr, 0, sizeof(attr));
	attr.user_context = srv;
	xio_modify_session(session, &attr,
			   XIO_SESSION_ATTR_USER_CTX);

	xio_context_stop_loop(xio_get_main_ctx());

	return 0;
}
Example #25
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
		struct xio_session_event_data *event_data,
		void *cb_user_context)
{
	struct xio_connection_params cparams;
	struct test_params *test_params = cb_user_context;

	printf("session event: %s. session:%p, connection:%p, reason: %s\n",
	       xio_session_event_str(event_data->event),
	       session, event_data->conn,
	       xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_NEW_CONNECTION_EVENT:
		/* assign connection private data */
		cparams.user_context = cb_user_context;
		xio_set_connection_params(event_data->conn, &cparams);
		break;
	case XIO_SESSION_REJECT_EVENT:
		xio_disconnect(event_data->conn);
		break;
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		printf("last sent:%"PRIu64", last comp:%"PRIu64", " \
		       "delta:%"PRIu64"\n",
		       test_params->nsent,  test_params->ncomp,
		       test_params->nsent-test_params->ncomp);
		xio_connection_destroy(event_data->conn);
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_session_destroy(session);
		xio_context_stop_loop(test_params->ctx, 0);
		break;
	default:
		break;
	};

	return 0;
}
Example #26
0
/*---------------------------------------------------------------------------*/
static int on_session_event(struct xio_session *session,
			    struct xio_session_event_data *event_data,
			    void *cb_user_context)
{
	struct ow_test_params *ow_params =
				(struct ow_test_params *)cb_user_context;

	printf("session event: %s. reason: %s\n",
	       xio_session_event_str(event_data->event),
	       xio_strerror(event_data->reason));

	switch (event_data->event) {
	case XIO_SESSION_CONNECTION_TEARDOWN_EVENT:
		xio_connection_destroy(event_data->conn);
		break;
	case XIO_SESSION_TEARDOWN_EVENT:
		xio_context_stop_loop(ow_params->ctx);  /* exit */
		break;
	default:
		break;
	};

	return 0;
}
Example #27
0
/*---------------------------------------------------------------------------*/
int run_server_test(struct perf_parameters *user_param)
{
	struct server_data	server_data;
	struct perf_command	command;
	int			i, len, retval;
	int			max_cpus;
	uint64_t		cpusmask;
	int			cpusnr;
	int			cpu;

	xio_init();

	max_cpus = sysconf(_SC_NPROCESSORS_ONLN);

	i = intf_name_best_cpus(user_param->intf_name, &cpusmask, &cpusnr);
	if (i == 0) {
		printf("best cpus [%d] %s\n", cpusnr,
		       intf_cpusmask_str(cpusmask, cpusnr, user_param->intf_name));
	}

	server_data.my_test_param.machine_type	= user_param->machine_type;
	server_data.my_test_param.test_type	= user_param->test_type;
	server_data.my_test_param.verb		= user_param->verb;
	server_data.my_test_param.data_len	= 0;


	server_data.tdata = calloc(user_param->threads_num,
				   sizeof(*server_data.tdata));

	/* spawn portals */
	for (i = 0, cpu = 0; i < user_param->threads_num; i++, cpu++) {
		while (1) {
			if (cpusmask_test_bit(cpu, &cpusmask))
				break;
			if (++cpu == max_cpus)
				cpu = 0;
		}
		server_data.tdata[i].affinity = cpu;

		server_data.tdata[i].portal_index =
					(i % user_param->portals_arr_len);
		server_data.tdata[i].user_param = user_param;

		pthread_create(&server_data.tdata[i].thread_id, NULL,
			       portal_server_cb, &server_data.tdata[i]);
	}

	server_data.user_param = user_param;
	pthread_create(&server_data.thread_id, NULL,
		       balancer_server_cb, &server_data);

	server_data.comm = create_comm_struct(user_param);
	if (establish_connection(server_data.comm)) {
		fprintf(stderr, "failed to establish connection\n");
		goto cleanup;
	}


	printf("%s", RESULT_FMT);
	printf("%s", RESULT_LINE);

	while (1) {
		/* sync test parameters */
		retval = ctx_read_data(server_data.comm, &command,
				       sizeof(command), &len);
		if (retval) {	/* disconnection */
			fprintf(stderr, "program aborted\n");
			break;
		}

		if (len == 0) { /* handshake */
			ctx_write_data(server_data.comm, NULL, 0);
			break;
		}
		switch (command.command) {
		case GetTestResults:
			on_test_results(&command.results);
			ctx_write_data(server_data.comm, NULL, 0);
			break;
		case  GetTestParams:
			break;
		default:
			fprintf(stderr, "unknown command %d\n", len);
			exit(0);
			break;
		};
	}
	if (retval == 0)
		printf("%s", RESULT_LINE);

	/* normal exit phase */
	ctx_close_connection(server_data.comm);

cleanup:
	for (i = 0; i < user_param->threads_num; i++)
		xio_context_stop_loop(server_data.tdata[i].ctx, 0);

	destroy_comm_struct(server_data.comm);

	/* join the threads */
	for (i = 0; i < user_param->threads_num; i++)
		pthread_join(server_data.tdata[i].thread_id, NULL);

	if (server_data.running)
		xio_context_stop_loop(server_data.ctx, 0);

	pthread_join(server_data.thread_id, NULL);

	free(server_data.tdata);

	xio_shutdown();

	return 0;
}