/* * Pretty simple: * 1) Set up SIGALRM signal handler * 2) set alarmpopped to FALSE; * 2) Record current time * 3) Call setmsalarm(ms) * 4) Call pause(2) * 5) Call cancelmstimer() * 6) Reset signal handler * 7) See if SIGALRM happened * if so: return zero * if not: get current time, and compute milliseconds left 'til signal * should arrive, and return that... */ long mssleep(long ms) { struct sigaction saveaction; longclock_t start; longclock_t finish; unsigned long elapsedms; memset(&saveaction, 0, sizeof(saveaction)); cl_signal_set_simple_handler(SIGALRM, st_timer_handler, &saveaction); alarmpopped = 0; start = time_longclock(); setmsalarm(ms); pause(); cancelmstimer(); cl_signal_set_simple_handler(SIGALRM, saveaction.sa_handler, &saveaction); if (alarmpopped) { return 0; } finish = time_longclock(); elapsedms = longclockto_ms(sub_longclock(finish, start)); return ms - elapsedms; }
gboolean G_CH_check_int(GSource* source) { GCHSource* chp = (GCHSource*)source; gboolean ret; longclock_t funstart; g_assert(IS_CHSOURCE(chp)); SAVESTART; if (chp->dontread){ /* Make sure output gets unblocked */ chp->ch->ops->resume_io(chp->ch); return FALSE; } ret = (chp->infd.revents != 0 || (!chp->fd_fdx && chp->outfd.revents != 0) || chp->ch->ops->is_message_pending(chp->ch)); if (ret) { lc_store((chp->detecttime), time_longclock()); } CHECKEND(chp); return ret; }
static gboolean G_SIG_check(GSource* source) { GSIGSource* sig_src = (GSIGSource*)source; g_assert(IS_SIGSOURCE(sig_src)); if (sig_src->signal_triggered) { clock_t now; clock_t diff; if (cmp_longclock(lc_fetch(sig_src->detecttime), zero_longclock) != 0){ return TRUE; } /* Otherwise, this is when it was first detected */ now = cl_times(); diff = now - sig_src->sh_detecttime; lc_store( sig_src->detecttime, sub_longclock(time_longclock(), (longclock_t)diff) ); return TRUE; } return FALSE; }
void G_main_set_trigger(GTRIGSource* source) { GTRIGSource* trig_src = (GTRIGSource*)source; g_assert(IS_TRIGSOURCE(trig_src)); trig_src->manual_trigger = TRUE; lc_store((trig_src->detecttime), time_longclock()); }
static gboolean G_WC_check(GSource * source) { GWCSource* wcp = (GWCSource*)source; g_assert(IS_WCSOURCE(wcp)); if (wcp->gpfd.revents != 0) { lc_store((wcp->detecttime), time_longclock()); return TRUE; } return FALSE; }
static gboolean G_fd_check(GSource* source) { GFDSource* fdp = (GFDSource*)source; g_assert(IS_FDSOURCE(fdp)); if (fdp->gpfd.revents) { lc_store((fdp->detecttime), time_longclock()); return TRUE; } return FALSE; }
/* g_main_loop-style check function */ static gboolean Gmain_timeout_check (GSource* src) { struct GTimeoutAppend* append = GTIMEOUT(src); longclock_t lnow = time_longclock(); g_assert(IS_TIMEOUTSRC(append)); if (cmp_longclock(lnow, append->nexttime) >= 0) { return TRUE; } return FALSE; }
static gboolean G_TRIG_check(GSource* source) { GTRIGSource* trig_src = (GTRIGSource*)source; g_assert(IS_TRIGSOURCE(trig_src)); if (trig_src->manual_trigger && cmp_longclock(lc_fetch(trig_src->detecttime), zero_longclock) == 0) { lc_store((trig_src->detecttime), time_longclock()); } return trig_src->manual_trigger; }
static gboolean send_rexmit_request( gpointer data) { struct rexmit_info* ri = (struct rexmit_info*) data; seqno_t seq = (seqno_t) ri->seq; struct node_info* node = ri->node; struct ha_msg* hmsg; if ((hmsg = ha_msg_new(6)) == NULL) { cl_log(LOG_ERR, "%s: no memory for " T_REXMIT, __FUNCTION__); return FALSE; } if (ha_msg_add(hmsg, F_TYPE, T_REXMIT) != HA_OK || ha_msg_add(hmsg, F_TO, node->nodename) !=HA_OK || ha_msg_add_int(hmsg, F_FIRSTSEQ, seq) != HA_OK || ha_msg_add_int(hmsg, F_LASTSEQ, seq) != HA_OK) { cl_log(LOG_ERR, "%s: adding fields to msg failed", __FUNCTION__); ha_msg_del(hmsg); return FALSE; } if (send_cluster_msg(hmsg) != HA_OK) { cl_log(LOG_ERR, "%s: cannot send " T_REXMIT " request to %s",__FUNCTION__, node->nodename); ha_msg_del(hmsg); return FALSE; } node->track.last_rexmit_req = time_longclock(); if (!g_hash_table_remove(rexmit_hash_table, ri)){ cl_log(LOG_ERR, "%s: entry not found in rexmit_hash_table" "for seq/node(%ld %s)", __FUNCTION__, ri->seq, ri->node->nodename); return FALSE; } schedule_rexmit_request(node, seq, max_rexmit_delay); return FALSE; }
/* g_main_loop-style prepare function */ static gboolean Gmain_timeout_prepare(GSource* src, gint* timeout) { struct GTimeoutAppend* append = GTIMEOUT(src); longclock_t lnow = time_longclock(); longclock_t remain; g_assert(IS_TIMEOUTSRC(append)); if (cmp_longclock(lnow, append->nexttime) >= 0) { *timeout = 0L; return TRUE; } /* This is safe - we will always have a positive result */ remain = sub_longclock(append->nexttime, lnow); /* This is also safe - we started out in 'ms' */ *timeout = longclockto_ms(remain); return ((*timeout) == 0); }
/* * For IPC_CHANNEL events, enable output checking when needed * and note when unread input is already queued. * * Note that we don't modify 'timeout' either. */ gboolean G_CH_prepare_int(GSource* source, gint* timeout) { GCHSource* chp = (GCHSource*)source; longclock_t funstart; gboolean ret; g_assert(IS_CHSOURCE(chp)); SAVESTART; if (chp->ch->ops->is_sending_blocked(chp->ch)) { if (chp->fd_fdx) { chp->infd.events |= OUTPUT_EVENTS; }else{ chp->outfd.events |= OUTPUT_EVENTS; } } if (chp->ch->recv_queue->current_qlen < chp->ch->recv_queue->max_qlen) { chp->infd.events |= INPUT_EVENTS; }else{ /* * This also disables EOF events - until we * read some of the packets we've already gotten * This prevents a tight loop in poll(2). */ chp->infd.events &= ~INPUT_EVENTS; } if (chp->dontread){ return FALSE; } ret = chp->ch->ops->is_message_pending(chp->ch); if (ret) { lc_store((chp->detecttime), time_longclock()); } CHECKEND(chp); return ret; }
/* g_main_loop-style dispatch function */ static gboolean Gmain_timeout_dispatch(GSource* src, GSourceFunc func, gpointer user_data) { struct GTimeoutAppend* append = GTIMEOUT(src); longclock_t dispstart; gboolean ret; g_assert(IS_TIMEOUTSRC(append)); lc_store(append->detecttime, append->nexttime); CHECK_DISPATCH_DELAY(append); /* Schedule our next dispatch */ append->nexttime = add_longclock(time_longclock() , msto_longclock(append->interval)); /* Then call the user function */ ret = func(user_data); CHECK_DISPATCH_TIME(append); return ret; }
static gboolean G_SIG_prepare(GSource* source, gint* timeoutms) { GSIGSource* sig_src = (GSIGSource*)source; g_assert(IS_SIGSOURCE(sig_src)); /* Don't let a timing window keep us in poll() forever * * The timing window in question looks like this: * No signal has occurred up to the point of prepare being called. * Signal comes in _after_ prepare was called, but _before_ poll. * signal_detected gets set, but no one checks it before going into poll * We wait in poll forever... It's not a pretty sight :-(. */ *timeoutms = 1000; /* Sigh... */ if (sig_src->signal_triggered) { clock_t now; clock_t diff; /* detecttime is reset in the dispatch function */ if (cmp_longclock(lc_fetch(sig_src->detecttime), zero_longclock) != 0) { cl_log(LOG_ERR, "%s: detecttime already set?", __FUNCTION__); return TRUE; } /* Otherwise, this is when it was first detected */ now = cl_times(); diff = now - sig_src->sh_detecttime; /* How long since signal occurred? */ lc_store( sig_src->detecttime, sub_longclock(time_longclock(), (longclock_t)diff) ); return TRUE; } return FALSE; }
guint Gmain_timeout_add_full(gint priority , guint interval , GSourceFunc function , gpointer data , GDestroyNotify notify) { struct GTimeoutAppend* append; GSource* source = g_source_new( &Gmain_timeout_funcs, sizeof(struct GTimeoutAppend)); append = GTIMEOUT(source); append->magno = MAG_GTIMEOUTSRC; append->maxdispatchms = DEFAULT_MAXDISPATCH; append->maxdispatchdelayms = DEFAULT_MAXDELAY; append->description = "(timeout)"; lc_store((append->detecttime), zero_longclock); append->udata = NULL; append->nexttime = add_longclock(time_longclock() , msto_longclock(interval)); append->interval = interval; g_source_set_priority(source, priority); g_source_set_can_recurse(source, FALSE); g_source_set_callback(source, function, data, notify); append->gsourceid = g_source_attach(source, NULL); g_source_unref(source); return append->gsourceid; }
int LogToLoggingDaemon(int priority, const char * buf, int bufstrlen, gboolean use_pri_str) { IPC_Channel* chan = logging_daemon_chan; static longclock_t nexttime = 0; IPC_Message* msg; int sendrc = IPC_FAIL; int intval = conn_logd_time; if (chan == NULL) { longclock_t lnow = time_longclock(); if (cmp_longclock(lnow, nexttime) >= 0){ nexttime = add_longclock( lnow, msto_longclock(intval)); logging_daemon_chan = chan = create_logging_channel(); } } if (chan == NULL){ cl_direct_log( priority, buf, TRUE, NULL, cl_process_pid, NULLTIME); return HA_FAIL; } msg = ChildLogIPCMessage(priority, buf, bufstrlen, use_pri_str, chan); if (msg == NULL) { drop_msg_num++; return HA_FAIL; } if (chan->ch_status == IPC_CONNECT){ if (chan->ops->is_sending_blocked(chan)) { chan->ops->resume_io(chan); } /* Make sure there is room for the drop message _and_ the * one we wish to log. Otherwise there is no point. * * Try to avoid bouncing on the limit by additionally * waiting until there is room for QUEUE_SATURATION_FUZZ * messages. */ if (drop_msg_num > 0 && chan->send_queue->current_qlen < (chan->send_queue->max_qlen -1 -QUEUE_SATURATION_FUZZ)) { /* have to send it this way so the order is correct */ send_dropped_message(use_pri_str, chan); } sendrc = chan->ops->send(chan, msg); } if (sendrc == IPC_OK) { return HA_OK; } else { if (chan->ops->get_chan_status(chan) != IPC_CONNECT) { if (!logging_chan_in_main_loop){ chan->ops->destroy(chan); } logging_daemon_chan = NULL; cl_direct_log(priority, buf, TRUE, NULL, cl_process_pid, NULLTIME); if (drop_msg_num > 0){ /* Direct logging here is ok since we're * switching to that for everything * "for a while" */ cl_log(LOG_ERR, "cl_log: %d messages were dropped" " : channel destroyed", drop_msg_num); } drop_msg_num=0; FreeChildLogIPCMessage(msg); return HA_FAIL; } drop_msg_num++; } FreeChildLogIPCMessage(msg); return HA_FAIL; }
/* * Some kind of event occurred - notify the user. */ gboolean G_CH_dispatch_int(GSource * source, GSourceFunc callback, gpointer user_data) { GCHSource* chp = (GCHSource*)source; longclock_t dispstart; longclock_t resume_start = zero_longclock; g_assert(IS_CHSOURCE(chp)); CHECK_DISPATCH_DELAY(chp); if (chp->dontread){ return TRUE; } /* Is output now unblocked? * * If so, turn off OUTPUT_EVENTS to avoid going into * a tight poll(2) loop. */ if (chp->fd_fdx) { if (chp->infd.revents & OUTPUT_EVENTS) { chp->infd.events &= ~OUTPUT_EVENTS; } }else if (chp->outfd.revents & OUTPUT_EVENTS) { chp->outfd.events &= ~OUTPUT_EVENTS; } if (ANYDEBUG) { resume_start = time_longclock(); } chp->ch->ops->resume_io(chp->ch); if (ANYDEBUG) { longclock_t resume_end = time_longclock(); unsigned long ms; ms = longclockto_ms(sub_longclock(resume_end , resume_start)); if (ms > 10) { cl_log(LOG_WARNING , "%s: resume_io() for %s took %lu ms" , __FUNCTION__ , chp->description, ms); } } if(chp->dispatch && chp->ch->ops->is_message_pending(chp->ch)) { if(!(chp->dispatch(chp->ch, chp->udata))){ g_source_remove_poll(source, &chp->infd); if (!chp->fd_fdx) { g_source_remove_poll(source, &chp->outfd); } CHECK_DISPATCH_TIME(chp); g_source_unref(source); return FALSE; } } CHECK_DISPATCH_TIME(chp); if (chp->ch->ch_status == IPC_DISCONNECT){ return FALSE; } return TRUE; }