Beispiel #1
0
void fvt_kv_utils_REP_LOOP(ARK       *ark,
                           void*    (*db_create)(uint32_t, uint32_t, uint32_t),
                           uint32_t (*db_regen) (kv_t*,    uint32_t, uint32_t),
                           uint32_t   klen,
                           uint32_t   vlen,
                           uint32_t   len,
                           uint32_t   secs)
{
    uint32_t i          = 0;
    uint32_t start      = 0;
    uint32_t cur        = 0;
    int32_t  LEN        = (int32_t)len;
    kv_t    *db         = NULL;
    uint32_t regen_vlen = vlen;

    ASSERT_TRUE(NULL != ark);
    ASSERT_TRUE(NULL != db_create);
    ASSERT_TRUE(NULL != db_regen);

    db = (kv_t*)db_create(LEN, klen, vlen);
    ASSERT_TRUE(db != NULL);

    start = time(0);

    do
    {
        /* don't regen on first iteration */
        if (i > 0)
        {
            /* regenerate values to each key */
            if (i%2) regen_vlen = vlen+1;
            else     regen_vlen = vlen;
            ASSERT_TRUE(0 == db_regen(db, LEN, regen_vlen));
        }

        /* load/replace all key/value pairs from the db into the ark */
        fvt_kv_utils_load(ark, db, LEN);

        /* query all key/value pairs from the db */
        fvt_kv_utils_query(ark, db, regen_vlen, LEN);

        cur = time(0);
        ++i;
    }
    while (cur-start < secs);

    /* delete all key/value pairs from the db */
    fvt_kv_utils_del(ark, db, LEN);

    kv_db_destroy(db, LEN);
}
Beispiel #2
0
void fvt_kv_utils_SGD_LOOP(ARK     *ark,
                           void*  (*db_create)(uint32_t, uint32_t, uint32_t),
                           uint32_t klen,
                           uint32_t vlen,
                           uint32_t len,
                           uint32_t secs)
{
    uint32_t start = 0;
    uint32_t cur   = 0;
    int32_t  LEN   = (int32_t)len;
    kv_t    *db    = NULL;

    ASSERT_TRUE(NULL != ark);
    ASSERT_TRUE(NULL != db_create);

    start = time(0);

    do
    {
        db = (kv_t*)db_create(LEN, klen, vlen);
        ASSERT_TRUE(db != NULL);

        /* load all key/value pairs from the db into the ark */
        fvt_kv_utils_load(ark, db, LEN);

        /* query all key/value pairs from the db */
        fvt_kv_utils_query(ark, db, vlen, LEN);

        /* delete all key/value pairs from the db */
        fvt_kv_utils_del(ark, db, LEN);

        /* query all key/value pairs from the db */
        fvt_kv_utils_query_empty(ark, db, vlen, LEN);

        kv_db_destroy(db, LEN);

        cur = time(0);
    }
    while (cur-start < secs);
}
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
void kv_async_job_perf(uint32_t jobs, uint32_t klen, uint32_t vlen,uint32_t len)
{
    long int wr_us    = 0;
    long int rd_us    = 0;
    long int mil      = 1000000;
    float    wr_s     = 0;
    float    rd_s     = 0;
    float    wr_mb    = 0;
    float    rd_mb    = 0;
    uint64_t mb64_1   = (uint64_t)KV_1M;
    uint64_t wr_bytes = 0;
    uint64_t rd_bytes = 0;
    uint64_t ops      = 0;
    uint64_t post_ops = 0;
    uint64_t ios      = 0;
    uint64_t post_ios = 0;
    float    wr_ops   = 0;
    float    wr_ios   = 0;
    float    rd_ops   = 0;
    float    rd_ios   = 0;
    uint32_t secs     = 5;
    uint32_t job      = 0;
    struct timeval stop, start;

    kv_async_init_ctxt(0, secs);

    for (job=0; job<jobs; job++)
    {
        kv_async_init_job(KV_ASYNC_CB_SGD|KV_ASYNC_CB_WRITE_PERF,
                          ASYNC_SINGLE_CONTEXT,
                          job, klen+job, vlen, len);
    }
    pCTs->flags |= KV_ASYNC_CT_PERF;

    /* do writes */
    (void)ark_stats(kv_async_get_ark(ASYNC_SINGLE_CONTEXT), &ops, &ios);
    KV_TRC(pFT, "PERF wr: ops:%"PRIu64" ios:%"PRIu64"", ops, ios);
    gettimeofday(&start, NULL);
    kv_async_run_jobs();        /* run write jobs */
    KV_TRC(pFT, "writes done");
    gettimeofday(&stop, NULL);
    wr_us += (stop.tv_sec*mil  + stop.tv_usec) -
             (start.tv_sec*mil + start.tv_usec);
    (void)ark_stats(kv_async_get_ark(ASYNC_SINGLE_CONTEXT),&post_ops,&post_ios);
    KV_TRC(pFT, "PERF wr: ops:%"PRIu64" ios:%"PRIu64"", post_ops, post_ios);
    wr_ops += post_ops - ops;
    wr_ios += post_ios - ios;

    /* calc bytes written */
    for (job=0; job<jobs; job++)
    {
        wr_bytes += (klen+vlen+job)*len*(pCTs->pCBs+job)->perf_loops;
    }

    /* do reads */
    for (job=0; job<jobs; job++)
    {
        if ((pCTs->pCBs+job)->perf_loops)
        {
            (pCTs->pCBs+job)->perf_loops = 0;
            (pCTs->pCBs+job)->flags = KV_ASYNC_CB_GET    |
                                      KV_ASYNC_CB_QUEUED |
                                      KV_ASYNC_CB_READ_PERF;
        }
    }
    pCTs->flags |= KV_ASYNC_CT_RUNNING;

    (void)ark_stats(kv_async_get_ark(0), &ops, &ios);
    KV_TRC(pFT, "PERF rd: ops:%"PRIu64" ios:%"PRIu64"", ops, ios);
    gettimeofday(&start, NULL);
    kv_async_run_jobs();        /* run read jobs */
    gettimeofday(&stop, NULL);
    KV_TRC(pFT, "reads done");
    rd_us += (stop.tv_sec*mil  + stop.tv_usec) -
             (start.tv_sec*mil + start.tv_usec);
    (void)ark_stats(kv_async_get_ark(0), &post_ops, &post_ios);
    KV_TRC(pFT, "PERF rd: ops:%"PRIu64" ios:%"PRIu64"", post_ops, post_ios);
    rd_ops += post_ops - ops;
    rd_ios += post_ios - ios;

    ASSERT_EQ(0, ark_delete(pCTs->ark));

    /* calc bytes read */
    for (job=0; job<jobs; job++)
    {
        rd_bytes += vlen*len*(pCTs->pCBs+job)->perf_loops;
        kv_db_destroy((pCTs->pCBs+job)->db, (pCTs->pCBs+job)->len);
        if ((pCTs->pCBs+job)->gvalue)
            free((pCTs->pCBs+job)->gvalue);
    }

    /* calc and print results */
    wr_s  = (float)((float)wr_us/(float)mil);
    wr_mb = (float)((double)wr_bytes / (double)mb64_1);
    rd_s  = (float)((float)rd_us/(float)mil);
    rd_mb = (float)((double)rd_bytes / (double)mb64_1);

    printf("ASYNC %dx%dx%d writes: %.3d jobs %2.3f mb in %.1f secs at ",
            klen, vlen, len, jobs, wr_mb, wr_s);
    printf("%2.3f mbps, %6.0f op/s, %.0f io/s\n",
            wr_mb/wr_s,
            wr_ops/wr_s,
            wr_ios/wr_s);
    printf("ASYNC %dx%dx%d reads:  %.3d jobs %2.3f mb in %.1f secs at ",
            klen, vlen, len, jobs, rd_mb, rd_s);
    printf("%2.3f mbps, %6.0f op/s, %.0f io/s\n",
            rd_mb/rd_s,
            rd_ops/rd_s,
            rd_ios/rd_s);
}
/**
 *******************************************************************************
 * \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
 ******************************************************************************/
void kv_async_run_jobs(void)
{
    async_CB_t *pCB          = NULL;
    uint32_t    ctxt_running = 0;
    uint32_t    jobs_running = 0;
    uint32_t    i            = 0;
    uint32_t    next         = 0;
    uint32_t    elapse       = 0;
    uint32_t    inject       = 0;
    uint32_t    secs         = 0;
    uint32_t    log_interval = 600;
    uint64_t    ops          = 0;
    uint64_t    ios          = 0;
    uint32_t    tops         = 0;
    uint32_t    tios         = 0;
    uint32_t    perf         = 0;

    KV_TRC(pFT, "ASYNC START: 0 minutes");

    if (!(pCTs->pCBs->flags & KV_ASYNC_CB_RUNNING)) start = time(0);
    next = log_interval;

    do
    {
        ctxt_running = FALSE;

        if (elapse > next)
        {
            KV_TRC(pFT, "ASYNC RUNNING: %d elapsed minutes", elapse/60);
            next += log_interval;
        }

        for (i=0; i<KV_ASYNC_MAX_CONTEXTS; i++)
        {
            if (! (pCTs[i].flags & KV_ASYNC_CT_RUNNING)) continue;

            jobs_running = kv_async_dispatch_jobs(i);

            if (!jobs_running)
            {
                pCTs[i].flags &= ~KV_ASYNC_CT_RUNNING;
                pCTs[i].flags |=  KV_ASYNC_CT_DONE;
                KV_TRC(pFT, "ASYNC DONE ctxt %d %x", i, pCTs[i].flags);
                continue;
            }
            else
            {
                ctxt_running = TRUE;
            }

            elapse = time(0) - start;

            if (elapse >= inject &&
                pCTs[i].flags & KV_ASYNC_CT_ERROR_INJECT)
            {
                KV_TRC_FFDC(pFT, "FFDC: INJECT ERRORS");
                FVT_KV_INJECT_READ_ERROR;
                FVT_KV_INJECT_WRITE_ERROR;
                FVT_KV_INJECT_ALLOC_ERROR;
                ++inject;
            }

            if (elapse >= pCTs[i].secs)
            {
                for (pCB=pCTs[i].pCBs;pCB<pCTs[i].pCBs+KV_ASYNC_JOB_Q;pCB++)
                {
                    if ((pCB->flags & KV_ASYNC_CB_RUNNING ||
                         pCB->flags & KV_ASYNC_CB_QUEUED)
                        &&
                        (!(pCB->flags & KV_ASYNC_CB_SHUTDOWN)) )
                    {
                        pCB->flags |=  KV_ASYNC_CB_SHUTDOWN;
                        KV_TRC_IO(pFT, "SHUTDOWN pCB %p (%d >= %d)", pCB, elapse, pCTs[i].secs);
                    }
                }
            }
            usleep(100);
        }
    }
    while (ctxt_running);

    stop = time(0);
    secs = stop - start;

    KV_TRC(pFT, "ASYNC RUNNING DONE: %d minutes", elapse/60);

    /* log cleanup, since the first ark_delete closes the log file */
    for (i=0; i<KV_ASYNC_MAX_CONTEXTS; i++)
    {
        if (pCTs[i].flags & KV_ASYNC_CT_DONE)
            KV_TRC(pFT, "ASYNC CLEANUP: ctxt:%d ark:%p", i, pCTs[i].ark);
    }

    /* check for MULTI_CTXT_IO, destroy common kv dbs */
    for (pCB=pCTs->pCBs;pCB<pCTs->pCBs+KV_ASYNC_JOB_Q;pCB++)
    {
        if (pCB->flags & KV_ASYNC_CB_MULTI_CTXT_IO)
        {
            kv_db_destroy(pCB->db, pCB->len);
        }
    }

    for (i=0; i<KV_ASYNC_MAX_CONTEXTS; i++)
    {
        /* if this context didn't run any I/O */
        if (! (pCTs[i].flags & KV_ASYNC_CT_DONE)) continue;

        pCTs[i].flags &= ~KV_ASYNC_CT_DONE;

        /* if perf then don't delete the ark here */
        if (pCTs[i].flags & KV_ASYNC_CT_PERF)
        {
            perf = TRUE;
            continue;
        }

        (void)ark_stats(pCTs[i].ark, &ops, &ios);
        tops += (uint32_t)ops;
        tios += (uint32_t)ios;
        KV_TRC(pFT, "PERF ark%p ops:%"PRIu64" ios:%"PRIu64"", pCTs[i].ark, ops, ios);

        EXPECT_EQ(0, ark_delete(pCTs[i].ark));
    }

    if (!perf)
    {
        tops = tops / secs;
        tios = tios / secs;
        printf("op/s:%d io/s:%d secs:%d\n", tops, tios, secs);
        KV_TRC(pFT, "PERF op/s:%d io/s:%d secs:%d",
                tops, tios, secs);
    }
}
Beispiel #6
0
void fvt_kv_utils_perf(ARK *ark, uint32_t vlen, uint32_t mb, uint32_t LEN)
{
    kv_t    *db       = NULL;
    uint64_t mb64_1   = (uint64_t)KV_1M;
    uint64_t bytes    = mb64_1*mb;
    uint32_t i        = 0;
    uint32_t klen     = 16;
    uint64_t lchunk   = LEN*vlen;
    uint32_t loops    = mb;
    long int wr_us    = 0;
    long int rd_us    = 0;
    long int mil      = 1000000;
    float    wr_s     = 0;
    float    rd_s     = 0;
    float    wr_mb    = 0;
    uint64_t ops      = 0;
    uint64_t post_ops = 0;
    uint64_t io       = 0;
    uint64_t post_io  = 0;
    float    wr_ops   = 0;
    float    wr_ios   = 0;
    float    rd_ops   = 0;
    float    rd_ios   = 0;
    struct timeval stop, start;

    ASSERT_TRUE(NULL != ark);

    loops    = (uint32_t)(bytes / lchunk);

    db = (kv_t*)kv_db_create_fixed(LEN, klen, vlen);
    ASSERT_TRUE(db != NULL);

    printf("SYNC %dx%dx%d\n", klen, vlen, LEN);

    for (i=0; i<loops; i++)
    {
        /* write/load all key/value pairs from the db into the ark */
        (void)ark_stats(ark, &ops, &io);
        gettimeofday(&start, NULL);
        fvt_kv_utils_load(ark, db, LEN);
        gettimeofday(&stop, NULL);
        wr_us += (stop.tv_sec*mil  + stop.tv_usec) -
                 (start.tv_sec*mil + start.tv_usec);
        (void)ark_stats(ark, &post_ops, &post_io);
        wr_ops += post_ops - ops;
        wr_ios += post_io  - io;

        /* read/query all key/value pairs from the db */
        (void)ark_stats(ark, &ops, &io);
        gettimeofday(&start, NULL);
        fvt_kv_utils_read(ark, db, vlen, LEN);
        gettimeofday(&stop, NULL);
        rd_us += (stop.tv_sec*mil  + stop.tv_usec) -
                 (start.tv_sec*mil + start.tv_usec);
        (void)ark_stats(ark, &post_ops, &post_io);
        rd_ops += post_ops - ops;
        rd_ios += post_io  - io;

        /* delete all key/value pairs from the db */
        fvt_kv_utils_del(ark, db, LEN);
    }
    wr_s = (float)((float)wr_us/(float)mil);
    rd_s = (float)((float)rd_us/(float)mil);
    wr_mb = (float)((double)(bytes+(uint64_t)(klen*LEN*loops)) / (double)mb64_1);
    printf("   writes: %d mb in %.1f secs at %.3f mbps, %.0f op/s, %.0f io/s\n",
            mb,
            wr_s,
            wr_mb/wr_s,
            wr_ops/wr_s,
            wr_ios/wr_s);
    printf("   reads:  %d mb in %.1f secs at %.3f mbps, %.0f op/s, %.0f io/s\n",
            mb,
            rd_s,
            (float)mb/rd_s,
            rd_ops/rd_s,
            rd_ios/rd_s);
    kv_db_destroy(db, LEN);
}
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
void Sync_pth::run_multi_ctxt_wr(uint32_t  num_ctxt,
                                 uint32_t  num_pth,
                                 uint32_t  npool,
                                 uint32_t  vlen,
                                 uint32_t  LEN,
                                 uint32_t  secs)
{
    uint32_t        i        = 0;
    uint32_t        ctxt_i   = 0;
    uint32_t        pth_i    = 0;
    uint32_t        klen     = 16;
    uint32_t        tot_pth  = num_ctxt * num_pth;
    set_get_args_t  pth_args[tot_pth];
    ARK            *ark[num_ctxt];
    kv_t           *db[num_pth];
    struct timeval  stop, start;
    uint64_t        ops      = 0;
    uint64_t        ios      = 0;
    uint32_t        t_ops    = 0;
    uint32_t        t_ios    = 0;

    if (num_pth > MAX_PTH_PER_CONTEXT)
    {
        printf("cannot exceed %d pthreads for sync ops\n", MAX_PTH_PER_CONTEXT);
        return;
    }

    memset(pth_args, 0, sizeof(set_get_args_t) * tot_pth);

    /* alloc one set of db's, to be used for each context */
    for (i=0; i<num_pth; i++)
    {
        db[i] = (kv_t*)kv_db_create_fixed(LEN, klen+i, vlen+i);
    }
    /* alloc one ark for each context */
    for (ctxt_i=0; ctxt_i<num_ctxt; ctxt_i++)
    {
        ASSERT_EQ(0, ark_create_verbose(getenv("FVT_DEV"), &ark[ctxt_i],
                                        1048576,
                                        4096,
                                        1048576,
                                        npool,
                                        256,
                                        8*1024,
                                        ARK_KV_VIRTUAL_LUN));
        ASSERT_TRUE(NULL != ark[ctxt_i]);
    }

    /* start timer */
    gettimeofday(&start, NULL);

    /* init each pth per context and run the pth */
    ctxt_i = 0;
    i      = 0;
    while (i < tot_pth)
    {
        pth_args[i].ark  = ark[ctxt_i];
        pth_args[i].db   = db[pth_i];
        pth_args[i].vlen = vlen+pth_i;
        pth_args[i].LEN  = LEN;
        pth_args[i].secs = secs;
        run_write_loop(pth_args+i);
        ++pth_i;
        ++i;
        if ((i%num_pth) == 0)
        {
            /* reset for next context */
            ++ctxt_i;
            pth_i = 0;
        }
    }
    printf("SYNC %dx%dx%d ctxt:%d pth:%d npool:%d ",
                     klen, vlen, LEN, num_ctxt, num_pth, npool); fflush(stdout);
    for (i=0; i<tot_pth; i++)
    {
        wait(pth_args+i);
    }

    /* stop timer */
    gettimeofday(&stop, NULL);
    secs = stop.tv_sec - start.tv_sec;

    t_ops = 0;
    t_ios = 0;

    for (i=0; i<num_ctxt; i++)
    {
        (void)ark_stats(ark[i], &ops, &ios);
        t_ops += (uint32_t)ops;
        t_ios += (uint32_t)ios;
        EXPECT_EQ(0, ark_delete(ark[i]));
    }
    for (i=0; i<num_pth; i++)
    {
        kv_db_destroy(db[i], LEN);
    }
    t_ops = t_ops / secs;
    t_ios = t_ios / secs;
    printf("op/s:%d io/s:%d secs:%d\n", t_ops, t_ios, secs);
}
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
TEST(FVT_KV_GOOD_PATH, PERSIST_FIXED_512x128x50000)
{
    ARK     *ark  = NULL;
    kv_t    *fdb  = NULL;
    kv_t    *mdb  = NULL;
    uint32_t klen = 512;
    uint32_t vlen = 128;
    uint32_t LEN  = 50000;
    uint32_t i    = 0;
    int64_t  res  = 0;
    char    *dev  = getenv("FVT_DEV_PERSIST");
    uint8_t  gvalue[vlen];
    struct stat sbuf;

    if (NULL == dev || stat(dev,&sbuf) != 0)
    {
        TESTCASE_SKIP("FVT_DEV_PERSIST==NULL or file not found");
        return;
    }

    printf("create k/v databases\n");
    fflush(stdout);
    fdb = (kv_t*)kv_db_create_fixed(LEN, klen, vlen);
    ASSERT_TRUE(fdb != NULL);
    mdb = (kv_t*)kv_db_create_mixed(LEN, klen-1, vlen);
    ASSERT_TRUE(mdb != NULL);

    printf("create ark\n");
    fflush(stdout);
    ARK_CREATE_NEW_PERSIST;

    printf("run 5 sec mixed REP_LOOP\n");
    fflush(stdout);
    fvt_kv_utils_REP_LOOP(ark,
                          kv_db_create_mixed,
                          kv_db_mixed_regen_values,
                          klen+1,
                          vlen,
                          1000,
                          5);

    printf("load ark with fixed db\n");
    fflush(stdout);
    fvt_kv_utils_load (ark, fdb, LEN);
    printf("query fixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, fdb, vlen, LEN);

    printf("persist ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("re-open ark and read persisted data\n");
    fflush(stdout);
    ARK_CREATE_PERSIST;

    printf("query fixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, fdb, vlen, LEN);

    printf("load ark with the mixed db\n");
    fflush(stdout);
    fvt_kv_utils_load (ark, mdb, LEN);
    printf("query mixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, mdb, vlen, LEN);

    printf("query fixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, fdb, vlen, LEN);
    printf("delete fixed db from ark\n");
    fflush(stdout);
    fvt_kv_utils_del(ark, fdb, LEN);

    printf("re-load ark with the fixed db\n");
    fflush(stdout);
    fvt_kv_utils_load (ark, fdb, LEN);
    printf("query db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, fdb, vlen, LEN);

    printf("delete mixed db from ark\n");
    fflush(stdout);
    fvt_kv_utils_del(ark, mdb, LEN);

    printf("persist ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("re-open ark without LOAD\n");
    fflush(stdout);
    ARK_CREATE_NEW_PERSIST;

    printf("verify ark is empty\n");
    fflush(stdout);

    for (i=0; i<LEN; i++)
    {
        ASSERT_EQ(ENOENT, ark_get(ark,
                                  fdb[i].klen,
                                  fdb[i].key,
                                  fdb[i].vlen,
                                  gvalue,
                                  0,
                                  &res));
    }

    kv_db_destroy(fdb, LEN);
    ARK_DELETE;
}
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
TEST(FVT_KV_GOOD_PATH, PERSIST)
{
    ARK     *ark    = NULL;
    kv_t    *fdb    = NULL;
    kv_t    *mdb    = NULL;
    kv_t    *bdb    = NULL;
    uint32_t klen   = 512;
    uint32_t vlen   = 256;
    uint32_t LEN    = 10000;
    uint32_t BLEN   = 1000;
    uint32_t i      = 0;
    int64_t  res    = 0;
    char    *dev    = getenv("FVT_DEV_PERSIST");
    uint8_t  gvalue[vlen];
    struct stat sbuf;

    if (NULL == dev || stat(dev,&sbuf) != 0)
    {
        TESTCASE_SKIP("FVT_DEV_PERSIST==NULL or file not found");
        return;
    }

    printf("create k/v databases\n");
    fflush(stdout);
    fdb = (kv_t*)kv_db_create_fixed(LEN, klen, vlen);
    ASSERT_TRUE(fdb != NULL);
    bdb = (kv_t*)kv_db_create_fixed(BLEN, klen+1, KV_1M);
    ASSERT_TRUE(bdb != NULL);
    mdb = (kv_t*)kv_db_create_mixed(LEN, klen-1, vlen);
    ASSERT_TRUE(mdb != NULL);

    printf("create new ark\n");
    fflush(stdout);
    ARK_CREATE_NEW_PERSIST;

    printf("delete ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("re-open empty ark\n");
    fflush(stdout);
    ARK_CREATE_PERSIST;

    printf("load ark with fixed db\n");
    fflush(stdout);
    fvt_kv_utils_load (ark, fdb, LEN);
    printf("query fixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, fdb, vlen, LEN);

    printf("delete ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("re-open ark containing fixed db\n");
    fflush(stdout);
    ARK_CREATE_PERSIST;

    printf("run SGD_LOOP on fixed db\n");
    fflush(stdout);
    fvt_kv_utils_SGD_LOOP(ark, kv_db_create_fixed, klen+10, vlen+10,1000,5);

    printf("query fixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, fdb, vlen, LEN);

    printf("delete ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("re-open ark containing fixed db\n");
    fflush(stdout);
    ARK_CREATE_PERSIST;

    printf("load ark with BIG db\n");
    fflush(stdout);
    fvt_kv_utils_load (ark, bdb, BLEN);
    printf("query BIG db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, bdb, KV_1M, BLEN);

    printf("query fixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, fdb, vlen, LEN);

    printf("run REP_LOOP on fixed db\n");
    fflush(stdout);
    fvt_kv_utils_REP_LOOP(ark,
                          kv_db_create_fixed,
                          kv_db_fixed_regen_values,
                          klen+100,
                          vlen,
                          5000,
                          5);

    printf("delete BIG db from ark\n");
    fflush(stdout);
    fvt_kv_utils_del(ark, bdb, BLEN);

    printf("load ark with the mixed db\n");
    fflush(stdout);
    fvt_kv_utils_load(ark, mdb, LEN);
    printf("query mixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, mdb, vlen, LEN);

    printf("delete ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("re-open ark with fixed and mixed db\n");
    fflush(stdout);
    ARK_CREATE_PERSIST;

    printf("query fixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, fdb, vlen, LEN);
    printf("delete fixed db from ark\n");
    fflush(stdout);
    fvt_kv_utils_del(ark, fdb, LEN);

    printf("query mixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, mdb, vlen, LEN);
    printf("delete mixed db from ark\n");
    fflush(stdout);
    fvt_kv_utils_del(ark, mdb, LEN);

    printf("run REP_LOOP on mixed db\n");
    fflush(stdout);
    fvt_kv_utils_REP_LOOP(ark,
                          kv_db_create_mixed,
                          kv_db_mixed_regen_values,
                          klen+256,
                          vlen,
                          100,
                          5);

    printf("load ark with the mixed db\n");
    fflush(stdout);
    fvt_kv_utils_load (ark, mdb, LEN);
    printf("query mixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, mdb, vlen, LEN);

    printf("delete ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("open new ark\n");
    fflush(stdout);
    ARK_CREATE_NEW_PERSIST;

    printf("verify empty\n");
    fflush(stdout);
    for (i=0; i<LEN; i++)
    {
        ASSERT_EQ(ENOENT, ark_get(ark,
                                  mdb[i].klen,
                                  mdb[i].key,
                                  mdb[i].vlen,
                                  gvalue,
                                  0,
                                  &res));
    }

    printf("delete ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("re-open ark as readonly\n");
    fflush(stdout);
    ARK_CREATE_PERSIST_READONLY;

    printf("load ark with the mixed db\n");
    fflush(stdout);
    fvt_kv_utils_load (ark, mdb, LEN);
    printf("query mixed db\n");
    fflush(stdout);
    fvt_kv_utils_query(ark, mdb, vlen, LEN);

    printf("run REP_LOOP on mixed db\n");
    fflush(stdout);
    fvt_kv_utils_REP_LOOP(ark,
                          kv_db_create_mixed,
                          kv_db_mixed_regen_values,
                          klen,
                          vlen,
                          LEN,
                          5);

    printf("delete ark\n");
    fflush(stdout);
    ARK_DELETE;

    printf("open new ark\n");
    fflush(stdout);
    ARK_CREATE_PERSIST;

    printf("verify empty\n");
    fflush(stdout);
    for (i=0; i<LEN; i++)
    {
        ASSERT_EQ(ENOENT, ark_get(ark,
                                  mdb[i].klen,
                                  mdb[i].key,
                                  mdb[i].vlen,
                                  gvalue,
                                  0,
                                  &res));
    }

    printf("delete ark\n");
    fflush(stdout);
    ARK_DELETE;

    kv_db_destroy(fdb, LEN);
    kv_db_destroy(mdb, LEN);
    kv_db_destroy(bdb, BLEN);
}