[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCHv3 9/9] rewrite and comment qemu_sendv_recvv()
From: |
Michael Tokarev |
Subject: |
[Qemu-devel] [PATCHv3 9/9] rewrite and comment qemu_sendv_recvv() |
Date: |
Mon, 12 Mar 2012 23:14:23 +0400 |
Make it much more understandable, and add
comments to it.
The new implementation has been extensively
tested by splitting a large buffer into
many small randomly-sized chunks, sending
it over socket to another, slow process
and verifying the receiving data is the
same.
Signed-off-by: Michael Tokarev <address@hidden>
---
cutils.c | 106 ++++++++++++++++++++++++++++++++------------------------------
1 files changed, 55 insertions(+), 51 deletions(-)
diff --git a/cutils.c b/cutils.c
index be2173f..7a19874 100644
--- a/cutils.c
+++ b/cutils.c
@@ -396,81 +396,85 @@ ssize_t qemu_sendv_recvv(int sockfd, struct iovec *iov,
size_t offset, size_t bytes,
bool do_sendv)
{
- int iovlen;
ssize_t ret;
- size_t diff;
- struct iovec *last_iov;
+ struct iovec *end;
- /* last_iov is inclusive, so count from one. */
- iovlen = 1;
- last_iov = iov;
- bytes += offset;
-
- while (last_iov->iov_len < bytes) {
- bytes -= last_iov->iov_len;
-
- last_iov++;
- iovlen++;
- }
-
- diff = last_iov->iov_len - bytes;
- last_iov->iov_len -= diff;
-
- while (iov->iov_len <= offset) {
+ /* Find the start position, skipping `offset' bytes:
+ * first, skip all full-sized vector elements, */
+ while(offset >= iov->iov_len) {
offset -= iov->iov_len;
-
- iov++;
- iovlen--;
+ ++iov;
+ }
+ if (offset) {
+ /* second, skip `offset' bytes from the (now) first element,
+ * undo it on exit */
+ iov->iov_base += offset;
+ iov->iov_len -= offset;
+ }
+ /* Find the end position skipping `bytes' bytes: */
+ /* first, skip all full-sized elements */
+ end = iov;
+ while(end->iov_len <= bytes) {
+ bytes -= end->iov_len;
+ ++end;
+ }
+ if (bytes) {
+ /* second, fixup the last element, and remember
+ * the length we've cut from the end of it in `bytes' */
+ size_t tail = end->iov_len - bytes;
+ end->iov_len = bytes;
+ ++end;
+ bytes = tail;
}
-
- iov->iov_base = (char *) iov->iov_base + offset;
- iov->iov_len -= offset;
{
#if defined CONFIG_IOVEC && defined CONFIG_POSIX
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = iov;
- msg.msg_iovlen = iovlen;
-
+ msg.msg_iovlen = end - iov;;
do {
- if (do_sendv) {
- ret = sendmsg(sockfd, &msg, 0);
- } else {
- ret = recvmsg(sockfd, &msg, 0);
- }
- } while (ret == -1 && errno == EINTR);
+ ret = do_sendv
+ ? sendmsg(sockfd, &msg, 0)
+ : recvmsg(sockfd, &msg, 0);
+ } while (ret < 0 && errno == EINTR);
#else
+ /* else send piece-by-piece */
+ /*XXX Note: windows has WSASend() and WSARecv() */
struct iovec *p = iov;
ret = 0;
- while (iovlen > 0) {
- int rc;
- if (do_sendv) {
- rc = send(sockfd, p->iov_base, p->iov_len, 0);
+ while(p < end) {
+ int r = do_sendv
+ ? send(sockfd, p->iov_base, p->iov_len, 0)
+ : recv(sockfd, p->iov_base, p->iov_len, 0);
+ if (r > 0) {
+ ret += r;
+ ++i;
+ } else if (!r) {
+ break;
+ } else if (errno == EINTR) {
+ continue;
} else {
- rc = qemu_recv(sockfd, p->iov_base, p->iov_len, 0);
- }
- if (rc == -1) {
- if (errno == EINTR) {
- continue;
- }
+ /* else it is some "other" error,
+ * only return if there was no data processed. */
if (ret == 0) {
ret = -1;
}
break;
}
- if (rc == 0) {
- break;
- }
- ret += rc;
- iovlen--, p++;
}
#endif
}
/* Undo the changes above */
- iov->iov_base = (char *) iov->iov_base - offset;
- iov->iov_len += offset;
- last_iov->iov_len += diff;
+ if (offset) {
+ iov->iov_base -= offset;
+ iov->iov_len += offset;
+ }
+ if (bytes) {
+ --end;
+ end->iov_len += bytes;
+ }
+
return ret;
}
--
1.7.9.1
- [Qemu-devel] [PATCHv3 0/9] cleanup/consolidate some iovec functions, Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 2/9] consolidate qemu_iovec_memset{, _skip}() into single function and use existing iov_memset(), Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 1/9] refresh iov_* functions, Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 4/9] consolidate qemu_iovec_copy() and qemu_iovec_concat() and make them consistent, Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 5/9] change qemu_iovec_to_buf() to match other to, from_buf functions, Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 8/9] cleanup qemu_co_sendv(), qemu_co_recvv() and friends, Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 7/9] export qemu_sendv_recvv() and use it in qemu_sendv() and qemu_recvv(), Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 3/9] allow qemu_iovec_from_buffer() to specify offset from which to start copying, Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 6/9] change prototypes of qemu_sendv() and qemu_recvv(), Michael Tokarev, 2012/03/12
- [Qemu-devel] [PATCHv3 9/9] rewrite and comment qemu_sendv_recvv(),
Michael Tokarev <=
- Re: [Qemu-devel] [PATCHv3 0/9] cleanup/consolidate some iovec functions, Michael Tokarev, 2012/03/13