static void ipc_read_handler(ngx_event_t *ev) { DBG("IPC channel handler"); //copypasta from os/unix/ngx_process_cycle.c (ngx_channel_handler) ngx_int_t n; ipc_alert_t alert; ngx_connection_t *c; if (ev->timedout) { ev->timedout = 0; return; } c = ev->data; while(1) { n = ipc_read_socket(c->fd, &alert, ev->log); if (n == NGX_ERROR) { ERR("IPC_READ_SOCKET failed: bad connection. This should never have happened, yet here we are..."); assert(0); return; } if (n == NGX_AGAIN) { return; } //ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "nchan: channel command: %d", ch.command); assert(n == sizeof(alert)); if(alert.worker_generation < memstore_worker_generation) { ERR("Got IPC alert for previous generation's worker. discarding."); } else { #if DEBUG_DELAY_IPC_RECEIVE_ALERT_MSEC delayed_alert_glob_t *glob = ngx_alloc(sizeof(*glob), ngx_cycle->log); if (NULL == glob) { ERR("Couldn't allocate memory for alert glob data."); return; } ngx_memzero(&glob->timer, sizeof(glob->timer)); nchan_init_timer(&glob->timer, fake_ipc_alert_delay_handler, glob); glob->alert = alert; glob->ipc = (ipc_t *)c->data; ngx_add_timer(&glob->timer, DEBUG_DELAY_IPC_RECEIVE_ALERT_MSEC); #else if(ngx_time() - alert.time_sent >= 2) { ipc_record_alert_receive_delay(ngx_time() - alert.time_sent); } nchan_update_stub_status(ipc_total_alerts_received, 1); ((ipc_t *)c->data)->handler(alert.src_slot, alert.code, alert.data); #endif } } }
ngx_int_t ipc_init(ipc_t *ipc) { int i = 0; ipc_process_t *proc; nchan_init_timer(&receive_alert_delay_log_timer, receive_alert_delay_log_timer_handler, NULL); nchan_init_timer(&send_alert_delay_log_timer, send_alert_delay_log_timer_handler, NULL); for(i=0; i< NGX_MAX_PROCESSES; i++) { proc = &ipc->process[i]; proc->ipc = ipc; proc->pipe[0]=NGX_INVALID_FILE; proc->pipe[1]=NGX_INVALID_FILE; proc->c=NULL; proc->active = 0; ngx_memzero(proc->wbuf.alerts, sizeof(proc->wbuf.alerts)); proc->wbuf.first = 0; proc->wbuf.n = 0; proc->wbuf.overflow_first = NULL; proc->wbuf.overflow_last = NULL; proc->wbuf.overflow_n = 0; } return NGX_OK; }
ngx_event_t *spooler_add_timer(channel_spooler_t *spl, ngx_msec_t timeout, void (*cb)(void *), void (*cancel)(void *), void *pd) { spooler_event_ll_t *spl_ev = ngx_alloc(sizeof(*spl_ev), ngx_cycle->log); ngx_memzero(&spl_ev->ev, sizeof(spl_ev->ev)); nchan_init_timer(&spl_ev->ev, spooler_timer_handler, pd); spl_ev->callback = cb; spl_ev->cancel = cancel; spl_ev->spooler = spl; spl_ev->next = spl->spooler_dependent_events; spl_ev->prev = NULL; if(spl->spooler_dependent_events) { spl->spooler_dependent_events->prev = spl_ev; } spl->spooler_dependent_events = spl_ev; ngx_add_timer(&spl_ev->ev, timeout); return &spl_ev->ev; }
void nchan_subscriber_init_timeout_timer(subscriber_t *sub, ngx_event_t *ev) { ngx_memzero(ev, sizeof(*ev)); nchan_init_timer(ev, nchan_subscriber_timeout_ev_handler, sub); }