summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-10-25 07:29:33 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-10-25 07:29:33 +0800
commitc094b7aa82322bfd5f7adbd55a071b893801b744 (patch)
treeba237edf3d444e17c2a112702c27789fc9e5a087
parenta0858239614fd1c0099090f4448bc0058581923f (diff)
downloadpttbbs-c094b7aa82322bfd5f7adbd55a071b893801b744.tar
pttbbs-c094b7aa82322bfd5f7adbd55a071b893801b744.tar.gz
pttbbs-c094b7aa82322bfd5f7adbd55a071b893801b744.tar.bz2
pttbbs-c094b7aa82322bfd5f7adbd55a071b893801b744.tar.lz
pttbbs-c094b7aa82322bfd5f7adbd55a071b893801b744.tar.xz
pttbbs-c094b7aa82322bfd5f7adbd55a071b893801b744.tar.zst
pttbbs-c094b7aa82322bfd5f7adbd55a071b893801b744.zip
* use readv/writev for vbuf_read/write. (thanks to kcwu)
git-svn-id: http://opensvn.csie.org/pttbbs/trunk@4984 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r--pttbbs/common/sys/vbuf.c105
-rw-r--r--pttbbs/include/cmsys.h8
2 files changed, 73 insertions, 40 deletions
diff --git a/pttbbs/common/sys/vbuf.c b/pttbbs/common/sys/vbuf.c
index 4dda19ed..d141ce98 100644
--- a/pttbbs/common/sys/vbuf.c
+++ b/pttbbs/common/sys/vbuf.c
@@ -27,9 +27,10 @@
#include <errno.h>
#include <assert.h>
-// for read/write/send/recv
+// for read/write/send/recv/readv/writev
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/uio.h>
#include <unistd.h>
// #include "vbuf.h"
@@ -142,7 +143,7 @@ vbuf_strchr(VBUF *v, char c)
const char *s = v->tail, *d = v->head;
if (vbuf_is_empty(v))
- return 0;
+ return -1;
if (d < s)
d = v->buf_end;
@@ -158,7 +159,7 @@ vbuf_strchr(VBUF *v, char c)
while (s < d)
if (*s++ == c)
- return s - v->tail -1;
+ return (v->buf_end - v->tail) + s - v->buf -1;
return -1;
}
@@ -184,6 +185,7 @@ vbuf_get(VBUF *v, char *s, size_t sz)
if (v->tail == v->buf_end)
v->tail = v->buf;
}
+ assert(sz == 0);
return 1;
}
@@ -205,48 +207,57 @@ vbuf_put(VBUF *v, const char *s, size_t sz)
if (v->head == v->buf_end)
v->head = v->buf;
}
+ assert(sz == 0);
return 1;
}
/* read/write callbacks */
static ssize_t
-vbuf_rw_write(const void *p, size_t len, void *ctx)
+vbuf_rw_write(struct iovec iov[2], void *ctx)
{
int fd = *(int*)ctx;
ssize_t ret;
- while ( (ret = write(fd, p, len)) < 0 &&
- (errno == EAGAIN || errno == EINTR));
+ while ( (ret = writev(fd, iov, iov[1].iov_len ? 2 : 1)) < 0 &&
+ (errno == EINTR));
+ if (ret < 0 && errno == EAGAIN)
+ ret = 0;
return ret;
}
static ssize_t
-vbuf_rw_read(void *p, size_t len, void *ctx)
+vbuf_rw_read(struct iovec iov[2], void *ctx)
{
int fd = *(int*)ctx;
ssize_t ret;
- while ( (ret = read(fd, p, len)) < 0 &&
- (errno == EAGAIN || errno == EINTR));
+ while ( (ret = readv(fd, iov, iov[1].iov_len ? 2 : 1)) < 0 &&
+ (errno == EINTR));
+ if (ret < 0 && errno == EAGAIN)
+ ret = 0;
return ret;
}
static ssize_t
-vbuf_rw_send(const void *p, size_t len, void *ctx)
+vbuf_rw_send(struct iovec iov[2], void *ctx)
{
int *fdflag = (int*)ctx;
ssize_t ret;
- while ( (ret = send(fdflag[0], p, len, fdflag[1])) < 0 &&
- (errno == EAGAIN || errno == EINTR));
+ while ( (ret = send(fdflag[0], iov[0].iov_base, iov[0].iov_len, fdflag[1])) < 0 &&
+ (errno == EINTR));
+ if (ret < 0 && errno == EAGAIN)
+ ret = 0;
return ret;
}
static ssize_t
-vbuf_rw_recv(void *p, size_t len, void *ctx)
+vbuf_rw_recv(struct iovec iov[2], void *ctx)
{
int *fdflag = (int*)ctx;
ssize_t ret;
- while ( (ret = recv(fdflag[0], p, len, fdflag[1])) < 0 &&
- (errno == EAGAIN || errno == EINTR));
+ while ( (ret = recv(fdflag[0], iov[0].iov_base, iov[0].iov_len, fdflag[1])) < 0 &&
+ (errno == EINTR));
+ if (ret < 0 && errno == EAGAIN)
+ ret = 0;
return ret;
}
@@ -283,10 +294,11 @@ vbuf_send (VBUF *v, int fd, ssize_t sz, int flags)
// write from vbuf to writer
ssize_t
vbuf_general_write(VBUF *v, ssize_t sz, void *ctx,
- ssize_t (writer)(const void *p, size_t len, void *ctx))
+ ssize_t (writer)(struct iovec[2], void *ctx))
{
ssize_t rw, copied = 0;
int is_min = 0;
+ struct iovec iov[2] = { { NULL } };
if (sz == VBUF_RWSZ_ALL)
{
@@ -303,15 +315,21 @@ vbuf_general_write(VBUF *v, ssize_t sz, void *ctx,
do {
rw = VBUF_TAIL_SZ(v);
- if ((size_t)rw > sz) rw = sz;
+ if (rw > sz) rw = sz;
- rw = writer(v->tail, rw, ctx);
+ iov[0].iov_base= v->tail;
+ iov[0].iov_len = rw;
+ iov[1].iov_base= v->buf;
+ iov[1].iov_len = sz-rw;
+
+ rw = writer(iov, ctx);
if (rw < 0)
return copied > 0 ? copied : -1;
+ assert(rw < VBUF_HEAD_SZ(v));
v->tail += rw; sz -= rw;
- if (v->tail == v->buf_end)
- v->tail = v->buf;
+ if (v->tail >= v->buf_end)
+ v->tail -= v->buf_end - v->buf;
} while (sz > 0 && !is_min);
@@ -321,10 +339,11 @@ vbuf_general_write(VBUF *v, ssize_t sz, void *ctx,
// read from reader to vbuf
ssize_t
vbuf_general_read(VBUF *v, ssize_t sz, void *ctx,
- ssize_t (reader)(void *p, size_t len, void *ctx))
+ ssize_t (reader)(struct iovec[2], void *ctx))
{
ssize_t rw, copied = 0;
int is_min = 0;
+ struct iovec iov[2] = { { NULL } };
if (sz == VBUF_RWSZ_ALL)
{
@@ -341,15 +360,21 @@ vbuf_general_read(VBUF *v, ssize_t sz, void *ctx,
do {
rw = VBUF_HEAD_SZ(v);
- if ((size_t)rw > sz) rw = sz;
+ if (rw > sz) rw = sz;
+
+ iov[0].iov_base= v->head;
+ iov[0].iov_len = rw;
+ iov[1].iov_base= v->buf;
+ iov[1].iov_len = sz-rw;
- rw = reader(v->head, rw, ctx);
+ rw = reader(iov, ctx);
if (rw < 0)
return copied > 0 ? copied : -1;
+ assert(rw < VBUF_HEAD_SZ(v));
v->head += rw; sz -= rw;
- if (v->head == v->buf_end)
- v->head = v->buf;
+ if (v->head >= v->buf_end)
+ v->head -= v->buf_end - v->buf;
} while (sz > 0 && !is_min);
@@ -359,6 +384,14 @@ vbuf_general_read(VBUF *v, ssize_t sz, void *ctx,
// testing sample
#ifdef _VBUF_TEST_MAIN
+void vbuf_rpt(VBUF *v)
+{
+ printf("v capacity: %u, size: %lu, empty: %s, ptr=(%p,h=%p,t=%p,%p)\n",
+ (unsigned int)vbuf_capacity(v), vbuf_size(v),
+ vbuf_is_empty(v) ? "YES" : "NO",
+ v->buf, v->head, v->tail, v->buf_end);
+}
+
int main()
{
int i;
@@ -370,15 +403,14 @@ int main()
for (i = 0; i < 10; i++)
{
vbuf_put(v, "blah", sizeof("blah"));
- printf("now capacity: %d, size: %d, empty: %s\n",
- vbuf_capacity(v), vbuf_size(v), vbuf_is_empty(v) ? "YES" : "NO");
+ vbuf_rpt(v);
}
for (i = 0; i < 10; i++)
{
char buf[64] = "";
vbuf_get(v, buf, 5);
- printf("[%s] now capacity: %d, size: %d, empty: %s\n", buf,
- vbuf_capacity(v), vbuf_size(v), vbuf_is_empty(v) ? "YES" : "NO");
+ printf("[got: %s] ", buf);
+ vbuf_rpt(v);
}
for (i = 0; i < 10; i++)
@@ -386,22 +418,19 @@ int main()
char buf[64] = "";
vbuf_put(v, "blah", sizeof("blah"));
vbuf_get(v, buf, 5);
- printf("[%s] now capacity: %d, size: %d, empty: %s\n", buf,
- vbuf_capacity(v), vbuf_size(v), vbuf_is_empty(v) ? "YES" : "NO");
+ printf("[got: %s] ", buf);
+ vbuf_rpt(v);
}
- vbuf_clear(v);
- printf("now capacity: %d, size: %d, empty: %s\n",
- vbuf_capacity(v), vbuf_size(v), vbuf_is_empty(v) ? "YES" : "NO");
+ // vbuf_clear(v);
+ vbuf_rpt(v);
printf("give me some input: "); fflush(stdout);
vbuf_read(v, 0, VBUF_RWSZ_MIN);
printf("index of 't' = %d\n", vbuf_strchr(v, 't'));
- printf("now capacity: %d, size: %d, empty: %s\n",
- vbuf_capacity(v), vbuf_size(v), vbuf_is_empty(v) ? "YES" : "NO");
+ vbuf_rpt(v);
printf("give me 4 chars: "); fflush(stdout);
vbuf_read(v, 0, 5);
- printf("now capacity: %d, size: %d, empty: %s\n",
- vbuf_capacity(v), vbuf_size(v), vbuf_is_empty(v) ? "YES" : "NO");
+ vbuf_rpt(v);
printf("\n flushing vbuf: ["); fflush(stdout);
vbuf_write(v, 1, VBUF_RWSZ_ALL);
printf("]\n");
diff --git a/pttbbs/include/cmsys.h b/pttbbs/include/cmsys.h
index 4dee67c5..04cde60a 100644
--- a/pttbbs/include/cmsys.h
+++ b/pttbbs/include/cmsys.h
@@ -3,6 +3,8 @@
#include <stdint.h>
#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
#include <stdbool.h>
#include <time.h>
@@ -219,10 +221,12 @@ extern ssize_t vbuf_recv (VBUF *v, int fd, ssize_t sz, int flags);
// write from vbuf to writer
extern ssize_t vbuf_general_write(VBUF *v, ssize_t sz, void *ctx,
- ssize_t (writer)(const void *p, size_t len, void *ctx));
+ ssize_t (writer)(struct iovec[2], void *ctx));
+ // ssize_t (writer)(const void *p[2], size_t len[2], void *ctx));
// read from reader to vbuf
extern ssize_t vbuf_general_read (VBUF *v, ssize_t sz, void *ctx,
- ssize_t (reader)(void *p, size_t len, void *ctx));
+ ssize_t (reader)(struct iovec[2], void *ctx));
+ // ssize_t (reader)(void *p[2], size_t len[2], void *ctx));
/* telnet.c */
struct TelnetCallback {