source: lib/format_helper.c @ 287b2b4

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 287b2b4 was 287b2b4, checked in by Shane Alcock <salcock@…>, 13 years ago
  • Fixed bug that was preventing sleep events from ever occuring when using the event framework to read traces from disk
  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007 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
38#include <stdlib.h>
39#include <stdio.h>
40#include <string.h>
41#include <errno.h>
42#include "format_helper.h"
43
44#include <assert.h>
45#include <stdarg.h>
46
47#ifdef WIN32
48#  include <io.h>
49#  include <share.h>
50#  include <sys/timeb.h>
51
52struct libtrace_eventobj_t trace_event_device(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
53    struct libtrace_eventobj_t event = {0,0,0.0,0};
54
55    trace_set_err(trace,TRACE_ERR_OPTION_UNAVAIL, "trace_event() is not "
56            "supported on devices under windows in this version");
57
58    event.type = TRACE_EVENT_TERMINATE;
59    return event;
60}
61#else
62#  include <sys/ioctl.h>
63
64struct libtrace_eventobj_t trace_event_device(struct libtrace_t *trace, 
65                                        struct libtrace_packet_t *packet) {
66        struct libtrace_eventobj_t event = {0,0,0.0,0};
67        int data;
68
69        assert(trace != NULL);
70        assert(packet != NULL);
71       
72        if (trace->format->get_fd) {
73                event.fd = trace->format->get_fd(trace);
74        } else {
75                event.fd = 0;
76        }
77        if (ioctl(event.fd,FIONREAD,&data)==-1) {
78                event.type = TRACE_EVENT_TERMINATE;
79                return event;
80        } 
81               
82        if (data>0) {
83                event.size = trace_read_packet(trace,packet);
84                event.type = TRACE_EVENT_PACKET;
85                return event;
86        }
87        event.type= TRACE_EVENT_IOWAIT;
88        return event;
89}
90#endif
91
92struct libtrace_eventobj_t trace_event_trace(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
93        struct libtrace_eventobj_t event = {0,0,0.0,0};
94        double ts;
95        double now;
96#ifdef WIN32
97        struct __timeb64 tstruct;
98#else
99        struct timeval stv;
100#endif
101
102        if (!trace->event.packet) {
103                trace->event.packet = trace_create_packet();
104                trace->event.psize=
105                        trace_read_packet(trace,trace->event.packet);
106                if (trace->event.psize<1) {
107                        /* return here, the test for
108                         * event.size will sort out the error
109                         */
110                        if (trace_is_err(trace)) {
111                                trace_perror(trace, "read packet");
112                        }
113                        event.type = TRACE_EVENT_TERMINATE;
114                        trace_destroy_packet(trace->event.packet);
115                        trace->event.packet = NULL;
116                        return event;
117                }
118        }
119
120        ts=trace_get_seconds(trace->event.packet);
121
122        /* Get the adjusted current time */
123#ifdef WIN32
124        _ftime64(&tstruct);
125        now = tstruct.time + 
126                ((double)tstruct.millitm / 1000.0);
127#else
128        gettimeofday(&stv, NULL);
129        now = stv.tv_sec + 
130                ((double)stv.tv_usec / 1000000.0);
131#endif
132
133       
134        if (fabs(trace->event.tdelta)>1e-9) {
135                /* adjust for trace delta */
136                now -= trace->event.tdelta; 
137
138                /* if the trace timestamp is still in the
139                 * future, return a SLEEP event,
140                 * otherwise fire the packet
141                 */
142                if (ts > now) {
143                        event.seconds = ts - 
144                                trace->event.trace_last_ts;
145                        event.type = TRACE_EVENT_SLEEP;
146                        return event;
147                }
148        } else {
149                /* work out the difference between the
150                 * start of trace replay, and the first
151                 * packet in the trace
152                 */
153                trace->event.tdelta = now - ts;
154        }
155
156        /* This is the first packet, so just fire away. */
157        /* TODO: finalise packet */
158       
159        /* XXX: Could we do this more efficiently? */
160        /* We do a lot of freeing and creating of packet buffers with this
161         * method, but at least it works unlike what was here previously */
162        if (packet->buf_control == TRACE_CTRL_PACKET) {
163                free(packet->buffer);
164        }
165               
166        packet->type = trace->event.packet->type;
167        packet->trace = trace->event.packet->trace;
168        packet->header = trace->event.packet->header;
169        packet->payload = trace->event.packet->payload;
170       
171        packet->buffer = trace->event.packet->buffer;
172        packet->buf_control = trace->event.packet->buf_control;
173
174        trace->event.packet->buffer = NULL;
175        trace->event.packet->buf_control = TRACE_CTRL_EXTERNAL;
176       
177        trace_destroy_packet(trace->event.packet);
178        trace->event.packet = NULL;
179
180        event.type = TRACE_EVENT_PACKET;
181
182        trace->event.trace_last_ts = ts;
183
184        return event;
185}
186
187/* Catch undefined O_LARGEFILE on *BSD etc */
188#ifndef O_LARGEFILE
189#  define O_LARGEFILE 0
190#endif
191
192/* Catching O_BINARY on all sane OS's */
193#ifndef O_BINARY
194#  define O_BINARY 0
195#endif
196
197/* open a file or stdin using gzip compression if necessary (and supported)
198 * @internal
199 */
200libtrace_io_t *trace_open_file(libtrace_t *trace)
201{
202        int fd;
203        libtrace_io_t *ret;
204
205
206        if (strcmp(trace->uridata,"-")==0) {
207                ret=libtrace_io_fdopen(fileno(stdin),"rb");
208                return ret;
209        }
210
211        /* We open the file with open(2), so we can provide O_LARGEFILE
212         * as zlib doesn't always do it itself
213         */
214        fd=open(trace->uridata,O_LARGEFILE|O_RDONLY|O_BINARY);
215        if (fd==-1) {
216                trace_set_err(trace,errno,"Unable to open %s",trace->uridata);
217                return 0;
218        }
219        ret=libtrace_io_fdopen(fd,"rb");
220        return ret;
221}
222
223/* Create a file or write to stdout using compression if requested
224 * @internal
225 */
226libtrace_io_t *trace_open_file_out(libtrace_out_t *trace,int level, int fileflag)
227{
228        int fd;
229        libtrace_io_t *ret;
230        char filemode[4]; /* wb9\0 */
231        assert(level<10);
232        assert(level>=0);
233#ifdef HAVE_LIBZ
234        snprintf(filemode,sizeof(filemode),"wb%d",level);
235#else
236        snprintf(filemode,sizeof(filemode),"wb");
237#endif
238
239        if (strcmp(trace->uridata,"-")==0) {
240                ret=libtrace_io_fdopen(fileno(stdout),filemode);
241                return ret;
242        }
243
244        /* We open the file with open(2), so we can provide O_LARGEFILE
245         * as zlib doesn't always do it itself
246         */
247        fd=open(trace->uridata,fileflag|O_LARGEFILE|O_BINARY,0666);
248        if (fd==-1) {
249                trace_set_err_out(trace,
250                                errno,"Unable to open %s",trace->uridata);
251                return 0;
252        }
253        ret=libtrace_io_fdopen(fd,filemode);
254        if (!ret) {
255                trace_set_err_out(trace,
256                                TRACE_ERR_INIT_FAILED,"gz out of memory");
257        }
258        return ret;
259}
260
261
262/** Update the libtrace error
263 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
264 * @param msg a plaintext error message
265 * @internal
266 */
267void trace_set_err(libtrace_t *trace,int errcode,const char *msg,...)
268{
269        char buf[256];
270        va_list va;
271        va_start(va,msg);
272        assert(errcode != 0 && "An error occurred, but it is unknown what it is");
273        trace->err.err_num=errcode;
274        if (errcode>0) {
275                vsnprintf(buf,sizeof(buf),msg,va);
276                snprintf(trace->err.problem,sizeof(trace->err.problem),
277                                "%s: %s",buf,strerror(errcode));
278        } else {
279                vsnprintf(trace->err.problem,sizeof(trace->err.problem),
280                                msg,va);
281        }
282        va_end(va);
283}
284
285/** Update the libtrace for output traces error
286 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
287 * @param msg a plaintext error message
288 * @internal
289 */
290void trace_set_err_out(libtrace_out_t *trace,int errcode,const char *msg,...)
291{
292        char buf[256];
293        va_list va;
294        va_start(va,msg);
295        assert(errcode != 0 && "An error occurred, but it is unknown what it is");
296        trace->err.err_num=errcode;
297        if (errcode>0) {
298                vsnprintf(buf,sizeof(buf),msg,va);
299                snprintf(trace->err.problem,sizeof(trace->err.problem),
300                                "%s: %s",buf,strerror(errno));
301        } else {
302                vsnprintf(trace->err.problem,sizeof(trace->err.problem),
303                                msg,va);
304        }
305        va_end(va);
306}
307
308uint64_t byteswap64(uint64_t num)
309{
310        return (byteswap32((num&0xFFFFFFFF00000000ULL)>>32))
311              |((uint64_t)byteswap32(num&0x00000000FFFFFFFFULL)<<32);
312}
313
314uint32_t byteswap32(uint32_t num)
315{
316        return ((num&0x000000FFU)<<24)
317                | ((num&0x0000FF00U)<<8)
318                | ((num&0x00FF0000U)>>8)
319                | ((num&0xFF000000U)>>24);
320}
321
322uint16_t byteswap16(uint16_t num)
323{
324        return ((num<<8)&0xFF00)|((num>>8)&0x00FF);
325}
326
Note: See TracBrowser for help on using the repository browser.