void _add_hportal_op(host_portal_t *hp, op_generic_t *hsop, int addtotop, int release_master) { command_op_t *hop = &(hsop->op->cmd); tbx_stack_ele_t *ele; hp->workload = hp->workload + hop->workload; if (addtotop == 1) { tbx_stack_push(hp->que, (void *)hsop); } else { tbx_stack_move_to_bottom(hp->que); tbx_stack_insert_below(hp->que, (void *)hsop); }; //** Since we've now added the op to the hp que we can release the master lock if needed //** without fear of having the compact_hportals() coming in and destroying the hp if (release_master == 1) apr_thread_mutex_unlock(hp->context->lock); //** Check if we need a little pre-processing if (hop->on_submit != NULL) { ele = tbx_stack_get_current_ptr(hp->que); hop->on_submit(hp->que, ele); } hportal_signal(hp); //** Send a signal for any tasks listening }
void _tp_submit_op(void *arg, gop_op_generic_t *gop) { gop_thread_pool_op_t *op = gop_get_tp(gop); apr_status_t aerr; int running; log_printf(15, "_tp_submit_op: gid=%d\n", gop_id(gop)); tbx_atomic_inc(op->tpc->n_submitted); op->via_submit = 1; running = tbx_atomic_inc(op->tpc->n_running) + 1; if (running > op->tpc->max_concurrency) { apr_thread_mutex_lock(_tp_lock); tbx_atomic_inc(op->tpc->n_overflow); if (op->depth >= op->tpc->recursion_depth) { //** Check if we hit the max recursion log_printf(0, "GOP has a recursion depth >= max specified in the TP!!!! gop depth=%d TPC max=%d\n", op->depth, op->tpc->recursion_depth); tbx_stack_push(op->tpc->reserve_stack[op->tpc->recursion_depth-1], gop); //** Need to do the push and overflow check } else { tbx_stack_push(op->tpc->reserve_stack[op->depth], gop); //** Need to do the push and overflow check } gop = _tpc_overflow_next(op->tpc); //** along with the submit or rollback atomically if (gop) { op = gop_get_tp(gop); aerr = apr_thread_pool_push(op->tpc->tp,(void *(*)(apr_thread_t *, void *))thread_pool_exec_fn, gop, APR_THREAD_TASK_PRIORITY_NORMAL, NULL); } else { tbx_atomic_dec(op->tpc->n_running); //** We didn't actually submit anything if (op->overflow_slot != -1) { //** Check if we need to undo our overflow slot op->tpc->overflow_running_depth[op->overflow_slot] = -1; } aerr = APR_SUCCESS; } apr_thread_mutex_unlock(_tp_lock); } else { aerr = apr_thread_pool_push(op->tpc->tp, (void *(*)(apr_thread_t *, void *))thread_pool_exec_fn, gop, APR_THREAD_TASK_PRIORITY_NORMAL, NULL); } if (aerr != APR_SUCCESS) { log_printf(0, "ERROR submiting task! aerr=%d gid=%d\n", aerr, gop_id(gop)); } }
void rsrs_update_register(resource_service_fn_t *rs, mq_frame_t *fid, mq_msg_t *address, int timeout) { rs_remote_server_priv_t *rsrs = (rs_remote_server_priv_t *)rs->priv; rsrs_update_handle_t *h; tbx_type_malloc(h, rsrs_update_handle_t, 1); //** Form the core message h->msg = mq_msg_new(); mq_msg_append_mem(h->msg, MQF_VERSION_KEY, MQF_VERSION_SIZE, MQF_MSG_KEEP_DATA); mq_msg_append_mem(h->msg, MQF_RESPONSE_KEY, MQF_RESPONSE_SIZE, MQF_MSG_KEEP_DATA); mq_msg_append_frame(h->msg, fid); mq_get_frame(fid, (void **)&(h->id), &(h->id_size)); //** Add the empty version frame and track it for filling in later h->version_frame = mq_frame_new(NULL, 0, MQF_MSG_AUTO_FREE); mq_msg_append_frame(h->msg, h->version_frame); //** Add the empty config frame and track it for filling in later h->config_frame = mq_frame_new(NULL, 0, MQF_MSG_AUTO_FREE); mq_msg_append_frame(h->msg, h->config_frame); //** End with an empty frame mq_msg_append_mem(h->msg, NULL, 0, MQF_MSG_KEEP_DATA); //** Now address it mq_apply_return_address_msg(h->msg, address, 0); //** Figure out when we wake up if no change if (timeout > 10) { h->reply_time = apr_time_from_sec(timeout-10); } else if (timeout > 5) { h->reply_time = apr_time_from_sec(timeout-5); } else { h->reply_time = apr_time_from_sec(1); } h->reply_time += apr_time_now(); apr_thread_mutex_lock(rsrs->lock); //** Add it to the queue tbx_stack_push(rsrs->pending, h); //** Check if we need to change when we wake up if ((h->reply_time < rsrs->wakeup_time) || (rsrs->wakeup_time == 0)) rsrs->wakeup_time = h->reply_time; log_printf(5, "timeout=%d now=" TT " reply_time=" TT " wakeup=" TT "\n", timeout, apr_time_now(), h->reply_time, rsrs->wakeup_time); apr_thread_mutex_unlock(rsrs->lock); }
int data_block_set_attr(lio_data_block_t *b, char *key, char *val) { lio_data_block_attr_t *attr; //** See if the key exists attr = db_find_key(b->attr_stack, key); if (attr == NULL) { //** See if we need to add the attribute tbx_type_malloc_clear(attr, lio_data_block_attr_t, 1); attr->key = strdup(key); } if (attr->value != NULL) free(attr->value); //** Free the old value attr->value = (val != NULL) ? strdup(val) : NULL; //** Store the new one if (b->attr_stack == NULL) b->attr_stack = tbx_stack_new(); tbx_stack_push(b->attr_stack, attr); return(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)); }
lio_data_block_t *data_block_deserialize_text(lio_service_manager_t *sm, ex_id_t id, lio_exnode_exchange_t *exp) { int bufsize=1024; char capgrp[bufsize]; char *text, *etext; int i; lio_data_block_t *b; lio_data_service_fn_t *ds; tbx_inip_file_t *cfd; tbx_inip_group_t *cg; tbx_inip_element_t *ele; char *key; lio_data_block_attr_t *attr; //** Parse the ini text cfd = exp->text.fd; //** Find the cooresponding cap snprintf(capgrp, bufsize, "block-" XIDT, id); cg = tbx_inip_group_find(cfd, capgrp); if (cg == NULL) { log_printf(0, "data_block_deserialize_text: id=" XIDT " not found!\n", id); return(NULL); } //** Determine the type and make a blank block text = tbx_inip_get_string(cfd, capgrp, "type", ""); ds = lio_lookup_service(sm, DS_SM_RUNNING, text); if (ds == NULL) { log_printf(0, "data_block_deserialize_text: b->id=" XIDT " Unknown data service tpye=%s!\n", id, text); return(NULL);; } free(text); //** Make the space b = data_block_create_with_id(ds, id); //** and parse the fields b->rid_key = tbx_inip_get_string(cfd, capgrp, "rid_key", ""); b->size = tbx_inip_get_integer(cfd, capgrp, "size", b->size); b->max_size = tbx_inip_get_integer(cfd, capgrp, "max_size", b->max_size); i = tbx_inip_get_integer(cfd, capgrp, "ref_count", b->ref_count); tbx_atomic_set(b->ref_count, 0); tbx_atomic_set(b->initial_ref_count, i); etext = tbx_inip_get_string(cfd, capgrp, "read_cap", ""); ds_set_cap(b->ds, b->cap, DS_CAP_READ, tbx_stk_unescape_text('\\', etext)); free(etext); etext = tbx_inip_get_string(cfd, capgrp, "write_cap", ""); ds_set_cap(b->ds, b->cap, DS_CAP_WRITE, tbx_stk_unescape_text('\\', etext)); free(etext); etext = tbx_inip_get_string(cfd, capgrp, "manage_cap", ""); ds_set_cap(b->ds, b->cap, DS_CAP_MANAGE, tbx_stk_unescape_text('\\', etext)); free(etext); //** Now cycle through any misc attributes set ele = tbx_inip_ele_first(tbx_inip_group_find(cfd, capgrp)); while (ele != NULL) { key = tbx_inip_ele_get_key(ele); //** Ignore the builtin commands if ((strcmp("rid_key", key) != 0) && (strcmp("size", key) != 0) && (strcmp("max_size", key) != 0) && (strcmp("type", key) != 0) && (strcmp("ref_count", key) != 0) && (strcmp("read_cap", key) != 0) && (strcmp("write_cap", key) != 0) && (strcmp("manage_cap", key) != 0)) { tbx_type_malloc(attr, lio_data_block_attr_t, 1); attr->key = tbx_stk_unescape_text('\\', tbx_inip_ele_get_key(ele)); attr->value = tbx_stk_unescape_text('\\', tbx_inip_ele_get_value(ele)); if (b->attr_stack == NULL) b->attr_stack = tbx_stack_new(); tbx_stack_push(b->attr_stack, attr); } ele = tbx_inip_ele_next(ele); } return(b); }
int submit_hp_direct_op(portal_context_t *hpc, op_generic_t *op) { int status; host_portal_t *hp, *shp; host_connection_t *hc; command_op_t *hop = &(op->op->cmd); apr_thread_mutex_lock(hpc->lock); //** Check if we should do a garbage run ** if (hpc->next_check < time(NULL)) { hpc->next_check = time(NULL) + hpc->compact_interval; apr_thread_mutex_unlock(hpc->lock); compact_hportals(hpc); apr_thread_mutex_lock(hpc->lock); } //** Find it in the list or make a new one hp = _lookup_hportal(hpc, hop->hostport); if (hp == NULL) { log_printf(15, "submit_hp_direct_op: New host: %s\n", hop->hostport); hp = create_hportal(hpc, hop->connect_context, hop->hostport, 1, 1, apr_time_from_sec(1)); if (hp == NULL) { log_printf(15, "submit_hp_direct_op: create_hportal failed!\n"); apr_thread_mutex_unlock(hpc->lock); return(-1); } apr_hash_set(hpc->table, hp->skey, APR_HASH_KEY_STRING, (const void *)hp); } apr_thread_mutex_unlock(hpc->lock); log_printf(15, "submit_hp_direct_op: start opid=%d\n", op->base.id); //** Scan the direct list for a free connection hportal_lock(hp); tbx_stack_move_to_top(hp->direct_list); while ((shp = (host_portal_t *)tbx_stack_get_current_data(hp->direct_list)) != NULL) { if (hportal_trylock(shp) == 0) { log_printf(15, "submit_hp_direct_op: opid=%d shp->wl=" I64T " stack_size=%d\n", op->base.id, shp->workload, tbx_stack_count(shp->que)); if (tbx_stack_count(shp->que) == 0) { if (tbx_stack_count(shp->conn_list) > 0) { tbx_stack_move_to_top(shp->conn_list); hc = (host_connection_t *)tbx_stack_get_current_data(shp->conn_list); if (trylock_hc(hc) == 0) { if ((tbx_stack_count(hc->pending_stack) == 0) && (hc->curr_workload == 0)) { log_printf(15, "submit_hp_direct_op(A): before submit ns=%d opid=%d wl=%d\n",tbx_ns_getid(hc->ns), op->base.id, hc->curr_workload); unlock_hc(hc); hportal_unlock(shp); status = submit_hportal(shp, op, 1, 0); log_printf(15, "submit_hp_direct_op(A): after submit ns=%d opid=%d\n",tbx_ns_getid(hc->ns), op->base.id); hportal_unlock(hp); return(status); } unlock_hc(hc); } } else { hportal_unlock(shp); log_printf(15, "submit_hp_direct_op(B): opid=%d\n", op->base.id); status = submit_hportal(shp, op, 1, 0); hportal_unlock(hp); return(status); } } hportal_unlock(shp); } tbx_stack_move_down(hp->direct_list); //** Move to the next hp in the list } //** If I made it here I have to add a new hportal shp = create_hportal(hpc, hop->connect_context, hop->hostport, 1, 1, apr_time_from_sec(1)); if (shp == NULL) { log_printf(15, "submit_hp_direct_op: create_hportal failed!\n"); hportal_unlock(hp); return(-1); } tbx_stack_push(hp->direct_list, (void *)shp); status = submit_hportal(shp, op, 1, 0); hportal_unlock(hp); return(status); }