Eina_Array *ea_copy(Eina_Array *a) { int i; Eina_Array *b; if (ea_count(a)) b = ea_new(ea_count(a)); else b = ea_new(4); for(i=0; i<ea_count(a); i++) ea_push(b, ea_data(a, i)); return b; }
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; }