xref: /freebsd/usr.sbin/fifolog/lib/fifolog_write_poll.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
1662cb04cSPoul-Henning Kamp /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
4662cb04cSPoul-Henning Kamp  * Copyright (c) 2005-2008 Poul-Henning Kamp
5662cb04cSPoul-Henning Kamp  * All rights reserved.
6662cb04cSPoul-Henning Kamp  *
7662cb04cSPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
8662cb04cSPoul-Henning Kamp  * modification, are permitted provided that the following conditions
9662cb04cSPoul-Henning Kamp  * are met:
10662cb04cSPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
11662cb04cSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
12662cb04cSPoul-Henning Kamp  * 2. Redistributions in binary form must reproduce the above copyright
13662cb04cSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer in the
14662cb04cSPoul-Henning Kamp  *    documentation and/or other materials provided with the distribution.
15662cb04cSPoul-Henning Kamp  *
16662cb04cSPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17662cb04cSPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18662cb04cSPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19662cb04cSPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20662cb04cSPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21662cb04cSPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22662cb04cSPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23662cb04cSPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24662cb04cSPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25662cb04cSPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26662cb04cSPoul-Henning Kamp  * SUCH DAMAGE.
27662cb04cSPoul-Henning Kamp  */
28662cb04cSPoul-Henning Kamp 
29662cb04cSPoul-Henning Kamp #include <assert.h>
30662cb04cSPoul-Henning Kamp #include <stdio.h>
31662cb04cSPoul-Henning Kamp #include <string.h>
32662cb04cSPoul-Henning Kamp #include <stdlib.h>
33662cb04cSPoul-Henning Kamp #include <unistd.h>
346e482ac5SPoul-Henning Kamp #include <stdint.h>
35662cb04cSPoul-Henning Kamp #include <time.h>
36662cb04cSPoul-Henning Kamp #include <sys/endian.h>
37662cb04cSPoul-Henning Kamp 
38662cb04cSPoul-Henning Kamp #include <zlib.h>
39662cb04cSPoul-Henning Kamp 
40662cb04cSPoul-Henning Kamp #include "fifolog.h"
41662cb04cSPoul-Henning Kamp #include "libfifolog_int.h"
42662cb04cSPoul-Henning Kamp #include "fifolog_write.h"
43662cb04cSPoul-Henning Kamp #include "miniobj.h"
44662cb04cSPoul-Henning Kamp 
456e482ac5SPoul-Henning Kamp static int fifolog_write_gzip(struct fifolog_writer *f, time_t now);
466e482ac5SPoul-Henning Kamp 
47662cb04cSPoul-Henning Kamp #define ALLOC(ptr, size) do {                   \
4860e600c8SPedro F. Giffuni 	(*(ptr)) = calloc(1, size);             \
49662cb04cSPoul-Henning Kamp 	assert(*(ptr) != NULL);                 \
50662cb04cSPoul-Henning Kamp } while (0)
51662cb04cSPoul-Henning Kamp 
52662cb04cSPoul-Henning Kamp 
53662cb04cSPoul-Henning Kamp const char *fifolog_write_statnames[] = {
54662cb04cSPoul-Henning Kamp 	[FIFOLOG_PT_BYTES_PRE] =	"Bytes before compression",
55662cb04cSPoul-Henning Kamp 	[FIFOLOG_PT_BYTES_POST] =	"Bytes after compression",
56662cb04cSPoul-Henning Kamp 	[FIFOLOG_PT_WRITES] =		"Writes",
57662cb04cSPoul-Henning Kamp 	[FIFOLOG_PT_FLUSH] =		"Flushes",
58662cb04cSPoul-Henning Kamp 	[FIFOLOG_PT_SYNC] =		"Syncs",
59662cb04cSPoul-Henning Kamp 	[FIFOLOG_PT_RUNTIME] =		"Runtime"
60662cb04cSPoul-Henning Kamp };
61662cb04cSPoul-Henning Kamp 
626e482ac5SPoul-Henning Kamp /**********************************************************************
63662cb04cSPoul-Henning Kamp  * Check that everything is all right
64662cb04cSPoul-Henning Kamp  */
65662cb04cSPoul-Henning Kamp static void
fifolog_write_assert(const struct fifolog_writer * f)66662cb04cSPoul-Henning Kamp fifolog_write_assert(const struct fifolog_writer *f)
67662cb04cSPoul-Henning Kamp {
68662cb04cSPoul-Henning Kamp 
69662cb04cSPoul-Henning Kamp 	CHECK_OBJ_NOTNULL(f, FIFOLOG_WRITER_MAGIC);
70662cb04cSPoul-Henning Kamp 	assert(f->ff->zs->next_out + f->ff->zs->avail_out == \
715d964b5cSPoul-Henning Kamp 	    f->obuf + f->obufsize);
72662cb04cSPoul-Henning Kamp }
73662cb04cSPoul-Henning Kamp 
746e482ac5SPoul-Henning Kamp /**********************************************************************
756e482ac5SPoul-Henning Kamp  * Allocate/Destroy a new fifolog writer instance
766e482ac5SPoul-Henning Kamp  */
776e482ac5SPoul-Henning Kamp 
78662cb04cSPoul-Henning Kamp struct fifolog_writer *
fifolog_write_new(void)79662cb04cSPoul-Henning Kamp fifolog_write_new(void)
80662cb04cSPoul-Henning Kamp {
81662cb04cSPoul-Henning Kamp 	struct fifolog_writer *f;
82662cb04cSPoul-Henning Kamp 
835d964b5cSPoul-Henning Kamp 	ALLOC_OBJ(f, FIFOLOG_WRITER_MAGIC);
845d964b5cSPoul-Henning Kamp 	assert(f != NULL);
85662cb04cSPoul-Henning Kamp 	return (f);
86662cb04cSPoul-Henning Kamp }
87662cb04cSPoul-Henning Kamp 
88662cb04cSPoul-Henning Kamp void
fifolog_write_destroy(struct fifolog_writer * f)89662cb04cSPoul-Henning Kamp fifolog_write_destroy(struct fifolog_writer *f)
90662cb04cSPoul-Henning Kamp {
916e482ac5SPoul-Henning Kamp 
926e482ac5SPoul-Henning Kamp 	free(f->obuf);
936e482ac5SPoul-Henning Kamp 	free(f->ibuf);
946e482ac5SPoul-Henning Kamp 	FREE_OBJ(f);
95662cb04cSPoul-Henning Kamp }
96662cb04cSPoul-Henning Kamp 
976e482ac5SPoul-Henning Kamp /**********************************************************************
986e482ac5SPoul-Henning Kamp  * Open/Close the fifolog
996e482ac5SPoul-Henning Kamp  */
1006e482ac5SPoul-Henning Kamp 
101662cb04cSPoul-Henning Kamp void
fifolog_write_close(struct fifolog_writer * f)102662cb04cSPoul-Henning Kamp fifolog_write_close(struct fifolog_writer *f)
103662cb04cSPoul-Henning Kamp {
1046e482ac5SPoul-Henning Kamp 	time_t now;
105662cb04cSPoul-Henning Kamp 
106662cb04cSPoul-Henning Kamp 	CHECK_OBJ_NOTNULL(f, FIFOLOG_WRITER_MAGIC);
1076e482ac5SPoul-Henning Kamp 	fifolog_write_assert(f);
1086e482ac5SPoul-Henning Kamp 
1096e482ac5SPoul-Henning Kamp 	f->cleanup = 1;
1106e482ac5SPoul-Henning Kamp 	time(&now);
1116e482ac5SPoul-Henning Kamp 	fifolog_write_gzip(f, now);
1126e482ac5SPoul-Henning Kamp 	fifolog_write_assert(f);
113662cb04cSPoul-Henning Kamp 	fifolog_int_close(&f->ff);
114103c0e21SPoul-Henning Kamp 	free(f->ff);
115662cb04cSPoul-Henning Kamp }
116662cb04cSPoul-Henning Kamp 
117662cb04cSPoul-Henning Kamp const char *
fifolog_write_open(struct fifolog_writer * f,const char * fn,unsigned writerate,unsigned syncrate,unsigned compression)1186e482ac5SPoul-Henning Kamp fifolog_write_open(struct fifolog_writer *f, const char *fn,
1196e482ac5SPoul-Henning Kamp     unsigned writerate, unsigned syncrate, unsigned compression)
120662cb04cSPoul-Henning Kamp {
121662cb04cSPoul-Henning Kamp 	const char *es;
122662cb04cSPoul-Henning Kamp 	int i;
123662cb04cSPoul-Henning Kamp 	time_t now;
124662cb04cSPoul-Henning Kamp 	off_t o;
125662cb04cSPoul-Henning Kamp 
126662cb04cSPoul-Henning Kamp 	CHECK_OBJ_NOTNULL(f, FIFOLOG_WRITER_MAGIC);
127662cb04cSPoul-Henning Kamp 
128662cb04cSPoul-Henning Kamp 	/* Check for legal compression value */
1296e482ac5SPoul-Henning Kamp 	if (compression > Z_BEST_COMPRESSION)
130662cb04cSPoul-Henning Kamp 		return ("Illegal compression value");
131662cb04cSPoul-Henning Kamp 
132662cb04cSPoul-Henning Kamp 	f->writerate = writerate;
133662cb04cSPoul-Henning Kamp 	f->syncrate = syncrate;
134662cb04cSPoul-Henning Kamp 	f->compression = compression;
135662cb04cSPoul-Henning Kamp 
136662cb04cSPoul-Henning Kamp 	/* Reset statistics */
137662cb04cSPoul-Henning Kamp 	memset(f->cnt, 0, sizeof f->cnt);
138662cb04cSPoul-Henning Kamp 
139662cb04cSPoul-Henning Kamp 	es = fifolog_int_open(&f->ff, fn, 1);
140662cb04cSPoul-Henning Kamp 	if (es != NULL)
141662cb04cSPoul-Henning Kamp 		return (es);
142662cb04cSPoul-Henning Kamp 	es = fifolog_int_findend(f->ff, &o);
143662cb04cSPoul-Henning Kamp 	if (es != NULL)
144662cb04cSPoul-Henning Kamp 		return (es);
145662cb04cSPoul-Henning Kamp 	i = fifolog_int_read(f->ff, o);
146662cb04cSPoul-Henning Kamp 	if (i)
147662cb04cSPoul-Henning Kamp 		return ("Read error, looking for seq");
148b183b801SPoul-Henning Kamp 	f->seq = be32dec(f->ff->recbuf);
149b183b801SPoul-Henning Kamp 	if (f->seq == 0) {
150b183b801SPoul-Henning Kamp 		/* Empty fifolog */
151b183b801SPoul-Henning Kamp 		f->seq = random();
152b183b801SPoul-Henning Kamp 	} else {
153662cb04cSPoul-Henning Kamp 		f->recno = o + 1;
154b183b801SPoul-Henning Kamp 		f->seq++;
155662cb04cSPoul-Henning Kamp 	}
156662cb04cSPoul-Henning Kamp 
1575d964b5cSPoul-Henning Kamp 	f->obufsize = f->ff->recsize;
1585d964b5cSPoul-Henning Kamp 	ALLOC(&f->obuf, f->obufsize);
1595d964b5cSPoul-Henning Kamp 
1606e482ac5SPoul-Henning Kamp 	f->ibufsize = f->obufsize * 10;
1616e482ac5SPoul-Henning Kamp 	ALLOC(&f->ibuf, f->ibufsize);
1626e482ac5SPoul-Henning Kamp 	f->ibufptr = 0;
1636e482ac5SPoul-Henning Kamp 
164662cb04cSPoul-Henning Kamp 	i = deflateInit(f->ff->zs, (int)f->compression);
165662cb04cSPoul-Henning Kamp 	assert(i == Z_OK);
166662cb04cSPoul-Henning Kamp 
167662cb04cSPoul-Henning Kamp 	f->flag |= FIFOLOG_FLG_RESTART;
1685d964b5cSPoul-Henning Kamp 	f->flag |= FIFOLOG_FLG_SYNC;
1695d964b5cSPoul-Henning Kamp 	f->ff->zs->next_out = f->obuf + 9;
1705d964b5cSPoul-Henning Kamp 	f->ff->zs->avail_out = f->obufsize - 9;
171662cb04cSPoul-Henning Kamp 
172662cb04cSPoul-Henning Kamp 	time(&now);
173662cb04cSPoul-Henning Kamp 	f->starttime = now;
1745d964b5cSPoul-Henning Kamp 	f->lastsync = now;
1755d964b5cSPoul-Henning Kamp 	f->lastwrite = now;
176662cb04cSPoul-Henning Kamp 
177662cb04cSPoul-Henning Kamp 	fifolog_write_assert(f);
178662cb04cSPoul-Henning Kamp 	return (NULL);
179662cb04cSPoul-Henning Kamp }
180662cb04cSPoul-Henning Kamp 
1816e482ac5SPoul-Henning Kamp /**********************************************************************
1826e482ac5SPoul-Henning Kamp  * Write an output record
1836e482ac5SPoul-Henning Kamp  * Returns -1 if there are trouble writing data
1846e482ac5SPoul-Henning Kamp  */
1856e482ac5SPoul-Henning Kamp 
1865d964b5cSPoul-Henning Kamp static int
fifolog_write_output(struct fifolog_writer * f,int fl,time_t now)1875d964b5cSPoul-Henning Kamp fifolog_write_output(struct fifolog_writer *f, int fl, time_t now)
188662cb04cSPoul-Henning Kamp {
1895d964b5cSPoul-Henning Kamp 	long h, l = f->ff->zs->next_out - f->obuf;
1906e482ac5SPoul-Henning Kamp 	ssize_t i, w;
1916e482ac5SPoul-Henning Kamp 	int retval = 0;
192662cb04cSPoul-Henning Kamp 
1935d964b5cSPoul-Henning Kamp 	h = 4;					/* seq */
1945d964b5cSPoul-Henning Kamp 	be32enc(f->obuf, f->seq);
1955d964b5cSPoul-Henning Kamp 	f->obuf[h] = f->flag;
1965d964b5cSPoul-Henning Kamp 	h += 1;					/* flag */
1975d964b5cSPoul-Henning Kamp 	if (f->flag & FIFOLOG_FLG_SYNC) {
1985d964b5cSPoul-Henning Kamp 		be32enc(f->obuf + h, now);
1995d964b5cSPoul-Henning Kamp 		h += 4;				/* timestamp */
200662cb04cSPoul-Henning Kamp 	}
2015d964b5cSPoul-Henning Kamp 
2026e482ac5SPoul-Henning Kamp 	assert(l <= (long)f->ff->recsize);	/* NB: l includes h */
2035d964b5cSPoul-Henning Kamp 	assert(l >= h);
2046e482ac5SPoul-Henning Kamp 
2056e482ac5SPoul-Henning Kamp 	/* We will never write an entirely empty buffer */
2065d964b5cSPoul-Henning Kamp 	if (l == h)
2075d964b5cSPoul-Henning Kamp 		return (0);
2085d964b5cSPoul-Henning Kamp 
2096e482ac5SPoul-Henning Kamp 	if (l < (long)f->ff->recsize && fl == Z_NO_FLUSH)
2105d964b5cSPoul-Henning Kamp 		return (0);
2115d964b5cSPoul-Henning Kamp 
2125d964b5cSPoul-Henning Kamp 	w = f->ff->recsize - l;
2135d964b5cSPoul-Henning Kamp 	if (w >  255) {
2145d964b5cSPoul-Henning Kamp 		be32enc(f->obuf + f->ff->recsize - 4, w);
2155d964b5cSPoul-Henning Kamp 		f->obuf[4] |= FIFOLOG_FLG_4BYTE;
2165d964b5cSPoul-Henning Kamp 	} else if (w > 0) {
2176e482ac5SPoul-Henning Kamp 		f->obuf[f->ff->recsize - 1] = (uint8_t)w;
2185d964b5cSPoul-Henning Kamp 		f->obuf[4] |= FIFOLOG_FLG_1BYTE;
2195d964b5cSPoul-Henning Kamp 	}
2205d964b5cSPoul-Henning Kamp 
2216e482ac5SPoul-Henning Kamp 	f->cnt[FIFOLOG_PT_BYTES_POST] += l - h;
2225d964b5cSPoul-Henning Kamp 
2235d964b5cSPoul-Henning Kamp 	i = pwrite(f->ff->fd, f->obuf, f->ff->recsize,
224662cb04cSPoul-Henning Kamp 	    (f->recno + 1) * f->ff->recsize);
2256e482ac5SPoul-Henning Kamp 	if (i != f->ff->recsize)
2266e482ac5SPoul-Henning Kamp 		retval = -1;
2276e482ac5SPoul-Henning Kamp 	else
2286e482ac5SPoul-Henning Kamp 		retval = 1;
2295d964b5cSPoul-Henning Kamp 
230662cb04cSPoul-Henning Kamp 	f->cnt[FIFOLOG_PT_WRITES]++;
2316e482ac5SPoul-Henning Kamp 	f->cnt[FIFOLOG_PT_RUNTIME] = now - f->starttime;
2325d964b5cSPoul-Henning Kamp 
2335d964b5cSPoul-Henning Kamp 	f->lastwrite = now;
2346e482ac5SPoul-Henning Kamp 	/*
2356e482ac5SPoul-Henning Kamp 	 * We increment these even on error, so as to properly skip bad,
2366e482ac5SPoul-Henning Kamp 	 * sectors or other light trouble.
2376e482ac5SPoul-Henning Kamp 	 */
2385d964b5cSPoul-Henning Kamp 	f->seq++;
2395d964b5cSPoul-Henning Kamp 	f->recno++;
240016bac89SAdrian Chadd 
241016bac89SAdrian Chadd 	/*
242016bac89SAdrian Chadd 	 * Ensure we wrap recno once we hit the file size (in records.)
243016bac89SAdrian Chadd 	 */
244016bac89SAdrian Chadd 	if (f->recno >= f->ff->logsize)
245016bac89SAdrian Chadd 		/* recno 0 is header; skip */
246016bac89SAdrian Chadd 		f->recno = 1;
247016bac89SAdrian Chadd 
2485d964b5cSPoul-Henning Kamp 	f->flag = 0;
2495d964b5cSPoul-Henning Kamp 
2505d964b5cSPoul-Henning Kamp 	memset(f->obuf, 0, f->obufsize);
2515d964b5cSPoul-Henning Kamp 	f->ff->zs->next_out = f->obuf + 5;
2525d964b5cSPoul-Henning Kamp 	f->ff->zs->avail_out = f->obufsize - 5;
2536e482ac5SPoul-Henning Kamp 	return (retval);
2545d964b5cSPoul-Henning Kamp }
2555d964b5cSPoul-Henning Kamp 
2566e482ac5SPoul-Henning Kamp /**********************************************************************
2576e482ac5SPoul-Henning Kamp  * Run the compression engine
2586e482ac5SPoul-Henning Kamp  * Returns -1 if there are trouble writing data
2596e482ac5SPoul-Henning Kamp  */
2606e482ac5SPoul-Henning Kamp 
2616e482ac5SPoul-Henning Kamp static int
fifolog_write_gzip(struct fifolog_writer * f,time_t now)2626e482ac5SPoul-Henning Kamp fifolog_write_gzip(struct fifolog_writer *f, time_t now)
2635d964b5cSPoul-Henning Kamp {
2646e482ac5SPoul-Henning Kamp 	int i, fl, retval = 0;
2655d964b5cSPoul-Henning Kamp 
2666e482ac5SPoul-Henning Kamp 	assert(now != 0);
2676e482ac5SPoul-Henning Kamp 	if (f->cleanup || now >= (int)(f->lastsync + f->syncrate)) {
2685d964b5cSPoul-Henning Kamp 		f->cleanup = 0;
2695d964b5cSPoul-Henning Kamp 		fl = Z_FINISH;
2705d964b5cSPoul-Henning Kamp 		f->cnt[FIFOLOG_PT_SYNC]++;
2715d964b5cSPoul-Henning Kamp 	} else if (now >= (int)(f->lastwrite + f->writerate)) {
2725d964b5cSPoul-Henning Kamp 		fl = Z_SYNC_FLUSH;
2735d964b5cSPoul-Henning Kamp 		f->cnt[FIFOLOG_PT_FLUSH]++;
2746e482ac5SPoul-Henning Kamp 	} else if (f->ibufptr == 0)
2756e482ac5SPoul-Henning Kamp 		return (0);
2765d964b5cSPoul-Henning Kamp 	else
2775d964b5cSPoul-Henning Kamp 		fl = Z_NO_FLUSH;
2785d964b5cSPoul-Henning Kamp 
2796e482ac5SPoul-Henning Kamp 	f->ff->zs->avail_in = f->ibufptr;
2806e482ac5SPoul-Henning Kamp 	f->ff->zs->next_in = f->ibuf;
2815d964b5cSPoul-Henning Kamp 
2825d964b5cSPoul-Henning Kamp 	while (1) {
2835d964b5cSPoul-Henning Kamp 		i = deflate(f->ff->zs, fl);
2845d964b5cSPoul-Henning Kamp 		assert(i == Z_OK || i == Z_BUF_ERROR || i == Z_STREAM_END);
2855d964b5cSPoul-Henning Kamp 
2866e482ac5SPoul-Henning Kamp 		i = fifolog_write_output(f, fl, now);
2876e482ac5SPoul-Henning Kamp 		if (i == 0)
2885d964b5cSPoul-Henning Kamp 			break;
2896e482ac5SPoul-Henning Kamp 		if (i < 0)
2906e482ac5SPoul-Henning Kamp 			retval = -1;
2915d964b5cSPoul-Henning Kamp 	}
2925d964b5cSPoul-Henning Kamp 	assert(f->ff->zs->avail_in == 0);
2936e482ac5SPoul-Henning Kamp 	f->ibufptr = 0;
2945d964b5cSPoul-Henning Kamp 	if (fl == Z_FINISH) {
2955d964b5cSPoul-Henning Kamp 		f->flag |= FIFOLOG_FLG_SYNC;
2965d964b5cSPoul-Henning Kamp 		f->ff->zs->next_out = f->obuf + 9;
2975d964b5cSPoul-Henning Kamp 		f->ff->zs->avail_out = f->obufsize - 9;
2985d964b5cSPoul-Henning Kamp 		f->lastsync = now;
2995d964b5cSPoul-Henning Kamp 		assert(Z_OK == deflateReset(f->ff->zs));
3005d964b5cSPoul-Henning Kamp 	}
3016e482ac5SPoul-Henning Kamp 	return (retval);
302662cb04cSPoul-Henning Kamp }
303662cb04cSPoul-Henning Kamp 
3046e482ac5SPoul-Henning Kamp /**********************************************************************
3056e482ac5SPoul-Henning Kamp  * Poll to see if we need to flush out a record
3066e482ac5SPoul-Henning Kamp  * Returns -1 if there are trouble writing data
3076e482ac5SPoul-Henning Kamp  */
3086e482ac5SPoul-Henning Kamp 
309662cb04cSPoul-Henning Kamp int
fifolog_write_poll(struct fifolog_writer * f,time_t now)310662cb04cSPoul-Henning Kamp fifolog_write_poll(struct fifolog_writer *f, time_t now)
311662cb04cSPoul-Henning Kamp {
3126e482ac5SPoul-Henning Kamp 
313662cb04cSPoul-Henning Kamp 	if (now == 0)
314662cb04cSPoul-Henning Kamp 		time(&now);
3156e482ac5SPoul-Henning Kamp 	return (fifolog_write_gzip(f, now));
316662cb04cSPoul-Henning Kamp }
317662cb04cSPoul-Henning Kamp 
3186e482ac5SPoul-Henning Kamp /**********************************************************************
3196e482ac5SPoul-Henning Kamp  * Attempt to write an entry into the ibuf.
320662cb04cSPoul-Henning Kamp  * Return zero if there is no space, one otherwise
321662cb04cSPoul-Henning Kamp  */
322662cb04cSPoul-Henning Kamp 
323662cb04cSPoul-Henning Kamp int
fifolog_write_record(struct fifolog_writer * f,uint32_t id,time_t now,const void * ptr,ssize_t len)3246e482ac5SPoul-Henning Kamp fifolog_write_record(struct fifolog_writer *f, uint32_t id, time_t now,
3256e482ac5SPoul-Henning Kamp     const void *ptr, ssize_t len)
326662cb04cSPoul-Henning Kamp {
327662cb04cSPoul-Henning Kamp 	const unsigned char *p;
3286e482ac5SPoul-Henning Kamp 	uint8_t buf[9];
329818bc415SPoul-Henning Kamp 	ssize_t bufl;
330662cb04cSPoul-Henning Kamp 
331662cb04cSPoul-Henning Kamp 	fifolog_write_assert(f);
332662cb04cSPoul-Henning Kamp 	assert(!(id & (FIFOLOG_TIMESTAMP|FIFOLOG_LENGTH)));
333662cb04cSPoul-Henning Kamp 	assert(ptr != NULL);
334662cb04cSPoul-Henning Kamp 
335662cb04cSPoul-Henning Kamp 	p = ptr;
336103c0e21SPoul-Henning Kamp 	if (len == 0) {
3376e482ac5SPoul-Henning Kamp 		len = strlen(ptr);
3386e482ac5SPoul-Henning Kamp 		len++;
339662cb04cSPoul-Henning Kamp 	} else {
340662cb04cSPoul-Henning Kamp 		assert(len <= 255);
341662cb04cSPoul-Henning Kamp 		id |= FIFOLOG_LENGTH;
342662cb04cSPoul-Henning Kamp 	}
3436e482ac5SPoul-Henning Kamp 	assert (len > 0);
344662cb04cSPoul-Henning Kamp 
3456e482ac5SPoul-Henning Kamp 	/* Do a timestamp, if needed */
346662cb04cSPoul-Henning Kamp 	if (now == 0)
347662cb04cSPoul-Henning Kamp 		time(&now);
348662cb04cSPoul-Henning Kamp 
3496e482ac5SPoul-Henning Kamp 	if (now != f->last)
350662cb04cSPoul-Henning Kamp 		id |= FIFOLOG_TIMESTAMP;
351662cb04cSPoul-Henning Kamp 
3525d964b5cSPoul-Henning Kamp 	/* Emit instance+flag */
3535d964b5cSPoul-Henning Kamp 	be32enc(buf, id);
3546e482ac5SPoul-Henning Kamp 	bufl = 4;
355662cb04cSPoul-Henning Kamp 
356662cb04cSPoul-Henning Kamp 	if (id & FIFOLOG_TIMESTAMP) {
3576e482ac5SPoul-Henning Kamp 		be32enc(buf + bufl, (uint32_t)now);
3586e482ac5SPoul-Henning Kamp 		bufl += 4;
359662cb04cSPoul-Henning Kamp 	}
3606e482ac5SPoul-Henning Kamp 	if (id & FIFOLOG_LENGTH)
3616e482ac5SPoul-Henning Kamp 		buf[bufl++] = (u_char)len;
362662cb04cSPoul-Henning Kamp 
3636e482ac5SPoul-Henning Kamp 	if (bufl + len + f->ibufptr > f->ibufsize)
3646e482ac5SPoul-Henning Kamp 		return (0);
3656e482ac5SPoul-Henning Kamp 
3666e482ac5SPoul-Henning Kamp 	memcpy(f->ibuf + f->ibufptr, buf, bufl);
3676e482ac5SPoul-Henning Kamp 	f->ibufptr += bufl;
3686e482ac5SPoul-Henning Kamp 	memcpy(f->ibuf + f->ibufptr, p, len);
3696e482ac5SPoul-Henning Kamp 	f->ibufptr += len;
3706e482ac5SPoul-Henning Kamp 	f->cnt[FIFOLOG_PT_BYTES_PRE] += bufl + len;
3716e482ac5SPoul-Henning Kamp 
3726e482ac5SPoul-Henning Kamp 	if (id & FIFOLOG_TIMESTAMP)
3736e482ac5SPoul-Henning Kamp 		f->last = now;
374662cb04cSPoul-Henning Kamp 	return (1);
375662cb04cSPoul-Henning Kamp }
376662cb04cSPoul-Henning Kamp 
3776e482ac5SPoul-Henning Kamp /**********************************************************************
3786e482ac5SPoul-Henning Kamp  * Write an entry, polling the gzip/writer until success.
379662cb04cSPoul-Henning Kamp  * Long binary entries are broken into 255 byte chunks.
3806e482ac5SPoul-Henning Kamp  * Returns -1 if there are problems writing data
381662cb04cSPoul-Henning Kamp  */
382662cb04cSPoul-Henning Kamp 
3836e482ac5SPoul-Henning Kamp int
fifolog_write_record_poll(struct fifolog_writer * f,uint32_t id,time_t now,const void * ptr,ssize_t len)3846e482ac5SPoul-Henning Kamp fifolog_write_record_poll(struct fifolog_writer *f, uint32_t id, time_t now,
3856e482ac5SPoul-Henning Kamp     const void *ptr, ssize_t len)
386662cb04cSPoul-Henning Kamp {
387662cb04cSPoul-Henning Kamp 	u_int l;
388662cb04cSPoul-Henning Kamp 	const unsigned char *p;
3896e482ac5SPoul-Henning Kamp 	int retval = 0;
390662cb04cSPoul-Henning Kamp 
3916e482ac5SPoul-Henning Kamp 	if (now == 0)
3926e482ac5SPoul-Henning Kamp 		time(&now);
393662cb04cSPoul-Henning Kamp 	fifolog_write_assert(f);
394662cb04cSPoul-Henning Kamp 
395662cb04cSPoul-Henning Kamp 	assert(!(id & (FIFOLOG_TIMESTAMP|FIFOLOG_LENGTH)));
396662cb04cSPoul-Henning Kamp 	assert(ptr != NULL);
397662cb04cSPoul-Henning Kamp 
398662cb04cSPoul-Henning Kamp 	if (len == 0) {
3996e482ac5SPoul-Henning Kamp 		if (!fifolog_write_record(f, id, now, ptr, len)) {
4006e482ac5SPoul-Henning Kamp 			if (fifolog_write_gzip(f, now) < 0)
4016e482ac5SPoul-Henning Kamp 				retval = -1;
4026e482ac5SPoul-Henning Kamp 			/* The string could be too long for the ibuf, so... */
4036e482ac5SPoul-Henning Kamp 			if (!fifolog_write_record(f, id, now, ptr, len))
4046e482ac5SPoul-Henning Kamp 				retval = -1;
405662cb04cSPoul-Henning Kamp 		}
406662cb04cSPoul-Henning Kamp 	} else {
407662cb04cSPoul-Henning Kamp 		for (p = ptr; len > 0; len -= l, p += l) {
408662cb04cSPoul-Henning Kamp 			l = len;
409662cb04cSPoul-Henning Kamp 			if (l > 255)
410662cb04cSPoul-Henning Kamp 				l = 255;
4116e482ac5SPoul-Henning Kamp 			while (!fifolog_write_record(f, id, now, p, l))
4126e482ac5SPoul-Henning Kamp 				if (fifolog_write_gzip(f, now) < 0)
4136e482ac5SPoul-Henning Kamp 					retval = -1;
414662cb04cSPoul-Henning Kamp 		}
415662cb04cSPoul-Henning Kamp 	}
4166e482ac5SPoul-Henning Kamp 	if (fifolog_write_gzip(f, now) < 0)
4176e482ac5SPoul-Henning Kamp 		retval = -1;
418662cb04cSPoul-Henning Kamp 	fifolog_write_assert(f);
4196e482ac5SPoul-Henning Kamp 	return (retval);
420662cb04cSPoul-Henning Kamp }
421