示例#1
0
ibp_capset_t *create_allocs(int nallocs, int asize)
{
    int i, err;
    ibp_attributes_t attr;
    ibp_depot_t *depot;
    opque_t *q;
    op_generic_t *op;

    ibp_capset_t *caps = (ibp_capset_t *)malloc(sizeof(ibp_capset_t)*nallocs);

    set_ibp_attributes(&attr, time(NULL) + a_duration, IBP_HARD, IBP_BYTEARRAY);
    q = new_opque();

    for (i=0; i<nallocs; i++) {
        depot = &(depot_list[i % n_depots]);
        op = new_ibp_alloc_op(ic, &(caps[i]), asize, depot, &attr, disk_cs_type, disk_blocksize, ibp_timeout);
        opque_add(q, op);
    }

    io_start(q);
    err = io_waitall(q);
    if (err != 0) {
        printf("create_allocs: At least 1 error occured! * ibp_errno=%d * nfailed=%d\n", err, opque_tasks_failed(q));
        abort();
    }
    opque_free(q, OP_DESTROY);

    return(caps);
}
示例#2
0
void remove_allocs(ibp_capset_t *caps_list, int nallocs)
{
    int i, err;
    opque_t *q;
    op_generic_t *op;

    q = new_opque();

    for (i=0; i<nallocs; i++) {
        op = new_ibp_remove_op(ic, get_ibp_cap(&(caps_list[i]), IBP_MANAGECAP), ibp_timeout);
        opque_add(q, op);
    }

    io_start(q);
    err = io_waitall(q);
    if (err != 0) {
        printf("remove_allocs: At least 1 error occured! * ibp_errno=%d * nfailed=%d\n", err, opque_tasks_failed(q));
    }
    opque_free(q, OP_DESTROY);

    //** Lastly free all the caps and the array
    for (i=0; i<nallocs; i++) {
        destroy_ibp_cap(get_ibp_cap(&(caps_list[i]), IBP_READCAP));
        destroy_ibp_cap(get_ibp_cap(&(caps_list[i]), IBP_WRITECAP));
        destroy_ibp_cap(get_ibp_cap(&(caps_list[i]), IBP_MANAGECAP));
    }

    free(caps_list);

    return;
}
示例#3
0
ibp_capset_t *create_alias_allocs(int nallocs, ibp_capset_t *base_caps, int n_base)
{
    int i, err;
    opque_t *q;
    op_generic_t *op;
    ibp_capset_t *bcap;

    ibp_capset_t *caps = (ibp_capset_t *)malloc(sizeof(ibp_capset_t)*nallocs);

    q = new_opque();

    for (i=0; i<nallocs; i++) {
        bcap = &(base_caps[i % n_base]);
        op = new_ibp_alias_alloc_op(ic, &(caps[i]), get_ibp_cap(bcap, IBP_MANAGECAP), 0, 0, 0, ibp_timeout);
        opque_add(q, op);
    }

    io_start(q);
    err = io_waitall(q);
    if (err != 0) {
        printf("create_alias_allocs: At least 1 error occured! * ibp_errno=%d * nfailed=%d\n", err, opque_tasks_failed(q));
    }
    opque_free(q, OP_DESTROY);

    return(caps);
}
示例#4
0
double small_read_allocs(ibp_capset_t *caps, int n, int asize, int small_count, int min_size, int max_size)
{
    int i, io_size, offset, slot, err;
    opque_t *q;
    op_generic_t *op;
    double rnd, lmin, lmax;
    double nbytes;
    tbuffer_t *buf;

    q = new_opque();

    lmin = log(min_size);
    lmax = log(max_size);

    if (asize < max_size) {
        max_size = asize;
        log_printf(0, "small_read_allocs:  Adjusting max_size=%d\n", max_size);
    }

    char *buffer = (char *)malloc(max_size);
    init_buffer(buffer, 'r', max_size);

    type_malloc_clear(buf, tbuffer_t, small_count);

    nbytes = 0;
    for (i=0; i<small_count; i++) {
        rnd = rand()/(RAND_MAX+1.0);
        slot = n * rnd;

        rnd = rand()/(RAND_MAX+1.0);
        rnd = lmin + (lmax - lmin) * rnd;
        io_size = exp(rnd);
        if (io_size == 0) io_size = 1;
        nbytes = nbytes + io_size;

        rnd = rand()/(RAND_MAX+1.0);
        offset = (asize - io_size) * rnd;

        tbuffer_single(&(buf[i]), io_size, buffer);

        op = new_ibp_read_op(ic, get_ibp_cap(&(caps[slot]), IBP_READCAP), offset, &(buf[i]), 0, io_size, ibp_timeout);
        opque_add(q, op);
    }

    io_start(q);
    err = io_waitall(q);
    if (err != 0) {
        printf("small_read_allocs: At least 1 error occured! * ibp_errno=%d * nfailed=%d\n", err, opque_tasks_failed(q));
    }
    opque_free(q, OP_DESTROY);

    free(buf);
    free(buffer);

    return(nbytes);
}
示例#5
0
void random_allocs(ibp_capset_t *caps, int n, int asize, int block_size, double rfrac)
{
    int i, err, bslot;
    int j, nblocks, rem, len;
    opque_t *q;
    op_generic_t *op;
    double rnd;
    tbuffer_t *buf;

    char *rbuffer = (char *)malloc(block_size);
    char *wbuffer = (char *)malloc(block_size);
    init_buffer(rbuffer, 'r', block_size);
    init_buffer(wbuffer, 'w', block_size);

    q = new_opque();

    nblocks = asize / block_size;
    rem = asize % block_size;
    if (rem > 0) nblocks++;

    type_malloc_clear(buf, tbuffer_t, n*nblocks);

    for (j=0; j<nblocks; j++) {
        for (i=0; i<n; i++) {
            rnd = rand()/(RAND_MAX + 1.0);

            if ((j==(nblocks-1)) && (rem > 0)) {
                len = rem;
            } else {
                len = block_size;
            }

            bslot = j*n + i;

            if (rnd < rfrac) {
                tbuffer_single(&(buf[bslot]), len, rbuffer);
                op = new_ibp_read_op(ic, get_ibp_cap(&(caps[i]), IBP_READCAP), j*block_size, &(buf[bslot]), 0, len, ibp_timeout);
            } else {
                tbuffer_single(&(buf[bslot]), len, wbuffer);
                op = new_ibp_write_op(ic, get_ibp_cap(&(caps[i]), IBP_WRITECAP), j*block_size, &(buf[bslot]), 0, len, ibp_timeout);
            }
            opque_add(q, op);
        }
    }

    io_start(q);
    err = io_waitall(q);
    if (err != 0) {
        printf("random_allocs: At least 1 error occured! * ibp_errno=%d * nfailed=%d\n", err, opque_tasks_failed(q));
    }
    opque_free(q, OP_DESTROY);

    free(buf);
    free(rbuffer);
    free(wbuffer);
}
示例#6
0
void write_allocs(ibp_capset_t *caps, int n, int asize, int block_size)
{
    int i, j, nblocks, rem, len, err, slot;
    opque_t *q;
    op_generic_t *op;
    tbuffer_t *buf;

    char *buffer = (char *)malloc(block_size);
    init_buffer(buffer, 'W', block_size);

    q = new_opque();

    nblocks = asize / block_size;
    rem = asize % block_size;
    if (rem > 0) nblocks++;

    type_malloc_clear(buf, tbuffer_t, n*nblocks);

//for (j=0; j<nblocks; j++) {
    for (j=nblocks-1; j>= 0; j--) {
        for (i=0; i<n; i++) {
            if ((j==(nblocks-1)) && (rem > 0)) {
                len = rem;
            } else {
                len = block_size;
            }
            slot = j*n + i;
            tbuffer_single(&(buf[slot]), len, buffer);
            op = new_ibp_write_op(ic, get_ibp_cap(&(caps[i]), IBP_WRITECAP), j*block_size, &(buf[slot]), 0, len, ibp_timeout);
            opque_add(q, op);
        }
    }

    io_start(q);
    err = io_waitall(q);
    if (err != 0) {
        printf("write_allocs: At least 1 error occured! * ibp_errno=%d * nfailed=%d\n", err, opque_tasks_failed(q));
    }
    opque_free(q, OP_DESTROY);

    free(buf);
    free(buffer);
}
示例#7
0
void *ds_ibp_warm_thread(apr_thread_t *th, void *data)
{
    data_service_fn_t *dsf = (data_service_fn_t *)data;
    ds_ibp_priv_t *ds = (ds_ibp_priv_t *)dsf->priv;
    apr_time_t max_wait;
    char *mcap;
    apr_ssize_t hlen;
    apr_hash_index_t *hi;
    ibp_capset_t *w;
    opque_t *q;
    int dt, err;

    dt = 60;
    max_wait = apr_time_make(ds->warm_interval, 0);
    apr_thread_mutex_lock(ds->lock);
    while (ds->warm_stop == 0) {
        //** Generate all the tasks
        log_printf(10, "Starting auto-warming run\n");

        q = new_opque();
        for (hi=apr_hash_first(NULL, ds->warm_table); hi != NULL; hi = apr_hash_next(hi)) {
            apr_hash_this(hi, (const void **)&mcap, &hlen, (void **)&w);
            opque_add(q, new_ibp_modify_alloc_op(ds->ic, mcap, -1, ds->warm_duration, -1, dt));
            log_printf(15, " warming: %s\n", mcap);

        }

        //** Wait until they all complete
        err = opque_waitall(q);
        log_printf(10, "opque_waitall=%d\n", err);

        opque_free(q, OP_DESTROY);  //** Clean up.  Don;t care if we are successfull or not:)

        //** Sleep until the next time or we get an exit request
        apr_thread_cond_timedwait(ds->cond, ds->lock, max_wait);
    }
    apr_thread_mutex_unlock(ds->lock);

    log_printf(10, "EXITING auto-warm thread\n");

    return(NULL);
}
示例#8
0
void validate_allocs(ibp_capset_t *caps_list, int nallocs)
{
    int i, err;
    int nalloc_bad, nblocks_bad;
    opque_t *q;
    op_generic_t *op;
    int *bad_blocks = (int *) malloc(sizeof(int)*nallocs);
    int correct_errors = 0;

    q = new_opque();

    for (i=0; i<nallocs; i++) {
        bad_blocks[i] = 0;
        op = new_ibp_validate_chksum_op(ic, get_ibp_cap(&(caps_list[i]), IBP_MANAGECAP), correct_errors, &(bad_blocks[i]),
                                        ibp_timeout);
        opque_add(q, op);
    }

    io_start(q);
    err = io_waitall(q);
    if (err != 0) {
        printf("validate_allocs: At least 1 error occured! * ibp_errno=%d * nfailed=%d\n", err, opque_tasks_failed(q));
        nalloc_bad = 0;
        nblocks_bad = 0;
        for (i=0; i<nallocs; i++) {
            if (bad_blocks[i] != 0) {
                printf("  %d   cap=%s  blocks_bad=%d\n", i, get_ibp_cap(&(caps_list[i]), IBP_MANAGECAP), bad_blocks[i]);
                nalloc_bad++;
                nblocks_bad = nblocks_bad + bad_blocks[i];
            }
        }

        printf("  Total Bad allocations: %d   Total Bad blocks: %d\n", nalloc_bad, nblocks_bad);
    }
    opque_free(q, OP_DESTROY);

    free(bad_blocks);

    return;
}
示例#9
0
op_status_t segment_copy_func(void *arg, int id)
{
    segment_copy_t *sc = (segment_copy_t *)arg;
    tbuffer_t *wbuf, *rbuf, *tmpbuf;
    tbuffer_t tbuf1, tbuf2;
    int err;
    ex_off_t bufsize;
    ex_off_t rpos, wpos, rlen, wlen, tlen, nbytes, dend;
    ex_iovec_t rex, wex;
    opque_t *q;
    op_generic_t *rgop, *wgop;
    op_status_t status;

    //** Set up the buffers
    bufsize = sc->bufsize / 2;  //** The buffer is split for R/W
    tbuffer_single(&tbuf1, bufsize, sc->buffer);
    tbuffer_single(&tbuf2, bufsize, &(sc->buffer[bufsize]));
    rbuf = &tbuf1;
    wbuf = &tbuf2;

    //** Check the length
    nbytes = segment_size(sc->src) - sc->src_offset;
    if (nbytes < 0) {
        rlen = bufsize;
    } else {
        rlen = (nbytes > bufsize) ? bufsize : nbytes;
    }
    if ((sc->len != -1) && (sc->len < nbytes)) nbytes = sc->len;

    //** Go ahead and reserve the space in the destintaion
    dend = sc->dest_offset + nbytes;
    log_printf(1, "reserving space=" XOT "\n", dend);
    gop_sync_exec(segment_truncate(sc->dest, sc->da, -dend, sc->timeout));

    //** Read the initial block
    rpos = sc->src_offset;
    wpos = sc->dest_offset;
//  rlen = (nbytes > bufsize) ? bufsize : nbytes;
    wlen = 0;
    ex_iovec_single(&rex, rpos, rlen);
    rpos += rlen;
    nbytes -= rlen;
    rgop = segment_read(sc->src, sc->da, sc->rw_hints, 1, &rex, rbuf, 0, sc->timeout);
    err = gop_waitall(rgop);
    if (err != OP_STATE_SUCCESS) {
        log_printf(1, "Intial read failed! src=%" PRIu64 " rpos=" XOT " len=" XOT "\n", segment_id(sc->src), rpos, rlen);
        gop_free(rgop, OP_DESTROY);
        return(op_failure_status);
    }
    gop_free(rgop, OP_DESTROY);

    q = new_opque();
    do {
        //** Swap the buffers
        tmpbuf = rbuf;
        rbuf = wbuf;
        wbuf = tmpbuf;
        tlen = rlen;
        rlen = wlen;
        wlen = tlen;

        log_printf(1, "sseg=" XIDT " dseg=" XIDT " wpos=%" PRId64 " rlen=%" PRId64 " wlen=%" PRId64 "\n", segment_id(sc->src), segment_id(sc->dest), wpos, rlen, wlen);

        //** Start the write
        ex_iovec_single(&wex, wpos, wlen);
        wpos += wlen;
        wgop = segment_write(sc->dest, sc->da, sc->rw_hints, 1, &wex, wbuf, 0, sc->timeout);
        opque_add(q, wgop);

        //** Read in the next block
//     rlen = (nbytes > bufsize) ? bufsize : nbytes;
        if (nbytes < 0) {
            rlen = bufsize;
        } else {
            rlen = (nbytes > bufsize) ? bufsize : nbytes;
        }
        if (rlen > 0) {
            ex_iovec_single(&rex, rpos, rlen);
            rpos += rlen;
            nbytes -= rlen;
            rgop = segment_read(sc->src, sc->da, sc->rw_hints, 1, &rex, rbuf, 0, sc->timeout);
            opque_add(q, rgop);
        }

        err = opque_waitall(q);
        if (err != OP_STATE_SUCCESS) {
            log_printf(1, "ERROR read/write failed! src=" XIDT " rpos=" XOT " len=" XOT "\n", segment_id(sc->src), rpos, rlen);
            opque_free(q, OP_DESTROY);
            return(op_failure_status);
        }
    } while (rlen > 0);

    opque_free(q, OP_DESTROY);

    if (sc->truncate == 1) {  //** Truncate if wanted
        gop_sync_exec(segment_truncate(sc->dest, sc->da, wpos, sc->timeout));
    }

    status = op_success_status;
    status.error_code = rpos;

    return(status);
}
示例#10
0
int rss_perform_check(resource_service_fn_t *rs)
{
    rs_simple_priv_t *rss = (rs_simple_priv_t *)rs->priv;
    apr_hash_index_t *hi;
    rss_check_entry_t *ce;
    int prev_status, status_change;
    char *rid;
    apr_ssize_t klen;
    op_status_t status;
    opque_t *q;
    op_generic_t *gop;

    log_printf(5, "START\n");

    //** Generate the task list
    q = new_opque();

    status_change = 0;
    apr_thread_mutex_lock(rss->lock);
    for (hi = apr_hash_first(NULL, rss->rid_mapping); hi != NULL; hi = apr_hash_next(hi)) {
        apr_hash_this(hi, (const void **)&rid, &klen, (void **)&ce);
//     if (ce->re->status != RS_STATUS_IGNORE) {
        gop = ds_res_inquire(rss->ds, ce->ds_key, rss->da, ce->space, rss->check_timeout);
        gop_set_private(gop, ce);
        opque_add(q, gop);
//     }
    }
    apr_thread_mutex_unlock(rss->lock);

    //** Wait for them all to complete
    opque_waitall(q);

    //** Process the results
    apr_thread_mutex_lock(rss->lock);
    if (rss->modify_time == rss->current_check) {  //** Only process the results if not updated
        for (gop = opque_get_next_finished(q); gop != NULL; gop = opque_get_next_finished(q)) {
            status = gop_get_status(gop);
            ce = gop_get_private(gop);
            prev_status = ce->re->status;
            if (status.op_status == OP_STATE_SUCCESS) {  //** Got a valid response
                ce->re->space_free = ds_res_inquire_get(rss->ds, DS_INQUIRE_FREE, ce->space);
                ce->re->space_used = ds_res_inquire_get(rss->ds, DS_INQUIRE_USED, ce->space);
                ce->re->space_total = ds_res_inquire_get(rss->ds, DS_INQUIRE_TOTAL, ce->space);
                if (ce->re->status != RS_STATUS_IGNORE) {
                    if (ce->re->space_free <= rss->min_free) {
                        ce->re->status = RS_STATUS_OUT_OF_SPACE;
                    } else {
                        ce->re->status = RS_STATUS_UP;
                    }
                }
            } else {  //** No response so mark it as down
                if (ce->re->status != RS_STATUS_IGNORE) ce->re->status = RS_STATUS_DOWN;
            }
            if (prev_status != ce->re->status) status_change = 1;

            log_printf(15, "ds_key=%s prev_status=%d new_status=%d\n", ce->ds_key, prev_status, ce->re->status);
            gop_free(gop, OP_DESTROY);
        }

    }

    opque_free(q, OP_DESTROY);
    apr_thread_mutex_unlock(rss->lock);

    log_printf(5, "END status_change=%d\n", status_change);

    return(status_change);
}
示例#11
0
op_generic_t *rs_simple_request(resource_service_fn_t *arg, data_attr_t *da, rs_query_t *rsq, data_cap_set_t **caps, rs_request_t *req, int req_size, rs_hints_t *hints_list, int fixed_size, int n_rid, int ignore_fixed_err, int timeout)
{
    rs_simple_priv_t *rss = (rs_simple_priv_t *)arg->priv;
    rsq_base_t *query_global = (rsq_base_t *)rsq;
    rsq_base_t *query_local;
    kvq_table_t kvq_global, kvq_local, *kvq;
    apr_hash_t *pick_from;
    rid_change_entry_t *rid_change;
    ex_off_t change;
    op_status_t status;
    opque_t *que;
    rss_rid_entry_t *rse;
    rsq_base_ele_t *q;
    int slot, rnd_off, i, j, k, i_unique, i_pickone, found, err_cnt, loop, loop_end;
    int state, *a, *b, *op_state, unique_size;
    tbx_stack_t *stack;

    log_printf(15, "rs_simple_request: START rss->n_rids=%d n_rid=%d req_size=%d fixed_size=%d\n", rss->n_rids, n_rid, req_size, fixed_size);

    for (i=0; i<req_size; i++) req[i].rid_key = NULL;  //** Clear the result in case of an error

    apr_thread_mutex_lock(rss->lock);
    i = _rs_simple_refresh(arg);  //** Check if we need to refresh the data
    if (i != 0) {
        apr_thread_mutex_unlock(rss->lock);
        return(gop_dummy(op_failure_status));
    }

    //** Determine the query sizes and make the processing arrays
    memset(&kvq, 0, sizeof(kvq));
    rs_query_count(arg, rsq, &i, &(kvq_global.n_unique), &(kvq_global.n_pickone));

    log_printf(15, "rs_simple_request: n_unique=%d n_pickone=%d\n", kvq_global.n_unique, kvq_global.n_pickone);
    tbx_log_flush();

    //** Make space the for the uniq and pickone fields.
    //** Make sure we have space for at least 1 more than we need of each to pass to the routines even though they aren't used
    j = (kvq_global.n_pickone == 0) ? 1 : kvq_global.n_pickone + 1;
    tbx_type_malloc_clear(kvq_global.pickone, kvq_ele_t, j);

    unique_size = kvq_global.n_unique + 1;
    tbx_type_malloc_clear(kvq_global.unique, kvq_ele_t *, unique_size);
    log_printf(15, "MALLOC j=%d\n", unique_size);
    for (i=0; i<unique_size; i++) {
        tbx_type_malloc_clear(kvq_global.unique[i], kvq_ele_t, n_rid);
    }

    //** We don't allow these on the local but make a temp space anyway
    kvq_local.n_pickone = 0;
    tbx_type_malloc_clear(kvq_local.pickone, kvq_ele_t, 1);
    kvq_global.n_unique = 0;
    tbx_type_malloc_clear(kvq_local.unique, kvq_ele_t *, 1);
    tbx_type_malloc_clear(kvq_local.unique[0], kvq_ele_t, n_rid);

    status = op_success_status;

    que = new_opque();
    stack = tbx_stack_new();

    err_cnt = 0;
    found = 0;
//  max_size = (req_size > fixed_size) ? req_size : fixed_size;

    for (i=0; i < n_rid; i++) {
        found = 0;
        loop_end = 1;
        query_local = NULL;
        rnd_off = tbx_random_get_int64(0, rss->n_rids-1);
//rnd_off = 0;  //FIXME

        if (hints_list != NULL) {
            query_local = (rsq_base_t *)hints_list[i].local_rsq;
            if (query_local != NULL) {
                loop_end = 2;
                rs_query_count(arg, query_local, &j, &(kvq_local.n_unique), &(kvq_local.n_pickone));
                if ((kvq_local.n_unique != 0) && (kvq_local.n_pickone != 0)) {
                    log_printf(0, "Unsupported use of pickone/unique in local RSQ hints_list[%d]=%s!\n", i, hints_list[i].fixed_rid_key);
                    status.op_status = OP_STATE_FAILURE;
                    status.error_code = RS_ERROR_FIXED_NOT_FOUND;
                    hints_list[i].status = RS_ERROR_HINTS_INVALID_LOCAL;
                    err_cnt++;
                    continue;
                }
            }

            if (i<fixed_size) {  //** Use the fixed list for assignment
                rse = tbx_list_search(rss->rid_table, hints_list[i].fixed_rid_key);
                if (rse == NULL) {
                    log_printf(0, "Missing element in hints list[%d]=%s! Ignoring check.\n", i, hints_list[i].fixed_rid_key);
                    hints_list[i].status = RS_ERROR_FIXED_NOT_FOUND;
                    continue;   //** Skip the check
                }
                rnd_off = rse->slot;
            }
        }

        //** See if we use a restrictive list.  Ususally used when rebalancing space
        pick_from = (hints_list != NULL) ? hints_list[i].pick_from : NULL;
        rid_change = NULL;
        change = 0;
        for (k=0; k<req_size; k++) {
            if (req[k].rid_index == i) {
                change += req[k].size;
            }
        }

        for (j=0; j<rss->n_rids; j++) {
            slot = (rnd_off+j) % rss->n_rids;
            rse = rss->random_array[slot];
            if (pick_from != NULL) {
                rid_change = apr_hash_get(pick_from, rse->rid_key, APR_HASH_KEY_STRING);
                log_printf(15, "PICK_FROM != NULL i=%d j=%d slot=%d rse->rid_key=%s rse->status=%d rid_change=%p\n", i, j, slot, rse->rid_key, rse->status, rid_change);

                if (rid_change == NULL) continue;  //** Not in our list so skip to the next
                ex_off_t delta = rid_change->delta - change;
                log_printf(15, "PICK_FROM != NULL i=%d j=%d slot=%d rse->rid_key=%s rse->status=%d rc->state=%d (" XOT ") > " XOT "????\n", i, j, slot, rse->rid_key, rse->status, rid_change->state, delta, rid_change->tolerance);

                //** Make sure we don't overshoot the target
                if (rid_change->state == 1) continue;   //** Already converged RID
                if (rid_change->delta <= 0) continue;   //** Need to move data OFF this RID
                if ((change - rid_change->delta) > rid_change->tolerance) continue;  //**delta>0 if we made it here
            }

            log_printf(15, "i=%d j=%d slot=%d rse->rid_key=%s rse->status=%d\n", i, j, slot, rse->rid_key, rse->status);
            if ((rse->status != RS_STATUS_UP) && (i>=fixed_size)) continue;  //** Skip this if disabled and not in the fixed list

            tbx_stack_empty(stack, 1);
            q = query_global->head;
            kvq = &kvq_global;
            for (loop=0; loop<loop_end; loop++) {
                i_unique = 0;
                i_pickone = 0;
                while (q != NULL) {
                    state = -1;
                    switch (q->op) {
                    case RSQ_BASE_OP_KV:
                        state = rss_test(q, rse, i, kvq->unique[i_unique], &(kvq->pickone[i_pickone]));
                        log_printf(0, "KV: key=%s val=%s i_unique=%d i_pickone=%d loop=%d rss_test=%d rse->rid_key=%s\n", q->key, q->val, i_unique, i_pickone, loop, state, rse->rid_key);
                        tbx_log_flush();
                        if ((q->key_op & RSQ_BASE_KV_UNIQUE) || (q->val_op & RSQ_BASE_KV_UNIQUE)) i_unique++;
                        if ((q->key_op & RSQ_BASE_KV_PICKONE) || (q->val_op & RSQ_BASE_KV_PICKONE)) i_pickone++;
                        break;
                    case RSQ_BASE_OP_NOT:
                        a = (int *)tbx_stack_pop(stack);
                        state = (*a == 0) ? 1 : 0;
                        //log_printf(0, "NOT(%d)=%d\n", *a, state);
                        free(a);
                        break;
                    case RSQ_BASE_OP_AND:
                        a = (int *)tbx_stack_pop(stack);
                        b = (int *)tbx_stack_pop(stack);
                        state = (*a) && (*b);
                        //log_printf(0, "%d AND %d = %d\n", *a, *b, state);
                        free(a);
                        free(b);
                        break;
                    case RSQ_BASE_OP_OR:
                        a = (int *)tbx_stack_pop(stack);
                        b = (int *)tbx_stack_pop(stack);
                        state = a || b;
                        //log_printf(0, "%d OR %d = %d\n", *a, *b, state);
                        free(a);
                        free(b);
                        break;
                    }

                    tbx_type_malloc(op_state, int, 1);
                    *op_state = state;
                    tbx_stack_push(stack, (void *)op_state);
                    log_printf(15, " stack_size=%d loop=%d push state=%d\n",tbx_stack_count(stack), loop, state);
                    tbx_log_flush();
                    q = q->next;
                }

                if (query_local != NULL) {
                    q = query_local->head;
                    kvq = &kvq_local;
                }
            }

            op_state = (int *)tbx_stack_pop(stack);
            state = -1;
            if (op_state != NULL) {
                state = *op_state;
                free(op_state);
            }

            if (op_state == NULL) {
                log_printf(1, "rs_simple_request: ERROR processing i=%d EMPTY STACK\n", i);
                found = 0;
                status.op_status = OP_STATE_FAILURE;
                status.error_code = RS_ERROR_EMPTY_STACK;
            } else if  (state == 1) { //** Got one
                log_printf(15, "rs_simple_request: processing i=%d ds_key=%s\n", i, rse->ds_key);
                found = 1;
                if ((i<fixed_size) && hints_list) hints_list[i].status = RS_ERROR_OK;

                for (k=0; k<req_size; k++) {
                    if (req[k].rid_index == i) {
                        log_printf(15, "rs_simple_request: i=%d ds_key=%s, rid_key=%s size=" XOT "\n", i, rse->ds_key, rse->rid_key, req[k].size);
                        req[k].rid_key = strdup(rse->rid_key);
                        req[k].gop = ds_allocate(rss->ds, rse->ds_key, da, req[k].size, caps[k], timeout);
                        opque_add(que, req[k].gop);
                    }
                }

                if (rid_change != NULL) { //** Flag that I'm tweaking things.  The caller does the source pending/delta half
                    rid_change->delta -= change;
                    rid_change->state = ((llabs(rid_change->delta) <= rid_change->tolerance) || (rid_change->tolerance == 0)) ? 1 : 0;
                }
                break;  //** Got one so exit the RID scan and start the next one
            } else if (i<fixed_size) {  //** This should have worked so flag an error
                if (hints_list) {
                   log_printf(1, "Match fail in fixed list[%d]=%s!\n", i, hints_list[i].fixed_rid_key);
                   hints_list[i].status = RS_ERROR_FIXED_MATCH_FAIL;
                } else {
                   log_printf(1, "Match fail in fixed list and no hints are provided!\n");
                }
                status.op_status = OP_STATE_FAILURE;
                status.error_code = RS_ERROR_FIXED_MATCH_FAIL;
                if (ignore_fixed_err == 0) err_cnt++;
                break;  //** Skip to the next in the list
            } else {
                found = 0;
            }
        }

        if ((found == 0) && (i>=fixed_size)) break;

    }


    //** Clean up
    log_printf(15, "FREE j=%d\n", unique_size);
    for (i=0; i<unique_size; i++) {
        free(kvq_global.unique[i]);
    }
    free(kvq_global.unique);
    free(kvq_global.pickone);

    free(kvq_local.unique[0]);
    free(kvq_local.unique);
    free(kvq_local.pickone);

    tbx_stack_free(stack, 1);

    log_printf(15, "rs_simple_request: END n_rid=%d\n", n_rid);

//callback_t *cb = (callback_t *)que->qd.list->top->data;
//op_generic_t *gop = (op_generic_t *)cb->priv;
//log_printf(15, "top gid=%d reg=%d\n", gop_id(gop), gop_id(req[0].gop));

    apr_thread_mutex_unlock(rss->lock);

    if ((found == 0) || (err_cnt>0)) {
        opque_free(que, OP_DESTROY);

        if (status.error_code == 0) {
            log_printf(1, "rs_simple_request: Can't find enough RIDs! requested=%d found=%d err_cnt=%d\n", n_rid, found, err_cnt);
            status.op_status = OP_STATE_FAILURE;
            status.error_code = RS_ERROR_NOT_ENOUGH_RIDS;
        }
        return(gop_dummy(status));
    }

    return(opque_get_gop(que));
}
示例#12
0
double write_allocs(ibp_capset_t *caps, int qlen, int n, int asize, int block_size)
{
    int count, i, j, nleft, nblocks, rem, len, err, block_start, alloc_start;
    int *slot;
    op_status_t status;
    int64_t nbytes, last_bytes, print_bytes, delta_bytes;
    apr_int32_t nfds, finished;
    double dbytes, r1, r2;
    apr_pool_t *pool;
    apr_file_t *fd_in;
    opque_t *q;
    op_generic_t *op;
    char *buffer = (char *)malloc(block_size);
    apr_interval_time_t dt = 10;
    apr_pollfd_t pfd;
    apr_time_t stime, dtime;
    int *tbuf_index;
    tbuffer_t *buf;
    Stack_t *tbuf_free;


    tbuf_free = new_stack();
    type_malloc_clear(tbuf_index, int, qlen);
    type_malloc_clear(buf, tbuffer_t, qlen);
    for (i=0; i<qlen; i++) {
        tbuf_index[i] = i;
        push(tbuf_free, &(tbuf_index[i]));
    }

    //** Make the stuff to capture the kbd
    apr_pool_create(&pool, NULL);

    nfds = 1;
    apr_file_open_stdin(&fd_in, pool);

    pfd.p = pool;
    pfd.desc_type = APR_POLL_FILE;
    pfd.reqevents = APR_POLLIN|APR_POLLHUP;
    pfd.desc.f = fd_in;
    pfd.client_data = NULL;


    //** Init the ibp stuff
    init_buffer(buffer, 'W', block_size);
    q = new_opque();
    opque_start_execution(q);

    nblocks = asize / block_size;
    rem = asize % block_size;
    if (rem > 0) nblocks++;
    block_start = 0;
    alloc_start = 0;

    finished = 0;
    apr_poll(&pfd, nfds, &finished, dt);
    count = 0;
    nbytes=0;
    last_bytes = 0;
    delta_bytes = 1024 * 1024 * 1024;
    print_bytes = delta_bytes;
    stime = apr_time_now();

    while (finished == 0) {
//    nleft = qlen - opque_tasks_left(q);
        nleft = stack_size(tbuf_free);
//    printf("\nLOOP: nleft=%d qlen=%d\n", nleft, qlen);
        if (nleft > 0) {
            for (j=block_start; j < nblocks; j++) {
                for (i=alloc_start; i<n; i++) {
                    nleft--;
                    if (nleft <= 0) {
                        block_start = j;
                        alloc_start = i;
                        goto skip_submit;
                    }

                    slot = (int *)pop(tbuf_free);

                    if ((j==(nblocks-1)) && (rem > 0)) {
                        len = rem;
                    } else {
                        len = block_size;
                    }
//             printf("%d=(%d,%d) ", count, j, i);

                    tbuffer_single(&(buf[*slot]), len, buffer);
                    op = new_ibp_write_op(ic, get_ibp_cap(&(caps[i]), IBP_WRITECAP), j*block_size, &(buf[*slot]), 0, len, ibp_timeout);
                    gop_set_id(op, *slot);
                    ibp_op_set_cc(ibp_get_iop(op), cc);
                    ibp_op_set_ncs(ibp_get_iop(op), ncs);
                    opque_add(q, op);
                }

                alloc_start = 0;
            }

            block_start = 0;
        }

skip_submit:
        finished = 1;
        apr_poll(&pfd, nfds, &finished, dt);

        do {  //** Empty the finished queue.  Always wait for for at least 1 to complete
            op = opque_waitany(q);
            status = gop_get_status(op);
            if (status.error_code != IBP_OK) {
                printf("ERROR: Aborting with error code %d\n", status.error_code);
                finished = 0;
            }

            count++;
            i = gop_get_id(op);
            nbytes = nbytes + tbuffer_size(&(buf[i]));
            if (nbytes > print_bytes) {
                dbytes = nbytes / (1.0*1024*1024*1024);
                dtime = apr_time_now() - stime;
                r2 = dtime / (1.0 * APR_USEC_PER_SEC);
                r1 = nbytes - last_bytes;
                r1 = r1 / (r2 * 1024.0 * 1024.0);
                printf("%.2lfGB written (%.2lfMB/s : %.2lf secs)\n", dbytes, r1, r2);
                print_bytes = print_bytes + delta_bytes;
                last_bytes = nbytes;
                stime = apr_time_now();
            }

            push(tbuf_free, &(tbuf_index[i]));
            gop_free(op, OP_DESTROY);
        } while (opque_tasks_finished(q) > 0);
    }

    err = opque_waitall(q);
    if (err != OP_STATE_SUCCESS) {
        printf("write_allocs: At least 1 error occured! * ibp_errno=%d * nfailed=%d\n", err, opque_tasks_failed(q));
    }
    opque_free(q, OP_DESTROY);

    free_stack(tbuf_free, 0);
    free(tbuf_index);
    free(buf);
    free(buffer);

    apr_pool_destroy(pool);

    dbytes = nbytes;
    return(dbytes);
}
示例#13
0
void *lru_dirty_thread(apr_thread_t *th, void *data)
{
    cache_t *c = (cache_t *)data;
    cache_lru_t *cp = (cache_lru_t *)c->fn.priv;
    double df;
    int n, i;
    ex_id_t *id;
    segment_t *seg;
    opque_t *q;
    op_generic_t *gop;
    cache_segment_t *s;
    skiplist_iter_t it;
    segment_t **flush_list;

    cache_lock(c);

    log_printf(15, "Dirty thread launched\n");
    while (c->shutdown_request == 0) {
        apr_thread_cond_timedwait(cp->dirty_trigger, c->lock, cp->dirty_max_wait);

        df = cp->max_bytes;
        df = c->stats.dirty_bytes / df;

        log_printf(15, "Dirty thread running.  dirty fraction=%lf dirty bytes=" XOT " inprogress=%d  cached segments=%d\n", df, c->stats.dirty_bytes, cp->flush_in_progress, list_key_count(c->segments));

        cp->flush_in_progress = 1;
        q = new_opque();

        n = list_key_count(c->segments);
        type_malloc(flush_list, segment_t *, n);

        it = list_iter_search(c->segments, NULL, 0);
        list_next(&it, (list_key_t **)&id, (list_data_t **)&seg);
        i = 0;
        while (seg != NULL) {
            log_printf(15, "Flushing seg=" XIDT " i=%d\n", *id, i);
            flush_log();
            flush_list[i] = seg;
            s = (cache_segment_t *)seg->priv;
            atomic_set(s->cache_check_in_progress, 1);  //** Flag it as being checked
            gop = cache_flush_range(seg, s->c->da, 0, -1, s->c->timeout);
            gop_set_myid(gop, i);
            opque_add(q, gop);
            i++;

            list_next(&it, (list_key_t **)&id, (list_data_t **)&seg);
        }
        cache_unlock(c);

        //** Flag the tasks as they complete
        opque_start_execution(q);
        while ((gop = opque_waitany(q)) != NULL) {
            i = gop_get_myid(gop);
            segment_lock(flush_list[i]);
            s = (cache_segment_t *)flush_list[i]->priv;

            log_printf(15, "Flush completed seg=" XIDT " i=%d\n", segment_id(flush_list[i]), i);
            flush_log();
            atomic_set(s->cache_check_in_progress, 0);  //** Flag it as being finished
            segment_unlock(flush_list[i]);

            gop_free(gop, OP_DESTROY);
        }
        opque_free(q, OP_DESTROY);

        cache_lock(c);

        cp->flush_in_progress = 0;
        free(flush_list);

        df = cp->max_bytes;
        df = c->stats.dirty_bytes / df;
        log_printf(15, "Dirty thread sleeping.  dirty fraction=%lf dirty bytes=" XOT " inprogress=%d\n", df, c->stats.dirty_bytes, cp->flush_in_progress);
//     apr_thread_cond_timedwait(cp->dirty_trigger, c->lock, cp->dirty_max_wait);
    }

    log_printf(15, "Dirty thread Exiting\n");

    cache_unlock(c);

    return(NULL);

}
示例#14
0
ex_off_t _lru_attempt_free_mem(cache_t *c, segment_t *page_seg, ex_off_t bytes_to_free)
{
    cache_lru_t *cp = (cache_lru_t *)c->fn.priv;
    cache_segment_t *s;
    segment_t *pseg;
    cache_page_t *p;
    page_lru_t *lp;
    Stack_ele_t *ele;
    op_generic_t *gop;
    opque_t *q;
    ex_off_t total_bytes, freed_bytes, pending_bytes, *poff;
    ex_off_t *segid;
    ex_off_t min_off, max_off;
    list_iter_t sit;
    int count, bits, cw, flush_count;
    list_t *table;
    page_table_t *ptable;
    pigeon_coop_hole_t pch, pt_pch;

    log_printf(15, "START seg=" XIDT " bytes_to_free=" XOT " bytes_used=" XOT " stack_size=%d\n", segment_id(page_seg), bytes_to_free, cp->bytes_used, stack_size(cp->stack));

    freed_bytes = 0;
    pending_bytes = 0;
    total_bytes = 0;

    //** cache_lock(c) is already acquired
    pch = reserve_pigeon_coop_hole(cp->free_pending_tables);
    table = *(list_t **)pigeon_coop_hole_data(&pch);

    //** Get the list of pages to free
    move_to_bottom(cp->stack);
    ele = stack_unlink_current(cp->stack, 1);
    while ((total_bytes < bytes_to_free) && (ele != NULL)) {
        p = (cache_page_t *)get_stack_ele_data(ele);
        lp = (page_lru_t *)p->priv;

        bits = atomic_get(p->bit_fields);
        log_printf(15, "checking page for release seg=" XIDT " p->offset=" XOT " bits=%d\n", segment_id(p->seg), p->offset, bits);
        flush_log();

        if ((bits & C_TORELEASE) == 0) { //** Skip it if already flagged for removal
            ptable = (page_table_t *)list_search(table, (list_key_t *)&(segment_id(p->seg)));
            if (ptable == NULL) {  //** Have to make a new segment entry
                pt_pch = reserve_pigeon_coop_hole(cp->free_page_tables);
                ptable = (page_table_t *)pigeon_coop_hole_data(&pt_pch);
                ptable->seg = p->seg;
                ptable->id = segment_id(p->seg);
                ptable->pch = pt_pch;
                list_insert(table, &(ptable->id), ptable);
            }

            cp->limbo_pages++;
            log_printf(15, "UNLINKING seg=" XIDT " p->offset=" XOT " bits=%d limbo=%d\n", segment_id(p->seg), p->offset, bits, cp->limbo_pages);

            atomic_inc(p->access_pending[CACHE_READ]);  //** Do this so it's not accidentally deleted
            push(ptable->stack, p);
            s = (cache_segment_t *)p->seg->priv;
            total_bytes += s->page_size;
            free(lp->ele);
            lp->ele = NULL;  //** Mark it as removed from the list so a page_release doesn't free also
        }

        if (total_bytes < bytes_to_free) ele = stack_unlink_current(cp->stack, 1);
    }


    if (total_bytes == 0) {  //** Nothing to do so exit
        log_printf(15, "Nothing to do so exiting\n");
        release_pigeon_coop_hole(cp->free_pending_tables, &pch);
        return(0);
    }

    cache_unlock(c);  //** Don't need the cache lock for the next part

    q = new_opque();
    opque_start_execution(q);

    //** Now cycle through the segments to be freed
    pending_bytes = 0;
    sit = list_iter_search(table, list_first_key(table), 0);
    list_next(&sit, (list_key_t **)&segid, (list_data_t **)&ptable);
    while (ptable != NULL) {
        //** Verify the segment is still valid.  If not then just delete everything
        pseg = list_search(c->segments, segid);
        if (pseg != NULL) {
            segment_lock(ptable->seg);
            min_off = s->total_size;
            max_off = -1;

            s = (cache_segment_t *)ptable->seg->priv;
            while ((p = pop(ptable->stack)) != NULL) {
                atomic_dec(p->access_pending[CACHE_READ]); //** Removed my access control from earlier
                flush_count = atomic_get(p->access_pending[CACHE_FLUSH]);
                cw = atomic_get(p->access_pending[CACHE_WRITE]);
                count = atomic_get(p->access_pending[CACHE_READ]) + cw + flush_count;
                bits = atomic_get(p->bit_fields);
                if (count != 0) { //** Currently in use so wait for it to be released
                    if (cw > 0) {  //** Got writes so need to wait until they complete otherwise the page may not get released
                        bits = bits | C_TORELEASE;  //** Mark it for release
                        atomic_set(p->bit_fields, bits);
                        _cache_drain_writes(p->seg, p);  //** Drain the write ops
                        bits = atomic_get(p->bit_fields);  //** Get the bit fields to see if it's dirty
                    }

                    if (flush_count == 0) {  //** Make sure it's not already being flushed
                        if ((bits & C_ISDIRTY) != 0) {  //** Have to flush it don't have to track it cause the flush will do the release
                            if (min_off > p->offset) min_off = p->offset;
                            if (max_off < p->offset) max_off = p->offset;
                        }
                    }
                    bits = bits | C_TORELEASE;

                    log_printf(15, "in use tagging for release seg=" XIDT " p->offset=" XOT " bits=%d\n", segment_id(p->seg), p->offset, bits);
                    atomic_set(p->bit_fields, bits);

                    pending_bytes += s->page_size;
                } else {  //** Not in use
                    if ((bits & (C_ISDIRTY|C_EMPTY)) == 0) {  //** Don't have to flush it just drop the page
                        cp->limbo_pages--;
                        log_printf(15, "FREEING page seg=" XIDT " p->offset=" XOT " bits=%d limbo=%d\n", segment_id(p->seg), p->offset, bits, cp->limbo_pages);
                        list_remove(s->pages, &(p->offset), p);  //** Have to do this here cause p->offset is the key var
                        if (p->data[0].ptr) free(p->data[0].ptr);
                        if (p->data[1].ptr) free(p->data[1].ptr);
                        lp = (page_lru_t *)p->priv;
                        free(lp);
                        freed_bytes += s->page_size;
                    } else {         //** Got to flush the page first but don't have to track it cause the flush will do the release
                        if (p->offset > -1) { //** Skip blank pages
                            if (min_off > p->offset) min_off = p->offset;
                            if (max_off < p->offset) max_off = p->offset;
                        }

                        bits = bits | C_TORELEASE;
                        atomic_set(p->bit_fields, bits);

                        pending_bytes += s->page_size;
                        if (p->offset > -1) {
                            log_printf(15, "FLUSHING page seg=" XIDT " p->offset=" XOT " bits=%d\n", segment_id(p->seg), p->offset, bits);
                        } else {
                            log_printf(15, "RELEASE trigger for empty page seg=" XIDT " p->offset=" XOT " bits=%d\n", segment_id(p->seg), p->offset, bits);
                        }
                    }
                }

                list_next(&sit, (list_key_t **)&poff, (list_data_t **)&p);
            }

            segment_unlock(ptable->seg);

            if (max_off>-1) {
                gop = cache_flush_range(ptable->seg, s->c->da, min_off, max_off + s->page_size - 1, s->c->timeout);
                opque_add(q, gop);
            }
        } else {  //** Segment has been deleted so drop everything cause it's already freeed
            empty_stack(ptable->stack, 0);
        }

        cache_lock(c);
        release_pigeon_coop_hole(cp->free_page_tables, &(ptable->pch));
        cache_unlock(c);

        list_next(&sit, (skiplist_key_t **)&pseg, (skiplist_data_t **)&ptable);
    }

    cache_lock(c);
    log_printf(15, "BEFORE waitall seg=" XIDT " bytes_to_free=" XOT " bytes_used=" XOT " freed_bytes=" XOT " pending_bytes=" XOT "\n",
               segment_id(page_seg), bytes_to_free, cp->bytes_used, freed_bytes, pending_bytes);
    cache_unlock(c);


    //** Wait for any tasks to complete
    opque_waitall(q);
    opque_free(q, OP_DESTROY);

    //** Had this when we came in
    cache_lock(c);

    log_printf(15, "AFTER waitall seg=" XIDT " bytes_used=" XOT "\n", segment_id(page_seg), cp->bytes_used);

    cp->bytes_used -= freed_bytes;  //** Update how much I directly freed

    log_printf(15, "AFTER used update seg=" XIDT " bytes_used=" XOT "\n", segment_id(page_seg), cp->bytes_used);

    //** Clean up
    empty_skiplist(table);
    release_pigeon_coop_hole(cp->free_pending_tables, &pch);

    log_printf(15, "total_bytes marked for removal =" XOT "\n", total_bytes);

    return(total_bytes);
}
示例#15
0
void *ongoing_heartbeat_thread(apr_thread_t *th, void *data)
{
    mq_ongoing_t *on = (mq_ongoing_t *)data;
    apr_time_t timeout = apr_time_make(on->check_interval, 0);
    op_generic_t *gop;
    mq_msg_t *msg;
    ongoing_hb_t *oh;
    ongoing_table_t *table;
    apr_hash_index_t *hi, *hit;
    opque_t *q;
    char *id;
    mq_msg_hash_t *remote_hash;
    apr_time_t now;
    apr_ssize_t id_len;
    int n, k;
    char *remote_host_string;

    apr_thread_mutex_lock(on->lock);
    n = 0;
    do {
        now = apr_time_now() - apr_time_from_sec(5);  //** Give our selves a little buffer
        log_printf(5, "Loop Start now=" TT "\n", apr_time_now());
        q = new_opque();
//     opque_start_execution(q);
        for (hit = apr_hash_first(NULL, on->table); hit != NULL; hit = apr_hash_next(hit)) {
            apr_hash_this(hit, (const void **)&remote_hash, &id_len, (void **)&table);

            k = apr_hash_count(table->table);
            if (log_level() > 1) {
                remote_host_string = mq_address_to_string(table->remote_host);
                log_printf(1, "host=%s count=%d\n", remote_host_string, k);
                free(remote_host_string);
            }

            for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) {
                apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh);
                log_printf(1, "id=%s now=" TT " next_check=" TT "\n", oh->id, apr_time_sec(apr_time_now()), apr_time_sec(oh->next_check));
                if (now > oh->next_check) {
                    log_printf(1, "id=%s sending HEARTBEAT EXEC SUBMIT nows=" TT " hb=%d\n", oh->id, apr_time_sec(apr_time_now()), oh->heartbeat);
                    flush_log();
                    //** Form the message
                    msg = mq_make_exec_core_msg(table->remote_host, 1);
                    mq_msg_append_mem(msg, ONGOING_KEY, ONGOING_SIZE, MQF_MSG_KEEP_DATA);
                    mq_msg_append_mem(msg, oh->id, oh->id_len, MQF_MSG_KEEP_DATA);
                    mq_msg_append_mem(msg, NULL, 0, MQF_MSG_KEEP_DATA);

                    //** Make the gop
                    gop = new_mq_op(on->mqc, msg, ongoing_response_status, NULL, NULL, oh->heartbeat);
                    gop_set_private(gop, table);
                    opque_add(q, gop);

                    oh->in_progress = 1; //** Flag it as in progress so it doesn't get deleted behind the scenes
                }
            }

        }
        log_printf(5, "Loop end now=" TT "\n", apr_time_now());

        //** Wait for it to complete
        apr_thread_mutex_unlock(on->lock);
        opque_waitall(q);
        apr_thread_mutex_lock(on->lock);

        //** Dec the counters
        while ((gop = opque_waitany(q)) != NULL) {
            log_printf(0, "gid=%d gotone status=%d now=" TT "\n", gop_id(gop), (gop_get_status(gop)).op_status, apr_time_sec(apr_time_now()));
            table = gop_get_private(gop);
            table->count--;

            //** Update the next check
            for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) {
                apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh);
                oh->next_check = apr_time_now() + apr_time_from_sec(oh->heartbeat);

                //** Check if we get rid of it
                oh->in_progress = 0;
                if (oh->count <= 0) {  //** Need to delete it
                    apr_hash_set(table->table, id, id_len, NULL);
                    free(oh->id);
                    free(oh);
                }
            }

            gop_free(gop, OP_DESTROY);
        }
        opque_free(q, OP_DESTROY);

        now = apr_time_now();
        log_printf(2, "sleeping %d now=" TT "\n", on->check_interval, now);

        //** Sleep until time for the next heartbeat or time to exit
        if (on->shutdown == 0) apr_thread_cond_timedwait(on->cond, on->lock, timeout);
        n = on->shutdown;

        now = apr_time_now() - now;
        log_printf(2, "main loop bottom n=%d dt=" TT " sec=" TT "\n", n, now, apr_time_sec(now));
    } while (n == 0);

    log_printf(2, "CLEANUP\n");

    for (hit = apr_hash_first(NULL, on->table); hit != NULL; hit = apr_hash_next(hit)) {
        apr_hash_this(hit, (const void **)&remote_hash, &id_len, (void **)&table);

        for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) {
            apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh);
            apr_hash_set(table->table, id, id_len, NULL);
            free(oh->id);
            free(oh);
        }

        apr_hash_set(on->table, &(table->remote_host_hash), sizeof(mq_msg_hash_t), NULL);
        mq_msg_destroy(table->remote_host);
        free(table);
    }

    log_printf(2, "EXITING\n");

    apr_thread_mutex_unlock(on->lock);

    return(NULL);
}
示例#16
0
int main(int argc, char **argv)
{
    int chunk_size = 10;
    int n_chunks = 10;
    int bufsize= n_chunks * chunk_size;
    char base_data[bufsize+1];
    char buffer[bufsize+1];
    char log1_data[bufsize+1];
    char log2_data[bufsize+1];
    char log3_data[bufsize+1];
    tbuffer_t tbuf;
    ex_iovec_t ex_iov, ex_iov_table[n_chunks];
    int i, err;
    char *fname = NULL;
    exnode_t *ex;
    exnode_exchange_t *exp;
    segment_t *seg, *clone, *clone2, *clone3;
    seglog_priv_t *s;
    opque_t *q;

    if (argc < 2) {
        printf("\n");
        printf("log_test LIO_COMMON_OPTIONS log.ex3\n");
        lio_print_options(stdout);
        printf("    log.ex3 - Log file to use.  IF the file is not empty all it's contents are truncated\n");
        printf("\n");
        return(1);
    }

    lio_init(&argc, &argv);

    //*** Parse the args
    //** This is the remote file to download
    i = 1;
    fname = argv[i];
    i++;
    if (fname == NULL) {
        printf("Missing log file!\n");
        return(2);
    }

    //** Load it
    exp = exnode_exchange_load_file(fname);

    //** and parse the remote exnode
    ex = exnode_create();
    if (exnode_deserialize(ex, exp, lio_gc->ess) != 0) {
        printf("ERROR parsing exnode!  Aborting!\n");
        abort();
    }

    //** Get the default view to use
    seg = exnode_get_default(ex);
    if (seg == NULL) {
        printf("No default segment!  Aborting!\n");
        abort();
    }
    s = (seglog_priv_t *)seg->priv;

    //** Verify the type
    if (strcmp(segment_type(seg), SEGMENT_TYPE_LOG) != 0) {
        printf("Invalid exnode type.  Segment should be a single level log but got a type of %s\n", segment_type(seg));
        abort();
    }

    //** Now get the base type.  It should NOT be a log
    if (strcmp(segment_type(s->base_seg), SEGMENT_TYPE_LOG) == 0) {
        printf("Log segments base should NOT be another log segment!\n");
        abort();
    }


    //** Truncate the log and base
    q = new_opque();
    opque_add(q, segment_truncate(s->table_seg, lio_gc->da, 0, lio_gc->timeout));
    opque_add(q, segment_truncate(s->data_seg, lio_gc->da, 0, lio_gc->timeout));
    opque_add(q, segment_truncate(s->base_seg, lio_gc->da, 0, lio_gc->timeout));
    err = opque_waitall(q);
    if (err != OP_STATE_SUCCESS) {
        printf("Error with truncate of initial log segment!\n");
        abort();
    }
    s->file_size = 0;
    s->data_size = 0;
    s->log_size = 0;

    //*************************************************************************
    //--------------------- Testing starts here -------------------------------
    //*************************************************************************

    //*************************************************************************
    //------- Generate a base with an empty log and read back -----------------
    //*************************************************************************
    //** Make the base buffer and write it
    memset(base_data, 'B', bufsize);
    base_data[bufsize] = '\0';
    tbuffer_single(&tbuf, bufsize, base_data);
    ex_iovec_single(&ex_iov, 0, bufsize);
    { int result = gop_sync_exec(segment_write(s->base_seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    s->file_size = bufsize;  //** Since we're peeking we have to adjust the file size
    tbuffer_single(&tbuf, bufsize, buffer);  //** Read it directly back fro mthe base to make sure that works
    { int result = gop_sync_exec(segment_read(s->base_seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    buffer[bufsize] = '\0';
    { int result = strcmp(buffer, base_data); assert(result == 0); }

    //** Do the same for the log
    { int result = gop_sync_exec(segment_read(seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, base_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //-- Clone the base structure and the use segment_copy to copy the data and verify --
    //*************************************************************************
    clone = NULL;
    { int result = gop_sync_exec(segment_clone(seg, lio_gc->da, &clone, CLONE_STRUCTURE, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = gop_sync_exec(segment_copy(lio_gc->tpc_unlimited, lio_gc->da, NULL, seg, clone, 0, 0, bufsize, chunk_size, buffer, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, base_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //-------------------- Write to the log and read back ---------------------
    //*************************************************************************
    //** We are writing 1's to the even chunks
    memcpy(log1_data, base_data, bufsize);
    memset(buffer, '1', chunk_size);
    for (i=0; i<n_chunks; i+=2) {
        memcpy(&(log1_data[i*chunk_size]), buffer, chunk_size);
        ex_iovec_single(&(ex_iov_table[i]), i*chunk_size, chunk_size);
        opque_add(q, segment_write(seg, lio_gc->da, NULL, 1, &(ex_iov_table[i]), &tbuf, 0, lio_gc->timeout));
    }
    { int result = opque_waitall(q); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log1_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //------------------- Merge_with base and verify --------------------------
    //*************************************************************************
    { int result = gop_sync_exec(slog_merge_with_base(seg, lio_gc->da, chunk_size, buffer, 1, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log1_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //--------------- Write to the new empty log and verify -------------------
    //*************************************************************************
    //** We are writing 2's to *most* of the odd chunks
    memcpy(log1_data, buffer, bufsize);
    memset(buffer, '2', chunk_size);
    for (i=1; i<n_chunks; i+=2) {
        memcpy(&(log1_data[i*chunk_size]), buffer, chunk_size);
        ex_iovec_single(&(ex_iov_table[i]), i*chunk_size, chunk_size);
        opque_add(q, segment_write(seg, lio_gc->da, NULL, 1, &(ex_iov_table[i]), &tbuf, 0, lio_gc->timeout));
    }
    { int result = opque_waitall(q); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(seg, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log1_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //---------- Replace the clones base with seg(Log1) and verify ------------
    //*************************************************************************
    { int result = gop_sync_exec(segment_remove(clone, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    segment_destroy(clone);
    clone = NULL;
    { int result = gop_sync_exec(segment_clone(seg, lio_gc->da, &clone, CLONE_STRUCTURE, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    s = (seglog_priv_t *)clone->priv;

    s->base_seg = seg;
    s->file_size = segment_size(seg);

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log1_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //---------- Write to the clones log and verify (now have 2 logs) ---------
    //*************************************************************************
    memcpy(log2_data, log1_data, bufsize);
    memset(buffer, '3', 1.5*chunk_size);
    for (i=0; i<n_chunks; i+=4) {
        memcpy(&(log2_data[i*chunk_size]), buffer, 1.5*chunk_size);
        ex_iovec_single(&(ex_iov_table[i]), i*chunk_size, 1.5*chunk_size);
        opque_add(q, segment_write(clone, lio_gc->da, NULL, 1, &(ex_iov_table[i]), &tbuf, 0, lio_gc->timeout));
    }
    { int result = opque_waitall(q); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log2_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //---- clone2 = clone (structure and data). Verify the contents -----------
    //*************************************************************************
    clone2 = NULL;
    { int result = gop_sync_exec(segment_clone(clone, lio_gc->da, &clone2, CLONE_STRUCT_AND_DATA, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone2, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log2_data, bufsize, 0); assert(result == 0); }

    //** We don't need this anymore so destroy it
    { int result = gop_sync_exec(segment_remove(clone2, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    segment_destroy(clone2);

    //*************************************************************************
    //---------------- Clone2 = clone's structure *only* ----------------------
    //*************************************************************************
    clone2 = NULL;
    { int result = gop_sync_exec(segment_clone(clone, lio_gc->da, &clone2, CLONE_STRUCTURE, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    //*************************************************************************
    //-------------- Replace clone2's base with clone and verify --------------
    //*************************************************************************
    s = (seglog_priv_t *)clone2->priv;
    { int result = gop_sync_exec(segment_remove(s->base_seg, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    segment_destroy(s->base_seg);

    s->base_seg = clone;
    s->file_size = segment_size(clone);

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone2, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log2_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //----------- Write to Clone2 and verify (now have 3 logs) ----------------
    //*************************************************************************
    memcpy(log3_data, log2_data, bufsize);
    memset(buffer, '4', chunk_size);
    for (i=0; i<n_chunks; i+=2) {
        memcpy(&(log3_data[i*chunk_size + chunk_size/3]), buffer, chunk_size);
        ex_iovec_single(&(ex_iov_table[i]), i*chunk_size + chunk_size/3, chunk_size);
        opque_add(q, segment_write(clone2, lio_gc->da, NULL, 1, &(ex_iov_table[i]), &tbuf, 0, lio_gc->timeout));
    }
    { int result = opque_waitall(q); assert(result == OP_STATE_SUCCESS); }

    //** Read it back
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone2, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log3_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    // -- clone3 = clone2 structure and contents and verify
    //*************************************************************************
    clone3 = NULL;
    { int result = gop_sync_exec(segment_clone(clone2, lio_gc->da, &clone3, CLONE_STRUCT_AND_DATA, NULL, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    memset(buffer, 0, bufsize);
    { int result = gop_sync_exec(segment_read(clone3, lio_gc->da, NULL, 1, &ex_iov, &tbuf, 0, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = compare_buffers_print(buffer, log3_data, bufsize, 0); assert(result == 0); }

    //*************************************************************************
    //--------------------- Testing Finished -------------------------------
    //*************************************************************************

    //** Clean up
    { int result = gop_sync_exec(segment_remove(clone3, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }
    { int result = gop_sync_exec(segment_remove(clone2, lio_gc->da, lio_gc->timeout)); assert(result == OP_STATE_SUCCESS); }

    segment_destroy(clone3);
    segment_destroy(clone2);
    segment_destroy(seg);


    exnode_exchange_destroy(exp);

    lio_shutdown();

    return(0);
}
示例#17
0
int main(int argc, char **argv)
{
    int i, j, ftype, rg_mode, start_option, start_index, prefix_len, nosort, err;
    ex_off_t fcount;
    char *fname;
    ls_entry_t *lse;
    tbx_list_t *table;
//  lio_path_tuple_t tuple;
    os_regex_table_t *rp_single, *ro_single;
    os_object_iter_t *it;
    tbx_list_iter_t lit;
    opque_t *q;
    op_generic_t *gop;
    char *keys[] = { "system.owner", "system.exnode.size", "system.modify_data", "os.create",  "os.link_count" };
    char *vals[5];
    int v_size[5];
    int n_keys = 5;
    int recurse_depth = 0;
    int obj_types = OS_OBJECT_ANY;
    int return_code = 0;

//printf("argc=%d\n", argc);
    if (argc < 2) {
        printf("\n");
        printf("lio_ls LIO_COMMON_OPTIONS [-rd recurse_depth] [-ns] LIO_PATH_OPTIONS\n");
        lio_print_options(stdout);
        lio_print_path_options(stdout);
        printf("\n");
        printf("    -rd recurse_depth  - Max recursion depth on directories. Defaults to %d\n", recurse_depth);
        printf("    -t  object_types   - Types of objects to list bitwise OR of 1=Files, 2=Directories, 4=symlink, 8=hardlink.  Default is %d.\n", obj_types);
        printf("    -ns                - Don't sort the output\n");
        return(1);
    }

    lio_init(&argc, &argv);

    //*** Parse the args
    rp_single = ro_single = NULL;
    nosort = 0;

    rg_mode = lio_parse_path_options(&argc, argv, lio_gc->auto_translate, &tuple, &rp_single, &ro_single);

    i=1;
    do {
        start_option = i;

        if (strcmp(argv[i], "-rd") == 0) { //** Recurse depth
            i++;
            recurse_depth = atoi(argv[i]);
            i++;
        } else if (strcmp(argv[i], "-t") == 0) {  //** Object types
            i++;
            obj_types = atoi(argv[i]);
            i++;
        } else if (strcmp(argv[i], "-ns") == 0) {  //** Strip off the path prefix
            i++;
            nosort = 1;
        }

    } while ((start_option < i) && (i<argc));
    start_index = i;

    if (rg_mode == 0) {
        if (i>=argc) {
            info_printf(lio_ifd, 0, "Missing directory!\n");
            return(2);
        }
    } else {
        start_index--;  //** Ther 1st entry will be the rp created in lio_parse_path_options
    }

    fcount = 0;

    q = new_opque();
    table = tbx_list_create(0, &tbx_list_string_compare, NULL, tbx_list_no_key_free, tbx_list_no_data_free);


    for (j=start_index; j<argc; j++) {
        log_printf(5, "path_index=%d argc=%d rg_mode=%d\n", j, argc, rg_mode);
        if (rg_mode == 0) {
            //** Create the simple path iterator
            tuple = lio_path_resolve(lio_gc->auto_translate, argv[j]);
            lio_path_wildcard_auto_append(&tuple);
            rp_single = os_path_glob2regex(tuple.path);
        } else {
            rg_mode = 0;  //** Use the initial rp
        }

        for (i=0; i<n_keys; i++) v_size[i] = -tuple.lc->max_attr;
        memset(vals, 0, sizeof(vals));
        it = lio_create_object_iter_alist(tuple.lc, tuple.creds, rp_single, ro_single, obj_types, recurse_depth, keys, (void **)vals, v_size, n_keys);
        if (it == NULL) {
            info_printf(lio_ifd, 0, "ERROR: Failed with object_iter creation\n");
            return_code = EIO;
            goto finished;
        }

        while ((ftype = lio_next_object(tuple.lc, it, &fname, &prefix_len)) > 0) {
            tbx_type_malloc_clear(lse, ls_entry_t, 1);
            lse->fname = fname;
            lse->ftype = ftype;
            lse->prefix_len = prefix_len;
            memcpy(lse->v_size, v_size, sizeof(v_size));
            memcpy(lse->vals, vals, sizeof(vals));

            for (i=0; i<n_keys; i++) v_size[i] = -tuple.lc->max_attr;
            memset(vals, 0, sizeof(vals));

            //** Check if we have a link.  If so we need to resolve the link path
            if ((ftype & OS_OBJECT_SYMLINK) > 0) {
                lse->link_size = -64*1024;
                gop = gop_lio_get_attr(tuple.lc, tuple.creds, lse->fname, NULL, "os.link", (void **)&(lse->link), &(lse->link_size));
                gop_set_private(gop, lse);
                opque_add(q, gop);
                if (nosort == 1) opque_waitall(q);
            }

            if (fcount == 0) {
                info_printf(lio_ifd, 0, "  Perms     Ref   Owner        Size           Creation date              Modify date             Filename [-> link]\n");
                info_printf(lio_ifd, 0, "----------  ---  ----------  ----------  ------------------------  ------------------------  ------------------------------\n");
            }
            fcount++;

            if (nosort == 1) {
                ls_format_entry(lio_ifd, lse);
            } else {
                tbx_list_insert(table, lse->fname, lse);
            }
        }

        lio_destroy_object_iter(tuple.lc, it);

        lio_path_release(&tuple);
        if (rp_single != NULL) {
            os_regex_table_destroy(rp_single);
            rp_single = NULL;
        }
        if (ro_single != NULL) {
            os_regex_table_destroy(ro_single);
            ro_single = NULL;
        }
    }

    //** Wait for any readlinks to complete
    err = (opque_task_count(q) > 0) ? opque_waitall(q) : OP_STATE_SUCCESS;
    if (err != OP_STATE_SUCCESS) {
        info_printf(lio_ifd, 0, "ERROR: Failed with readlink operation!\n");
        return_code = EIO;
    }

    //** Now sort and print things if needed
    if (nosort == 0) {
        lit = tbx_list_iter_search(table, NULL, 0);
        while ((tbx_list_next(&lit, (tbx_list_key_t **)&fname, (tbx_list_data_t **)&lse)) == 0) {
            ls_format_entry(lio_ifd, lse);
        }
    }

    tbx_list_destroy(table);

    if (fcount == 0) return_code = 2;

finished:
    opque_free(q, OP_DESTROY);

    lio_shutdown();

    return(return_code);
}