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); }
op_generic_t *gop_timed_waitany(op_generic_t *g, int dt) { op_generic_t *gop = NULL; apr_interval_time_t adt = apr_time_from_sec(dt); int loop; lock_gop(g); _gop_start_execution(g); //** Make sure things have been submitted loop = 0; if (gop_get_type(g) == Q_TYPE_QUE) { while (((gop = (op_generic_t *)pop(g->q->finished)) == NULL) && (g->q->nleft > 0) && (loop == 0)) { apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes loop++; } } else { while ((g->base.state == 0) && (loop == 0)) { apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes loop++; } if (g->base.state != 0) gop = g; } unlock_gop(g); return(gop); }
int gop_timed_waitall(op_generic_t *g, int dt) { int status; int loop; apr_interval_time_t adt = apr_time_from_sec(dt); lock_gop(g); _gop_start_execution(g); //** Make sure things have been submitted loop = 0; if (gop_get_type(g) == Q_TYPE_QUE) { while ((g->q->nleft > 0) && (loop == 0)) { apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes loop++; } status = (g->q->nleft > 0) ? OP_STATE_RETRY : _gop_completed_successfully(g); } else { while ((g->base.state == 0) && (loop == 0)) { apr_thread_cond_timedwait(g->base.ctl->cond, g->base.ctl->lock, adt); //** Sleep until something completes loop++; } status = (g->base.state == 0) ? OP_STATE_RETRY : _gop_completed_successfully(g); } unlock_gop(g); return(status); }
void _gop_start_execution(op_generic_t *g) { if (gop_get_type(g) == Q_TYPE_QUE) { _opque_start_execution(g->q->opque); } else if (g->base.started_execution == 0) { log_printf(15, "gid=%d started_execution=%d\n", gop_get_id(g), g->base.started_execution); g->base.started_execution = 1; g->base.pc->fn->submit(g->base.pc->arg, g); } }
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 gop_finished_submission(op_generic_t *g) { lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { g->q->finished_submission = 1; //** If nothing left to do trigger the condition in case anyone's waiting if (g->q->nleft == 0) { apr_thread_cond_broadcast(g->base.ctl->cond); } } unlock_gop(g); }
int _gop_completed_successfully(op_generic_t *g) { int status; if (gop_get_type(g) == Q_TYPE_QUE) { status = stack_size(g->q->failed); status = (status == 0) ? g->base.status.op_status : OP_STATE_FAILURE; } else { status = g->base.status.op_status; } return(status); }
int gop_tasks_finished(op_generic_t *g) { int nf; lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { nf = stack_size(g->q->finished); } else { nf = (g->base.state == 1) ? 1 : 0; } unlock_gop(g); return(nf); }
int gop_tasks_failed(op_generic_t *g) { int nf; lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { nf = stack_size(g->q->failed); } else { nf = (g->base.status.op_status == OP_STATE_SUCCESS) ? 0 : 1; } unlock_gop(g); return(nf); }
int gop_tasks_left(op_generic_t *g) { int n; lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { n = g->q->nleft; } else { n = (g->base.state == 1) ? 0 : 1; } unlock_gop(g); return(n); }
int gop_will_block(op_generic_t *g) { int status = 0; lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { if ((stack_size(g->q->finished) == 0) && (g->q->nleft > 0)) status = 1; } else { if (g->base.state == 0) status = 1; } unlock_gop(g); return(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); } }
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); }
op_generic_t *gop_get_next_failed(op_generic_t *g) { op_generic_t *gop = NULL; lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { gop = (op_generic_t *)pop(g->q->failed); } else { gop = NULL; if (g->base.failure_mode != OP_FM_GET_END) { g->base.failure_mode = OP_FM_GET_END; if (g->base.status.op_status != OP_STATE_SUCCESS) gop = g; } } unlock_gop(g); return(gop); }
op_generic_t *gop_get_next_finished(op_generic_t *g) { op_generic_t *gop; lock_gop(g); if (gop_get_type(g) == Q_TYPE_QUE) { gop = (op_generic_t *)pop(g->q->finished); } else { gop = NULL; if (g->base.failure_mode != OP_FM_GET_END) { g->base.failure_mode = OP_FM_GET_END; gop = g; } } unlock_gop(g); return(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); }
void gop_set_exec_mode(op_generic_t *g, int mode) { if (gop_get_type(g) == Q_TYPE_OPERATION) { g->base.execution_mode = mode; } }