static struct wproc_job *create_job(int type, void *arg, time_t timeout, const char *cmd) { struct wproc_job *job; struct wproc_worker *wp; wp = get_worker(cmd); if (!wp) return NULL; job = calloc(1, sizeof(*job)); if (!job) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to allocate memory for worker job: %s\n", strerror(errno)); return NULL; } job->wp = wp; job->id = get_job_id(wp); job->type = type; job->arg = arg; job->timeout = timeout; if (fanout_add(wp->jobs, job->id, job) < 0 || !(job->command = strdup(cmd))) { free(job); return NULL; } return job; }
/* * Handles adding the command and macros to the kvvec, * as well as shipping the command off to a designated * worker */ static int wproc_run_job(worker_job *job, nagios_macros *mac) { static struct kvvec kvv = KVVEC_INITIALIZER; worker_process *wp; /* * get_worker() also adds job to the workers list * and sets job_id */ wp = get_worker(job); if (!wp || job->id < 0) return ERROR; /* * XXX FIXME: add environment macros as * kvvec_addkv(kvv, "env", "NAGIOS_LALAMACRO=VALUE"); * kvvec_addkv(kvv, "env", "NAGIOS_LALAMACRO2=VALUE"); * so workers know to add them to environment. For now, * we don't support that though. */ if (!kvvec_init(&kvv, 4)) /* job_id, type, command and timeout */ return ERROR; kvvec_addkv(&kvv, "job_id", (char *)mkstr("%d", job->id)); kvvec_addkv(&kvv, "type", (char *)mkstr("%d", job->type)); kvvec_addkv(&kvv, "command", job->command); kvvec_addkv(&kvv, "timeout", (char *)mkstr("%u", job->timeout)); send_kvvec(wp->sd, &kvv); wp->jobs_running++; wp->jobs_started++; return 0; }
void G_begin_execute(void (*func)(void *), void *closure, void **ref, int force) { struct worker *w; if (*ref) G_fatal_error(_("Task already has a worker")); pthread_mutex_lock(&worker_mutex); while (w = get_worker(), force && !w) pthread_cond_wait(&worker_cond, &worker_mutex); *ref = w; if (!w) { pthread_mutex_unlock(&worker_mutex); (*func)(closure); return; } pthread_mutex_lock(&w->mutex); w->func = func; w->closure = closure; w->ref = ref; pthread_cond_signal(&w->cond); pthread_mutex_unlock(&w->mutex); pthread_mutex_unlock(&worker_mutex); }
static void fo_reassign_wproc_job(void *job_) { struct wproc_job *job = (struct wproc_job *)job_; job->wp = get_worker(job->command); job->id = get_job_id(job->wp); /* macros aren't used right now anyways */ wproc_run_job(job, NULL); }
/* * common routine for extract_path functions */ static inline Datum get_path_all(PG_FUNCTION_ARGS, bool as_text) { text *json = PG_GETARG_TEXT_P(0); ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); text *result; Datum *pathtext; bool *pathnulls; int npath; char **tpath; int *ipath; int i; long ind; char *endptr; if (array_contains_nulls(path)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot call function with null path elements"))); deconstruct_array(path, TEXTOID, -1, false, 'i', &pathtext, &pathnulls, &npath); tpath = palloc(npath * sizeof(char *)); ipath = palloc(npath * sizeof(int)); for (i = 0; i < npath; i++) { tpath[i] = TextDatumGetCString(pathtext[i]); if (*tpath[i] == '\0') ereport( ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot call function with empty path elements"))); /* * we have no idea at this stage what structure the document is so * just convert anything in the path that we can to an integer and set * all the other integers to -1 which will never match. */ ind = strtol(tpath[i], &endptr, 10); if (*endptr == '\0' && ind <= INT_MAX && ind >= 0) ipath[i] = (int) ind; else ipath[i] = -1; } result = get_worker(json, NULL, -1, tpath, ipath, npath, as_text); if (result != NULL) PG_RETURN_TEXT_P(result); else PG_RETURN_NULL(); }
Datum json_array_element_text(PG_FUNCTION_ARGS) { text *json = PG_GETARG_TEXT_P(0); text *result; int element = PG_GETARG_INT32(1); result = get_worker(json, NULL, element, NULL, NULL, -1, true); if (result != NULL) PG_RETURN_TEXT_P(result); else PG_RETURN_NULL(); }
Datum json_object_field_text(PG_FUNCTION_ARGS) { text *json = PG_GETARG_TEXT_P(0); text *result; text *fname = PG_GETARG_TEXT_P(1); char *fnamestr = text_to_cstring(fname); result = get_worker(json, fnamestr, -1, NULL, NULL, -1, true); if (result != NULL) PG_RETURN_TEXT_P(result); else PG_RETURN_NULL(); }
void ThreadPool::operator()() { try { while (!boost::this_thread::interruption_requested()) { taskp task; if (!m_tasks.timed_pop_front(task, m_idle)) { reclaim_workers(); } else { workerp worker; get_worker(worker); worker->acquire(task); } } } catch (boost::thread_interrupted &msg) { } }
bool resend_pending(void) { if(!pending.ready) return false; for(;;) { size_t worker = get_worker(); if(worker == -1) { // clog us up until we can get a worker printf("can't find a worker to send %d\n", pending.m.id); return false; } if(send_message(worker,pending.m)) { puts("sent message"); pfd[INCOMING].events = POLLIN; pending.ready = false; return true; } perror("send message failed..."); workers[worker].status = BUSY; // then try getting another worker. } }
void on_subscribe(Subscriber o) const { static_assert(is_subscriber<Subscriber>::value, "subscribe must be passed a subscriber"); // creates a worker whose lifetime is the same as this subscription auto coordinator = initial.coordination.create_coordinator(o.get_subscription()); auto controller = coordinator.get_worker(); auto counter = std::make_shared<long>(0); auto producer = [o, counter](const rxsc::schedulable&) { // send next value o.on_next(++(*counter)); }; auto selectedProducer = on_exception( [&](){return coordinator.act(producer);}, o); if (selectedProducer.empty()) { return; } controller.schedule_periodically(initial.initial, initial.period, selectedProducer.get()); }
size_t get_worker(void) { // get a worker // off, so we don't check worker 0 a million times static size_t off = -1; static int tries = 0; ++off; int which; for(which=0;which<numworkers;++which) { size_t derp = (which+off)%numworkers; switch(workers[derp].status) { case IDLE: workers[derp].status = BUSY; PFD(derp).events = POLLIN; tries = 0; return derp; }; } if(tries < 3) { ++tries; // if we timeout 3 times, stop waiting for idle workers. return -1; } /* no idle found, try starting some workers */ if(numworkers < MAXWORKERS) { // add a worker to the end if(start_worker()) { tries = 0; return numworkers-1; } } else { reap_workers(); for(which=0;which<numworkers;++which) { if(workers[which].status == DOOMED) { /* if 995 ns left (expiration - now) and doom delay is 1000ns 1000 - 995 < 50, so wait a teensy bit longer please */ Time diff = timediff(DOOM_DELAY, timediff(workers[which].expiration, getnow())); if(diff.tv_nsec > 50) { // waited too long, kill the thing. kill_worker(which); if(start_worker()) { tries = 0; return numworkers-1; } } } } } if(wait_for_accept()) { if(accept_workers()) { return get_worker(); } } // have to wait until the new worker connects errno = EAGAIN; // eh return -1; }