source: lib/iow-lzo.c @ 5e26f1d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 5e26f1d was 5e26f1d, checked in by Perry Lorier <perry@…>, 12 years ago

Add support for lzo write compression

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Perry Lorier
8 *          Shane Alcock
9 *         
10 * All rights reserved.
11 *
12 * This code has been developed by the University of Waikato WAND
13 * research group. For further information please see http://www.wand.net.nz/
14 *
15 * libtrace is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * libtrace is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with libtrace; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 *
29 * $Id: iow-zlib.c 1521 2010-02-08 22:21:16Z salcock $
30 *
31 */
32
33
34#include <lzo/lzo1x.h>
35#include "wandio.h"
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <fcntl.h>
39#include <stdlib.h>
40#include <string.h>
41#include <time.h> /* for mtime */
42#include <errno.h>
43#include <assert.h>
44#include <inttypes.h>
45#include <arpa/inet.h>
46
47enum { 
48        M_LZO1X_1     =     1,
49        M_LZO1X_1_15  =     2,
50        M_LZO1X_999   =     3,
51        M_NRV1A       =  0x1a,
52        M_NRV1B       =  0x1b,
53        M_NRV2A       =  0x2a,
54        M_NRV2B       =  0x2b,
55        M_NRV2D       =  0x2d,
56        M_ZLIB        =   128,
57};
58
59const int F_OS_UNIX   = 0x03000000L;
60const int F_OS_MASK   = 0xff000000L;
61
62const int F_CS_NATIVE = 0x00000000L;
63const int F_CS_MASK   = 0x00f00000L;
64
65const int F_H_CRC32   = 0x00001000L;
66const int F_ADLER32_D = 0x00000001L;
67const int F_ADLER32_C = 0x00000002L;
68
69static const unsigned char lzop_magic[9] =
70    { 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a };
71
72
73/* Libtrace IO module implementing a lzo writer */
74
75enum err_t {
76        ERR_OK  = 1,
77        ERR_EOF = 0,
78        ERR_ERROR = -1
79};
80
81const int ADLER32_INIT_VALUE = 1;
82const int CRC32_INIT_VALUE = 0;
83
84struct lzow_t {
85        uint8_t outbuff[1024*1024];
86        iow_t *child;
87        enum err_t err;
88        int inoffset;
89        int outoffset;
90        void *buffer;
91};
92
93extern iow_source_t lzo_wsource; 
94
95#define DATA(iow) ((struct lzow_t *)((iow)->data))
96#define min(a,b) ((a)<(b) ? (a) : (b))
97
98static void write_buf(iow_t *iow,const void *data, size_t len)
99{
100        assert(DATA(iow)->outoffset + len < sizeof(DATA(iow)->outbuff) && "Exceeded output buffer size in lzo compressor");
101        memcpy(&DATA(iow)->outbuff[DATA(iow)->outoffset], data, len);
102        DATA(iow)->outoffset += len;
103}
104
105static void write32(iow_t *iow, uint32_t value)
106{
107        value = htonl(value);
108        write_buf(iow, &value, sizeof(value));
109}
110
111static void write16(iow_t *iow, uint16_t value)
112{
113        value = htons(value);
114        write_buf(iow, &value, sizeof(value));
115}
116
117static void write8(iow_t *iow, uint8_t value)
118{
119        write_buf(iow, &value, sizeof(value));
120}
121
122iow_t *lzo_wopen(iow_t *child, int compress_level)
123{
124        const int opt_filter = 0;
125        int flags;
126        iow_t *iow;
127
128        if (!child)
129                return NULL;
130
131        if (lzo_init() != LZO_E_OK) {
132                /* Fail */
133                return NULL;
134        }
135
136        iow = malloc(sizeof(iow_t));
137        iow->source = &lzo_wsource;
138        iow->data = malloc(sizeof(struct lzow_t));
139
140        DATA(iow)->child = child;
141        DATA(iow)->err = ERR_OK;
142
143        DATA(iow)->outoffset = 0;
144        DATA(iow)->buffer = malloc(LZO1X_1_MEM_COMPRESS);
145
146
147        flags = 0;
148        flags |= F_OS_UNIX & F_OS_MASK; /* Operating System */
149        flags |= F_CS_NATIVE & F_CS_MASK;       /* Character Set */
150        flags |= F_ADLER32_D; /* We adler32 the uncompressed data */
151        /* flags |= F_STDIN; */
152        /* flags |= F_STDOUT */
153        /* flags |= F_MULTIPART; */
154        /* flags |= F_H_CRC32; */
155
156        write_buf(iow, lzop_magic, sizeof(lzop_magic));
157        write16(iow, 0x1010 &0xFFFF); /* version: pretend to be LZOP version 0x1010 from lzop's version.h */
158        write16(iow, lzo_version() & 0xFFFF); /* libversion */
159        write16(iow, opt_filter ? 0x0950 : 0x0940); /* version needed to extract */
160        write8(iow, M_LZO1X_1); /* method */
161        write8(iow, 5); /* level */
162        write32(iow, flags); /* flags */
163        /* if (flags & F_H_FILTER)
164                write32(iow, opt_filter);
165        */ 
166        write32(iow, 0x600); /* mode: We assume traces may be sensitive */
167        write32(iow, time(NULL)); /* mtime */
168        write32(iow, 0); /* GMTdiff */
169
170        /* Length, filename */
171        write8(iow, strlen("compresseddata"));
172        write_buf(iow, "compresseddata",strlen("compresseddata"));
173
174        if (flags & F_H_CRC32) {
175                write32(iow, lzo_crc32(CRC32_INIT_VALUE, DATA(iow)->outbuff, DATA(iow)->outoffset));
176        }
177        else {
178                uint32_t chksum=lzo_adler32(
179                        ADLER32_INIT_VALUE, 
180                        DATA(iow)->outbuff+sizeof(lzop_magic), 
181                        DATA(iow)->outoffset-sizeof(lzop_magic));
182                fprintf(stderr,"writing adler32 checksum (%08x)\n",chksum);
183                write32(iow, chksum);
184        }
185
186        wandio_wwrite(DATA(iow)->child,
187                (char *)DATA(iow)->outbuff,
188                DATA(iow)->outoffset);
189        DATA(iow)->outoffset = 0;
190
191        return iow;
192}
193
194static off_t lzo_wwrite_block(iow_t *iow, const char *buffer, off_t len)
195{
196        char b2[1024*1024];
197        int err;
198        lzo_uint dst_len;
199       
200        if (DATA(iow)->err == ERR_EOF) {
201                return 0; /* EOF */
202        }
203        if (DATA(iow)->err == ERR_ERROR) {
204                return -1; /* ERROR! */
205        }
206
207        err=lzo1x_1_compress((void*)buffer, len, (void*)b2, &dst_len, DATA(iow)->buffer);
208
209        switch(err) {
210                case LZO_E_OK:
211                        break;
212                case LZO_E_ERROR:
213                        DATA(iow)->err = EINVAL; /* "WTF?" */
214                        break;
215                case LZO_E_OUT_OF_MEMORY:
216                        DATA(iow)->err = ENOMEM; 
217                        break;
218                case LZO_E_NOT_COMPRESSIBLE:
219                        DATA(iow)->err = EINVAL; /* Claimed not to be used, dunno what we'll do */
220                        break;
221                case LZO_E_INPUT_OVERRUN:
222                        DATA(iow)->err = EINVAL; 
223                        break;
224                case LZO_E_OUTPUT_OVERRUN:
225                        DATA(iow)->err = ENOMEM;
226                        break;
227                case LZO_E_LOOKBEHIND_OVERRUN:
228                        DATA(iow)->err = EINVAL;
229                        break;
230                case LZO_E_EOF_NOT_FOUND:
231                        DATA(iow)->err = ENOENT;
232                        break;
233                case LZO_E_INPUT_NOT_CONSUMED:
234                        DATA(iow)->err = EINVAL;
235                        break;
236                case LZO_E_NOT_YET_IMPLEMENTED:
237                        DATA(iow)->err = ENOSYS;
238                        break;
239                default:
240                        fprintf(stderr,"Unknown lzo error %d\n",err);
241                        DATA(iow)->err = EINVAL;
242                        break;
243        }
244
245        write32(iow, len); /* Original length */
246        write32(iow, min((uint32_t)len,(uint32_t)dst_len));
247        /* CRC32 of the uncompressed buffer */
248#if 0
249        write32(iow, lzo_crc32(CRC32_INIT_VALUE, (void*)buffer, len));
250#endif
251        write32(iow, lzo_adler32(ADLER32_INIT_VALUE, (const void*)buffer, len));
252        write_buf(iow, b2, dst_len);
253
254        /* Flush the data out */
255        wandio_wwrite(DATA(iow)->child,
256                (char *)DATA(iow)->outbuff,
257                DATA(iow)->outoffset);
258        DATA(iow)->outoffset = 0;
259
260        /* Return the number of bytes compressed */
261        return len;
262}
263
264static off_t lzo_wwrite(iow_t *iow, const char *buffer, off_t len)
265{
266        /* lzo can only deal with blocks up to 256k */
267        off_t ret = 0;
268        while (len>0) {
269                off_t size = (len >= 256*1024 ? 256*1024 : len);
270                off_t err;
271
272                err=lzo_wwrite_block(iow, buffer, size);
273
274                if (err < 0) {/* Error */
275                        if (ret == 0)
276                                return err;
277                        /* If we've written some data, return that fact now, let them call back
278                         * and try and write more data, fail again then.
279                         */
280                        return ret;
281                }
282                else {
283                        assert(err == size);
284                        buffer += size;
285                        len -= size;
286                }
287        }
288        return ret;
289}
290
291static void lzo_wclose(iow_t *iow)
292{
293        const uint32_t zero = 0;
294        /* Write out an end of file marker */
295        wandio_wwrite(DATA(iow)->child,
296                &zero,
297                sizeof(zero));
298        wandio_wdestroy(DATA(iow)->child);
299        free(DATA(iow)->buffer);
300        free(iow->data);
301        free(iow);
302}
303
304iow_source_t lzo_wsource = {
305        "lzo",
306        lzo_wwrite,
307        lzo_wclose
308};
309
Note: See TracBrowser for help on using the repository browser.