Example #1
0
/*
 * Three cases to handle:
 *  - buf has data, iocache doesn't.
 *  - iocache has data, buf doesn't.
 *  - both buf and iocache has data.
 */
int iocache_sendto(iocache *ioc, int fd, char *buf, unsigned int len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
{
	int sent;

	errno = 0;
	if (!ioc)
		return -1;

	if (!ioc->ioc_buflen && !len)
		return 0;

	if (ioc->ioc_buf && iocache_available(ioc)) {
		if (buf && len) {
			/* copy buf and len to iocache buffer to use just one write */
			if (iocache_capacity(ioc) < len) {
				if (iocache_grow(ioc, iocache_size(ioc)) < 0)
					return -1;
			}
			if (iocache_add(ioc, buf, len) < 0)
				return -1;
		}
		buf = ioc->ioc_buf;
		len = iocache_available(ioc);
	}

	sent = sendto(fd, buf, len, flags, dest_addr, addrlen);
	if (sent < 1)
		return -errno;

	if (iocache_available(ioc))
		iocache_use_size(ioc, sent);

	return sent;
}
Example #2
0
File: node.c Project: ageric/merlin
/*
 * Fetch one event from the node's iocache. If the cache is
 * exhausted, we handle partial events and iocache resets and
 * return NULL
 */
merlin_event *node_get_event(merlin_node *node)
{
	merlin_event *pkt;
	iocache *ioc = node->ioc;

	pkt = (merlin_event *)(iocache_use_size(ioc, HDR_SIZE));

	/*
	 * buffer is empty
	 */
	if (pkt == NULL) {
		return NULL;
	}

	/*
	 * If buffer is smaller than expected, put the header back
	 * and wait for more data
	 */
	if (pkt->hdr.len > iocache_available(ioc)) {
		ldebug("IOC: packet is longer (%i) than remaining data (%lu) from %s - will read more and try again", pkt->hdr.len, iocache_available(ioc), node->name);
		if (iocache_unuse_size(ioc, HDR_SIZE) < 0)
			lerr("IOC: Failed to unuse %d bytes from iocache. Next packet from %s will be invalid\n", HDR_SIZE, node->name);
		return NULL;
	}

	if (pkt->hdr.sig.id != MERLIN_SIGNATURE) {
		lerr("Invalid signature on packet from '%s'. Disconnecting node", node->name);
		node_disconnect(node, "Invalid signature");
		return NULL;
	}
	node->stats.events.read++;
	iocache_use_size(ioc, pkt->hdr.len);
	return pkt;
}
Example #3
0
static int print_input(int sd, int events, void *wp_)
{
	int ret, pkt = 0;
	simple_worker *wp = (simple_worker *)wp_;
	struct kvvec kvv = KVVEC_INITIALIZER;
	char *buf;
	unsigned long tot_bytes = 0, size;

	/*
	 * if some command filled the buffer, we grow it and read some
	 * more until we hit the limit
	 * @todo Define a limit :p
	 */
	size = iocache_size(wp->ioc);
	if (!iocache_capacity(wp->ioc)) {
		if (iocache_size(wp->ioc) < MAX_IOCACHE_SIZE) {
			/* double the size */
			iocache_grow(wp->ioc, iocache_size(wp->ioc));
			printf("Growing iocache for worker %d. sizes old/new %lu/%lu\n",
				   wp->pid, size, iocache_size(wp->ioc));
		} else {
			printf("iocache_size() for worker %d is already at max\n", wp->pid);
		}
	}

	ret = iocache_read(wp->ioc, sd);
	if (!ret) {
		printf("Worker with pid %d seems to have crashed. Exiting\n", wp->pid);
		exit(1);
	}
	if (ret < 0) {
		printf("iocache_read() from worker %d returned %d: %m\n", wp->pid, ret);
		return 0;
	}
	printf("read %d bytes from worker with pid %d::\n", ret, wp->pid);
	while ((buf = worker_ioc2msg(wp->ioc, &size, 0))) {
		int i, ret;
		tot_bytes += size;
		ret = worker_buf2kvvec_prealloc(&kvv, buf, (unsigned int)size, KVVEC_ASSIGN);
		if (!ret < 0) {
			printf("main: Failed to parse buffer of size %lu to key/value vector\n", size);
			continue;
		}
		for (i = 0; i < kvv.kv_pairs; i++) {
			struct key_value *kv = &kvv.kv[i];
			if (!i && memcmp(kv->key, buf, kv->key_len)) {
				printf("### kv[0]->key doesn't match buf. error in kvvec?\n");
			}
			printf("main: %2d.%02d: %s=%s\n", pkt, i, kv->key, kv->value);
		}
		pkt++;
	}

	printf("iocache: available: %lu; size: %lu; capacity: %lu\n",
		   iocache_available(wp->ioc), iocache_size(wp->ioc), iocache_capacity(wp->ioc));
	printf("Got %d packets in %ld bytes (ret: %d)\n", pkt, tot_bytes, ret);

	return 0;
}
Example #4
0
char *iocache_use_size(iocache *ioc, unsigned long size)
{
	char *ret;

	if (!ioc || !ioc->ioc_buf)
		return NULL;
	if (ioc->ioc_bufsize < size || iocache_available(ioc) < size)
		return NULL;

	ret = ioc->ioc_buf + ioc->ioc_offset;
	ioc->ioc_offset += size;

	return ret;
}
Example #5
0
char *iocache_use_delim(iocache *ioc, const char *delim, size_t delim_len, unsigned long *size)
{
	char *ptr = NULL;
	char *buf;
	unsigned long remains;

	if (!ioc || !ioc->ioc_buf || !ioc->ioc_bufsize || !ioc->ioc_buflen)
		return NULL;

	*size = 0;
	if (ioc->ioc_offset >= ioc->ioc_buflen) {
		iocache_move_data(ioc);
		return NULL;
	}

	buf = &ioc->ioc_buf[ioc->ioc_offset];
	remains = iocache_available(ioc);
	while (remains >= delim_len) {
		unsigned long jump;
		ptr = memchr(buf, *delim, remains - (delim_len - 1));
		if (!ptr) {
			return NULL;
		}
		if (delim_len == 1 || !memcmp(ptr, delim, delim_len)) {
			unsigned long ioc_start;

			ioc_start = (unsigned long)ioc->ioc_buf + ioc->ioc_offset;
			*size = (unsigned long)ptr - ioc_start;

			/* make sure we use up all of the delimiter as well */
			return iocache_use_size(ioc, delim_len + *size);
		}
		jump = 1 + (unsigned long)ptr - (unsigned long)buf;
		remains -= jump;
		buf += jump;
	}
	return NULL;
}