Beispiel #1
0
static int node_binlog_add(merlin_node *node, merlin_event *pkt)
{
	int result;

	/*
	 * we skip stashing some packet types in the binlog. Typically
	 * those that get generated immediately upon reconnect anyway
	 * since they would just cause unnecessary overhead and might
	 * trigger a lot of unnecessary actions if stashed.
	 */
	if (pkt->hdr.type == CTRL_PACKET) {
		if (pkt->hdr.code == CTRL_ACTIVE || pkt->hdr.code == CTRL_INACTIVE)
			return 0;
	}

	if (!node->binlog) {
		char *path;

		/* +20 to safely accommodate for "/.module.binlog\0" */
		path = calloc(1, strlen(binlog_dir) + strlen(node->name) + 20);
		sprintf(path, "%s/%s.%s.binlog",
		        binlog_dir, is_module ? "module" : "daemon", node->name);
		linfo("Creating binary backlog for %s. On-disk location: %s",
			  node->name, path);

		/* 10MB in memory, 100MB on disk */
		node->binlog = binlog_create(path, 10 << 20, 100 << 20, BINLOG_UNLINK);
		if (!node->binlog) {
			lerr("Failed to create binary backlog for %s: %s",
				 node->name, strerror(errno));
			return -1;
		}
		free(path);
	}

	result = binlog_add(node->binlog, pkt, packet_size(pkt));
	if (result < 0) {
		binlog_wipe(node->binlog, BINLOG_UNLINK);
		/* XXX should mark node as unsynced here */
		node->stats.events.dropped += node->stats.events.logged + 1;
		node->stats.bytes.dropped += node->stats.bytes.logged + packet_size(pkt);
		node->stats.events.logged = 0;
		node->stats.bytes.logged = 0;
	} else {
		node->stats.events.logged++;
		node->stats.bytes.logged += packet_size(pkt);
	}

	node_log_event_count(node, 0);

	return result;
}
Beispiel #2
0
void binlog_destroy(binlog *bl, int flags)
{
	if (!bl)
		return;

	binlog_wipe(bl, flags);

	if (bl->path) {
		free(bl->path);
		bl->path = NULL;
	}

	free(bl);
}
Beispiel #3
0
int node_send_binlog(merlin_node *node, merlin_event *pkt)
{
	merlin_event *temp_pkt;
	uint len;

	ldebug("Emptying backlog for %s", node->name);
	while (io_write_ok(node->sock, 10) && !binlog_read(node->binlog, (void **)&temp_pkt, &len)) {
		int result;
		if (!temp_pkt || packet_size(temp_pkt) != (int)len ||
		    !len || !packet_size(temp_pkt) || packet_size(temp_pkt) > MAX_PKT_SIZE)
		{
			if (!temp_pkt) {
				lerr("BACKLOG: binlog returned 0 but presented no data");
			} else {
				lerr("BACKLOG: binlog returned a packet claiming to be of size %d", packet_size(temp_pkt));
			}
			lerr("BACKLOG: binlog claims the data length is %u", len);
			lerr("BACKLOG: wiping backlog. %s is now out of sync", node->name);
			binlog_wipe(node->binlog, BINLOG_UNLINK);
			return -1;
		}
		errno = 0;
		result = node_send(node, temp_pkt, packet_size(temp_pkt), MSG_DONTWAIT);

		/* keep going while we successfully send something */
		if (result == packet_size(temp_pkt)) {
			node->stats.events.sent++;
			node->stats.events.logged--;
			node->stats.bytes.logged -= packet_size(temp_pkt);

			/*
			 * binlog duplicates the memory, so we must release it
			 * when we've sent and counted it
			 */
			free(temp_pkt);
			continue;
		}

		/*
		 * we can recover from total failures by unread()'ing
		 * the entry we just read and then adding the new entry
		 * to the binlog in the hopes that we'll get a
		 * connection up and running again before it's time to
		 * send more data to this node
		 */
		if (result <= 0) {
			if (!binlog_unread(node->binlog, temp_pkt, len)) {
				if (pkt)
					return node_binlog_add(node, pkt);
				return 0;
			} else {
				free(temp_pkt);
			}
		}

		/*
		 * we wrote a partial event or failed to unread the event,
		 * so this node is now out of sync. We must wipe the binlog
		 * and possibly mark this node as being out of sync.
		 */
		lerr("Wiping binlog for %s node %s", node_type(node), node->name);
		binlog_wipe(node->binlog, BINLOG_UNLINK);
		if (pkt) {
			node->stats.events.dropped += node->stats.events.logged + 1;
			node->stats.bytes.dropped += node->stats.bytes.logged + packet_size(pkt);
		}
		node_log_event_count(node, 0);
		return -1;
	}

	return 0;
}