/*---------------------------------------------------------------------------*/ static int on_client_message(struct xio_session *session, struct xio_msg *msg, int more_in_batch, void *cb_prv_data) { if (msg->status) printf("**** request completed with error. [%s]\n", xio_strerror(msg->status)); /* process message */ process_request(msg); xio_release_msg(msg); return 0; }
/*---------------------------------------------------------------------------*/ static int on_msg_error(struct xio_session *session, enum xio_status error, enum xio_msg_direction direction, struct xio_msg *msg, void *cb_user_context) { struct ow_test_params *ow_params = (struct ow_test_params *)cb_user_context; printf("**** [%p] message [%lu] failed. reason: %s\n", session, msg->sn, xio_strerror(error)); msg_pool_put(ow_params->pool, msg); return 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; }
/*---------------------------------------------------------------------------*/ static int on_session_event(struct xio_session *session, struct xio_session_event_data *event_data, void *cb_user_context) { printf("%s. reason: %s\n", xio_session_event_str(event_data->event), xio_strerror(event_data->reason)); switch (event_data->event) { case XIO_SESSION_TEARDOWN_EVENT: xio_session_close(session); break; default: break; }; return 0; }
/*---------------------------------------------------------------------------*/ static int on_message_delivered(struct xio_session *session, struct xio_msg *msg, int more_in_batch, void *cb_user_context) { struct xio_msg *new_msg; struct ow_test_params *ow_params = cb_user_context; ow_params->ndelivered++; /* can be safely freed */ msg_pool_put(ow_params->pool, msg); #if TEST_DISCONNECT if (ow_params->ndelivered == DISCONNECT_NR) { xio_disconnect(ow_params->connection); return 0; } if (ow_params->nsent == DISCONNECT_NR) return 0; #endif /* peek new message from the pool */ new_msg = msg_pool_get(ow_params->pool); new_msg->more_in_batch = 0; /* fill response */ msg_write(&ow_params->msg_params, new_msg, NULL, test_config.hdr_len, NULL, test_config.data_len); new_msg->flags = XIO_MSG_FLAG_REQUEST_READ_RECEIPT; if (xio_send_msg(ow_params->connection, new_msg) == -1) { printf("**** [%p] Error - xio_send_msg failed. %s\n", session, xio_strerror(xio_errno())); msg_pool_put(ow_params->pool, new_msg); } ow_params->nsent++; return 0; }
/*---------------------------------------------------------------------------*/ static int on_message_delivered(struct xio_session *session, struct xio_msg *msg, int more_in_batch, void *cb_user_context) { struct xio_msg *new_msg; process_tx_message(msg); /* can be safely returned to pool */ msg_pool_put(pool, msg); /* peek message from the pool */ new_msg = msg_pool_get(pool); if (new_msg == NULL) { printf("pool is empty\n"); return 0; } /* assign buffers to the message */ msg_write(new_msg, NULL, test_config.hdr_len, NULL, test_config.data_len); /* * ask for receipt since we need to put the message back * to pool */ new_msg->flags = XIO_MSG_FLAG_REQUEST_READ_RECEIPT; /* send it */ if (xio_send_msg(conn, new_msg) == -1) { if (xio_errno() != EAGAIN) printf("**** [%p] Error - xio_send_msg " \ "failed. %s\n", session, xio_strerror(xio_errno())); msg_pool_put(pool, new_msg); return 0; } return 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; }
/*---------------------------------------------------------------------------*/ static int on_connection_established(struct xio_connection *conn) { struct xio_msg *msg; pr_info("**** starting ...\n"); /* create transaction */ msg = msg_pool_get(pool); if (!msg) return 0; /* get pointers to internal buffers */ msg->in.header.iov_base = NULL; msg->in.header.iov_len = 0; msg->in.data_tbl.nents = 0; /* sglist = vmsg_sglist(&msg->in); sglist[0].iov_base = NULL; sglist[0].iov_len = ONE_MB; sglist[0].mr = NULL; vmsg_sglist_set_nents(&msg->in, 1); */ /* recycle the message and fill new request */ msg_build_out_sgl(&msg_params, msg, test_config.hdr_len, 1, test_config.data_len); /* try to send it */ if (xio_send_request(conn, msg) == -1) { pr_info("**** sent %d messages\n", 1); if (xio_errno() != EAGAIN) pr_info("**** [%p] Error - xio_send_msg " \ "failed. %s\n", conn, xio_strerror(xio_errno())); msg_pool_put(pool, msg); xio_assert(0); } return 0; }
/*---------------------------------------------------------------------------*/ static int on_server_message(struct xio_session *session, struct xio_msg *msg, int more_in_batch, void *cb_user_context) { /* server send message */ /* process the incoming message */ process_rx_message(msg); if (msg->status) printf("**** message completed with error. [%s]\n", xio_strerror(msg->status)); /* message is no longer needed */ xio_release_msg(msg); return 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; }
/*---------------------------------------------------------------------------*/ static int on_msg_error(struct xio_session *session, enum xio_status error, enum xio_msg_direction direction, struct xio_msg *msg, void *cb_user_context) { pr_info("**** [%p] message [%llu] failed. reason: %s\n", session, msg->sn, xio_strerror(error)); msg_pool_put(pool, msg); switch (error) { case XIO_E_MSG_FLUSHED: break; default: xio_disconnect(g_connection); break; }; return 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; }
/*---------------------------------------------------------------------------*/ static int on_session_event(struct xio_session *session, struct xio_session_event_data *event_data, void *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_REJECT_EVENT: case XIO_SESSION_CONNECTION_DISCONNECTED_EVENT: xio_disconnect(event_data->conn); break; case XIO_SESSION_TEARDOWN_EVENT: xio_ev_loop_stop(loop); /* 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. 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, 0); /* exit */ break; default: break; }; return 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); break; default: break; }; return 0; }
/*---------------------------------------------------------------------------*/ static int on_msg_error(struct xio_session *session, enum xio_status error, enum xio_msg_direction direction, struct xio_msg *msg, void *cb_user_context) { printf("**** [%p] message [%lu] failed. reason: %s\n", session, msg->sn, xio_strerror(error)); msg_pool_put(pool, msg); switch (error) { case XIO_E_MSG_DISCARDED: case XIO_E_MSG_FLUSHED: break; default: /* need to send response here */ xio_assert(0); break; }; return 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; unsigned int i; switch (event_data->event) { case XIO_SESSION_CONNECTION_ERROR_EVENT: case XIO_SESSION_CONNECTION_REFUSED_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); 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 session_data *session_data = 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_session_destroy(session); event_base_loopbreak(session_data->evbase); break; default: break; }; return 0; }
/*---------------------------------------------------------------------------*/ static int on_msg_send_complete(struct xio_session *session, struct xio_msg *msg, void *cb_user_context) { struct test_params *test_params = cb_user_context; process_message(test_params, msg); test_params->ncomp++; /* can be safely freed */ msg_pool_put(test_params->pool, msg); if (test_params->finite_run) { if ((test_params->ncomp+test_params->ndelivered) > test_params->disconnect_nr) return 0; if ((test_params->ncomp + test_params->ndelivered) == test_params->disconnect_nr) { xio_disconnect(test_params->connection); return 0; } } if (test_params->closed) return 0; /* peek message from the pool */ msg = msg_pool_get(test_params->pool); if (msg == NULL) { printf("pool is empty\n"); return 0; } /* reset message */ msg->in.header.iov_base = NULL; msg->in.header.iov_len = 0; msg->in.data_iov.nents = 0; msg->more_in_batch = 0; /* assign buffers to the message */ msg_write(&test_params->msg_params, msg, test_config.hdr_len, 1, test_config.data_len); /* try to send it */ if (test_params->ask_for_receipt) msg->flags = XIO_MSG_FLAG_REQUEST_READ_RECEIPT; else msg->flags = 0; if (xio_send_msg(test_params->connection, msg) == -1) { if (xio_errno() != EAGAIN) printf("**** [%p] Error - xio_send_request " \ "failed %s\n", session, xio_strerror(xio_errno())); msg_pool_put(test_params->pool, msg); xio_assert(0); } test_params->nsent++; return 0; }
/*---------------------------------------------------------------------------*/ static int xio_client_main(void *data) { char url[256]; struct xio_session_params params; struct xio_context_params ctx_params; struct xio_connection_params cparams; int error; int retval = 0; atomic_add(2, &module_state); print_counter = PRINT_COUNTER; print_test_config(&test_config); memset(¶ms, 0, sizeof(params)); memset(&cparams, 0, sizeof(cparams)); /* prepare buffers for this test */ if (msg_api_init(&msg_params, test_config.hdr_len, test_config.data_len, 0) != 0) { pr_err("msg_api_init failed\n"); return -1; } pool = msg_pool_alloc(MAX_POOL_SIZE, 1, 1); if (!pool) { pr_err("msg_pool_alloc failed\n"); goto cleanup; } /* create thread context for the server */ memset(&ctx_params, 0, sizeof(ctx_params)); ctx_params.flags = XIO_LOOP_GIVEN_THREAD; ctx_params.worker = current; ctx = xio_context_create(&ctx_params, POLLING_TIMEOUT, cpu); if (!ctx) { pr_err("context open failed\n"); goto cleanup; } sprintf(url, "%s://%s:%d", test_config.transport, test_config.server_addr, test_config.server_port); params.type = XIO_SESSION_CLIENT; params.ses_ops = &ses_ops; params.uri = url; g_session = xio_session_create(¶ms); if (!g_session) pr_err("session creation failed\n"); cparams.session = g_session; cparams.ctx = ctx; cparams.conn_idx = test_config.conn_idx; /* connect the session */ g_connection = xio_connect(&cparams); /* the default xio supplied main loop */ if (atomic_add_unless(&module_state, 4, 0x83)) retval = xio_context_run_loop(ctx); atomic_sub(4, &module_state); if (retval != 0) { error = xio_errno(); pr_err("running event loop failed. reason %d - (%s)\n", error, xio_strerror(error)); xio_assert(retval == 0); } /* normal exit phase */ pr_info("exit signaled\n"); xio_context_destroy(ctx); msg_pool_free(pool); cleanup: msg_api_free(&msg_params); pr_info("exit complete\n"); complete_and_exit(&cleanup_complete, 0); return 0; }
/*---------------------------------------------------------------------------*/ int run_client_test(struct perf_parameters *user_param) { struct session_data sess_data; struct perf_comm *comm; struct thread_data *tdata; char url[256]; int i = 0; int max_cpus; pthread_t statistics_thread_id; struct perf_command command; int size_log2; int max_size_log2 = 24; /* client session attributes */ struct xio_session_attr attr = { &ses_ops, NULL, 0 }; xio_init(); g_mhz = get_cpu_mhz(0); max_cpus = sysconf(_SC_NPROCESSORS_ONLN); threads_iter = 1; size_log2 = 0; tdata = calloc(user_param->threads_num, sizeof(*tdata)); if (tdata == NULL) { fprintf(fd, "malloc failed\n"); return -1; } comm = create_comm_struct(user_param); if (establish_connection(comm)) { fprintf(stderr, "failed to establish connection\n"); free(tdata); destroy_comm_struct(comm); return -1; } if (user_param->output_file) { fd = fopen(user_param->output_file, "w"); if (fd == NULL) { fprintf(fd, "file open failed. %s\n", user_param->output_file); free(sess_data.tdata); destroy_comm_struct(comm); return -1; } fprintf(fd, "size, threads, tps, bw[Mbps], lat[usec]\n"); fflush(fd); } printf("%s", RESULT_FMT); printf("%s", RESULT_LINE); while (threads_iter <= user_param->threads_num) { data_len = (uint64_t)1 << size_log2; memset(&sess_data, 0, sizeof(sess_data)); memset(tdata, 0, user_param->threads_num*sizeof(*tdata)); sess_data.tdata = tdata; command.test_param.machine_type = user_param->machine_type; command.test_param.test_type = user_param->test_type; command.test_param.verb = user_param->verb; command.test_param.data_len = data_len; command.command = GetTestParams; ctx_write_data(comm, &command, sizeof(command)); sprintf(url, "rdma://%s:%d", user_param->server_addr, user_param->server_port); sess_data.session = xio_session_create(XIO_SESSION_CLIENT, &attr, url, 0, 0, &sess_data); if (sess_data.session == NULL) { int error = xio_errno(); fprintf(stderr, "session creation failed. reason %d - (%s)\n", error, xio_strerror(error)); goto cleanup; } pthread_create(&statistics_thread_id, NULL, statistics_thread_cb, &sess_data); /* spawn threads to handle connection */ for (i = 0; i < threads_iter; i++) { sess_data.tdata[i].affinity = ((user_param->cpu + i) % max_cpus); sess_data.tdata[i].cid = i; sess_data.tdata[i].sdata = &sess_data; sess_data.tdata[i].user_param = user_param; sess_data.tdata[i].data_len = data_len; /* all threads are working on the same session */ sess_data.tdata[i].session = sess_data.session; pthread_create(&sess_data.tdata[i].thread_id, NULL, worker_thread, &sess_data.tdata[i]); } pthread_join(statistics_thread_id, NULL); /* join the threads */ for (i = 0; i < threads_iter; i++) pthread_join(sess_data.tdata[i].thread_id, NULL); /* close the session */ xio_session_destroy(sess_data.session); if (sess_data.abort) { fprintf(stderr, "program aborted\n"); goto cleanup; } /* send result to server */ command.results.bytes = data_len; command.results.threads = threads_iter; command.results.tps = sess_data.tps; command.results.avg_bw = sess_data.avg_bw; command.results.avg_lat = sess_data.avg_lat_us; command.results.min_lat = sess_data.min_lat_us; command.results.max_lat = sess_data.max_lat_us; command.command = GetTestResults; /* sync point */ ctx_write_data(comm, &command, sizeof(command)); printf(REPORT_FMT, data_len, threads_iter, sess_data.tps, sess_data.avg_bw, sess_data.avg_lat_us, sess_data.min_lat_us, sess_data.max_lat_us); if (fd) fprintf(fd, "%lu, %d, %lu, %.2lf, %.2lf\n", data_len, threads_iter, sess_data.tps, sess_data.avg_bw, sess_data.avg_lat_us); fflush(fd); /* sync point */ ctx_read_data(comm, NULL, 0, NULL); if (++size_log2 < max_size_log2) continue; threads_iter++; size_log2 = 0; } printf("%s", RESULT_LINE); cleanup: if (fd) fclose(fd); ctx_hand_shake(comm); ctx_close_connection(comm); destroy_comm_struct(comm); free(tdata); xio_shutdown(); return 0; }
/*---------------------------------------------------------------------------*/ static void *worker_thread(void *data) { struct thread_data *tdata = data; cpu_set_t cpuset; struct xio_msg *msg; int i; /* set affinity to thread */ CPU_ZERO(&cpuset); CPU_SET(tdata->affinity, &cpuset); pthread_setaffinity_np(tdata->thread_id, sizeof(cpu_set_t), &cpuset); /* prepare data for the cuurent thread */ tdata->pool = msg_pool_alloc(tdata->user_param->queue_depth); /* create thread context for the client */ tdata->ctx = xio_context_create(NULL, tdata->user_param->poll_timeout, tdata->affinity); /* connect the session */ tdata->conn = xio_connect(tdata->session, tdata->ctx, tdata->cid, NULL, tdata); if (tdata->data_len) tdata->xbuf = xio_alloc(tdata->data_len); for (i = 0; i < tdata->user_param->queue_depth; i++) { /* create transaction */ msg = msg_pool_get(tdata->pool); if (msg == NULL) break; /* get pointers to internal buffers */ msg->in.header.iov_len = 0; msg->in.data_iovlen = 0; msg->out.header.iov_len = 0; if (tdata->data_len) { msg->out.data_iovlen = 1; msg->out.data_iov[0].iov_base = tdata->xbuf->addr; msg->out.data_iov[0].iov_len = tdata->xbuf->length; msg->out.data_iov[0].mr = tdata->xbuf->mr; } else { msg->out.data_iovlen = 0; } msg->user_context = (void *)get_cycles(); /* send first message */ if (xio_send_request(tdata->conn, msg) == -1) { if (xio_errno() != EAGAIN) printf("**** [%p] Error - xio_send_request " \ "failed. %s\n", tdata->session, xio_strerror(xio_errno())); msg_pool_put(tdata->pool, msg); return 0; } if (tdata->do_stat) tdata->stat.scnt++; tdata->tx_nr++; } /* the default xio supplied main loop */ xio_context_run_loop(tdata->ctx, XIO_INFINITE); /* normal exit phase */ if (tdata->pool) msg_pool_free(tdata->pool); if (tdata->xbuf) xio_free(&tdata->xbuf); /* free the context */ xio_context_destroy(tdata->ctx); return NULL; }
static int on_request(struct xio_session *session, struct xio_msg *req, int last_in_rxq, void *cb_user_context) { struct xio_msg *rsp; struct io_worker_data *wdata; struct xio_iovec_ex *in_sglist; struct xio_iovec_ex *out_sglist; struct rdb_req_hdr *req_hdr; void *ptr; int *status; char *value; size_t key_size, value_size; // int len; wdata = cb_user_context; rsp = &wdata->rsp; in_sglist = vmsg_sglist(&req->in); req_hdr = in_sglist[0].iov_base; ptr = in_sglist[0].iov_base; ptr += sizeof (*req_hdr); switch (req_hdr->rdb_command) { case RDB_CMD_PUT: { struct rdb_put_req_hdr *put_hdr; put_hdr = ptr; struct __attribute__((__packed__)) rdb_put_req { struct rdb_key { struct rdb_key_hdr key_hdr; char key_data[put_hdr->key_size]; } key; struct rdb_value { struct rdb_value_hdr value_hdr; char value_data[put_hdr->value_size]; } value; } *put_req; ptr += sizeof (*put_hdr); put_req = ptr; key_size = sizeof (struct rdb_key); value_size = sizeof (struct rdb_value); if (!null_mode) if (!rocksdb_server_put(wdata->rdb, (char *)&put_req->key, &key_size, (char *)&put_req->value, &value_size)) { fprintf(stderr, "rocksdb put failed\n"); } // len = (int) in_sglist[0].iov_len; break; } case RDB_CMD_MPUT: { struct rdb_mput_req_hdr *mput_hdr; char *records; mput_hdr = ptr; struct __attribute__((__packed__)) rdb_mput_req { struct multi_kv_pairs { struct rdb_key { struct rdb_key_hdr key_hdr; char key_data[mput_hdr->key_size]; } key; struct rdb_value { struct rdb_value_hdr value_hdr; char value_data[mput_hdr->value_size]; } value; } m_kv_pairs[mput_hdr->num_records]; } *mput_req; ptr += sizeof (*mput_hdr); mput_req = ptr; key_size = sizeof (struct rdb_key); value_size = sizeof (struct rdb_value); records = (char *)mput_req->m_kv_pairs; if (!null_mode) if (!rocksdb_server_mput(wdata->rdb, records, &key_size, &value_size, &mput_hdr->num_records)) { fprintf(stderr, "rocksdb mput failed\n"); } // len = (int) in_sglist[0].iov_len; break; } case RDB_CMD_GET: { struct rdb_get_req_hdr *get_hdr; get_hdr = ptr; struct __attribute__((__packed__)) rdb_get_req { struct rdb_key { struct rdb_key_hdr key_hdr; char key_data[get_hdr->key_size]; } key; } *get_req; ptr += sizeof (*get_hdr); get_req = ptr; key_size = sizeof (get_req->key); out_sglist = vmsg_sglist(&rsp->out); out_sglist[0].iov_base = wdata->reg_mem.addr; out_sglist[0].mr = wdata->reg_mem.mr; if (!null_mode) { status = wdata->reg_mem.addr; value = wdata->reg_mem.addr + sizeof (*status); *status = rocksdb_server_get(wdata->rdb, (char *)&get_req->key, &key_size, value, &value_size); if (*status) out_sglist[0].iov_len = value_size + sizeof (*status); else out_sglist[0].iov_len = sizeof (*status); } else { status = wdata->reg_mem.addr; *status = 1; out_sglist[0].iov_len = sizeof (*status); } // len = (int) out_sglist[0].iov_len; vmsg_sglist_set_nents(&rsp->out, 1); break; } case RDB_CMD_MGET: { struct rdb_mget_req_hdr *mget_hdr; char *records; mget_hdr = ptr; struct __attribute__((__packed__)) rdb_mget_req { struct multi_k_pairs { struct rdb_key { struct rdb_key_hdr key_hdr; char key_data[mget_hdr->key_size]; } key; } m_k_pairs[mget_hdr->num_records]; } *mget_req; ptr += sizeof (*mget_hdr); mget_req = ptr; key_size = sizeof (struct rdb_key); records = (char *) mget_req->m_k_pairs; out_sglist = vmsg_sglist(&rsp->out); out_sglist[0].iov_base = wdata->reg_mem.addr; out_sglist[0].mr = wdata->reg_mem.mr; if (!null_mode) { status = wdata->reg_mem.addr; value = wdata->reg_mem.addr + sizeof (*status); *status = rocksdb_server_mget(wdata->rdb, records, &key_size, value, &value_size, &mget_hdr->num_records); if (*status) out_sglist[0].iov_len = value_size + sizeof (*status); else out_sglist[0].iov_len = sizeof (*status); } else { status = wdata->reg_mem.addr; *status = 1; out_sglist[0].iov_len = sizeof (*status); } // len = (int) out_sglist[0].iov_len; vmsg_sglist_set_nents(&rsp->out, 1); break; } default: break; }; /*printf("thread : portal : %s, command : %d, version : %d, key : %s, value : %s, len : %d\n", wdata->portal, *payload_cmd, *payload_version, key, value, len);*/ in_sglist[0].iov_base = NULL; in_sglist[0].iov_len = 0; vmsg_sglist_set_nents(&req->in, 0); rsp->request = req; if (xio_send_response(rsp) == -1) { fprintf(stderr, "failed to send response for thread %s. reason %d - (%s)\n", wdata->portal, xio_errno(), xio_strerror(xio_errno())); } return (0); }
/*---------------------------------------------------------------------------*/ static int xio_server_main(void *data) { struct xio_server *server; struct xio_context_params ctx_params; char url[256]; atomic_add(2, &module_state); print_test_config(&test_config); g_test_params.finite_run = test_config.finite_run; g_test_params.disconnect_nr = PRINT_COUNTER * DISCONNECT_FACTOR; memset(&ctx_params, 0, sizeof(ctx_params)); ctx_params.flags = XIO_LOOP_GIVEN_THREAD; ctx_params.worker = current; g_test_params.ctx = xio_context_create(&ctx_params, 0, g_test_params.cpu); if (!g_test_params.ctx) { int error = xio_errno(); pr_err("context creation failed. reason %d - (%s)\n", error, xio_strerror(error)); goto cleanup; } sprintf(url, "%s://%s:%d", test_config.transport, test_config.server_addr, test_config.server_port); server = xio_bind(g_test_params.ctx, &server_ops, url, NULL, 0, &g_test_params); if (server) { pr_info("listen to %s\n", url); if (atomic_add_unless(&module_state, 4, 0x83)) xio_context_run_loop(g_test_params.ctx); atomic_sub(4, &module_state); /* normal exit phase */ pr_info("exit signaled\n"); /* free the server */ xio_unbind(server); } else { pr_err("**** Error - xio_bind failed - %s. " \ "Did you load a transport module?\n", xio_strerror(xio_errno())); /*xio_assert(0);*/ } xio_context_destroy(g_test_params.ctx); kfree(g_test_params.xbuf); g_test_params.xbuf = NULL; cleanup: complete_and_exit(&cleanup_complete, 0); return 0; }
/*---------------------------------------------------------------------------*/ static int on_response(struct xio_session *session, struct xio_msg *msg, int last_in_rxq, void *cb_user_context) { struct test_params *test_params = (struct test_params *)cb_user_context; struct xio_iovec_ex *sglist; static int chain_messages = CHAIN_MESSAGES; size_t j; test_params->nrecv++; process_response(test_params, msg); /* message is no longer needed */ xio_release_response(msg); msg_pool_put(test_params->pool, msg); if (test_params->finite_run) { if (test_params->nrecv == test_params->disconnect_nr) { xio_disconnect(test_params->connection); return 0; } if (test_params->nsent == test_params->disconnect_nr) return 0; } /* peek message from the pool */ msg = msg_pool_get(test_params->pool); if (msg == NULL) { printf("pool is empty\n"); return 0; } msg->in.header.iov_base = NULL; msg->in.header.iov_len = 0; sglist = vmsg_sglist(&msg->in); vmsg_sglist_set_nents(&msg->in, test_config.in_iov_len); /* tell accelio to use 1MB buffer from its internal pool */ for (j = 0; j < test_config.in_iov_len; j++) { sglist[j].iov_base = NULL; sglist[j].iov_len = ONE_MB; sglist[j].mr = NULL; } msg->sn = 0; /* assign buffers to the message */ msg_build_out_sgl(&test_params->msg_params, msg, test_config.hdr_len, test_config.out_iov_len, test_config.data_len); if (chain_messages) { msg->next = NULL; if (test_params->chain.head == NULL) { test_params->chain.head = msg; test_params->chain.tail = test_params->chain.head; } else { test_params->chain.tail->next = msg; test_params->chain.tail = test_params->chain.tail->next; } if (++test_params->chain.sz == MAX_OUTSTANDING_REQS) { if (xio_send_request(test_params->connection, test_params->chain.head) == -1) { if (xio_errno() != EAGAIN) printf("**** [%p] Error - xio_send_request " \ "failed %s\n", session, xio_strerror(xio_errno())); msg_pool_put(test_params->pool, msg); xio_assert(xio_errno() == EAGAIN); } test_params->nsent += test_params->chain.sz; test_params->chain.head = NULL; test_params->chain.sz = 0; } } else { /* try to send it */ /*msg->flags = XIO_MSG_FLAG_REQUEST_READ_RECEIPT; */ /*msg->flags = XIO_MSG_FLAG_PEER_READ_REQ;*/ if (xio_send_request(test_params->connection, msg) == -1) { if (xio_errno() != EAGAIN) printf("**** [%p] Error - xio_send_request " \ "failed %s\n", session, xio_strerror(xio_errno())); msg_pool_put(test_params->pool, msg); xio_assert(xio_errno() == EAGAIN); } test_params->nsent++; } return 0; }