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