op_status_t gop_sync_exec_status(op_generic_t *gop) { int err; op_status_t status; if (gop->type == Q_TYPE_OPERATION) { //** Got an operation so see if we can directly exec it if (gop->base.pc->fn->sync_exec != NULL) { //** Yup we can! log_printf(15, "sync_exec -- waiting for gid=%d to complete\n", gop_id(gop)); gop->base.pc->fn->sync_exec(gop->base.pc, gop); status = gop->base.status; log_printf(15, "sync_exec -- gid=%d completed with err=%d\n", gop_id(gop), status.op_status); gop_free(gop, OP_DESTROY); return(status); } } log_printf(15, "waiting for gid=%d to complete\n", gop_id(gop)); err = gop_waitall(gop); status = gop_get_status(gop); log_printf(15, "gid=%d completed with err=%d\n", gop_id(gop), err); gop_free(gop, OP_DESTROY); log_printf(15, "After gop destruction\n"); return(status); }
void _opque_start_execution(opque_t *que) { int n, i; callback_t *cb; op_generic_t *gop; que_data_t *q = &(que->qd); gop = opque_get_gop(que); if (gop->base.started_execution != 0) { return; } gop->base.started_execution = 1; n = stack_size(q->list); move_to_top(q->list); for (i=0; i<n; i++) { cb = (callback_t *)pop(q->list); gop = (op_generic_t *)cb->priv; if (gop->type == Q_TYPE_OPERATION) { log_printf(15, "qid=%d gid=%d\n",gop_id(opque_get_gop(que)), gop_get_id(gop)); gop->base.started_execution = 1; gop->base.pc->fn->submit(gop->base.pc->arg, gop); } else { //** It's a queue log_printf(15, "qid=%d Q gid=%d\n",gop_id(opque_get_gop(que)), gop_get_id(gop)); lock_opque(gop->q); _opque_start_execution(gop->q->opque); unlock_opque(gop->q); } } // unlock_opque(q); }
void single_gop_mark_completed(op_generic_t *gop, op_status_t status) { op_common_t *base = &(gop->base); int mode; log_printf(15, "gop_mark_completed: START gid=%d status=%d\n", gop_id(gop), status.op_status); lock_gop(gop); log_printf(15, "gop_mark_completed: after lock gid=%d\n", gop_id(gop)); //** Store the status base->status = status; //** and trigger any callbacks log_printf(15, "gop_mark_completed: before cb gid=%d op_status=%d\n", gop_id(gop), base->status.op_status); callback_execute(base->cb, base->status.op_status); log_printf(15, "gop_mark_completed: after cb gid=%d op_success=%d\n", gop_id(gop), base->status.op_status); base->state = 1; //** Lastly trigger the signal. for anybody listening apr_thread_cond_broadcast(gop->base.ctl->cond); log_printf(15, "gop_mark_completed: after brodcast gid=%d\n", gop_id(gop)); mode = gop_get_auto_destroy(gop); //** Get the auto destroy status w/in the lock unlock_gop(gop); //** Check if we do an auto cleanop if (mode == 1) gop_free(gop, OP_DESTROY); }
void mq_stream_read_destroy(mq_stream_t *mqs) { log_printf(1, "START msid=%d\n", mqs->msid); if (mqs->mpool == NULL) { //** Nothing to do pack_destroy(mqs->pack); if (mqs->stream_id != NULL) free(mqs->stream_id); free(mqs); return; } //** Change the flag which signals we don't want anything else apr_thread_mutex_lock(mqs->lock); mqs->want_more = MQS_ABORT; //** Consume all the current data and request the pending while ((mqs->gop_processed != NULL) || (mqs->gop_waiting != NULL)) { log_printf(1, "Clearing pending processed=%d waiting=%p msid=%d\n", mqs->gop_processed, mqs->gop_waiting, mqs->msid); if (mqs->gop_processed != NULL) log_printf(1, "processed gid=%d\n", gop_id(mqs->gop_processed)); if (mqs->gop_waiting != NULL) log_printf(1, "waiting gid=%d\n", gop_id(mqs->gop_waiting)); mqs->want_more = MQS_ABORT; apr_thread_mutex_unlock(mqs->lock); mq_stream_read_wait(mqs); apr_thread_mutex_lock(mqs->lock); } if (log_level() >= 15) { char *rhost = mq_address_to_string(mqs->remote_host); log_printf(15, "remote_host as string = %s\n", rhost); if (rhost) free(rhost); } if (mqs->remote_host != NULL) mq_ongoing_host_dec(mqs->ongoing, mqs->remote_host, mqs->host_id, mqs->hid_len); apr_thread_mutex_unlock(mqs->lock); log_printf(2, "msid=%d transfer_packets=%d\n", mqs->msid, mqs->transfer_packets); //** Clean up if (mqs->stream_id != NULL) free(mqs->stream_id); pack_destroy(mqs->pack); apr_thread_mutex_destroy(mqs->lock); apr_thread_cond_destroy(mqs->cond); apr_pool_destroy(mqs->mpool); if (mqs->remote_host != NULL) mq_msg_destroy(mqs->remote_host); free(mqs); return; }
void init_opque(opque_t *q) { que_data_t *que = &(q->qd); op_generic_t *gop = &(q->op); type_memclear(q, opque_t, 1); gop_init(gop); log_printf(15, "init_opque: qid=%d\n", gop_id(gop)); //**Set up the pointers gop->q = que; gop->q->opque = q; q->op.type = Q_TYPE_QUE; que->list = new_stack(); que->finished = new_stack(); que->failed = new_stack(); que->nleft = 0; que->nsubmitted = 0; gop->base.retries = 0; // que->started_execution = 0; que->finished_submission = 0; // que->success = OP_STATE_FAILURE; // que->success = 12345; }
void _gop_dummy_submit_op(void *arg, op_generic_t *op) { int dolock = 0; log_printf(15, "gid=%d\n", gop_id(op)); // if (op->base.cb != NULL) { //** gop is on a q apr_thread_mutex_lock(gd_lock); push(gd_stack, op); apr_thread_cond_signal(gd_cond); apr_thread_mutex_unlock(gd_lock); return; // } //*-------* This isn't executed below ----------- if (apr_thread_mutex_trylock(op->base.ctl->lock) != APR_SUCCESS) dolock = 1; unlock_gop(op); //log_printf(15, "dolock=%d gid=%d err=%d APR_SUCCESS=%d\n", dolock, gop_id(op), err, APR_SUCCESS); op->base.started_execution = 1; gop_mark_completed(op, op->base.status); if (dolock == 1) { lock_gop(op); } //** lock_gop is a macro so need the {} return; }
void _tp_op_free(gop_op_generic_t *gop, int mode) { gop_thread_pool_op_t *top = gop_get_tp(gop); int id = gop_id(gop); log_printf(15, "_tp_op_free: mode=%d gid=%d gop=%p\n", mode, gop_id(gop), gop); tbx_log_flush(); if (top->my_op_free != NULL) top->my_op_free(top->arg); gop_generic_free(gop, OP_FINALIZE); //** I free the actual op if (top->dop.cmd.hostport) free(top->dop.cmd.hostport); if (mode == OP_DESTROY) free(gop->free_ptr); log_printf(15, "_tp_op_free: gid=%d END\n", id); tbx_log_flush(); }
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)); } }
int gop_waitall(op_generic_t *g) { int status; op_generic_t *g2; callback_t *cb; //log_printf(15, "START gid=%d type=%d\n", gop_id(g), gop_get_type(g)); log_printf(5, "START gid=%d type=%d\n", gop_id(g), gop_get_type(g)); lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { log_printf(15, "sync_exec_que_check gid=%d stack_size=%d started_exec=%d\n", gop_id(g), stack_size(g->q->opque->qd.list), g->base.started_execution); if ((stack_size(g->q->opque->qd.list) == 1) && (g->base.started_execution == 0)) { //** See if we can directly exec log_printf(15, "sync_exec_que -- waiting for gid=%d to complete\n", gop_id(g)); cb = (callback_t *)pop(g->q->opque->qd.list); g2 = (op_generic_t *)cb->priv; unlock_gop(g); //** Don't need this for a direct exec status = gop_waitall(g2); log_printf(15, "sync_exec -- gid=%d completed with err=%d\n", gop_id(g), status); return(status); } else { //** Got to submit it normally _gop_start_execution(g); //** Make sure things have been submitted while (g->q->nleft > 0) { apr_thread_cond_wait(g->base.ctl->cond, g->base.ctl->lock); //** Sleep until something completes } } } else { //** Got a single task if ((g->base.pc->fn->sync_exec != NULL) && (g->base.started_execution == 0)) { //** See if we can directly exec unlock_gop(g); //** Don't need this for a direct exec log_printf(15, "sync_exec -- waiting for gid=%d to complete\n", gop_id(g)); g->base.pc->fn->sync_exec(g->base.pc, g); status = _gop_completed_successfully(g); log_printf(15, "sync_exec -- gid=%d completed with err=%d\n", gop_id(g), status); return(status); } else { //** Got to submit it the normal way _gop_start_execution(g); //** Make sure things have been submitted while (g->base.state == 0) { log_printf(15, "gop_waitall: WHILE gid=%d state=%d\n", gop_id(g), g->base.state); apr_thread_cond_wait(g->base.ctl->cond, g->base.ctl->lock); //** Sleep until something completes } } } status = _gop_completed_successfully(g); log_printf(15, "END gid=%d type=%d\n", gop_id(g), gop_get_type(g)); unlock_gop(g); return(status); }
int gop_wait(op_generic_t *gop) { op_status_t status; //log_printf(15, "gop_wait: START gid=%d state=%d\n", gop_id(gop), gop->base.state); lock_gop(gop); //log_printf(15, "gop_wait: after lock gid=%d state=%d\n", gop_id(gop), gop->base.state); while (gop->base.state == 0) { log_printf(15, "gop_wait: WHILE gid=%d state=%d\n", gop_id(gop), gop->base.state); apr_thread_cond_wait(gop->base.ctl->cond, gop->base.ctl->lock); //** Sleep until something completes } status = gop_get_status(gop); // state = _gop_completed_successfully(gop); log_printf(15, "gop_wait: FINISHED gid=%d status=%d err=%d\n", gop_id(gop), status.op_status, status.error_code); unlock_gop(gop); return(status.op_status); }
void gop_free(op_generic_t *gop, int mode) { int type; log_printf(15, "gop_free: gid=%d tid=%d\n", gop_id(gop), atomic_thread_id); //** Get the status type = gop_get_type(gop); if (type == Q_TYPE_QUE) { opque_free(gop->q->opque, mode); } else { //** the gop is locked in gop_generic_free before freeing gop->base.free(gop, mode); } }
op_generic_t *gop_waitany(op_generic_t *g) { op_generic_t *gop = g; callback_t *cb; lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { log_printf(15, "sync_exec_que_check gid=%d stack_size=%d started_exec=%d\n", gop_id(g), stack_size(g->q->opque->qd.list), g->base.started_execution); if ((stack_size(g->q->opque->qd.list) == 1) && (g->base.started_execution == 0)) { //** See if we can directly exec g->base.started_execution = 1; cb = (callback_t *)pop(g->q->opque->qd.list); gop = (op_generic_t *)cb->priv; log_printf(15, "sync_exec_que -- waiting for pgid=%d cgid=%d to complete\n", gop_id(g), gop_id(gop)); unlock_gop(g); gop_waitany(gop); pop(g->q->finished); //** Remove it from the finished list. return(gop); } else { _gop_start_execution(g); //** Make sure things have been submitted while (((gop = (op_generic_t *)pop(g->q->finished)) == NULL) && (g->q->nleft > 0)) { apr_thread_cond_wait(g->base.ctl->cond, g->base.ctl->lock); //** Sleep until something completes } } if (gop != NULL) log_printf(15, "POP finished qid=%d gid=%d\n", gop_id(g), gop_id(gop)); //log_printf(15, "Printing qid=%d finished stack\n", gop_id(g)); //_opque_print_stack(g->q->finished); } else { log_printf(15, "gop_waitany: BEFORE (type=op) While gid=%d state=%d\n", gop_id(g), g->base.state); flush_log(); if ((g->base.pc->fn->sync_exec != NULL) && (g->base.started_execution == 0)) { //** See if we can directly exec unlock_gop(g); //** Don't need this for a direct exec log_printf(15, "sync_exec -- waiting for gid=%d to complete\n", gop_id(g)); g->base.pc->fn->sync_exec(g->base.pc, g); log_printf(15, "sync_exec -- gid=%d completed with err=%d\n", gop_id(g), g->base.state); return(g); } else { //** Got to submit it normally unlock_gop(g); //** It's a single task so no need to hold the lock. Otherwise we can deadlock _gop_start_execution(g); //** Make sure things have been submitted lock_gop(g); //** but we do need it for detecting when we're finished. while (g->base.state == 0) { apr_thread_cond_wait(g->base.ctl->cond, g->base.ctl->lock); //** Sleep until something completes } } log_printf(15, "gop_waitany: AFTER (type=op) While gid=%d state=%d\n", gop_id(g), g->base.state); flush_log(); } unlock_gop(g); return(gop); }
void _opque_print_stack(Stack_t *stack) { op_generic_t *gop; int i=0; if (log_level() <= 15) return; move_to_top(stack); while ((gop = (op_generic_t *)get_ele_data(stack)) != NULL) { log_printf(15, " i=%d gid=%d type=%d\n", i, gop_id(gop), gop_get_type(gop)); i++; move_down(stack); } if (stack_size(stack) != i) log_printf(0, "Stack size mismatch! stack_size=%d i=%d\n", stack_size(stack), i); }
void gop_init(op_generic_t *gop) { pigeon_coop_hole_t pch; op_common_t *base = &(gop->base); type_memclear(gop, op_generic_t, 1); base->id = atomic_global_counter(); log_printf(15, "gop ptr=%p gid=%d\n", gop, gop_id(gop)); //** Get the control struct pch = reserve_pigeon_coop_hole(_gop_control); gop->base.ctl = (gop_control_t *)pigeon_coop_hole_data(&pch); gop->base.ctl->pch = pch; }
void opque_free(opque_t *opq, int mode) { que_data_t *q = &(opq->qd); log_printf(15, "qid=%d nfin=%d nlist=%d nfailed=%d\n", gop_id(&(opq->op)), stack_size(q->finished), stack_size(q->list), stack_size(q->failed)); lock_opque(&(opq->qd)); //** Lock it to make sure Everything is finished and safe to free //** Free the stacks free_stack(q->failed, 0); free_finished_stack(q->finished, mode); free_list_stack(q->list, mode); unlock_opque(&(opq->qd)); //** Has to be unlocked for gop_generic_free to work cause it also locks it gop_generic_free(opque_get_gop(opq), mode); if (mode == OP_DESTROY) free(opq); }
void *gd_thread_func(apr_thread_t *th, void *data) { op_generic_t *gop; apr_thread_mutex_lock(gd_lock); while (gd_shutdown == 0) { //** Execute everything on the stack while ((gop = (op_generic_t *)pop(gd_stack)) != NULL) { log_printf(15, "DUMMY gid=%d status=%d\n", gop_id(gop), gop->base.status.op_status); apr_thread_mutex_unlock(gd_lock); gop_mark_completed(gop, gop->base.status); apr_thread_mutex_lock(gd_lock); } //** Wait for more work apr_thread_cond_wait(gd_cond, gd_lock); } apr_thread_mutex_unlock(gd_lock); return(NULL); }
void free_list_stack(Stack_t *stack, int mode) { op_generic_t *gop; callback_t *cb; cb = (callback_t *)pop(stack); while (cb != NULL) { gop = (op_generic_t *)cb->priv; log_printf(15, "gid=%d\n", gop_id(gop)); if (gop->type == Q_TYPE_QUE) { //log_printf(15, "free_opque_stack: gop->type=QUE\n"); flush_log(); opque_free(gop->q->opque, mode); } else { //log_printf(15, "free_opque_stack: gop->type=OPER\n"); flush_log(); //DONE in op_generic_destroy callback_destroy(gop->base.cb); //** Free the callback chain as well if (gop->base.free != NULL) gop->base.free(gop, mode); } cb = (callback_t *)pop(stack); } free_stack(stack, 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); }
void _zsock_submit_op(void *arg, op_generic_t *gop) { portal_context_t *pc = gop->base.pc; log_printf(15, "_zsock_submit_op: hpc=%p hpc->table=%p gop=%p gid=%d\n", pc, pc->table, gop, gop_id(gop)); if (gop->base.execution_mode == OP_EXEC_DIRECT) { submit_hp_direct_op(pc, gop); } else { submit_hp_que_op(pc, gop); } }
void _opque_cb(void *v, int mode) { int type, n; op_status_t success; op_generic_t *gop = (op_generic_t *)v; que_data_t *q = &(gop->base.parent_q->qd); log_printf(15, "_opque_cb: START qid=%d gid=%d\n", gop_id(&(q->opque->op)), gop_id(gop)); //** Get the status (gop is already locked) type = gop_get_type(gop); if (type == Q_TYPE_QUE) { n = stack_size(gop->q->failed); log_printf(15, "_opque_cb: qid=%d gid=%d stack_size(q->failed)=%d gop->status=%d\n", gop_id(&(q->opque->op)), gop_id(gop), n, gop->base.status.op_status); success = (n == 0) ? gop->base.status : op_failure_status; } else { success = gop->base.status; } lock_opque(q); log_printf(15, "_opque_cb: qid=%d gid=%d success=%d gop_type(gop)=%d\n", gop_id(&(q->opque->op)), gop_id(gop), success, gop_get_type(gop)); //** It always goes on the finished list move_to_bottom(q->finished); insert_below(q->finished, gop); log_printf(15, "PUSH finished gid=%d qid=%d\n", gop_id(gop), gop_id(&(q->opque->op))); log_printf(15, "Printing finished stack for qid=%d\n", gop_id(&(q->opque->op))); if (log_level() > 15) _opque_print_stack(q->finished); if (success.op_status == OP_STATE_FAILURE) push(q->failed, gop); //** Push it on the failed list if needed q->nleft--; log_printf(15, "_opque_cb: qid=%d gid=%d nleft=%d stack_size(q->failed)=%d stack_size(q->finished)=%d\n", gop_id(&(q->opque->op)), gop_id(gop), q->nleft, stack_size(q->failed), stack_size(q->finished)); flush_log(); if (q->nleft <= 0) { //** we're finished if (stack_size(q->failed) == 0) { q->opque->op.base.status = op_success_status; callback_execute(q->opque->op.base.cb, OP_STATE_SUCCESS); //** Lastly trigger the signal. for anybody listening apr_thread_cond_broadcast(q->opque->op.base.ctl->cond); } else if (q->opque->op.base.retries == 0) { //** How many times we're retried //** Trigger the callbacks q->opque->op.base.retries++; q->nleft = 0; q->opque->op.base.failure_mode = 0; callback_execute(&(q->failure_cb), OP_STATE_FAILURE); //** Attempt to fix things if (q->opque->op.base.failure_mode == 0) { //** No retry q->opque->op.base.status = op_failure_status; callback_execute(q->opque->op.base.cb, OP_STATE_FAILURE); //**Execute the other CBs apr_thread_cond_broadcast(q->opque->op.base.ctl->cond); //** and fail for good } //** If retrying don't send the broadcast log_printf(15, "_opque_cb: RETRY END qid=%d gid=%d\n", gop_id(&(q->opque->op)), gop_id(gop)); flush_log(); } else { //** Finished with errors but trigger the signal for anybody listening apr_thread_cond_broadcast(q->opque->op.base.ctl->cond); } } else { //** Not finished but trigger the signal for anybody listening apr_thread_cond_broadcast(q->opque->op.base.ctl->cond); } log_printf(15, "_opque_cb: END qid=%d gid=%d\n", gop_id(&(q->opque->op)), gop_id(gop)); flush_log(); unlock_opque(q); }
int mq_stream_read_wait(mq_stream_t *mqs) { int err = 0; apr_interval_time_t dt; op_status_t status; //** If 1st time make all the variables if (mqs->mpool == NULL) { apr_pool_create(&mqs->mpool, NULL); apr_thread_mutex_create(&(mqs->lock), APR_THREAD_MUTEX_DEFAULT, mqs->mpool); apr_thread_cond_create(&(mqs->cond), mqs->mpool); } dt = apr_time_from_sec(1); //** Flag the just processed gop to clean up apr_thread_mutex_lock(mqs->lock); log_printf(5, "START msid=%d waiting=%d processed=%d gop_processed=%p\n", mqs->msid, mqs->waiting, mqs->processed, mqs->gop_processed); if (mqs->gop_processed != NULL) mqs->processed = 1; apr_thread_cond_broadcast(mqs->cond); if (mqs->data) { if (mqs->data[MQS_STATE_INDEX] != MQS_MORE) err = 1; } apr_thread_mutex_unlock(mqs->lock); if (mqs->gop_processed != NULL) { gop_waitany(mqs->gop_processed); gop_free(mqs->gop_processed, OP_DESTROY); mqs->gop_processed = NULL; } if (err != 0) { log_printf(2, "ERROR no more data available!\n"); return(-1); } //** Now handle the waiting gop apr_thread_mutex_lock(mqs->lock); log_printf(5, "before loop msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed); while (mqs->waiting == 1) { log_printf(5, "LOOP msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed); if (gop_will_block(mqs->gop_waiting) == 0) { //** Oops! failed request status = gop_get_status(mqs->gop_waiting); log_printf(2, "msid=%d gid=%d status=%d\n", mqs->msid, gop_id(mqs->gop_waiting), status.op_status); if (status.op_status != OP_STATE_SUCCESS) { mqs->waiting = -3; err = 1; } else { apr_thread_cond_timedwait(mqs->cond, mqs->lock, dt); } } else { apr_thread_cond_timedwait(mqs->cond, mqs->lock, dt); } } if (mqs->waiting == 0) { //** Flag the receiver to accept the data mqs->waiting = -1; apr_thread_cond_broadcast(mqs->cond); //** Let the receiver know we're ready to accept the data //** Wait for the data to be accepted while (mqs->waiting != -2) { apr_thread_cond_wait(mqs->cond, mqs->lock); } } else if (mqs->waiting == -3) { //**error occured err = 1; } apr_thread_mutex_unlock(mqs->lock); //** Flip states mqs->gop_processed = mqs->gop_waiting; mqs->gop_waiting = NULL; //** This shouldn't get triggered but just in case lets throw an error. if ((mqs->gop_processed == NULL) && (mqs->data != NULL)) { if ((mqs->data[MQS_STATE_INDEX] == MQS_MORE) && (mqs->want_more == MQS_MORE)) { err = 3; log_printf(0, "ERROR: MQS gop processed=waiting=NULL want_more set!!!!!! err=%d\n", err); fprintf(stderr, "ERROR: MQS gop processed=waiting=NULL want_more set!!!!!! err=%d\n", err); } } //** Check if we need to fire off the next request if (mqs->data != NULL) { if ((mqs->data[MQS_STATE_INDEX] == MQS_MORE) && (mqs->want_more == MQS_MORE)) { mq_stream_read_request(mqs); } } log_printf(5, "err=%d\n", err); return(err); }