From: Marko Kreen Date: Tue, 22 Jan 2008 15:31:06 +0000 (+0000) Subject: missing include file from last commit and Makefile update X-Git-Tag: pgbouncer_1_2_rc2~50 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e2338f2ff0d52cbcd152ad38155ad5a7695733f4;p=pgbouncer missing include file from last commit and Makefile update --- diff --git a/Makefile b/Makefile index db81031..7dea730 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ SRCS = client.c loader.c objects.c pooler.c proto.c sbuf.c server.c util.c \ varcache.c aatree.c hash.c slab.c HDRS = client.h loader.h objects.h pooler.h proto.h sbuf.h server.h util.h \ admin.h stats.h takeover.h md5.h janitor.h pktbuf.h system.h bouncer.h \ - list.h mbuf.h varcache.h aatree.h hash.h slab.h + list.h mbuf.h varcache.h aatree.h hash.h slab.h iobuf.h # data & dirs to include in tgz DOCS = doc/overview.txt doc/usage.txt doc/config.txt doc/todo.txt diff --git a/include/iobuf.h b/include/iobuf.h new file mode 100644 index 0000000..3197c73 --- /dev/null +++ b/include/iobuf.h @@ -0,0 +1,180 @@ +/* + * PgBouncer - Lightweight connection pooler for PostgreSQL. + * + * Copyright (c) 2007 Marko Kreen, Skype Technologies OÜ + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Temporary buffer for single i/o. + * + * Pattern: + * + * iobuf_get_and_reset() + * start: + * iobuf_recv() + * loop: + * if (new_pkt) + * iobuf_parse() + * + * if (send) { + * iobuf_tag_send() + * } else { + * send_pending() + * iobuf_tag_skip() + * } + * if (more-unparsed) + * goto loop; + * send_pending(); + */ + +extern int cf_sbuf_len; + +/* + * 0 .. done_pos -- sent + * done_pos .. parse_pos -- parsed, to send + * parse_pos .. recv_pos -- received, to parse + */ +struct iobuf { + int done_pos; + int parse_pos; + int recv_pos; + uint8_t buf[FLEX_ARRAY]; +}; +typedef struct iobuf IOBuf; + +static inline bool iobuf_sane(const IOBuf *io) +{ + return io->done_pos >= 0 + && io->parse_pos >= io->done_pos + && io->recv_pos >= io->parse_pos + && cf_sbuf_len >= io->recv_pos; +} + +static inline bool iobuf_empty(const IOBuf *buf) +{ + return buf->done_pos == buf->recv_pos; +} + +/* unsent amount */ +static inline int iobuf_amount_pending(const IOBuf *buf) +{ + return buf->parse_pos - buf->done_pos; +} + +/* max possible to parse (tag_send/tag_skip) */ +static inline int iobuf_amount_parse(const IOBuf *buf) +{ + return buf->recv_pos - buf->parse_pos; +} + +/* max possible to recv */ +static inline int iobuf_amount_recv(const IOBuf *buf) +{ + return cf_sbuf_len - buf->recv_pos; +} + +/* put all unparsed to mbuf */ +static inline int iobuf_parse_all(const IOBuf *buf, MBuf *mbuf) +{ + int avail = iobuf_amount_parse(buf); + const uint8_t *pos = buf->buf + buf->parse_pos; + mbuf_init(mbuf, pos, avail); + return avail; +} + +/* put all unparsed to mbuf, with size limit */ +static inline int iobuf_parse_limit(const IOBuf *buf, MBuf *mbuf, int limit) +{ + int avail = iobuf_amount_parse(buf); + const uint8_t *pos = buf->buf + buf->parse_pos; + if (avail > limit) + avail = limit; + mbuf_init(mbuf, pos, avail); + return avail; +} + +/* recv */ +static inline int _MUSTCHECK iobuf_recv_limit(IOBuf *io, int fd, int len) +{ + uint8_t *pos = io->buf + io->recv_pos; + int got; + int avail = iobuf_amount_recv(io); + + if (len > avail) + len = avail; + + Assert(len > 0); + + got = safe_recv(fd, pos, len, 0); + if (got > 0) + io->recv_pos += got; + return got; +} + +static inline int _MUSTCHECK iobuf_recv_max(IOBuf *io, int fd) +{ + return iobuf_recv_limit(io, fd, iobuf_amount_recv(io)); +} + +/* send tagged data */ +static inline int _MUSTCHECK iobuf_send_pending(IOBuf *io, int fd) +{ + uint8_t *pos = io->buf + io->done_pos; + int len, res; + + len = io->parse_pos - io->done_pos; + Assert(len > 0); + + res = safe_send(fd, pos, len, 0); + if (res > 0) + io->done_pos += res; + return res; +} + +static inline void iobuf_tag_send(IOBuf *io, int len) +{ + Assert(len > 0 && len <= iobuf_amount_parse(io)); + + io->parse_pos += len; +} + +static inline void iobuf_tag_skip(IOBuf *io, int len) +{ + Assert(io->parse_pos == io->done_pos); /* no send pending */ + Assert(len > 0 && len <= iobuf_amount_parse(io)); + + io->parse_pos += len; + io->done_pos = io->parse_pos; +} + +static inline void iobuf_try_resync(IOBuf *io, int small_pkt) +{ + int avail = io->recv_pos - io->done_pos; + if (avail == 0) { + if (io->recv_pos > 0) + io->recv_pos = io->parse_pos = io->done_pos = 0; + } else if (avail < small_pkt && io->done_pos > 0) { + memmove(io->buf, io->buf + io->done_pos, avail); + io->parse_pos -= io->done_pos; + io->recv_pos = avail; + io->done_pos = 0; + } +} + +static inline void iobuf_reset(IOBuf *io) +{ + io->recv_pos = io->parse_pos = io->done_pos = 0; +} +