Ejemplo n.º 1
0
int ea_delete(EA *ea)
{
    int rc = 0;

    if ( ea->st_type == EA_STORE_TYPE_MEMORY )
    {
        KV_TRC(pAT, "free ea %p ea->st_memory %p", ea, ea->st_memory);
        // Simple free the block of store
        if (ea->st_memory)
        {
            free(ea->st_memory);
            ea->st_memory=NULL;
        }
    }
    else
    {
        // Call to close out the chunk and free the space
        // for the device name
        rc = cblk_close(ea->st_flash, 0);
        am_free(ea->st_device);
    }

    if ( rc == 0 )
    {
        KV_TRC(pAT, "free ea %p", ea);
        am_free(ea);
    }

    return rc;
}
Ejemplo n.º 2
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
uint32_t kv_async_init_perf_io(uint32_t num_ctxt,
                               uint32_t jobs,
                               uint32_t npool,
                               uint32_t klen,
                               uint32_t vlen,
                               uint32_t LEN,
                               uint32_t secs)
{
    uint32_t job  = 0;
    uint32_t ctxt = 0;
    kv_t    *db[jobs];

    printf("ASYNC %dx%dx%d", klen, vlen, LEN); fflush(stdout);
    for (job=0; job<jobs; job++)
    {
        db[job] = (kv_t*)kv_db_create_fixed(LEN, klen+job, vlen);
    }
    printf("."); fflush(stdout);
    for (ctxt=0; ctxt<num_ctxt; ctxt++)
    {
        if (kv_async_init_ctxt_perf(ctxt, npool, secs)) return ENOMEM;

        for (job=0; job<jobs; job++)
        {
            kv_async_set_job(KV_ASYNC_CB_SGD           |
                             KV_ASYNC_CB_MULTI_CTXT_IO |
                             KV_ASYNC_CB_GTEST,
                             ctxt, job, db[job], vlen, LEN);
            KV_TRC(pFT, "CREATE_JOB FIXED %dx%dx%d", klen+job, vlen, LEN);
        }
    }
    printf("> "); fflush(stdout);
    return 0;
}
Ejemplo n.º 3
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
void kv_async_init_ark_io(uint32_t num_ctxt,
                          uint32_t jobs,
                          uint32_t vlen,
                          uint32_t secs)
{
    uint32_t klen     = 16;
    uint32_t LEN      = 50;
    uint32_t job      = 0;
    uint32_t ctxt     = 0;
    kv_t    *db[jobs];

    printf("ctxt:%d jobs:%d ASYNC %dx%dx%d",
            num_ctxt, jobs, klen, vlen, LEN); fflush(stdout);
    for (job=0; job<jobs; job++)
    {
        db[job] = (kv_t*)kv_db_create_fixed(LEN, klen+job, vlen);
    }
    printf("."); fflush(stdout);
    for (ctxt=0; ctxt<num_ctxt; ctxt++)
    {
        kv_async_init_ctxt(ctxt, secs);

        for (job=0; job<jobs; job++)
        {
            kv_async_set_job(KV_ASYNC_CB_SGD | KV_ASYNC_CB_MULTI_CTXT_IO,
                             ctxt, job, db[job], vlen, LEN);
            KV_TRC(pFT, "CREATE_JOB FIXED %dx%dx%d", klen+job, vlen, LEN);
        }
    }
    printf("> "); fflush(stdout);
}
Ejemplo n.º 4
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
void kv_async_init_ctxt(uint32_t ctxt, uint32_t secs)
{
    char            *env_FVT = getenv("FVT_DEV");
    async_context_t *pCT     = pCTs+ctxt;

    if (ctxt < 0 || ctxt > KV_ASYNC_MAX_CONTEXTS)
    {
        printf("FFDC: kv_async_init_ctxt %d %X\n", ctxt, ctxt);
        return;
    }
    memset(pCT,       0, sizeof(async_context_t));
    memset(pCT->pCBs, 0, sizeof(async_CB_t)*KV_ASYNC_JOB_Q);

    ASSERT_EQ(0, ark_create_verbose(env_FVT, &pCT->ark,
                                    1048576,
                                    4096,
                                    1048576,
                                    20,
                                    256,
                                    8*1024,
                                    ARK_KV_VIRTUAL_LUN));
    ASSERT_TRUE(NULL != pCT->ark);

    pCT->flags |= KV_ASYNC_CT_RUNNING;
    pCT->secs   = secs;
    KV_TRC(pFT, "init_ctxt ctxt:%d ark:%p secs:%d", ctxt, pCT->ark, pCT->secs);
}
Ejemplo n.º 5
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
void kv_async_set_job(uint32_t  flags,
                      uint32_t  ctxt,
                      uint32_t  job,
                      kv_t     *db,
                      uint32_t  vlen,
                      uint32_t  len)
{
    async_context_t *pCT     = pCTs+ctxt;
    async_CB_t      *pCB     = NULL;
    char             type[4] = {0};

    ASSERT_TRUE(NULL != pCT);
    ASSERT_TRUE(ctxt >= 0);
    ASSERT_TRUE(ctxt < KV_ASYNC_MAX_CONTEXTS);
    ASSERT_TRUE(0 != len);

    if (flags & KV_ASYNC_CB_SGD) sprintf(type, "SGD");
    else                         sprintf(type, "REP");

    pCB            = pCT->pCBs+job; memset(pCB, 0, sizeof(async_CB_t));
    pCB->ark       = pCT->ark;
    pCB->flags     = flags | KV_ASYNC_CB_SET | KV_ASYNC_CB_QUEUED;
    pCB->db        = db;
    pCB->regen     = kv_db_fixed_regen_values;
    pCB->len       = len;
    pCB->cb        = kv_async_cb;
    pCB->regen_len = vlen;
    pCB->gvalue    = (char*)malloc(pCB->regen_len);
    pCB->b_mark    = B_MARK;
    pCB->e_mark    = E_MARK;

    KV_TRC(pFT, "CREATE_JOB: ctxt:%d ark:%p %s:   pCB:%p flags:%X",
       ctxt, pCT->ark, type, pCB, pCB->flags);
}
Ejemplo n.º 6
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
IV *iv_new(uint64_t n, uint64_t m) {

  uint64_t bits  = n * m;
  uint64_t words = divup(bits, 64);
  uint64_t bytes = sizeof(IV) + words * sizeof(uint64_t);

  IV *iv = am_malloc(bytes);
  if (iv == NULL)
  {
    errno = ENOMEM;
    KV_TRC_FFDC(pAT, "FFDC: n %"PRIu64" m %"PRIu64", errno = %d", n, m, errno);
  }
  else
  {
    memset(iv,0x00, bytes);
    iv->n      =  n;
    iv->m      = m;
    iv->bits   = bits;
    iv->words  = words;
    iv->mask   = 1;
    iv->mask <<= m;
    iv->mask  -= 1;
    iv->bar    = 64 - m;
  }
  KV_TRC(pAT, "iv:%p n:%ld m:%ld", iv, n, m);
  return iv;
}
Ejemplo n.º 7
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
uint32_t kv_async_init_ctxt_perf(uint32_t ctxt, uint32_t npool, uint32_t secs)
{
    char            *env_FVT = getenv("FVT_DEV");
    async_context_t *pCT     = pCTs+ctxt;

    if (ctxt < 0 || ctxt > KV_ASYNC_MAX_CONTEXTS)
    {
        printf("FFDC: kv_async_init_ctxt %d %X\n", ctxt, ctxt);
        return EINVAL;
    }
    memset(pCT,       0, sizeof(async_context_t));
    memset(pCT->pCBs, 0, sizeof(async_CB_t)*KV_ASYNC_JOB_Q);

    if (ark_create_verbose(env_FVT, &pCT->ark,
                                        1048576,
                                        4096,
                                        1048576,
                                        npool,
                                        256,
                                        8*1024,
                                        ARK_KV_VIRTUAL_LUN))
    {
        printf("ark_create failed for ctxt:%d\n", ctxt);
        return ENOMEM;
    }
    if (NULL == pCT->ark) return ENOMEM;

    pCT->flags |= KV_ASYNC_CT_RUNNING;
    pCT->secs   = secs;
    KV_TRC(pFT, "init_ctxt ctxt:%d ark:%p", ctxt, pCT->ark);
    return 0;
}
Ejemplo n.º 8
0
void ark_persistence_calc(_ARK *_arkp)
{
  uint64_t bytes = 0;

  // We need to determine the total size of the data
  // that needs to be persisted.  Items that we persist
  // are:
  //
  // - Configuration
  // - Hash Table (hash_t)
  // - Block List (BL)
  // - IV->data

  // Configuration
  _arkp->pers_cs_bytes = sizeof(p_cntr_t) + sizeof(P_ARK_t);

  // Hash Table
  _arkp->pers_cs_bytes += sizeof(hash_t) + (_arkp->ht->n * sizeof(uint64_t));

  // Block List
  _arkp->pers_cs_bytes += sizeof(BL);

  // calculate for a full ark
  bytes  = _arkp->pers_cs_bytes;
  bytes += _arkp->bl->list->words * sizeof(uint64_t);
  _arkp->pers_max_blocks = divup(bytes, _arkp->bsize);

  KV_TRC(pAT, "PERSIST_CALC pers_cs_bytes:%ld pers_max_blocks:%ld",
          _arkp->pers_cs_bytes, _arkp->pers_max_blocks);
  return;
}
Ejemplo n.º 9
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
void kv_async_init_job(uint32_t  flags,
                       uint32_t  ctxt,
                       uint32_t  job,
                       uint32_t  klen,
                       uint32_t  vlen,
                       uint32_t  len)
{
    kv_t *db = (kv_t*)kv_db_create_fixed(len, klen, vlen);
    ASSERT_TRUE(NULL != db);

    KV_TRC(pFT, "CREATE_JOB FIXED %dx%dx%d", klen, vlen, len);

    kv_async_set_job(flags|KV_ASYNC_CB_GTEST, ctxt, job, db, vlen, len);
}
Ejemplo n.º 10
0
/**
 *******************************************************************************
 * \brief
 ******************************************************************************/
static void kv_async_perf_done(async_CB_t *pCB)
{
    ++pCB->perf_loops;

    if (pCB->flags & KV_ASYNC_CB_SHUTDOWN)
    {
        KV_TRC(pFT, "shutdown %p %d", pCB, pCB->perf_loops);

        pCB->flags &= ~(KV_ASYNC_CB_SET        |
                        KV_ASYNC_CB_GET        |
                        KV_ASYNC_CB_WRITE_PERF |
                        KV_ASYNC_CB_READ_PERF  |
                        KV_ASYNC_CB_RUNNING);
        return;
    }

    kv_async_dispatch(pCB);
}
Ejemplo n.º 11
0
/**
 *******************************************************************************
 * \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);
    }
}
Ejemplo n.º 12
0
/**
 *******************************************************************************
 * \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);
}
Ejemplo n.º 13
0
EA *ea_new(const char *path, uint64_t bsize, int basyncs,
           uint64_t *size, uint64_t *bcount, uint64_t vlun)
{
    int             rc    = 0;
    size_t          plen  = 0;
    uint8_t        *store = NULL;
    EA             *ea    = NULL;
    chunk_id_t      chkid = NULL_CHUNK_ID;
    chunk_ext_arg_t ext   = 0;

    if (!(fetch_and_or(&cflsh_blk_lib_init,1)))
    {
        // We need to call cblk_init once before
        // we use any other cblk_ interfaces
        rc = cblk_init(NULL,0);
        if (rc)
        {
            KV_TRC_FFDC(pAT, "cblk_init failed path %s bsize %"PRIu64" "
                             "size %"PRIu64" bcount %"PRIu64", errno = %d",
                             path, bsize, *size, *bcount, errno);
            goto error_exit;
        }
    }

    ea = am_malloc(sizeof(EA));
    if (NULL == ea)
    {
        KV_TRC_FFDC(pAT, "Out of memory path %s bsize %"PRIu64" size %"PRIu64" "
                         "bcount %"PRIu64", errno = %d",
                         path, bsize, *size, *bcount, errno);
        goto error_exit;
    }

    // We need to check the path parameter to see if
    // we are going to use memory or a file/capi
    // device (to be determined by the block layer)
    if ( (NULL == path) || (strlen(path) == 0) )
    {
        KV_TRC(pAT, "EA_STORE_TYPE_MEMORY");
        // Using memory for store
        ea->st_type = EA_STORE_TYPE_MEMORY;

        store = malloc(*size);
        if (NULL == store)
        {
            errno = ENOMEM;
            KV_TRC_FFDC(pAT, "Out of memory for store path %s bsize %"PRIu64" "
                             "size %"PRIu64" bcount %"PRIu64", errno = %d",
                             path, bsize, *size, *bcount, errno);
            goto error_exit;
        }

        *bcount = ((*size) / bsize);
        ea->st_memory = store;
    }
    else
    {
        KV_TRC(pAT, "EA_STORE_TYPE_FILE(%s)", path);

        // Using a file.  We don't care if it's an actual
        // file or a CAPI device, we let block layer
        // decide and we just use the chunk ID that is
        // passed back from the cblk_open call.
        ea->st_type = EA_STORE_TYPE_FILE;

        // Check to see if we need to create the store on a
        // physical or virtual LUN.  Previously, in GA1,
        // we keyed off the size and if it was 0, then we
        // asked for the LUN to be physical.  Now, the user
        // can specify with a flag.
        if ( vlun == 0 )
        {
            KV_TRC(pAT, "cblk_open PHYSICAL LUN: %s", path);
            chkid = cblk_open(path, basyncs, O_RDWR, ext,
                              CBLK_OPN_NO_INTRP_THREADS);

            if (NULL_CHUNK_ID == chkid)
            {
                printf("cblk_open physical lun failed\n");
                KV_TRC_FFDC(pAT, "cblk_open phys lun failed path:%s bsize:%ld "
                                 "size:%ld bcount:%ld, errno:%d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            rc = cblk_get_size(chkid, (size_t *)bcount, 0);
            if ( (rc != 0) || (*bcount == 0) )
            {
                // An error was encountered, close the chunk
                cblk_close(chkid, 0);
                chkid = NULL_CHUNK_ID;
                KV_TRC_FFDC(pAT, "cblk_get_size failed path %s bsize %"PRIu64" "
                                 "size %"PRIu64" bcount %"PRIu64", errno = %d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            // Set the size to be returned
            *size = *bcount * bsize;
        }
        else
        {
            KV_TRC(pAT, "cblk_open VIRTUAL LUN: %s", path);
            chkid = cblk_open(path, basyncs, O_RDWR, ext,
                              CBLK_OPN_VIRT_LUN|CBLK_OPN_NO_INTRP_THREADS);

            if (NULL_CHUNK_ID == chkid)
            {
                printf("cblk_open virtual lun failed\n");
                KV_TRC_FFDC(pAT, "cblk_open virt lun failed path:%s bsize:%ld "
                                 "size:%ld bcount:%ld, errno:%d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            // A specific size was passed in so we try to set the
            // size of the chunk.
            *bcount = *size / bsize;
            rc = cblk_set_size(chkid, (size_t)*bcount, 0);
            if ( rc != 0 )
            {
                printf("cblk_set_size failed for %ld\n", *bcount);
                // An error was encountered, close the chunk
                cblk_close(chkid, 0);
                chkid = NULL_CHUNK_ID;
                KV_TRC_FFDC(pAT, "cblk_set_size failed path %s bsize %"PRIu64" "
                                 "size %"PRIu64" bcount %"PRIu64", errno = %d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }
        }

        // Save off the chunk ID and the device name
        ea->st_flash  = chkid;
        plen          = strlen(path) + 1;
        ea->st_device = (char *)am_malloc(plen);
        if (!ea->st_device)
        {
            cblk_close(chkid, 0);
            KV_TRC_FFDC(pAT, "MALLOC st_device failed (%s) plen=%ld errno:%d",
                        path, plen, errno);
            goto error_exit;
        }

        memset(ea->st_device, 0, plen);
        strncpy(ea->st_device, path, plen);
    }

    // Fill in the EA struct
    pthread_rwlock_init(&(ea->ea_rwlock), NULL);
    ea->bsize  = bsize;
    ea->bcount = *bcount;
    ea->size   = *size;

    KV_TRC(pAT, "path %s bsize %"PRIu64" size %"PRIu64" bcount %"PRIu64"",
           path, bsize, *size, *bcount);
    goto done;

error_exit:
    am_free(ea);
    ea = NULL;
    if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOSPC;}

done:
    return ea;
}
Ejemplo n.º 14
0
int ark_delete(ARK *ark) {
  int rc = 0;
  int i = 0;
  _ARK *_arkp = (_ARK *)ark;
  scb_t *scbp = NULL;

  if (NULL == ark)
  {
    rc = EINVAL;
    KV_TRC_FFDC(pAT, "Invalid ARK control block parameter: %d", rc);
    goto ark_delete_ark_err;
  }

  // Wait for all active threads to exit
  for (i = 0; i < _arkp->nthrds; i++)
  {
      scbp = &(_arkp->poolthreads[i]);
      scbp->poolstate = PT_EXIT;

      queue_lock(scbp->rqueue);
      queue_wakeup(scbp->rqueue);
      queue_unlock(scbp->rqueue);

      pthread_join(scbp->pooltid, NULL);

      queue_free(scbp->rqueue);
      queue_free(scbp->tqueue);
      queue_free(scbp->ioqueue);

      pthread_mutex_destroy(&(scbp->poolmutex));
      pthread_cond_destroy(&(scbp->poolcond));
      KV_TRC(pAT, "thread %d joined", i);
  }

  if (_arkp->poolthreads) am_free(_arkp->poolthreads);

  if (_arkp->pts) am_free(_arkp->pts);

  for ( i = 0; i < _arkp->nasyncs ; i++ )
  {
    pthread_cond_destroy(&(_arkp->rcbs[i].acond));
    pthread_mutex_destroy(&(_arkp->rcbs[i].alock));
  }

  for ( i = 0; i < _arkp->ntasks; i++ )
  {

    bt_delete(_arkp->tcbs[i].inb);
    bt_delete(_arkp->tcbs[i].oub);
    am_free(_arkp->tcbs[i].vb_orig);
  }

  if (_arkp->iocbs)
  {
    am_free(_arkp->iocbs);
  }

  if (_arkp->tcbs)
  {
    am_free(_arkp->tcbs);
  }

  if (_arkp->rcbs)
  {
    am_free(_arkp->rcbs);
  }

  if (_arkp->ttags)
  {
    tag_free(_arkp->ttags);
  }

  if (_arkp->rtags)
  {
    tag_free(_arkp->rtags);
  }

  if (!(_arkp->flags & ARK_KV_VIRTUAL_LUN))
  {
    rc = ark_persist(_arkp);
    if ( rc != 0 )
    {
      KV_TRC_FFDC(pAT, "FFDC: ark_persist failed: %d", rc);
    }
  }

  pthread_mutex_destroy(&_arkp->mainmutex);

  (void)ea_delete(_arkp->ea);
  hash_free(_arkp->ht);
  bl_delete(_arkp->bl);
  KV_TRC(pAT, "ark_delete done %p", _arkp);
  am_free(_arkp);

ark_delete_ark_err:
  KV_TRC_CLOSE(pAT);
  return rc;
}
Ejemplo n.º 15
0
int ark_create_verbose(char *path, ARK **arkret,
                       uint64_t size, uint64_t bsize, uint64_t hcount,
                       int nthrds, int nqueue, int basyncs, uint64_t flags)
{
  int          rc = 0;
  int        p_rc = 0;
  uint64_t bcount = 0;
  uint64_t      x = 0;
  int           i = 0;
  int        tnum = 0;
  int        rnum = 0;
  scb_t     *scbp = NULL;

  KV_TRC_OPEN(pAT, "arkdb");

  if (NULL == arkret)
  {
    KV_TRC_FFDC(pAT, "Incorrect value for ARK control block: rc=EINVAL");
    rc = EINVAL;
    goto ark_create_ark_err;
  }

  if ( (flags & (ARK_KV_PERSIST_LOAD|ARK_KV_PERSIST_STORE)) && 
         (flags & ARK_KV_VIRTUAL_LUN) )
  {
    KV_TRC_FFDC(pAT, "Invalid persistence combination with ARK flags: %016lx",
                flags);
    rc = EINVAL;
    goto ark_create_ark_err;
  }

  if (nthrds <= 0)
  {
      KV_TRC_FFDC(pAT, "invalid nthrds:%d", nthrds);
      rc = EINVAL;
      goto ark_create_ark_err;
  }

  _ARK *ark = am_malloc(sizeof(_ARK));
  if (ark == NULL) {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocating ARK control structure for %ld",
                sizeof(_ARK));
    goto ark_create_ark_err;
  }

  KV_TRC(pAT, "%p path(%s) size %ld bsize %ld hcount %ld "
              "nthrds %d nqueue %d basyncs %d flags:%08lx",
              ark, path, size, bsize, hcount, 
              nthrds, nqueue, basyncs, flags);

  ark->bsize    = bsize;
  ark->rthread  = 0;
  ark->persload = 0;
  ark->nasyncs  = ((nqueue <= 0) ? ARK_MAX_ASYNC_OPS : nqueue);
  ark->basyncs  = basyncs;
  ark->ntasks   = ARK_MAX_TASK_OPS;
  ark->nthrds   = ARK_VERBOSE_NTHRDS_DEF; // hardcode, perf requirement

  // Create the KV storage, whether that will be memory based
  // or flash
  ark->ea = ea_new(path, ark->bsize, basyncs, &size, &bcount,
                    (flags & ARK_KV_VIRTUAL_LUN));
  if (ark->ea == NULL)
  {
    if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
    rc = errno;
    KV_TRC_FFDC(pAT, "KV storage initialization failed: rc/errno:%d", rc);
    goto ark_create_ea_err;
  }

  // Now that the "connection" to the store has been established
  // we need to check to see if data was persisted from a previous
  // instantiation of the KV store.
  p_rc = ark_check_persistence(ark, flags);
  if (p_rc > 0)
  {
    // We ran into an error while trying to read from
    // the store.
    rc = p_rc;
    KV_TRC_FFDC(pAT, "Persistence check failed: %d", rc);
    goto ark_create_persist_err;
  }
  else if (p_rc == -1)
  {
    KV_TRC(pAT, "NO PERSIST LOAD FLAG");
    // There was no persistence data, so we just build off
    // of what was passed into the API.

    ark->size = size;
    ark->bcount = bcount;
    ark->hcount = hcount;
    ark->vlimit = ARK_VERBOSE_VLIMIT_DEF;
    ark->blkbits = ARK_VERBOSE_BLKBITS_DEF;
    ark->grow = ARK_VERBOSE_GROW_DEF;
    ark->rthread = 0;
    ark->flags = flags;
    ark->astart = 0;
    ark->blkused = 1;
    ark->ark_exit = 0;
    ark->nactive = 0;
    ark->pers_stats.kv_cnt = 0;
    ark->pers_stats.blk_cnt = 0;
    ark->pers_stats.byte_cnt = 0;
    ark->pcmd = PT_IDLE;

    // Create the requests and tag control blocks and queues.
    x = ark->hcount / ark->nthrds;
    ark->npart  = x + (ark->hcount % ark->nthrds ? 1 : 0);

    // Create the hash table
    ark->ht = hash_new(ark->hcount);
    if (ark->ht == NULL)
    {
      if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
      rc = errno;
      KV_TRC_FFDC(pAT, "Hash initialization failed: %d", rc);
      goto ark_create_ht_err;
    }

    // Create the block list
    ark->bl = bl_new(ark->bcount, ark->blkbits);
    if (ark->bl == NULL)
    {
      if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
      rc = errno;
      KV_TRC_FFDC(pAT, "Block list initialization failed: %d", rc);
      goto ark_create_bl_err;
    }
    if (flags & ARK_KV_PERSIST_STORE)
    {
      ark_persistence_calc(ark);
      if (bl_reserve(ark->bl, ark->pers_max_blocks))
          {goto ark_create_bl_err;}
    }
  }
  else
  {
      KV_TRC(pAT, "PERSIST: %p path(%s) size %ld bsize %ld hcount %ld "
                  "nthrds %d nqueue %ld basyncs %d bcount %ld blkbits %ld",
                  ark, path, ark->size, ark->bsize, ark->hcount,
                  ark->nthrds, ark->nasyncs, ark->basyncs,
                  ark->bcount, ark->blkbits);
  }

  rc = pthread_mutex_init(&ark->mainmutex,NULL);
  if (rc != 0)
  {
    KV_TRC_FFDC(pAT, "pthread_mutex_init for main mutex failed: %d", rc);
    goto ark_create_pth_mutex_err;
  }

  ark->rtags = tag_new(ark->nasyncs);
  if ( NULL == ark->rtags )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Tag initialization for requests failed: %d", rc);
    goto ark_create_rtag_err;
  }

  ark->ttags = tag_new(ark->ntasks);
  if ( NULL == ark->ttags )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Tag initialization for tasks failed: %d", rc);
    goto ark_create_ttag_err;
  }

  ark->rcbs = am_malloc(ark->nasyncs * sizeof(rcb_t));
  if ( NULL == ark->rcbs )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for request control blocks", (ark->nasyncs * sizeof(rcb_t)));
    goto ark_create_rcbs_err;
  }

  ark->tcbs = am_malloc(ark->ntasks * sizeof(tcb_t));
  if ( NULL == ark->tcbs )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for task control blocks", (ark->ntasks * sizeof(rcb_t)));
    goto ark_create_tcbs_err;
  }

  ark->iocbs = am_malloc(ark->ntasks * sizeof(iocb_t));
  if ( NULL == ark->iocbs )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for io control blocks", (ark->ntasks * sizeof(iocb_t)));
    goto ark_create_iocbs_err;
  }

  ark->poolthreads = am_malloc(ark->nthrds * sizeof(scb_t));
  if ( NULL == ark->poolthreads )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation of %"PRIu64" bytes for server thread control blocks", (ark->nthrds * sizeof(scb_t)));
    goto ark_create_poolthreads_err;
  }

  for ( rnum = 0; rnum < ark->nasyncs ; rnum++ )
  {
    ark->rcbs[rnum].stat = A_NULL;
    pthread_cond_init(&(ark->rcbs[rnum].acond), NULL);
    pthread_mutex_init(&(ark->rcbs[rnum].alock), NULL);
  }

  for ( tnum = 0; tnum < ark->ntasks; tnum++ )
  {
    ark->tcbs[tnum].inb = bt_new(0, ark->vlimit, sizeof(uint64_t), 
                                       &(ark->tcbs[tnum].inblen),
                                       &(ark->tcbs[tnum].inb_orig));
    if (ark->tcbs[tnum].inb == NULL)
    {
      if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
      rc = errno;
      KV_TRC_FFDC(pAT, "Bucket allocation for inbuffer failed: %d", rc);
      goto ark_create_taskloop_err;
    }

    ark->tcbs[tnum].oub = bt_new(0, ark->vlimit, sizeof(uint64_t), 
                                       &(ark->tcbs[tnum].oublen),
                                       &(ark->tcbs[tnum].oub_orig));
    if (ark->tcbs[tnum].oub == NULL)
    {
      if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
      rc = errno;
      KV_TRC_FFDC(pAT, "Bucket allocation for outbuffer failed: %d", rc);
      goto ark_create_taskloop_err;
    }

    //ark->tcbs[tnum].vbsize = bsize * 1024;
    ark->tcbs[tnum].vbsize = bsize * 256;
    ark->tcbs[tnum].vb_orig = am_malloc(ark->tcbs[tnum].vbsize);
    if (ark->tcbs[tnum].vb_orig == NULL)
    {
      rc = ENOMEM;
      KV_TRC_FFDC(pAT, "Out of memory allocation for %"PRIu64" bytes for variable size buffer", (bsize * 1024));
      goto ark_create_taskloop_err;
    }
    ark->tcbs[tnum].vb = ptr_align(ark->tcbs[tnum].vb_orig);
  }

  *arkret = (void *)ark;

  ark->pts = (PT *)am_malloc(sizeof(PT) * ark->nthrds);
  if ( ark->pts == NULL )
  {
    rc = ENOMEM;
    KV_TRC_FFDC(pAT, "Out of memory allocation for %"PRIu64" bytes for server thread data", (sizeof(PT) * ark->nthrds));
    goto ark_create_taskloop_err;
  }

  for (i = 0; i < ark->nthrds; i++) {
    PT *pt = &(ark->pts[i]);
    scbp = &(ark->poolthreads[i]);

    memset(scbp, 0, sizeof(scb_t));

    // Start off the random start point for this thread
    // at -1, to show that it has not been part of a
    // ark_random call.
    scbp->rlast = -1;
    scbp->holds = 0;
    scbp->poolstate = PT_RUN;

    scbp->poolstats.io_cnt = 0;
    scbp->poolstats.ops_cnt = 0;
    scbp->poolstats.kv_cnt = 0;
    scbp->poolstats.blk_cnt = 0;
    scbp->poolstats.byte_cnt = 0;

    pthread_mutex_init(&(scbp->poolmutex), NULL);
    pthread_cond_init(&(scbp->poolcond), NULL);

    scbp->rqueue = queue_new(ark->nasyncs);
    scbp->tqueue = queue_new(ark->ntasks);
    scbp->ioqueue = queue_new(ark->ntasks);

    pt->id = i;
    pt->ark = ark;
    rc = pthread_create(&(scbp->pooltid), NULL, pool_function, pt);
    if (rc != 0)
    {
      KV_TRC_FFDC(pAT, "pthread_create of server thread failed: %d", rc);
      goto ark_create_poolloop_err;
    }
  }

#if 0
  while (ark->nactive < ark->nthrds) {
    usleep(1);
    //printf("Create waiting %d/%d\n", ark->nactive, ark->nthrds);
  }
#endif

  ark->pcmd = PT_RUN;

  goto ark_create_return;

ark_create_poolloop_err:

  for (; i >= 0; i--)
  {
    scbp = &(ark->poolthreads[i]);

    if (scbp->pooltid != 0)
    {
      queue_lock(scbp->rqueue);
      queue_wakeup(scbp->rqueue);
      queue_unlock(scbp->rqueue);
      pthread_join(scbp->pooltid, NULL);

      pthread_mutex_destroy(&(scbp->poolmutex));
      pthread_cond_destroy(&(scbp->poolcond));

      if ( scbp->rqueue != NULL )
      {
        queue_free(scbp->rqueue);
      }

      if ( scbp->tqueue != NULL )
      {
        queue_free(scbp->tqueue);
      }
    
      if ( scbp->ioqueue != NULL )
      {
        queue_free(scbp->ioqueue);
      }
    }
  }

  if ( ark->pts != NULL )
  {
    am_free(ark->pts);
  }

ark_create_taskloop_err:
  for ( tnum = 0; tnum < ark->ntasks; tnum++ )
  {
    if (ark->tcbs[tnum].inb)
    {
      bt_delete(ark->tcbs[tnum].inb);
    }

    if (ark->tcbs[tnum].oub)
    {
      bt_delete(ark->tcbs[tnum].oub);
    }

    if (ark->tcbs[tnum].vb_orig)
    {
      am_free(ark->tcbs[tnum].vb_orig);
    }
  }

  for (rnum = 0; rnum < ark->nasyncs; rnum++)
  {
    pthread_cond_destroy(&(ark->rcbs[rnum].acond));
    pthread_mutex_destroy(&(ark->rcbs[rnum].alock));
  }

  if ( ark->poolthreads != NULL )
  {
    am_free(ark->poolthreads);
  }

ark_create_poolthreads_err:
  if (ark->iocbs)
  {
    am_free(ark->iocbs);
  }

ark_create_iocbs_err:
  if (ark->tcbs)
  {
    am_free(ark->tcbs);
  }

ark_create_tcbs_err:
  if (ark->rcbs)
  {
    am_free(ark->rcbs);
  }

ark_create_rcbs_err:
  if (ark->ttags)
  {
    tag_free(ark->ttags);
  }

ark_create_ttag_err:
  if (ark->rtags)
  {
    tag_free(ark->rtags);
  }

ark_create_rtag_err:
  pthread_mutex_destroy(&ark->mainmutex);

ark_create_pth_mutex_err:
  bl_delete(ark->bl);

ark_create_bl_err:
  hash_free(ark->ht);

ark_create_ht_err:
ark_create_persist_err:
  ea_delete(ark->ea);

ark_create_ea_err:
  am_free(ark);
  *arkret = NULL;

ark_create_ark_err:
  KV_TRC_CLOSE(pAT);

ark_create_return:
  return rc;
}
Ejemplo n.º 16
0
int ark_check_persistence(_ARK *_arkp, uint64_t flags)
{
  int32_t  rc = -1;
  char    *p_data_orig = NULL;
  char    *p_data = NULL;
  ark_io_list_t *bl_array = NULL;
  p_cntr_t *pptr = NULL;
  P_ARK_t  *pcfg = NULL;
  hash_t   *htp = NULL;
  BL       *blp = NULL;
  uint64_t  rdblks = 0;

  if (flags & ARK_KV_PERSIST_LOAD) {KV_TRC(pAT, "PERSIST_LOAD");}

  // Ignore the persistence data and load from scratch
  if ( (!(flags & ARK_KV_PERSIST_LOAD)) || (flags & ARK_KV_VIRTUAL_LUN) )
  {
    return -1;
  }

  p_data_orig = am_malloc(_arkp->bsize);
  if (p_data_orig == NULL)
  {
    KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" bytes for the first "
                     "persistence block", _arkp->bsize);
    rc = ENOMEM;
  }
  else
  {
    p_data = ptr_align(p_data_orig);
    bl_array = bl_chain_no_bl(0, 1);
    rc = ea_async_io(_arkp->ea, ARK_EA_READ, (void *)p_data, 
                      bl_array, 1, 1);
    am_free(bl_array);
  }

  if (rc == 0)
  {
    // We've read the first block.  We check to see if
    // persistence data is present and if so, then
    // read the rest of the data from the flash.
    pptr = (p_cntr_t *)p_data;
    _arkp->persdata = p_data_orig;
    if ( memcmp(pptr->p_cntr_magic, ARK_P_MAGIC, 
                 sizeof(pptr->p_cntr_magic) != 0))
    {
      KV_TRC_FFDC(pAT, "No magic number found in persistence data: %d", EINVAL);
      // The magic number does not match so data is either
      // not present or is corrupted.
      rc = -1;
    }
    else
    {
      // Now we check version and the first persistence data
      // needs to be the ARK_PERSIST_CONFIG block
      if (pptr->p_cntr_version != ARK_P_VERSION_1 &&
          pptr->p_cntr_version != ARK_P_VERSION_2)
      {
        KV_TRC_FFDC(pAT, "Invalid / unsupported version: %"PRIu64"",
                    pptr->p_cntr_version);
        rc = EINVAL;
      }
      else
      {
        // Read in the rest of the persistence data
        pcfg   = (P_ARK_t *)(pptr->p_cntr_data + pptr->p_cntr_cfg_offset);
        rdblks = pcfg->pblocks;
        if (rdblks > 1)
        {
          p_data_orig = am_realloc(p_data_orig, (rdblks * _arkp->bsize));
          if (p_data_orig == NULL)
          {
            KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" bytes for "
                             "full persistence block",
                             (rdblks * _arkp->bsize));
            rc = ENOMEM;
          }
          else
          {
            p_data = ptr_align(p_data_orig);
            bl_array = bl_chain_no_bl(0, rdblks);
            if (bl_array == NULL)
            {
              KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" blocks for "
                               "full persistence data", rdblks);
              rc = ENOMEM;
            }
          }

          // We are still good to read the rest of the data
          // from the flash
          if (rc == 0)
          {
            KV_TRC(pAT, "PERSIST_RD rdblks:%ld", rdblks);
            rc = ea_async_io(_arkp->ea, ARK_EA_READ, (void *)p_data,
                           bl_array, rdblks, 1);
            am_free(bl_array);
            pptr = (p_cntr_t *)p_data;
            pcfg   = (P_ARK_t *)(pptr->p_cntr_data + pptr->p_cntr_cfg_offset);
            _arkp->persdata = p_data_orig;
          }
        }
      }
    }
  }

  // If rc == 0, that means we have persistence data
  if (rc == 0)
  {
      KV_TRC(pAT, "PERSIST_META size %ld bsize %ld hcount %ld bcount %ld "
                  "nthrds %d nasyncs %d basyncs %d blkbits %ld version:%ld",
                  pcfg->size, pcfg->bsize, pcfg->hcount, pcfg->bcount,
                  pcfg->nthrds, pcfg->nasyncs, pcfg->basyncs, pcfg->blkbits,
                  pptr->p_cntr_version);

    _arkp->persload            = 1;
    _arkp->size                = pcfg->size;
    _arkp->flags               = flags;
    _arkp->bsize               = pcfg->bsize;
    _arkp->bcount              = pcfg->bcount;
    _arkp->blkbits             = pcfg->blkbits;
    _arkp->grow                = pcfg->grow;
    _arkp->hcount              = pcfg->hcount;
    _arkp->vlimit              = pcfg->vlimit;
    _arkp->blkused             = pcfg->blkused;
    _arkp->pers_stats.kv_cnt   = pcfg->pstats.kv_cnt;
    _arkp->pers_stats.blk_cnt  = pcfg->pstats.blk_cnt;
    _arkp->pers_stats.byte_cnt = pcfg->pstats.byte_cnt;

    KV_TRC(pAT, "ARK_META size %ld bsize %ld hcount %ld bcount %ld "
                "nthrds %d nasyncs %ld basyncs %d blkbits %ld",
                _arkp->size, _arkp->bsize, _arkp->hcount, _arkp->bcount,
                _arkp->nthrds, _arkp->nasyncs, _arkp->basyncs, _arkp->blkbits);

    htp = (hash_t *)(pptr->p_cntr_data + pptr->p_cntr_ht_offset);
    _arkp->ht = hash_new(htp->n);
    if (_arkp->ht == NULL)
    {
        if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
        rc = errno;
        KV_TRC_FFDC(pAT, "ht_new failed: n:%ld rc:%d", htp->n, rc);
        goto error_exit;
    }
    memcpy(_arkp->ht, htp, pptr->p_cntr_ht_size);

    blp = (BL *)(pptr->p_cntr_data + pptr->p_cntr_bl_offset);
    _arkp->bl = bl_new(blp->n, blp->w);
    if (_arkp->bl == NULL)
    {
        if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOMEM;}
        rc = errno;
        KV_TRC_FFDC(pAT, "bl_new failed: n:%ld w:%ld rc:%d",
                    blp->n, blp->w, rc);
        goto error_exit;
    }
    _arkp->bl->count = blp->count;
    _arkp->bl->head  = blp->head;
    _arkp->bl->hold  = blp->hold;
    _arkp->bl->top   = blp->top;

    if (pptr->p_cntr_version == ARK_P_VERSION_1)
    {
        IV *piv = (IV *)(pptr->p_cntr_data + pptr->p_cntr_bliv_offset);

        KV_TRC(pAT, "PERSIST_VERSION_1 LOADED");
        _arkp->bl->top = _arkp->bl->n;

        // copy IV->data from piv->data
        memcpy(_arkp->bl->list->data,
               piv->data,
               pptr->p_cntr_bliv_size);
    }
    else if (pptr->p_cntr_version == ARK_P_VERSION_2)
    {
        KV_TRC(pAT, "PERSIST_VERSION_2 LOADED");
        // copy IV->data from bliv_offset
        memcpy(_arkp->bl->list->data,
               pptr->p_cntr_data + pptr->p_cntr_bliv_offset,
               pptr->p_cntr_bliv_size);
    }
    else
    {
        rc = EINVAL;
        KV_TRC_FFDC(pAT, "bad persistent version number: ver:%ld",
                    pptr->p_cntr_version);
        goto error_exit;
    }

    KV_TRC(pAT, "BL_META: n:%ld count:%ld head:%ld hold:%ld top:%ld",
            _arkp->bl->n, _arkp->bl->count, _arkp->bl->head, _arkp->bl->hold,
            _arkp->bl->top);
  }

error_exit:
  am_free(p_data_orig);
  return rc;
}
Ejemplo n.º 17
0
int ark_persist(_ARK *_arkp)
{
  int32_t        rc          = 0;
  uint64_t       tot_bytes   = 0;
  uint64_t       wrblks      = 0;
  char          *p_data_orig = NULL;
  char          *p_data      = NULL;
  p_cntr_t      *pptr        = NULL;
  char          *dptr        = NULL;
  P_ARK_t       *pcfg        = NULL;
  ark_io_list_t *bl_array    = NULL;

  if ( (_arkp->ea->st_type == EA_STORE_TYPE_MEMORY) ||
      !(_arkp->flags & ARK_KV_PERSIST_STORE) )
  {
    return 0;
  }

  ark_persistence_calc(_arkp);

  // allocate write buffer
  tot_bytes   = _arkp->pers_max_blocks * _arkp->bsize;
  p_data_orig = am_malloc(tot_bytes);
  if (p_data_orig == NULL)
  {
    KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" bytes for "
                     "persistence data", tot_bytes);
    return ENOMEM;
  }
  memset(p_data_orig, 0, tot_bytes);
  p_data = ptr_align(p_data_orig);

  // Record cntr data
  pptr   = (p_cntr_t *)p_data;
  memcpy(pptr->p_cntr_magic, ARK_P_MAGIC, sizeof(pptr->p_cntr_magic));
  pptr->p_cntr_version = ARK_P_VERSION_2;
  pptr->p_cntr_size    = sizeof(p_cntr_t);

  // Record configuration info
  pcfg = (P_ARK_t*)pptr->p_cntr_data;
  pcfg->flags   = _arkp->flags;
  pcfg->size    = _arkp->ea->size;
  pcfg->bsize   = _arkp->bsize;
  pcfg->bcount  = _arkp->bcount;
  pcfg->blkbits = _arkp->blkbits;
  pcfg->grow    = _arkp->blkbits;
  pcfg->hcount  = _arkp->hcount;
  pcfg->vlimit  = _arkp->vlimit;
  pcfg->blkused = _arkp->blkused;
  pcfg->nasyncs = _arkp->nasyncs;
  pcfg->basyncs = _arkp->basyncs;
  pcfg->ntasks  = _arkp->ntasks;
  pcfg->nthrds  = _arkp->nthrds;
  ark_persist_stats(_arkp, &(pcfg->pstats));
  pptr->p_cntr_cfg_offset = 0;
  pptr->p_cntr_cfg_size   = sizeof(P_ARK_t);

  dptr = pptr->p_cntr_data;

  // Record hash info
  dptr                  += pptr->p_cntr_cfg_size;
  pptr->p_cntr_ht_offset = dptr - pptr->p_cntr_data;
  pptr->p_cntr_ht_size   = sizeof(hash_t) + (_arkp->ht->n * sizeof(uint64_t));
  memcpy(dptr, _arkp->ht, pptr->p_cntr_ht_size);

  // Record block list info
  dptr                  += pptr->p_cntr_ht_size;
  pptr->p_cntr_bl_offset = dptr - pptr->p_cntr_data;
  pptr->p_cntr_bl_size   = sizeof(BL);
  memcpy(dptr, _arkp->bl, pptr->p_cntr_bl_size);

  // Record IV list info
  dptr                    += pptr->p_cntr_bl_size;
  pptr->p_cntr_bliv_offset = dptr - pptr->p_cntr_data;

  // bliv_size = bytes in bl->list->data[cs_blocks + kvdata_blocks]
  // add 2 to top because of how IV->data chaining works
  pptr->p_cntr_bliv_size = divup((_arkp->bl->top+2) * _arkp->bl->w, 8);
  memcpy(dptr, _arkp->bl->list->data, pptr->p_cntr_bliv_size);

  // Calculate wrblks: number of persist metadata blocks to write
  tot_bytes = _arkp->pers_cs_bytes + pptr->p_cntr_bliv_size;
  wrblks    = pcfg->pblocks = divup(tot_bytes, _arkp->bsize);

  KV_TRC(pAT, "PERSIST_WR dev:%s top:%ld wrblks:%ld vs pers_max_blocks:%ld",
         _arkp->ea->st_device, _arkp->bl->top, pcfg->pblocks,
         _arkp->pers_max_blocks);

  bl_array = bl_chain_blocks(_arkp->bl, 0, wrblks);
  if ( NULL == bl_array )
  {
    KV_TRC_FFDC(pAT, "Out of memory allocating %"PRIu64" blocks for block list",
                wrblks);
    rc = ENOMEM;
  }
  else
  {
    rc = ea_async_io(_arkp->ea, ARK_EA_WRITE, (void *)p_data, 
                     bl_array, wrblks, _arkp->nthrds);
    am_free(bl_array);
  }

  KV_TRC(pAT, "PERSIST_DATA_STORED rc:%d", rc);

  am_free(p_data_orig);
  return rc;
}