2 * PgBouncer - Lightweight connection pooler for PostgreSQL.
4 * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * Temporary buffer for single i/o.
24 * iobuf_get_and_reset()
43 * 0 .. done_pos -- sent
44 * done_pos .. parse_pos -- parsed, to send
45 * parse_pos .. recv_pos -- received, to parse
51 uint8_t buf
[FLEX_ARRAY
];
53 typedef struct iobuf IOBuf
;
55 static inline bool iobuf_sane(const IOBuf
*io
)
57 return (io
== NULL
) ||
58 ( io
->parse_pos
>= io
->done_pos
59 && io
->recv_pos
>= io
->parse_pos
60 && (unsigned)cf_sbuf_len
>= io
->recv_pos
);
63 static inline bool iobuf_empty(const IOBuf
*io
)
65 return io
== NULL
|| io
->done_pos
== io
->recv_pos
;
69 static inline unsigned iobuf_amount_pending(const IOBuf
*buf
)
71 return buf
->parse_pos
- buf
->done_pos
;
74 /* max possible to parse (tag_send/tag_skip) */
75 static inline unsigned iobuf_amount_parse(const IOBuf
*buf
)
77 return buf
->recv_pos
- buf
->parse_pos
;
80 /* max possible to recv */
81 static inline unsigned iobuf_amount_recv(const IOBuf
*buf
)
83 return cf_sbuf_len
- buf
->recv_pos
;
86 /* put all unparsed to mbuf */
87 static inline unsigned iobuf_parse_all(const IOBuf
*buf
, MBuf
*mbuf
)
89 unsigned avail
= iobuf_amount_parse(buf
);
90 const uint8_t *pos
= buf
->buf
+ buf
->parse_pos
;
91 mbuf_init(mbuf
, pos
, avail
);
95 /* put all unparsed to mbuf, with size limit */
96 static inline unsigned iobuf_parse_limit(const IOBuf
*buf
, MBuf
*mbuf
, unsigned limit
)
98 unsigned avail
= iobuf_amount_parse(buf
);
99 const uint8_t *pos
= buf
->buf
+ buf
->parse_pos
;
102 mbuf_init(mbuf
, pos
, avail
);
107 static inline int _MUSTCHECK
iobuf_recv_limit(IOBuf
*io
, int fd
, unsigned len
)
109 uint8_t *pos
= io
->buf
+ io
->recv_pos
;
111 unsigned avail
= iobuf_amount_recv(io
);
118 got
= safe_recv(fd
, pos
, len
, 0);
124 static inline int _MUSTCHECK
iobuf_recv_max(IOBuf
*io
, int fd
)
126 return iobuf_recv_limit(io
, fd
, iobuf_amount_recv(io
));
129 /* send tagged data */
130 static inline int _MUSTCHECK
iobuf_send_pending(IOBuf
*io
, int fd
)
132 uint8_t *pos
= io
->buf
+ io
->done_pos
;
135 len
= io
->parse_pos
- io
->done_pos
;
138 res
= safe_send(fd
, pos
, len
, 0);
144 static inline void iobuf_tag_send(IOBuf
*io
, unsigned len
)
146 Assert(len
> 0 && len
<= iobuf_amount_parse(io
));
148 io
->parse_pos
+= len
;
151 static inline void iobuf_tag_skip(IOBuf
*io
, unsigned len
)
153 Assert(io
->parse_pos
== io
->done_pos
); /* no send pending */
154 Assert(len
> 0 && len
<= iobuf_amount_parse(io
));
156 io
->parse_pos
+= len
;
157 io
->done_pos
= io
->parse_pos
;
160 static inline void iobuf_try_resync(IOBuf
*io
, unsigned small_pkt
)
162 unsigned avail
= io
->recv_pos
- io
->done_pos
;
164 if (io
->recv_pos
> 0)
165 io
->recv_pos
= io
->parse_pos
= io
->done_pos
= 0;
166 } else if (avail
<= small_pkt
&& io
->done_pos
> 0) {
167 memmove(io
->buf
, io
->buf
+ io
->done_pos
, avail
);
168 io
->parse_pos
-= io
->done_pos
;
169 io
->recv_pos
= avail
;
174 static inline void iobuf_reset(IOBuf
*io
)
176 io
->recv_pos
= io
->parse_pos
= io
->done_pos
= 0;