/* * remove_remote -- (internal) remove remote pool */ static int remove_remote(const char *target, const char *pool_set) { #ifdef USE_RPMEM struct rpmem_target_info *info = rpmem_target_parse(target); if (!info) goto err_parse; struct rpmem_ssh *ssh = rpmem_ssh_exec(info, "--remove", pool_set, "--force", NULL); if (!ssh) { goto err_ssh_exec; } if (rpmem_ssh_monitor(ssh, 0)) goto err_ssh_monitor; int ret = rpmem_ssh_close(ssh); rpmem_target_free(info); return ret; err_ssh_monitor: rpmem_ssh_close(ssh); err_ssh_exec: rpmem_target_free(info); err_parse: return -1; #else FATAL("remote replication not supported"); return -1; #endif }
/* * client_open -- perform open request */ int client_open(const struct test_case *tc, int argc, char *argv[]) { if (argc < 1) UT_FATAL("usage: %s <addr>[:<port>]", tc->name); char *target = argv[0]; int ret; struct rpmem_obc *rpc; struct rpmem_target_info *info; struct rpmem_req_attr req = REQ_ATTR_INIT; struct rpmem_pool_attr ex_pool_attr = POOL_ATTR_INIT; struct rpmem_pool_attr pool_attr; struct rpmem_resp_attr ex_res = RESP_ATTR_INIT; struct rpmem_resp_attr res; info = rpmem_target_parse(target); UT_ASSERTne(info, NULL); rpc = rpmem_obc_init(); UT_ASSERTne(rpc, NULL); ret = rpmem_obc_connect(rpc, info); UT_ASSERTeq(ret, 0); rpmem_target_free(info); ret = rpmem_obc_monitor(rpc, 1); UT_ASSERTeq(ret, 1); ret = rpmem_obc_open(rpc, &req, &res, &pool_attr); UT_ASSERTeq(ret, 0); UT_ASSERTeq(ex_res.port, res.port); UT_ASSERTeq(ex_res.rkey, res.rkey); UT_ASSERTeq(ex_res.raddr, res.raddr); UT_ASSERTeq(ex_res.persist_method, res.persist_method); UT_ASSERTeq(ex_res.nlanes, res.nlanes); UT_ASSERTeq(memcmp(&ex_pool_attr, &pool_attr, sizeof(ex_pool_attr)), 0); ret = rpmem_obc_monitor(rpc, 1); UT_ASSERTeq(ret, 1); ret = rpmem_obc_close(rpc); UT_ASSERTeq(ret, 0); ret = rpmem_obc_disconnect(rpc); UT_ASSERTeq(ret, 0); rpmem_obc_fini(rpc); return 1; }
/* * clnt_connect -- create a ssh connection with specified target */ struct rpmem_ssh * clnt_connect(char *target) { struct rpmem_target_info *info; info = rpmem_target_parse(target); UT_ASSERTne(info, NULL); struct rpmem_ssh *ssh = rpmem_ssh_open(info); UT_ASSERTne(ssh, NULL); rpmem_target_free(info); return ssh; }
/* * client_set_attr -- perform set attributes request */ int client_set_attr(const struct test_case *tc, int argc, char *argv[]) { if (argc < 1) UT_FATAL("usage: %s <addr>[:<port>]", tc->name); char *target = argv[0]; int ret; struct rpmem_obc *rpc; struct rpmem_target_info *info; const struct rpmem_pool_attr pool_attr = POOL_ATTR_ALT; info = rpmem_target_parse(target); UT_ASSERTne(info, NULL); rpc = rpmem_obc_init(); UT_ASSERTne(rpc, NULL); ret = rpmem_obc_connect(rpc, info); UT_ASSERTeq(ret, 0); rpmem_target_free(info); ret = rpmem_obc_monitor(rpc, 1); UT_ASSERTeq(ret, 1); ret = rpmem_obc_set_attr(rpc, &pool_attr); UT_ASSERTeq(ret, 0); ret = rpmem_obc_monitor(rpc, 1); UT_ASSERTeq(ret, 1); ret = rpmem_obc_close(rpc); UT_ASSERTeq(ret, 0); ret = rpmem_obc_disconnect(rpc); UT_ASSERTeq(ret, 0); rpmem_obc_fini(rpc); return 1; }
/* * remove_remote -- (internal) remove remote pool */ static int remove_remote(const char *target, const char *pool_set) { #ifdef USE_RPMEM char cask = 'y'; switch (ask_mode) { case ASK_ALWAYS: cask = '?'; break; case ASK_NEVER: case ASK_SOMETIMES: cask = 'y'; break; } if (ask_Yn(cask, "remove remote pool '%s' on '%s'?", pool_set, target) != 'y') return 0; struct rpmem_target_info *info = rpmem_target_parse(target); if (!info) goto err_parse; struct rpmem_ssh *ssh; if (force) { ssh = rpmem_ssh_exec(info, "--remove", pool_set, "--force", NULL); } else { ssh = rpmem_ssh_exec(info, "--remove", pool_set, NULL); } if (!ssh) goto err_ssh_exec; int ret = 0; if (rpmem_ssh_monitor(ssh, 0)) ret = 1; if (rpmem_ssh_close(ssh)) ret = 1; if (ret) goto err_ssh_exec; rpmem_target_free(info); outv(1, "removed '%s' on '%s'\n", pool_set, target); return ret; err_ssh_exec: rpmem_target_free(info); err_parse: if (!force) outv_err("cannot remove '%s' on '%s'", pool_set, target); return 1; #else outv_err("remote replication not supported"); return 1; #endif }
/* * client_init -- test case for client initialization */ int client_init(const struct test_case *tc, int argc, char *argv[]) { if (argc < 3) UT_FATAL("usage: %s <target> <provider> <persist method>", tc->name); char *target = argv[0]; char *prov_name = argv[1]; char *persist_method = argv[2]; set_rpmem_cmd("server_init %s", persist_method); char fip_service[NI_MAXSERV]; struct rpmem_target_info *info; info = rpmem_target_parse(target); UT_ASSERTne(info, NULL); unsigned nlanes; enum rpmem_provider provider = get_provider(info->node, prov_name, &nlanes); client_t *client; struct rpmem_resp_attr resp; client = client_exchange(info, NLANES, provider, &resp); struct rpmem_fip_attr attr = { .provider = provider, .persist_method = resp.persist_method, .laddr = lpool, .size = POOL_SIZE, .nlanes = resp.nlanes, .raddr = (void *)resp.raddr, .rkey = resp.rkey, }; ssize_t sret = snprintf(fip_service, NI_MAXSERV, "%u", resp.port); UT_ASSERT(sret > 0); struct rpmem_fip *fip; fip = rpmem_fip_init(info->node, fip_service, &attr, &nlanes); UT_ASSERTne(fip, NULL); client_close_begin(client); client_close_end(client); rpmem_fip_fini(fip); rpmem_target_free(info); return 3; } /* * server_init -- test case for server initialization */ int server_init(const struct test_case *tc, int argc, char *argv[]) { if (argc < 1) UT_FATAL("usage: %s <persist method>", tc->name); enum rpmem_persist_method persist_method = get_persist_method(argv[0]); unsigned nlanes; enum rpmem_provider provider; char *addr = NULL; server_exchange_begin(&nlanes, &provider, &addr); UT_ASSERTne(addr, NULL); struct rpmemd_fip_attr attr = { .addr = rpool, .size = POOL_SIZE, .nlanes = nlanes, .provider = provider, .persist_method = persist_method, .persist = pmem_persist, .nthreads = NTHREADS, }; struct rpmem_resp_attr resp; struct rpmemd_fip *fip; enum rpmem_err err; fip = rpmemd_fip_init(addr, NULL, &attr, &resp, &err); UT_ASSERTne(fip, NULL); server_exchange_end(resp); server_close_begin(); server_close_end(); rpmemd_fip_fini(fip); FREE(addr); return 1; } /* * client_connect -- test case for establishing connection - client side */ int client_connect(const struct test_case *tc, int argc, char *argv[]) { if (argc < 3) UT_FATAL("usage: %s <target> <provider> <persist method>", tc->name); char *target = argv[0]; char *prov_name = argv[1]; char *persist_method = argv[2]; set_rpmem_cmd("server_connect %s", persist_method); char fip_service[NI_MAXSERV]; struct rpmem_target_info *info; int ret; info = rpmem_target_parse(target); UT_ASSERTne(info, NULL); unsigned nlanes; enum rpmem_provider provider = get_provider(info->node, prov_name, &nlanes); client_t *client; struct rpmem_resp_attr resp; client = client_exchange(info, NLANES, provider, &resp); struct rpmem_fip_attr attr = { .provider = provider, .persist_method = resp.persist_method, .laddr = lpool, .size = POOL_SIZE, .nlanes = resp.nlanes, .raddr = (void *)resp.raddr, .rkey = resp.rkey, }; ssize_t sret = snprintf(fip_service, NI_MAXSERV, "%u", resp.port); UT_ASSERT(sret > 0); struct rpmem_fip *fip; fip = rpmem_fip_init(info->node, fip_service, &attr, &nlanes); UT_ASSERTne(fip, NULL); ret = rpmem_fip_connect(fip); UT_ASSERTeq(ret, 0); client_close_begin(client); ret = rpmem_fip_close(fip); UT_ASSERTeq(ret, 0); client_close_end(client); rpmem_fip_fini(fip); rpmem_target_free(info); return 3; } /* * server_connect -- test case for establishing connection - server side */ int server_connect(const struct test_case *tc, int argc, char *argv[]) { if (argc < 1) UT_FATAL("usage: %s <persist method>", tc->name); enum rpmem_persist_method persist_method = get_persist_method(argv[0]); unsigned nlanes; enum rpmem_provider provider; char *addr = NULL; server_exchange_begin(&nlanes, &provider, &addr); UT_ASSERTne(addr, NULL); struct rpmemd_fip_attr attr = { .addr = rpool, .size = POOL_SIZE, .nlanes = nlanes, .provider = provider, .persist_method = persist_method, .persist = pmem_persist, .nthreads = NTHREADS, }; int ret; struct rpmem_resp_attr resp; struct rpmemd_fip *fip; enum rpmem_err err; fip = rpmemd_fip_init(addr, NULL, &attr, &resp, &err); UT_ASSERTne(fip, NULL); server_exchange_end(resp); ret = rpmemd_fip_accept(fip, -1); UT_ASSERTeq(ret, 0); server_close_begin(); server_close_end(); ret = rpmemd_fip_wait_close(fip, -1); UT_ASSERTeq(ret, 0); ret = rpmemd_fip_close(fip); UT_ASSERTeq(ret, 0); rpmemd_fip_fini(fip); FREE(addr); return 1; } /* * server_process -- test case for processing data on server side */ int server_process(const struct test_case *tc, int argc, char *argv[]) { if (argc < 1) UT_FATAL("usage: %s <persist method>", tc->name); enum rpmem_persist_method persist_method = get_persist_method(argv[0]); set_pool_data(rpool, 1); unsigned nlanes; enum rpmem_provider provider; char *addr = NULL; server_exchange_begin(&nlanes, &provider, &addr); UT_ASSERTne(addr, NULL); struct rpmemd_fip_attr attr = { .addr = rpool, .size = POOL_SIZE, .nlanes = nlanes, .provider = provider, .persist_method = persist_method, .persist = pmem_persist, .nthreads = NTHREADS, }; int ret; struct rpmem_resp_attr resp; struct rpmemd_fip *fip; enum rpmem_err err; fip = rpmemd_fip_init(addr, NULL, &attr, &resp, &err); UT_ASSERTne(fip, NULL); server_exchange_end(resp); ret = rpmemd_fip_accept(fip, -1); UT_ASSERTeq(ret, 0); ret = rpmemd_fip_process_start(fip); server_close_begin(); ret = rpmemd_fip_process_stop(fip); UT_ASSERTeq(ret, 0); server_close_end(); ret = rpmemd_fip_wait_close(fip, -1); UT_ASSERTeq(ret, 0); ret = rpmemd_fip_close(fip); UT_ASSERTeq(ret, 0); rpmemd_fip_fini(fip); FREE(addr); return 1; } /* * client_persist -- test case for single-threaded persist operation */ int client_persist(const struct test_case *tc, int argc, char *argv[]) { if (argc < 3) UT_FATAL("usage: %s <target> <provider> <persist method>", tc->name); char *target = argv[0]; char *prov_name = argv[1]; char *persist_method = argv[2]; set_rpmem_cmd("server_process %s", persist_method); char fip_service[NI_MAXSERV]; struct rpmem_target_info *info; info = rpmem_target_parse(target); UT_ASSERTne(info, NULL); int ret; set_pool_data(lpool, 1); set_pool_data(rpool, 1); unsigned nlanes; enum rpmem_provider provider = get_provider(info->node, prov_name, &nlanes); client_t *client; struct rpmem_resp_attr resp; client = client_exchange(info, NLANES, provider, &resp); struct rpmem_fip_attr attr = { .provider = provider, .persist_method = resp.persist_method, .laddr = lpool, .size = POOL_SIZE, .nlanes = resp.nlanes, .raddr = (void *)resp.raddr, .rkey = resp.rkey, }; ssize_t sret = snprintf(fip_service, NI_MAXSERV, "%u", resp.port); UT_ASSERT(sret > 0); struct rpmem_fip *fip; fip = rpmem_fip_init(info->node, fip_service, &attr, &nlanes); UT_ASSERTne(fip, NULL); ret = rpmem_fip_connect(fip); UT_ASSERTeq(ret, 0); ret = rpmem_fip_process_start(fip); UT_ASSERTeq(ret, 0); struct persist_arg arg = { .fip = fip, .lane = 0, }; client_persist_thread(&arg); ret = rpmem_fip_read(fip, rpool, POOL_SIZE, 0); UT_ASSERTeq(ret, 0); ret = rpmem_fip_process_stop(fip); UT_ASSERTeq(ret, 0); client_close_begin(client); ret = rpmem_fip_close(fip); UT_ASSERTeq(ret, 0); client_close_end(client); rpmem_fip_fini(fip); ret = memcmp(rpool, lpool, POOL_SIZE); UT_ASSERTeq(ret, 0); rpmem_target_free(info); return 3; } /* * client_persist_mt -- test case for multi-threaded persist operation */ int client_persist_mt(const struct test_case *tc, int argc, char *argv[]) { if (argc < 3) UT_FATAL("usage: %s <target> <provider> <persist method>", tc->name); char *target = argv[0]; char *prov_name = argv[1]; char *persist_method = argv[2]; set_rpmem_cmd("server_process %s", persist_method); char fip_service[NI_MAXSERV]; struct rpmem_target_info *info; int ret; info = rpmem_target_parse(target); UT_ASSERTne(info, NULL); set_pool_data(lpool, 1); set_pool_data(rpool, 1); unsigned nlanes; enum rpmem_provider provider = get_provider(info->node, prov_name, &nlanes); client_t *client; struct rpmem_resp_attr resp; client = client_exchange(info, NLANES, provider, &resp); struct rpmem_fip_attr attr = { .provider = provider, .persist_method = resp.persist_method, .laddr = lpool, .size = POOL_SIZE, .nlanes = resp.nlanes, .raddr = (void *)resp.raddr, .rkey = resp.rkey, }; ssize_t sret = snprintf(fip_service, NI_MAXSERV, "%u", resp.port); UT_ASSERT(sret > 0); struct rpmem_fip *fip; fip = rpmem_fip_init(info->node, fip_service, &attr, &nlanes); UT_ASSERTne(fip, NULL); ret = rpmem_fip_connect(fip); UT_ASSERTeq(ret, 0); ret = rpmem_fip_process_start(fip); UT_ASSERTeq(ret, 0); pthread_t *persist_thread = MALLOC(resp.nlanes * sizeof(pthread_t)); struct persist_arg *args = MALLOC(resp.nlanes * sizeof(struct persist_arg)); for (unsigned i = 0; i < nlanes; i++) { args[i].fip = fip; args[i].lane = i; PTHREAD_CREATE(&persist_thread[i], NULL, client_persist_thread, &args[i]); } for (unsigned i = 0; i < nlanes; i++) PTHREAD_JOIN(persist_thread[i], NULL); ret = rpmem_fip_read(fip, rpool, POOL_SIZE, 0); UT_ASSERTeq(ret, 0); ret = rpmem_fip_process_stop(fip); UT_ASSERTeq(ret, 0); client_close_begin(client); ret = rpmem_fip_close(fip); UT_ASSERTeq(ret, 0); client_close_end(client); rpmem_fip_fini(fip); FREE(persist_thread); FREE(args); ret = memcmp(rpool, lpool, POOL_SIZE); UT_ASSERTeq(ret, 0); rpmem_target_free(info); return 3; } /* * client_read -- test case for read operation */ int client_read(const struct test_case *tc, int argc, char *argv[]) { if (argc < 3) UT_FATAL("usage: %s <target> <provider> <persist method>", tc->name); char *target = argv[0]; char *prov_name = argv[1]; char *persist_method = argv[2]; set_rpmem_cmd("server_process %s", persist_method); char fip_service[NI_MAXSERV]; struct rpmem_target_info *info; int ret; info = rpmem_target_parse(target); UT_ASSERTne(info, NULL); set_pool_data(lpool, 0); set_pool_data(rpool, 1); unsigned nlanes; enum rpmem_provider provider = get_provider(info->node, prov_name, &nlanes); client_t *client; struct rpmem_resp_attr resp; client = client_exchange(info, NLANES, provider, &resp); struct rpmem_fip_attr attr = { .provider = provider, .persist_method = resp.persist_method, .laddr = lpool, .size = POOL_SIZE, .nlanes = resp.nlanes, .raddr = (void *)resp.raddr, .rkey = resp.rkey, }; ssize_t sret = snprintf(fip_service, NI_MAXSERV, "%u", resp.port); UT_ASSERT(sret > 0); struct rpmem_fip *fip; fip = rpmem_fip_init(info->node, fip_service, &attr, &nlanes); UT_ASSERTne(fip, NULL); ret = rpmem_fip_connect(fip); UT_ASSERTeq(ret, 0); ret = rpmem_fip_process_start(fip); UT_ASSERTeq(ret, 0); ret = rpmem_fip_read(fip, lpool, POOL_SIZE, 0); UT_ASSERTeq(ret, 0); ret = rpmem_fip_process_stop(fip); UT_ASSERTeq(ret, 0); client_close_begin(client); ret = rpmem_fip_close(fip); UT_ASSERTeq(ret, 0); client_close_end(client); rpmem_fip_fini(fip); ret = memcmp(rpool, lpool, POOL_SIZE); UT_ASSERTeq(ret, 0); rpmem_target_free(info); return 3; } /* * test_cases -- available test cases */ static struct test_case test_cases[] = { TEST_CASE(client_init), TEST_CASE(server_init), TEST_CASE(client_connect), TEST_CASE(server_connect), TEST_CASE(client_persist), TEST_CASE(client_persist_mt), TEST_CASE(server_process), TEST_CASE(client_read), }; #define NTESTS (sizeof(test_cases) / sizeof(test_cases[0])) int main(int argc, char *argv[]) { /* workaround for left-opened files by libfabric */ rpmem_fip_probe_get("localhost", NULL); START(argc, argv, "rpmem_obc"); common_init("rpmem_fip", "RPMEM_LOG_LEVEL", "RPMEM_LOG_FILE", 0, 0); rpmem_util_cmds_init(); rpmemd_log_init("rpmemd", getenv("RPMEMD_LOG_FILE"), 0); rpmemd_log_level = rpmemd_log_level_from_str( getenv("RPMEMD_LOG_LEVEL")); TEST_CASE_PROCESS(argc, argv, test_cases, NTESTS); common_fini(); rpmemd_log_close(); rpmem_util_cmds_fini(); DONE(NULL); }