void init_kv_db(void)
{
    uint32_t i,j;
    uint64_t *p,tag;

    assert(8 <= KV_ASYNC_KLEN && 0 == KV_ASYNC_KLEN%8);
    assert(8 <= KV_ASYNC_VLEN && 0 == KV_ASYNC_VLEN%8);

    /* ensure unique keys for each k/v in all dbs */
    for (i=0; i<KV_ASYNC_JOBS_PER_CTXT; i++)
    {
        for (j=0; j<KV_ASYNC_NUM_KV; j++)
        {
            for (p=(uint64_t*)(dbs[i].db[j].key);
                 p<(uint64_t*)(dbs[i].db[j].key+KV_ASYNC_KLEN);
                 p++)
            {
                tag = SET_ITAG(0xfeed,i);
                *p=tag+j;
            }
            for (p=(uint64_t*)(dbs[i].db[j].value);
                 p<(uint64_t*)(dbs[i].db[j].value+KV_ASYNC_VLEN);
                 p++)
            {
                tag = SET_ITAG(0xfeed,i);
                *p=tag+j;
            }
        }
    }
}
void kv_async_init_io(char    *dev,
                      uint32_t jobs,
                      uint32_t klen,
                      uint32_t vlen,
                      uint32_t LEN)
{
    async_context_t *pCT     = NULL;
    async_CB_t      *pCB     = NULL;
    uint32_t         job     = 0;
    uint32_t         ctxt    = 0;

    printf("dev:%s ctxt:%d async_ops:%d k/v:%dx%d: \n",
            dev, KV_ASYNC_CTXT_PER_DEV, jobs, klen, vlen);
    fflush(stdout);

    init_kv_db();

    for (ctxt=KV_ASYNC_CONTEXTS;
         ctxt<KV_ASYNC_CONTEXTS+KV_ASYNC_CTXT_PER_DEV; ctxt++)
    {
        pCT = pCTs+ctxt;
        assert(0 == ark_create(dev, &pCT->ark, ark_create_flag));
        assert(NULL != pCT->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].db;
            pCB->len       = LEN;
        }
    }
}
/**
********************************************************************************
** \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);
}