Пример #1
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);
}
Пример #2
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);
}
Пример #3
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);
}
Пример #4
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);
}
Пример #5
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);
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
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);
}