static int is_dupe(merlin_event *pkt) { if (!check_dupes) { return 0; } if (last_pkt.hdr.type != pkt->hdr.type) { return 0; } if (packet_size(&last_pkt) != packet_size(pkt)) { return 0; } /* if this is truly a dupe, return 1 and log every 100'th */ if (!memcmp(&last_pkt, pkt, packet_size(pkt))) { dupe_bytes += packet_size(pkt); if (!(++dupes % 100)) { ldebug("%s in %llu duplicate packets dropped", human_bytes(dupe_bytes), dupes); } return 1; } return 0; }
/* * Reads input from a particular node and ships it off to * the "handle_event()" */ int net_input(int sd, int io_evt, void *node_) { merlin_event *pkt; merlin_node *node = (merlin_node *)node_; int len, events = 0; errno = 0; ldebug("NETINPUT from %p (%s)", node, node ? node->name : "oops"); len = node_recv(node); if (len < 0) { return 0; } node->stats.bytes.read += len; node->last_recv = time(NULL); while ((pkt = node_get_event(node))) { events++; handle_event(node, pkt); free(pkt); } ldebug("Read %d events in %s from %s node %s", events, human_bytes(len), node_type(node), node->name); return events; }
static int ipc_reap_events(void) { int len, events = 0; merlin_event *pkt; node_log_event_count(&ipc, 0); len = node_recv(&ipc); if (len < 0) return len; while ((pkt = node_get_event(&ipc))) { events++; handle_ipc_event(pkt); } ldebug("Read %d events in %s from %s", events, human_bytes(len), ipc.name); return 0; }
/* * Reads input from a particular node and ships it off to * the "handle_network_event()" routine up above */ static int net_input(merlin_node *node) { merlin_event *pkt; int len, events = 0; errno = 0; len = node_recv(node); if (len < 0) { return 0; } node->stats.bytes.read += len; node->last_recv = time(NULL); while ((pkt = node_get_event(node))) { events++; handle_network_event(node, pkt); } ldebug("Read %d events in %s from %s node %s", events, human_bytes(len), node_type(node), node->name); return events; }
void node_log_event_count(merlin_node *node, int force) { struct timeval now; merlin_node_stats *s = &node->stats; unsigned long long b_in, b_out, e_in, e_out; const char *dura; /* * This works like a 'mark' that syslogd produces. We log once * every 60 seconds */ gettimeofday(&now, NULL); if (!force && s->last_logged && s->last_logged + 60 > now.tv_sec) return; s->last_logged = now.tv_sec; dura = tv_delta(&self.start, &now); b_in = s->bytes.read; b_out = s->bytes.sent + s->bytes.logged + s->bytes.dropped; e_in = s->events.read; e_out = s->events.sent + s->events.logged + s->events.dropped; linfo("Handled %llu events from/to %s in %s. in: %llu, out: %llu", e_in + e_out, node->name, dura, e_in, e_out); linfo("Handled %s from/to %s in %s. in: %s, out: %s", human_bytes(b_in + b_out), node->name, dura, human_bytes(b_in), human_bytes(b_out)); if (!e_out) return; linfo("%s events/bytes: read %llu/%s, sent %llu/%s, dropped %llu/%s, logged %llu/%s, logsize %u/%s", node->name, e_in, human_bytes(b_in), s->events.sent, human_bytes(s->bytes.sent), s->events.dropped, human_bytes(s->bytes.dropped), s->events.logged, human_bytes(s->bytes.logged), binlog_entries(node->binlog), human_bytes(binlog_size(node->binlog))); }
void node_set_state(merlin_node *node, int state, const char *reason) { int prev_state, add; if (!node) return; if (node->state == state) return; if (reason) { linfo("NODESTATE: %s: %s -> %s: %s", node->name, node_state_name(node->state), node_state_name(state), reason); } /* * Keep track of active nodes. Setting 'add' to the proper * value means we needn't bother with an insane chain of * if()'s later. * add = +1 if state changes TO 'STATE_CONNECTED'. * add = -1 if state changes FROM 'STATE_CONNECTED' * add remains zero for all other cases */ if (state == STATE_CONNECTED) { add = 1; node->connect_time = time(NULL); } else if (node->state == STATE_CONNECTED) { add = -1; } else { add = 0; } if (node->type == MODE_POLLER) self.active_pollers += add; else if (node->type == MODE_PEER) self.active_peers += add; else if (node->type == MODE_MASTER) self.active_masters += add; prev_state = node->state; node->state = state; if (node->state != STATE_CONNECTED && prev_state != STATE_CONNECTED) return; if (node->action) node->action(node, prev_state); if (node->state == STATE_CONNECTED && node->sock >= 0) { int snd, rcv; socklen_t size = sizeof(int); /* mark this so we can disconnect nodes that never send data */ node->last_recv = time(NULL); merlin_set_socket_options(node->sock, 224 * 1024); getsockopt(node->sock, SOL_SOCKET, SO_SNDBUF, &snd, &size); getsockopt(node->sock, SOL_SOCKET, SO_SNDBUF, &rcv, &size); ldebug("send / receive buffers are %s / %s for node %s", human_bytes(snd), human_bytes(rcv), node->name); } }