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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }