delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2006/05/10/07:19:41

X-Spam-Check-By: sourceware.org
Date: Wed, 10 May 2006 04:19:19 -0700
From: clayne AT anodized DOT com
To: cygwin AT cygwin DOT com
Cc: dave DOT korn AT artimi DOT com
Subject: Re: readv() questions
Message-ID: <20060510111919.GN18330@ns1.anodized.com>
References: <20060509143556 DOT GI18330 AT ns1 DOT anodized DOT com> <02ab01c67378$71ad2440$a501a8c0 AT CAM DOT ARTIMI DOT COM> <20060510051135 DOT GK18330 AT ns1 DOT anodized DOT com>
Mime-Version: 1.0
In-Reply-To: <20060510051135.GK18330@ns1.anodized.com>
User-Agent: Mutt/1.5.11
X-Assp-Spam-Prob: 0.00000
X-Assp-Whitelisted: Yes
X-Assp-Envelope-From: clayne AT ns1 DOT anodized DOT com
X-IsSubscribed: yes
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Unsubscribe: <mailto:cygwin-unsubscribe-archive-cygwin=delorie DOT com AT cygwin DOT com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

On Tue, May 09, 2006 at 10:11:35PM -0700, clayne AT anodized DOT com wrote:
> 
> So far so good, but if anyone sees anything glaring might as well point it
> out - although this is not really CW related at this point.
> 
> -cl

Just to follow up on this.. I did take your advice fully Dave, and decided
to just modify the partial iovec in place and restore a copy of it after
handling the partial situation. Reason being that it's beneficial to set
an iovec array once and pass it to read or writev on every call (if one
is using relatively non changing locations assigned to each iov_base per
vector - if not, it still works anyways). So far so good, I setup a test
case and have transfered over 20,000,000 records via 6 iovecs each at
around ~20-70 bytes average record size. I've also verified that partials
are occuring, in addition to both mid-vector and mid-array. 200K/sec - so
I think we can rest assured race conditions are out of the picture. My
code was the culprit, cygwin's was not :).

In case anyone needs the code for any purpose (I know that I searched usenet
and web quite a bit looking for any references to short|trunc|partial, etc.
WRT readv()/writev() and found very little, so this may come in handy to
others.

-cl


/* header */
#ifndef __NIOV_H
#define __NIOV_H

#define n_recv_iov(a,b,c,d) \
	n_iov_generic(a,b,c,d,N_IOV_RECV)
#define n_send_iov(a,b,c,d) \
	n_iov_generic(a,b,c,d,N_IOV_SEND)

enum n_iov_type__ {
	N_IOV_RECV,
	N_IOV_SEND
};
typedef enum n_iov_type__ n_iov_type;

ssize_t n_iov_generic(const int, struct iovec *, ssize_t, const int, n_iov_type);
ssize_t n_iov_offset(const struct iovec *, const ssize_t, ssize_t *);
ssize_t n_iov_total(const struct iovec *, const ssize_t);

#endif /* __NIOV_H */


/* module */
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include "niov.h"

#define _POSIX_SOURCE 1

ssize_t n_iov_offset(const struct iovec *v, const ssize_t c, ssize_t *os)
{
	ssize_t		l, cv;

	/*
	 * compute filled iovec count and set any partial offset in "os".
	 * "os" should point to the number of bytes previously read when
	 * called.
	 */
	for (cv = 0; cv < c; cv++) {
		if ((l = v[cv].iov_len) > *os) break;
		*os -= l;
	}

	return cv;
}

ssize_t n_iov_total(const struct iovec *v, const ssize_t c)
{
	ssize_t		cv, bt;

	for (cv = bt = 0; cv < c; cv++)
		bt += v[cv].iov_len;

	return bt;
}

ssize_t n_iov_generic(const int s, struct iovec *v, ssize_t c, const int t, n_iov_type nt)
{
	struct timeval	to;
	struct iovec	iov_o = { NULL, 0 };
	fd_set		fds, fds_m, *rfds = NULL, *wfds = NULL;
	ssize_t		(*nf_iov)(int, const struct iovec *, ssize_t);
	ssize_t		cv, b, be, bt;
	int		res;

	switch (nt) {
	case N_IOV_RECV:
		nf_iov = readv;
		rfds = &fds;
		break;
	case N_IOV_SEND:
		nf_iov = writev;
		wfds = &fds;
		break;
	default: break;
	}

	FD_ZERO(&fds_m);
	FD_SET(s, &fds_m);

	for (bt = 0, be = n_iov_total(v, c); bt < be; ) {
		fds = fds_m;
		to.tv_sec = t;
		to.tv_usec = 0;

		b = nf_iov(s, v, c);

		if (b == -1) {
			switch (errno) {
			case EWOULDBLOCK:
			case EINTR:
				break;
			default:
				perror(nt == N_IOV_RECV ? "readv" : "writev");
				bt = -1;
				break;
			}

			if (bt == -1) break;
		} else if (b && (bt += b) < be) {
			/*
			 * short count situation.
			 *
			 * if not within mid-vector, advance past filled, else
			 * temporarily modify original iovec to make up the
			 * difference and restore on exit.
			 */

			/* if previously saved, restore before modify */
			if (iov_o.iov_base) {
				memcpy(v, &iov_o, sizeof(*v));
				iov_o.iov_base = NULL;
			}

			/*
			 * cv = filled vectors returned, advance past these.
			 * b = mid-vector offset in case of partial vector.
			 */
			cv = n_iov_offset(v, c, &b);
			v += cv;
			c -= cv;

			/* if mid-vector, save original before modifying */
			if (b) {
				memcpy(&iov_o, v, sizeof(*v));
				v->iov_base = (char *)v->iov_base + b;
				v->iov_len -= b;
			}

			continue;
		} else {
			break;
		}

		if ((res = select(s + 1, rfds, wfds, NULL, &to)) == 0) {
			bt = -1;		/* timeout */
			break;
		} else if (res == -1) {
			perror("select");	/* never happen */
			bt = -1;
			break;
		}
	}

	/* restore original if still modified */
	if (iov_o.iov_base)
		memcpy(v, &iov_o, sizeof(iov_o));

	return bt;
}


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019