source: lib/format_helper.c @ c66068d

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

Rewrite the libtrace io subsystem to use the new wandio abstraction layer.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
31#include "config.h"
32#include <sys/types.h>
33#include <fcntl.h> /* for O_LARGEFILE */
34#include <math.h>
35#include "libtrace.h"
36#include "libtrace_int.h"
37#include "wandio.h"
38
39#include <stdlib.h>
40#include <stdio.h>
41#include <string.h>
42#include <errno.h>
43#include "format_helper.h"
44
45#include <assert.h>
46#include <stdarg.h>
47
48#ifdef WIN32
49#  include <io.h>
50#  include <share.h>
51#  include <sys/timeb.h>
52
53struct libtrace_eventobj_t trace_event_device(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
54    struct libtrace_eventobj_t event = {0,0,0.0,0};
55
56    trace_set_err(trace,TRACE_ERR_OPTION_UNAVAIL, "trace_event() is not "
57            "supported on devices under windows in this version");
58
59    event.type = TRACE_EVENT_TERMINATE;
60    return event;
61}
62#else
63#  include <sys/ioctl.h>
64
65struct libtrace_eventobj_t trace_event_device(struct libtrace_t *trace, 
66                                        struct libtrace_packet_t *packet) {
67        struct libtrace_eventobj_t event = {0,0,0.0,0};
68        int data;
69
70        assert(trace != NULL);
71        assert(packet != NULL);
72       
73        if (trace->format->get_fd) {
74                event.fd = trace->format->get_fd(trace);
75        } else {
76                event.fd = 0;
77        }
78        if (ioctl(event.fd,FIONREAD,&data)==-1) {
79                event.type = TRACE_EVENT_TERMINATE;
80                return event;
81        } 
82               
83        if (data>0) {
84                event.size = trace_read_packet(trace,packet);
85                event.type = TRACE_EVENT_PACKET;
86                return event;
87        }
88        event.type= TRACE_EVENT_IOWAIT;
89        return event;
90}
91#endif
92
93struct libtrace_eventobj_t trace_event_trace(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
94        struct libtrace_eventobj_t event = {0,0,0.0,0};
95        double ts;
96        double now;
97#ifdef WIN32
98        struct __timeb64 tstruct;
99#else
100        struct timeval stv;
101#endif
102
103        if (!trace->event.packet) {
104                trace->event.packet = trace_create_packet();
105                trace->event.psize=
106                        trace_read_packet(trace,trace->event.packet);
107                if (trace->event.psize<1) {
108                        /* return here, the test for
109                         * event.size will sort out the error
110                         */
111                        if (trace_is_err(trace)) {
112                                trace_perror(trace, "read packet");
113                        }
114                        event.type = TRACE_EVENT_TERMINATE;
115                        trace_destroy_packet(trace->event.packet);
116                        trace->event.packet = NULL;
117                        return event;
118                }
119        }
120
121        ts=trace_get_seconds(trace->event.packet);
122
123        /* Get the adjusted current time */
124#ifdef WIN32
125        _ftime64(&tstruct);
126        now = tstruct.time + 
127                ((double)tstruct.millitm / 1000.0);
128#else
129        gettimeofday(&stv, NULL);
130        now = stv.tv_sec + 
131                ((double)stv.tv_usec / 1000000.0);
132#endif
133
134       
135        if (fabs(trace->event.tdelta)>1e-9) {
136                /* adjust for trace delta */
137                now -= trace->event.tdelta; 
138
139                /* if the trace timestamp is still in the
140                 * future, return a SLEEP event,
141                 * otherwise fire the packet
142                 */
143                if (ts > now) {
144                        event.seconds = ts - 
145                                trace->event.trace_last_ts;
146                        event.type = TRACE_EVENT_SLEEP;
147                        return event;
148                }
149        } else {
150                /* work out the difference between the
151                 * start of trace replay, and the first
152                 * packet in the trace
153                 */
154                trace->event.tdelta = now - ts;
155        }
156
157        /* This is the first packet, so just fire away. */
158        /* TODO: finalise packet */
159       
160        /* XXX: Could we do this more efficiently? */
161        /* We do a lot of freeing and creating of packet buffers with this
162         * method, but at least it works unlike what was here previously */
163        if (packet->buf_control == TRACE_CTRL_PACKET) {
164                free(packet->buffer);
165        }
166               
167        packet->type = trace->event.packet->type;
168        packet->trace = trace->event.packet->trace;
169        packet->header = trace->event.packet->header;
170        packet->payload = trace->event.packet->payload;
171       
172        packet->buffer = trace->event.packet->buffer;
173        packet->buf_control = trace->event.packet->buf_control;
174
175        trace->event.packet->buffer = NULL;
176        trace->event.packet->buf_control = TRACE_CTRL_EXTERNAL;
177       
178        trace_destroy_packet(trace->event.packet);
179        trace->event.packet = NULL;
180
181        event.type = TRACE_EVENT_PACKET;
182
183        trace->event.trace_last_ts = ts;
184
185        return event;
186}
187
188/* Catch undefined O_LARGEFILE on *BSD etc */
189#ifndef O_LARGEFILE
190#  define O_LARGEFILE 0
191#endif
192
193/* Catching O_BINARY on all sane OS's */
194#ifndef O_BINARY
195#  define O_BINARY 0
196#endif
197
198/* open a file or stdin using gzip compression if necessary (and supported)
199 * @internal
200 */
201io_t *trace_open_file(libtrace_t *trace)
202{
203        return wandio_create(trace->uridata);
204}
205
206/* Create a file or write to stdout using compression if requested
207 * @internal
208 */
209iow_t *trace_open_file_out(libtrace_out_t *trace,int level, int fileflag)
210{
211        assert(level<10);
212        assert(level>=0);
213
214        return wandio_wcreate(trace->uridata, level, fileflag);
215}
216
217
218/** Update the libtrace error
219 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
220 * @param msg a plaintext error message
221 * @internal
222 */
223void trace_set_err(libtrace_t *trace,int errcode,const char *msg,...)
224{
225        char buf[256];
226        va_list va;
227        va_start(va,msg);
228        assert(errcode != 0 && "An error occurred, but it is unknown what it is");
229        trace->err.err_num=errcode;
230        if (errcode>0) {
231                vsnprintf(buf,sizeof(buf),msg,va);
232                snprintf(trace->err.problem,sizeof(trace->err.problem),
233                                "%s: %s",buf,strerror(errcode));
234        } else {
235                vsnprintf(trace->err.problem,sizeof(trace->err.problem),
236                                msg,va);
237        }
238        va_end(va);
239}
240
241/** Update the libtrace for output traces error
242 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
243 * @param msg a plaintext error message
244 * @internal
245 */
246void trace_set_err_out(libtrace_out_t *trace,int errcode,const char *msg,...)
247{
248        char buf[256];
249        va_list va;
250        va_start(va,msg);
251        assert(errcode != 0 && "An error occurred, but it is unknown what it is");
252        trace->err.err_num=errcode;
253        if (errcode>0) {
254                vsnprintf(buf,sizeof(buf),msg,va);
255                snprintf(trace->err.problem,sizeof(trace->err.problem),
256                                "%s: %s",buf,strerror(errno));
257        } else {
258                vsnprintf(trace->err.problem,sizeof(trace->err.problem),
259                                msg,va);
260        }
261        va_end(va);
262}
263
264uint64_t byteswap64(uint64_t num)
265{
266        return (byteswap32((num&0xFFFFFFFF00000000ULL)>>32))
267              |((uint64_t)byteswap32(num&0x00000000FFFFFFFFULL)<<32);
268}
269
270uint32_t byteswap32(uint32_t num)
271{
272        return ((num&0x000000FFU)<<24)
273                | ((num&0x0000FF00U)<<8)
274                | ((num&0x00FF0000U)>>8)
275                | ((num&0xFF000000U)>>24);
276}
277
278uint16_t byteswap16(uint16_t num)
279{
280        return ((num<<8)&0xFF00)|((num>>8)&0x00FF);
281}
282
Note: See TracBrowser for help on using the repository browser.