2 * Buffering of output and input.
3 * Copyright (C) 1998 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
37 struct buffer_data *head;
38 struct buffer_data *tail;
40 /* Size of each buffer_data chunk. */
47 struct buffer_data *next;
49 /* Location to add new data. */
52 /* Pointer to data not yet flushed. */
55 /* Actual data stream (variable length). */
56 unsigned char data[]; /* real dimension is buffer->size */
59 /* It should always be true that: 0 <= sp <= cp <= size */
61 /* Default buffer size (used if none specified). It is rounded up to the
62 next page boundery. */
63 #define BUFFER_SIZE_DEFAULT 4096
66 #define BUFFER_DATA_FREE(D) XFREE(MTYPE_BUFFER_DATA, (D))
68 /* Make new buffer. */
70 buffer_new (size_t size)
74 b = XCALLOC (MTYPE_BUFFER, sizeof (struct buffer));
80 static size_t default_size;
83 long pgsz = sysconf(_SC_PAGESIZE);
84 default_size = ((((BUFFER_SIZE_DEFAULT-1)/pgsz)+1)*pgsz);
86 b->size = default_size;
94 buffer_free (struct buffer *b)
97 XFREE (MTYPE_BUFFER, b);
100 /* Make string clone. */
102 buffer_getstr (struct buffer *b)
105 struct buffer_data *data;
109 for (data = b->head; data; data = data->next)
110 totlen += data->cp - data->sp;
111 if (!(s = XMALLOC(MTYPE_TMP, totlen+1)))
114 for (data = b->head; data; data = data->next)
116 memcpy(p, data->data + data->sp, data->cp - data->sp);
117 p += data->cp - data->sp;
123 /* Return 1 if buffer is empty. */
125 buffer_empty (struct buffer *b)
127 return (b->head == NULL);
130 /* Clear and free all allocated data. */
132 buffer_reset (struct buffer *b)
134 struct buffer_data *data;
135 struct buffer_data *next;
137 for (data = b->head; data; data = next)
140 BUFFER_DATA_FREE(data);
142 b->head = b->tail = NULL;
145 /* Add buffer_data to the end of buffer. */
146 static struct buffer_data *
147 buffer_add (struct buffer *b)
149 struct buffer_data *d;
151 d = XMALLOC(MTYPE_BUFFER_DATA, offsetof(struct buffer_data, data) + b->size);
164 /* Write data to buffer. */
166 buffer_put(struct buffer *b, const void *p, size_t size)
168 struct buffer_data *data = b->tail;
171 /* We use even last one byte of data buffer. */
176 /* If there is no data buffer add it. */
177 if (data == NULL || data->cp == b->size)
178 data = buffer_add (b);
180 chunk = ((size <= (b->size - data->cp)) ? size : (b->size - data->cp));
181 memcpy ((data->data + data->cp), ptr, chunk);
188 /* Insert character into the buffer. */
190 buffer_putc (struct buffer *b, u_char c)
192 buffer_put(b, &c, 1);
195 /* Put string to the buffer. */
197 buffer_putstr (struct buffer *b, const char *c)
199 buffer_put(b, c, strlen(c));
202 /* Keep flushing data to the fd until the buffer is empty or an error is
203 encountered or the operation would block. */
205 buffer_flush_all (struct buffer *b, int fd)
208 struct buffer_data *head;
213 head_sp = (head = b->head)->sp;
214 /* Flush all data. */
215 while ((ret = buffer_flush_available(b, fd)) == BUFFER_PENDING)
217 if ((b->head == head) && (head_sp == head->sp) && (errno != EINTR))
218 /* No data was flushed, so kernel buffer must be full. */
220 head_sp = (head = b->head)->sp;
226 /* Flush enough data to fill a terminal window of the given scene (used only
227 by vty telnet interface). */
229 buffer_flush_window (struct buffer *b, int fd, int width, int height,
230 int erase_flag, int no_more_flag)
236 struct iovec small_iov[3];
237 char more[] = " --More-- ";
238 char erase[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
239 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
240 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
241 struct buffer_data *data;
249 zlog_warn("%s called with non-positive window height %d, forcing to 1",
253 else if (height >= 2)
257 zlog_warn("%s called with non-positive window width %d, forcing to 1",
262 /* For erase and more data add two to b's buffer_data count.*/
263 if (b->head->next == NULL)
265 iov_alloc = array_size(small_iov);
270 iov_alloc = ((height*(width+2))/b->size)+10;
271 iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov));
275 /* Previously print out is performed. */
278 iov[iov_index].iov_base = erase;
279 iov[iov_index].iov_len = sizeof erase;
284 column = 1; /* Column position of next character displayed. */
285 for (data = b->head; data && (height > 0); data = data->next)
290 while ((cp < data->cp) && (height > 0))
292 /* Calculate lines remaining and column position after displaying
294 if (data->data[cp] == '\r')
296 else if ((data->data[cp] == '\n') || (column == width))
305 iov[iov_index].iov_base = (char *)(data->data + data->sp);
306 iov[iov_index++].iov_len = cp-data->sp;
309 if (iov_index == iov_alloc)
310 /* This should not ordinarily happen. */
313 if (iov != small_iov)
315 zlog_warn("%s: growing iov array to %d; "
316 "width %d, height %d, size %lu",
317 __func__, iov_alloc, width, height, (u_long)b->size);
318 iov = XREALLOC(MTYPE_TMP, iov, iov_alloc*sizeof(*iov));
322 /* This should absolutely never occur. */
323 zlog_err("%s: corruption detected: iov_small overflowed; "
324 "head %p, tail %p, head->next %p",
325 __func__, (void *)b->head, (void *)b->tail,
326 (void *)b->head->next);
327 iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov));
328 memcpy(iov, small_iov, sizeof(small_iov));
333 /* In case of `more' display need. */
334 if (b->tail && (b->tail->sp < b->tail->cp) && !no_more_flag)
336 iov[iov_index].iov_base = more;
337 iov[iov_index].iov_len = sizeof more;
343 /* IOV_MAX are normally defined in <sys/uio.h> , Posix.1g.
344 example: Solaris2.6 are defined IOV_MAX size at 16. */
346 struct iovec *c_iov = iov;
347 nbytes = 0; /* Make sure it's initialized. */
349 while (iov_index > 0)
353 iov_size = ((iov_index > IOV_MAX) ? IOV_MAX : iov_index);
354 if ((nbytes = writev(fd, c_iov, iov_size)) < 0)
356 zlog_warn("%s: writev to fd %d failed: %s",
357 __func__, fd, safe_strerror(errno));
361 /* move pointer io-vector */
363 iov_index -= iov_size;
367 if ((nbytes = writev (fd, iov, iov_index)) < 0)
368 zlog_warn("%s: writev to fd %d failed: %s",
369 __func__, fd, safe_strerror(errno));
372 /* Free printed buffer data. */
373 while (b->head && (b->head->sp == b->head->cp))
375 struct buffer_data *del;
376 if (!(b->head = (del = b->head)->next))
378 BUFFER_DATA_FREE(del);
381 if (iov != small_iov)
382 XFREE (MTYPE_TMP, iov);
384 return (nbytes < 0) ? BUFFER_ERROR :
385 (b->head ? BUFFER_PENDING : BUFFER_EMPTY);
388 /* This function (unlike other buffer_flush* functions above) is designed
389 to work with non-blocking sockets. It does not attempt to write out
390 all of the queued data, just a "big" chunk. It returns 0 if it was
391 able to empty out the buffers completely, 1 if more flushing is
392 required later, or -1 on a fatal write error. */
394 buffer_flush_available(struct buffer *b, int fd)
397 /* These are just reasonable values to make sure a significant amount of
398 data is written. There's no need to go crazy and try to write it all
401 #define MAX_CHUNKS ((IOV_MAX >= 16) ? 16 : IOV_MAX)
403 #define MAX_CHUNKS 16
405 #define MAX_FLUSH 131072
407 struct buffer_data *d;
409 struct iovec iov[MAX_CHUNKS];
413 for (d = b->head; d && (iovcnt < MAX_CHUNKS) && (nbyte < MAX_FLUSH);
414 d = d->next, iovcnt++)
416 iov[iovcnt].iov_base = d->data+d->sp;
417 nbyte += (iov[iovcnt].iov_len = d->cp-d->sp);
421 /* No data to flush: should we issue a warning message? */
424 /* only place where written should be sign compared */
425 if ((ssize_t)(written = writev(fd,iov,iovcnt)) < 0)
427 if (ERRNO_IO_RETRY(errno))
428 /* Calling code should try again later. */
429 return BUFFER_PENDING;
430 zlog_warn("%s: write error on fd %d: %s",
431 __func__, fd, safe_strerror(errno));
435 /* Free printed buffer data. */
438 struct buffer_data *d;
441 zlog_err("%s: corruption detected: buffer queue empty, "
442 "but written is %lu", __func__, (u_long)written);
445 if (written < d->cp-d->sp)
448 return BUFFER_PENDING;
451 written -= (d->cp-d->sp);
452 if (!(b->head = d->next))
457 return b->head ? BUFFER_PENDING : BUFFER_EMPTY;
464 buffer_write(struct buffer *b, int fd, const void *p, size_t size)
469 /* Should we attempt to drain any previously buffered data? This could help
470 reduce latency in pushing out the data if we are stuck in a long-running
471 thread that is preventing the main select loop from calling the flush
473 if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR))
477 /* Buffer is not empty, so do not attempt to write the new data. */
479 else if ((nbytes = write(fd, p, size)) < 0)
481 if (ERRNO_IO_RETRY(errno))
485 zlog_warn("%s: write error on fd %d: %s",
486 __func__, fd, safe_strerror(errno));
490 /* Add any remaining data to the buffer. */
492 size_t written = nbytes;
494 buffer_put(b, ((const char *)p)+written, size-written);
496 return b->head ? BUFFER_PENDING : BUFFER_EMPTY;