int event_queue_free(struct event_queue *eq) { assert(eq != NULL); if(!event_queue_empty(eq)) return(-1); /* if(eq->thread_id) pthread_cancel(eq->thread_id); */ pthread_rwlock_destroy(&eq->update_lock); pthread_mutex_destroy(&eq->cond_lock); pthread_cond_destroy(&eq->ready_cond); #if defined(INTERLOGD_HANDLE_CMD) && defined(INTERLOGD_FLUSH) pthread_cond_destroy(&eq->flush_cond); #endif if(eq->dest_name) free(eq->dest_name); if(eq->dest) free(eq->dest); if(eq->owner) free(eq->owner); free(eq); return(0); }
/* Send events from the queue. Return 0 on error. */ static int flush_events (struct client *cli) { enum noblock_io_status st = NB_IO_OK; LOCK (cli->events_mtx); while (!event_queue_empty(&cli->events) && (st = event_send_noblock(cli->socket, &cli->events)) == NB_IO_OK) ; UNLOCK (cli->events_mtx); return st != NB_IO_ERR ? 1 : 0; }
/* Add clients file descriptors to fds. */ static void add_clients_fds (fd_set *read, fd_set *write) { int i; for (i = 0; i < CLIENTS_MAX; i++) if (clients[i].socket != -1) { if (locking_client() == -1 || is_locking(&clients[i])) FD_SET (clients[i].socket, read); LOCK (clients[i].events_mtx); if (!event_queue_empty(&clients[i].events)) FD_SET (clients[i].socket, write); UNLOCK (clients[i].events_mtx); } }
int event_queue_send(struct event_queue *eq) { OutputPlugin *output = (OutputPlugin*)eq->plugin_data; edg_wll_Context context; edg_wll_Event *notif_event; edg_wll_JobStat *state_out; il_octet_string_t event; char *jobstat_char; int ret; assert(output != NULL); edg_wll_InitContext(&context); while(!event_queue_empty(eq)) { struct server_msg *msg; cms::TextMessage *cms_msg; char *s; unsigned int i; std::string val; if(event_queue_get(eq, &msg) < 0) { goto err; } try { if(decode_il_msg(&event, msg->msg) < 0) { set_error(IL_LBAPI, EINVAL, "event_queue_send: error parsing notification event data"); goto err; } ret=edg_wll_ParseNotifEvent(context, event.data, ¬if_event); if(ret) { set_error(IL_LBAPI, ret, "event_queue_send: error parsing notification event"); goto err; } jobstat_char = glite_lbu_UnescapeXML((const char *) notif_event->notification.jobstat); if (jobstat_char == NULL) { set_error(IL_LBAPI, EINVAL, "event_queue_send: error unescaping job status"); goto err; } if ( edg_wll_ParseJobStat(context, jobstat_char, strlen(jobstat_char), state_out)) { set_error(IL_LBAPI, EINVAL, "event_queue_send: error parsing job status"); goto err; } cms_msg = output->session->createTextMessage(); /* ownerDn */ val.assign(state_out->owner); cms_msg->setStringProperty("ownerDn", val); /* voname */ s = edg_wll_JDLField(state_out,"VirtualOrganisation"); val.assign(s); free(s); cms_msg->setStringProperty("voname", val); /* bkHost */ glite_jobid_getServerParts(state_out->jobId, &s, &i); val.assign(s); free(s); cms_msg->setStringProperty("bkHost", val); /* networkServer */ /* TODO: XXX cut out hostname */ val.assign(state_out->network_server); cms_msg->setStringProperty("networkHost", val); timeval2str(&state_out->lastUpdateTime, &s); val.assign(s); if(s) free(s); cms_msg->setStringProperty("lastUpdateTime", val); /* stateName */ s = edg_wll_StatToString(state_out->state); val.assign(s); if(s) free(s); cms_msg->setStringProperty("stateName", val); timeval2str(&state_out->stateEnterTime, &s); val.assign(s); if(s) free(s); cms_msg->setStringProperty("stateStartTime", val); /* condorId */ val.assign(state_out->condorId); cms_msg->setStringProperty("condorId", val); /* destSite */ val.assign(state_out->destination); cms_msg->setStringProperty("destSite", val); /* exitCode */ cms_msg->setIntProperty("exitCode", state_out->exit_code); /* doneCode */ cms_msg->setIntProperty("doneCode", state_out->done_code); /* statusReason */ val.assign(state_out->reason); cms_msg->setStringProperty("statusReason", val); free(event.data); edg_wll_FreeEvent(notif_event); free(notif_event); edg_wll_FreeStatus(state_out); free(state_out); free(jobstat_char); } catch(cms::CMSException &e) { goto err; } try { output->send(cms_msg); delete cms_msg; if(event_store_commit(msg->es, msg->ev_len, queue_list_is_log(eq), msg->generation) < 0) { /* failure committing message, this is bad */ goto err; } event_queue_remove(eq); eq->first_event_sent = 1; } catch(cms::CMSException &e) { delete cms_msg; output->cleanup(); eq->timeout = TIMEOUT; edg_wll_FreeContext(context); return 0; } } edg_wll_FreeContext(context); return 1; err: if(event.data) { free(event.data); } if(notif_event) { edg_wll_FreeEvent(notif_event); free(notif_event); } if(jobstat_char) { free(jobstat_char); } if(state_out) { edg_wll_FreeStatus(state_out); free(state_out); } return -1; }
int event_queue_send(struct event_queue *eq, struct queue_thread *me) { OutputPlugin *output = (OutputPlugin*)eq->plugin_data; edg_wll_Context context; edg_wll_Event *notif_event; edg_wll_JobStat state_out; il_octet_string_t event; char *jobstat_char; int ret; assert(output != NULL); edg_wll_InitContext(&context); while(!event_queue_empty(eq)) { struct server_msg *msg; cms::Message *cms_msg = NULL; if(event_queue_get(eq, me, &msg) == 0) { break; } if(0 == msg->len) { glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_DEBUG, " not sending empty message at offset %ld for job %s", msg->offset, msg->job_id_s); if(event_store_commit(msg->es, msg->ev_len, 0, msg->generation) < 0) { /* failure committing message, this is bad */ goto err; } event_queue_remove(eq, me); continue; } glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_DEBUG, " trying to deliver event at offset %ld for job %s", msg->offset, msg->job_id_s); if(decode_il_msg(&event, msg->msg + 17) < 0) { set_error(IL_LBAPI, EINVAL, "event_queue_send: error parsing notification event data"); goto err; } ret=edg_wll_ParseNotifEvent(context, event.data, ¬if_event); if(ret) { set_error(IL_LBAPI, ret, "event_queue_send: error parsing notification event"); goto err; } jobstat_char = glite_lbu_UnescapeXML((const char *) notif_event->notification.jobstat); if (jobstat_char == NULL) { set_error(IL_LBAPI, EINVAL, "event_queue_send: error unescaping job status"); goto err; } if ( edg_wll_ParseJobStat(context, jobstat_char, strlen(jobstat_char), &state_out)) { set_error(IL_LBAPI, EINVAL, "event_queue_send: error parsing job status"); fprintf(stderr, "Status string: %s\n", jobstat_char); goto err; } try { cms_msg = output->createMessage(state_out); free(event.data); event.data = NULL; edg_wll_FreeEvent(notif_event); free(notif_event); notif_event = NULL; edg_wll_FreeStatus(&state_out); free(jobstat_char); jobstat_char = NULL; output->send(cms_msg); delete cms_msg; if(event_store_commit(msg->es, msg->ev_len, 0, msg->generation) < 0) { /* failure committing message, this is bad */ goto err; } glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_DEBUG, " event sent to %s", eq->dest_name); } catch(cms::CMSException &e) { if(cms_msg) { delete cms_msg; } me->timeout = TIMEOUT; edg_wll_FreeContext(context); set_error(IL_DL, 0, e.what()); return 0; } event_queue_remove(eq, me); me->first_event_sent = 1; eq->last_sent = time(NULL); } edg_wll_FreeContext(context); return 1; err: if(event.data) { free(event.data); } if(notif_event) { edg_wll_FreeEvent(notif_event); free(notif_event); } if(jobstat_char) { free(jobstat_char); } edg_wll_FreeStatus(&state_out); return -1; }
/* * Send all events from the queue. * Returns: -1 - system error, 0 - not send, 1 - queue empty */ int event_queue_send(struct event_queue *eq, struct queue_thread *me) { assert(eq != NULL); assert(me != NULL); #ifdef LB_PERF if(!nosend) { #endif if(me->gss.context == NULL) return(0); #ifdef LB_PERF } #endif /* feed the server with events */ while (!event_queue_empty(eq)) { struct server_msg *msg; char *rep; int ret, code, code_min; size_t bytes_sent; struct timeval tv; edg_wll_GssStatus gss_stat; clear_error(); if(event_queue_get(eq, me, &msg) == 0) return(1); glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_DEBUG, " trying to deliver event at offset %ld for job %s", msg->offset, msg->job_id_s); #ifdef LB_PERF if(!nosend) { #endif if (msg->len) { tv.tv_sec = TIMEOUT; tv.tv_usec = 0; ret = edg_wll_gss_write_full(&me->gss, msg->msg, msg->len, &tv, &bytes_sent, &gss_stat); if(ret < 0) { if (ret == EDG_WLL_GSS_ERROR_ERRNO && errno == EPIPE && me->first_event_sent ) me->timeout = 0; else me->timeout = TIMEOUT; server_msg_release(msg); return(0); } if((code = get_reply(eq, me, &rep, &code_min)) < 0) { /* could not get the reply properly, so try again later */ if (me->first_event_sent) { /* could be expected server connection preemption */ clear_error(); me->timeout = 1; } else { me->timeout = TIMEOUT; glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_WARN, " error reading server %s reply: %s", eq->dest_name, error_get_msg()); } server_msg_release(msg); return(0); } } else { code = LB_OK; code_min = 0; rep = strdup("not sending empty message"); } #ifdef LB_PERF } else { glite_wll_perftest_consumeEventIlMsg(msg->msg+17); code = LB_OK; rep = strdup("OK"); } #endif glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_DEBUG, " event sent, server %s replied with %d, %s", eq->dest_name, code, rep); free(rep); /* the reply is back here */ switch(code) { /* NOT USED: case LB_TIME: */ case LB_NOMEM: /* NOT USED: case LB_SYS: */ /* NOT USED: case LB_AUTH: */ case LB_DBERR: /* check minor code */ if(!(ENOENT == code_min)) { /* non fatal errors (for us) */ me->timeout = TIMEOUT; server_msg_release(msg); return(0); } case LB_OK: /* event 'successfully' delivered */ case LB_PERM: default: /* LB_PROTO */ /* the event was not accepted by the server */ /* update the event pointer */ if(event_store_commit(msg->es, msg->ev_len, queue_list_is_log(eq), msg->generation) < 0) { /* failure committing message, this is bad */ server_msg_release(msg); return(-1); } /* if we have just delivered priority message from the queue, send confirmation */ ret = 1; #if defined(INTERLOGD_EMS) if(server_msg_is_priority(msg) && ((ret=confirm_msg(msg, code, code_min)) < 0)) return(ret); #endif if((ret == 0) && (error_get_maj() != IL_OK)) glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_ERROR, "send_event: %s", error_get_msg()); event_queue_remove(eq, me); me->first_event_sent = 1; eq->last_sent = time(NULL); break; } /* switch */ } /* while */ return(1); } /* send_events */
uint8_t get_event(void) { return event_queue_empty() ? EV_NONE : event_queue[(event_queue_tail++) & (EVENT_QUEUE_SIZE - 1)]; }
static int handle_cmd(il_octet_string_t *event, long offset) { char *job_id_s; struct event_queue *eq; int num_replies, num_threads = 0; int timeout, result; long receipt; struct timespec endtime; struct timeval tv; /* parse command */ if(parse_cmd(event->data, &job_id_s, &receipt, &timeout) < 0) return(0); #if defined(INTERLOGD_FLUSH) glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_DEBUG, "received FLUSH command"); /* catchup with all neccessary event files */ if(job_id_s) { struct event_store *es = event_store_find(job_id_s, NULL); if(es == NULL) { goto cmd_error; } result = event_store_recover(es); /* NOTE: if flush had been stored in file, there would have been no need to lock the event_store at all */ event_store_release(es); if(result < 0) { glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_ERROR, " error trying to catch up with event file: %s", error_get_msg()); clear_error(); } } else /* this call does not fail :-) */ event_store_recover_all(); glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_DEBUG, " alerting threads to report status"); /* prevent threads from reporting too early */ if(pthread_mutex_lock(&flush_lock) < 0) { /*** this error is considered too serious to allow the program run anymore! set_error(IL_SYS, errno, "pthread_mutex_lock: error locking flush lock"); goto cmd_error; */ abort(); } /* wake up all threads */ if(job_id_s) { /* find appropriate queue */ eq = queue_list_get(job_id_s); if(eq == NULL) goto cmd_error; if(!event_queue_empty(eq) && !queue_list_is_log(eq)) { num_threads++; event_queue_cond_lock(eq); eq->flushing = 1; event_queue_wakeup(eq); event_queue_cond_unlock(eq); } } else { /* iterate over event queues */ for(eq=queue_list_first(); eq != NULL; eq=queue_list_next()) { if(!event_queue_empty(eq) && !queue_list_is_log(eq)) { num_threads++; event_queue_cond_lock(eq); eq->flushing = 1; event_queue_wakeup(eq); event_queue_cond_unlock(eq); } } } if(!bs_only) { eq = queue_list_get(NULL); if(eq == NULL) goto cmd_error; if(!event_queue_empty(eq)) { num_threads++; event_queue_cond_lock(eq); eq->flushing = 1; event_queue_wakeup(eq); event_queue_cond_unlock(eq); } } /* wait for thread replies */ num_replies = 0; result = 1; gettimeofday(&tv, NULL); endtime.tv_sec = tv.tv_sec + timeout; endtime.tv_nsec = 1000 * tv.tv_usec; while(num_replies < num_threads) { int ret; if((ret=pthread_cond_timedwait(&flush_cond, &flush_lock, &endtime)) < 0) { char buf[256]; il_strerror_r(errno, buf, sizeof(buf)); glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_ERROR, " error waiting for thread reply: %s", buf); result = (ret == ETIMEDOUT) ? 0 : -1; break; } /* collect results from reporting threads */ if(job_id_s) { /* find appropriate queue */ eq = queue_list_get(job_id_s); if(eq == NULL) goto cmd_error; if(!queue_list_is_log(eq)) { event_queue_cond_lock(eq); if(eq->flushing == 2) { eq->flushing = 0; num_replies++; result = ((result == 1) || (eq->flush_result < 0)) ? eq->flush_result : result; } event_queue_cond_unlock(eq); } } else { /* iterate over event queues */ for(eq=queue_list_first(); eq != NULL; eq=queue_list_next()) { if(!queue_list_is_log(eq)) { event_queue_cond_lock(eq); if(eq->flushing == 2) { eq->flushing = 0; num_replies++; glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_DEBUG, " thread reply: %d", eq->flush_result); result = ((result == 1) || (eq->flush_result < 0)) ? eq->flush_result : result; } event_queue_cond_unlock(eq); } } } if(!bs_only) { eq = queue_list_get(NULL); if(eq == NULL) goto cmd_error; event_queue_cond_lock(eq); if(eq->flushing == 2) { eq->flushing = 0; num_replies++; result = ((result == 1) || (eq->flush_result < 0)) ? eq->flush_result : result; } event_queue_cond_unlock(eq); } } /* prevent deadlock in next flush */ if(pthread_mutex_unlock(&flush_lock) < 0) abort(); /* report back to local logger */ switch(result) { case 1: result = 0; break; case 0: result = EDG_WLL_IL_EVENTS_WAITING; break; default: result = EDG_WLL_IL_SYS; break; } if(job_id_s) free(job_id_s); result = send_confirmation(receipt, result); if(result <= 0) glite_common_log(IL_LOG_CATEGORY, LOG_PRIORITY_ERROR, "handle_cmd: error sending status: %s", error_get_msg()); return(1); cmd_error: if(job_id_s) free(job_id_s); return(-1); #else return(0); #endif /* INTERLOGD_FLUSH */ }