/** ******************************************************************************* * \brief ******************************************************************************/ static void kv_async_dispatch(async_CB_t *pCB) { uint32_t new_flags = pCB->flags; new_flags &= ~KV_ASYNC_CB_QUEUED; new_flags |= KV_ASYNC_CB_RUNNING; pCB->flags = new_flags; if (pCB->flags & KV_ASYNC_CB_SET) { KV_TRC_IO(pFT, "DISPATCH: SET: %p", pCB); kv_async_SET_KEY(pCB); } else if (pCB->flags & KV_ASYNC_CB_GET) { KV_TRC_IO(pFT, "DISPATCH: GET: %p", pCB); kv_async_GET_KEY(pCB); } else if (pCB->flags & KV_ASYNC_CB_EXISTS) { KV_TRC_IO(pFT, "DISPATCH: EXI: %p", pCB); kv_async_EXISTS_KEY(pCB); } else if (pCB->flags & KV_ASYNC_CB_DEL) { KV_TRC_IO(pFT, "DISPATCH: DEL: %p", pCB); kv_async_DEL_KEY(pCB); } else { EXPECT_TRUE(0); } }
int main(int argc, char **argv) { async_CB_t *pCB = NULL; uint32_t i = 1; uint32_t ctxt = 0; if (1 == argc) { printf("usage: run_kv_async_multi [-p] <dev1> <dev2> ...\n"); printf(" ex: run_kv_async_multi /dev/cxl/afu0.0s /dev/cxl/afu1.0s\n"); printf(" ex: run_kv_async_multi /dev/sdb /dev/sdh /dev/sdq\n"); printf(" ex: run_kv_async_multi -p /dev/sg4 /dev/sg8\n"); exit(0); } bzero(pCTs, sizeof(pCTs)); if (0 == strncmp(argv[1], "-p", 7)) { printf("Attempting to run with physical lun\n"); ark_create_flag = ARK_KV_PERSIST_STORE; KV_ASYNC_CTXT_PER_DEV = 1; i = 2; } else { //KV_ASYNC_CTXT_PER_DEV = 1; KV_ASYNC_CTXT_PER_DEV = 4; KV_ASYNC_JOBS_PER_CTXT = 60; } while (argv[i] != NULL && KV_ASYNC_CONTEXTS <= KV_ASYNC_MAX_CONTEXTS) { kv_async_init_io(argv[i++], KV_ASYNC_JOBS_PER_CTXT, KV_ASYNC_KLEN, KV_ASYNC_VLEN, KV_ASYNC_NUM_KV); KV_ASYNC_CONTEXTS += KV_ASYNC_CTXT_PER_DEV; } start = time(0); /* start all jobs for all contexts */ for (ctxt=0; ctxt<KV_ASYNC_CONTEXTS; ctxt++) { for (pCB=pCTs[ctxt].pCBs; pCB<pCTs[ctxt].pCBs+KV_ASYNC_JOBS_PER_CTXT; pCB++) { pCB->flags |= KV_ASYNC_RUNNING; kv_async_SET_KEY(pCB); } } kv_async_wait_jobs(); return 0; }
/** ******************************************************************************* * \brief * callback function for set/get/exists/del ******************************************************************************/ static void kv_async_cb(int errcode, uint64_t dt, int64_t res) { async_CB_t *pCB = (async_CB_t*)dt; kv_t *p_kv = NULL; uint64_t tag = (uint64_t)pCB; if (pCB == NULL) { KV_TRC_FFDC(pFT, "FFDC: pCB NULL"); return; } if (pCB->b_mark != B_MARK) { KV_TRC_FFDC(pFT, "FFDC: B_MARK FAILURE %p: %"PRIx64"", pCB, pCB->b_mark); return; } if (pCB->e_mark != E_MARK) { KV_TRC_FFDC(pFT, "FFDC: E_MARK FAILURE %p: %"PRIx64"", pCB, pCB->e_mark); return; } if (EBUSY == errcode) {kv_async_q_retry(pCB); goto done;} if (IS_GTEST) { EXPECT_EQ(0, errcode); EXPECT_EQ(tag, pCB->tag); } p_kv = pCB->db + pCB->len_i; ++pCB->len_i; if (pCB->flags & KV_ASYNC_CB_SET) { KV_TRC_IO(pFT, "KV_ASYNC_CB_SET, %p %d %d", pCB, pCB->len_i, pCB->len); if (0 != errcode) printf("ark_set failed, errcode=%d\n", errcode); if (tag != pCB->tag) printf("ark_set bad tag\n"); if (res != p_kv->vlen) printf("ark_set bad vlen\n"); if (IS_GTEST) { EXPECT_EQ(res, p_kv->vlen);} /* end of db len sequence, move to next step */ if (pCB->len_i == pCB->len) { if (pCB->flags & KV_ASYNC_CB_WRITE_PERF) { pCB->len_i = 0; kv_async_perf_done(pCB); goto done; } pCB->len_i = 0; pCB->flags &= ~KV_ASYNC_CB_SET; pCB->flags |= KV_ASYNC_CB_GET; kv_async_GET_KEY(pCB); goto done; } kv_async_SET_KEY(pCB); goto done; } else if (pCB->flags & KV_ASYNC_CB_GET) { uint32_t miscompare = memcmp(p_kv->value, pCB->gvalue, p_kv->vlen); KV_TRC_IO(pFT, "KV_ASYNC_CB_GET, %p %d %d", pCB, pCB->len_i, pCB->len); if (0 != errcode) printf("ark_get failed, errcode=%d\n", errcode); if (tag != pCB->tag) printf("ark_get bad tag\n"); if (res != p_kv->vlen) printf("ark_get bad vlen\n"); if (IS_GTEST) { EXPECT_EQ(0, miscompare);} /* end of db len sequence, move to next step */ if (pCB->len_i == pCB->len) { if (pCB->flags & KV_ASYNC_CB_READ_PERF) { pCB->len_i = 0; kv_async_perf_done(pCB); goto done; } pCB->len_i = 0; pCB->flags &= ~KV_ASYNC_CB_GET; pCB->flags |= KV_ASYNC_CB_EXISTS; kv_async_EXISTS_KEY(pCB); goto done; } kv_async_GET_KEY(pCB); goto done; } else if (pCB->flags & KV_ASYNC_CB_EXISTS) { KV_TRC_IO(pFT, "KV_ASYNC_CB_EXISTS, %p %d %d", pCB, pCB->len_i, pCB->len); if (0 != errcode) printf("ark_exists failed,errcode=%d\n",errcode); if (tag != pCB->tag) printf("ark_exists bad tag\n"); if (res != p_kv->vlen) printf("ark_exists bad vlen\n"); if (IS_GTEST) { EXPECT_EQ(res, p_kv->vlen);} /* if end of db len sequence, move to next step */ if (pCB->len_i == pCB->len) { pCB->len_i = 0; pCB->flags &= ~KV_ASYNC_CB_EXISTS; if (pCB->flags & KV_ASYNC_CB_SGD) { pCB->flags |= KV_ASYNC_CB_DEL; kv_async_DEL_KEY(pCB); goto done; } else if (pCB->flags & KV_ASYNC_CB_REPLACE) { /* make sure we don't shutdown before we have replaced once */ if (pCB->replace && pCB->flags & KV_ASYNC_CB_SHUTDOWN) { pCB->flags |= KV_ASYNC_CB_DEL; kv_async_DEL_KEY(pCB); goto done; } pCB->replace = TRUE; if (0 != pCB->regen(pCB->db, pCB->len, pCB->regen_len)) { printf("regen failure, fatal\n"); KV_TRC_FFDC(pFT, "FFDC: regen failure"); memset(pCB, 0, sizeof(async_CB_t)); goto done; } pCB->flags |= KV_ASYNC_CB_SET; kv_async_SET_KEY(pCB); goto done; } else { /* should not be here */ EXPECT_TRUE(0); } } kv_async_EXISTS_KEY(pCB); goto done; } else if (pCB->flags & KV_ASYNC_CB_DEL) { KV_TRC_IO(pFT, "KV_ASYNC_CB_DEL, %p i:%d len:%d", pCB, pCB->len_i,pCB->len); if (0 != errcode) printf("ark_del failed, errcode=%d\n",errcode); if (tag != pCB->tag) printf("ark_del bad tag\n"); if (res != p_kv->vlen) printf("ark_del bad vlen\n"); if (IS_GTEST) { EXPECT_EQ(res, p_kv->vlen);} /* end of db len sequence, move to next step */ if (pCB->len_i == pCB->len) { if (pCB->flags & KV_ASYNC_CB_SHUTDOWN) { if (!(pCB->flags & KV_ASYNC_CB_MULTI_CTXT_IO)) { kv_db_destroy(pCB->db, pCB->len); } if (pCB->gvalue) free(pCB->gvalue); memset(pCB, 0, sizeof(async_CB_t)); KV_TRC_IO(pFT, "LOOP_DONE: %p", pCB); goto done; } KV_TRC_IO(pFT, "NEXT_LOOP, %p", pCB); pCB->flags &= ~KV_ASYNC_CB_DEL; pCB->flags |= KV_ASYNC_CB_SET; pCB->len_i = 0; kv_async_SET_KEY(pCB); goto done; } kv_async_DEL_KEY(pCB); goto done; } else { /* should not be here */ EXPECT_TRUE(0); } done: return; }
/** ******************************************************************************** ** \brief ** do an ark asynchronous IO performance run *******************************************************************************/ void kv_async_io(char *dev, uint32_t ctxts, uint32_t jobs, uint32_t vlen, uint32_t len, uint32_t read) { async_context_t *pCT = NULL; async_CB_t *pCB = NULL; uint32_t job = 0; uint32_t ctxt = 0; uint32_t ctxt_running = 0; uint32_t i = 0; uint32_t e_secs = 0; uint64_t ops = 0; uint64_t ios = 0; uint32_t tops = 0; uint32_t tios = 0; if (read == 75) read100 = FALSE; else read100 = TRUE; printf("ASYNC: ctxt:%-2d QD:%-3d size:%2dk read:%3d%% ", ctxts, jobs, vlen/1000, read); fflush(stdout); init_kv_db(jobs, KLEN, vlen, len); pCTs = (async_context_t*) malloc(ctxts*sizeof(async_context_t)); assert(0 != pCTs); for (ctxt=0; ctxt<ctxts; ctxt++) { ARK *ark = NULL; pCT = pCTs+ctxt; memset(pCT, 0, sizeof(async_context_t)); NEW_ARK(dev, &ark); pCT->ark = ark; for (job=0; job<jobs; job++) { pCB = pCT->pCBs+job; pCB->itag = SET_ITAG(ctxt,job); pCB->ark = pCT->ark; pCB->flags = KV_ASYNC_SET; pCB->db = dbs+job; pCB->len = len; } } testcase_start = time(0); /* start all jobs for all contexts */ for (ctxt=0; ctxt<ctxts; ctxt++) { for (pCB=pCTs[ctxt].pCBs; pCB<pCTs[ctxt].pCBs+jobs; pCB++) { pCB->flags |= KV_ASYNC_RUNNING; kv_async_SET_KEY(pCB); } } /* loop until all jobs are done or until time elapses */ do { ctxt_running = FALSE; /* loop through contexts(arks) and check if all jobs are done or * time has elapsed */ for (i=0; i<ctxts; i++) { /* check if all jobs are done */ for (pCB=pCTs[i].pCBs;pCB<pCTs[i].pCBs+jobs;pCB++) { if (pCB->flags & KV_ASYNC_RUNNING) { ctxt_running = TRUE; } } if (!ctxt_running) continue; /* check if time has elapsed */ if (time(0) - testcase_start < KV_MIN_SECS) continue; for (pCB=pCTs[i].pCBs;pCB<pCTs[i].pCBs+jobs;pCB++) { if (pCB->flags & KV_ASYNC_RUNNING && (!(pCB->flags & KV_ASYNC_SHUTDOWN)) ) { pCB->flags |= KV_ASYNC_SHUTDOWN; } } } } while (ctxt_running); testcase_stop = time(0); e_secs = testcase_stop - testcase_start; /* sum perf ops for all contexts/jobs and delete arks */ for (i=0; i<ctxts; i++) { (void)ark_stats(pCTs[i].ark, &ops, &ios); tops += (uint32_t)ops; tios += (uint32_t)ios; } tops = tops / e_secs; tios = tios / e_secs; printf("op/s:%-7d io/s:%-7d secs:%d\n", tops, tios, e_secs); /* sum perf ops for all contexts/jobs and delete arks */ for (i=0; i<ctxts; i++) { assert(0 == ark_delete(pCTs[i].ark)); } free_kv_db(jobs, len); }
/** ******************************************************************************** ** \brief ** callback for ark functions: set,get,exists,del *******************************************************************************/ void kv_async_cb(int errcode, uint64_t dt, int64_t res) { async_context_t *pCT = pCTs+GET_CTXT(dt); async_CB_t *pCB = NULL; kv_t *p_kv = NULL; if (NULL == pCT) KV_ERR_STOP(pCB, "bad dt: ctxt", 0); pCB = pCT->pCBs+GET_CB(dt); if (NULL == pCB) KV_ERR_STOP(pCB, "bad dt: cb", 0); if (0 != errcode) KV_ERR_STOP(pCB, "bad errcode", errcode); if (dt != pCB->tag) KV_ERR_STOP(pCB, "bad tag", 0); if (res != pCB->db->vlen) KV_ERR_STOP(pCB, "bad res", 0); p_kv = pCB->db->kv + pCB->len_i; ++pCB->len_i; if (pCB->flags & KV_ASYNC_SET) { /* end of db len sequence, move to next step */ if (pCB->len_i == pCB->len) { pCB->len_i = 0; pCB->flags &= ~KV_ASYNC_SET; pCB->flags |= KV_ASYNC_GET; kv_async_GET_KEY(pCB); goto done; } kv_async_SET_KEY(pCB); goto done; } else if (pCB->flags & KV_ASYNC_GET) { if (0 != memcmp(p_kv->value, pCB->gvalue, pCB->db->vlen)) { KV_ERR_STOP(pCB,"get miscompare",0); } /* end of db len sequence, move to next step */ if (pCB->len_i == pCB->len) { pCB->len_i = 0; if (read100 && !(pCB->flags & KV_ASYNC_SHUTDOWN)) { kv_async_GET_KEY(pCB); } else { pCB->flags &= ~KV_ASYNC_GET; pCB->flags |= KV_ASYNC_EXISTS; kv_async_EXISTS_KEY(pCB); } goto done; } kv_async_GET_KEY(pCB); goto done; } else if (pCB->flags & KV_ASYNC_EXISTS) { /* if end of db len sequence, move to next step */ if (pCB->len_i == pCB->len) { pCB->len_i = 0; pCB->flags &= ~KV_ASYNC_EXISTS; pCB->flags |= KV_ASYNC_DEL; kv_async_DEL_KEY(pCB); goto done; } kv_async_EXISTS_KEY(pCB); goto done; } else if (pCB->flags & KV_ASYNC_DEL) { /* end of db len sequence, move to next step */ if (pCB->len_i == pCB->len) { if (pCB->flags & KV_ASYNC_SHUTDOWN) { pCB->flags &= ~KV_ASYNC_RUNNING; goto done; } pCB->flags &= ~KV_ASYNC_DEL; pCB->flags |= KV_ASYNC_SET; pCB->len_i = 0; kv_async_SET_KEY(pCB); goto done; } kv_async_DEL_KEY(pCB); goto done; } else { /* should not be here */ assert(0); } done: return; }