source: lib/format_helper.c @ dd06159

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

Fix typo in previous commit

  • 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        if (fabs(trace->event.tdelta)<1e-9) {
134                /* adjust for trace delta */
135                now -= trace->event.tdelta; 
136
137                /* if the trace timestamp is still in the
138                 * future, return a SLEEP event,
139                 * otherwise fire the packet
140                 */
141                if (ts > now) {
142                        event.seconds = ts - 
143                                trace->event.trace_last_ts;
144                        event.type = TRACE_EVENT_SLEEP;
145                        return event;
146                }
147        } else {
148                /* work out the difference between the
149                 * start of trace replay, and the first
150                 * packet in the trace
151                 */
152                trace->event.tdelta = now - ts;
153        }
154
155        /* This is the first packet, so just fire away. */
156        /* TODO: finalise packet */
157       
158        /* XXX: Could we do this more efficiently? */
159        /* We do a lot of freeing and creating of packet buffers with this
160         * method, but at least it works unlike what was here previously */
161        if (packet->buf_control == TRACE_CTRL_PACKET) {
162                free(packet->buffer);
163        }
164               
165        packet->type = trace->event.packet->type;
166        packet->trace = trace->event.packet->trace;
167        packet->header = trace->event.packet->header;
168        packet->payload = trace->event.packet->payload;
169       
170        packet->buffer = trace->event.packet->buffer;
171        packet->buf_control = trace->event.packet->buf_control;
172
173        trace->event.packet->buffer = NULL;
174        trace->event.packet->buf_control = TRACE_CTRL_EXTERNAL;
175       
176        trace_destroy_packet(trace->event.packet);
177        trace->event.packet = NULL;
178
179        event.type = TRACE_EVENT_PACKET;
180
181        trace->event.trace_last_ts = ts;
182
183        return event;
184}
185
186/* Catch undefined O_LARGEFILE on *BSD etc */
187#ifndef O_LARGEFILE
188#  define O_LARGEFILE 0
189#endif
190
191/* Catching O_BINARY on all sane OS's */
192#ifndef O_BINARY
193#  define O_BINARY 0
194#endif
195
196/* open a file or stdin using gzip compression if necessary (and supported)
197 * @internal
198 */
199libtrace_io_t *trace_open_file(libtrace_t *trace)
200{
201        int fd;
202        libtrace_io_t *ret;
203
204
205        if (strcmp(trace->uridata,"-")==0) {
206                ret=libtrace_io_fdopen(fileno(stdin),"rb");
207                return ret;
208        }
209
210        /* We open the file with open(2), so we can provide O_LARGEFILE
211         * as zlib doesn't always do it itself
212         */
213        fd=open(trace->uridata,O_LARGEFILE|O_RDONLY|O_BINARY);
214        if (fd==-1) {
215                trace_set_err(trace,errno,"Unable to open %s",trace->uridata);
216                return 0;
217        }
218        ret=libtrace_io_fdopen(fd,"rb");
219        return ret;
220}
221
222/* Create a file or write to stdout using compression if requested
223 * @internal
224 */
225libtrace_io_t *trace_open_file_out(libtrace_out_t *trace,int level, int fileflag)
226{
227        int fd;
228        libtrace_io_t *ret;
229        char filemode[4]; /* wb9\0 */
230        assert(level<10);
231        assert(level>=0);
232#ifdef HAVE_LIBZ
233        snprintf(filemode,sizeof(filemode),"wb%d",level);
234#else
235        snprintf(filemode,sizeof(filemode),"wb");
236#endif
237
238        if (strcmp(trace->uridata,"-")==0) {
239                ret=libtrace_io_fdopen(fileno(stdout),filemode);
240                return ret;
241        }
242
243        /* We open the file with open(2), so we can provide O_LARGEFILE
244         * as zlib doesn't always do it itself
245         */
246        fd=open(trace->uridata,fileflag|O_LARGEFILE|O_BINARY,0666);
247        if (fd==-1) {
248                trace_set_err_out(trace,
249                                errno,"Unable to open %s",trace->uridata);
250                return 0;
251        }
252        ret=libtrace_io_fdopen(fd,filemode);
253        if (!ret) {
254                trace_set_err_out(trace,
255                                TRACE_ERR_INIT_FAILED,"gz out of memory");
256        }
257        return ret;
258}
259
260
261/** Update the libtrace error
262 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
263 * @param msg a plaintext error message
264 * @internal
265 */
266void trace_set_err(libtrace_t *trace,int errcode,const char *msg,...)
267{
268        char buf[256];
269        va_list va;
270        va_start(va,msg);
271        assert(errcode != 0 && "An error occurred, but it is unknown what it is");
272        trace->err.err_num=errcode;
273        if (errcode>0) {
274                vsnprintf(buf,sizeof(buf),msg,va);
275                snprintf(trace->err.problem,sizeof(trace->err.problem),
276                                "%s: %s",buf,strerror(errcode));
277        } else {
278                vsnprintf(trace->err.problem,sizeof(trace->err.problem),
279                                msg,va);
280        }
281        va_end(va);
282}
283
284/** Update the libtrace for output traces error
285 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
286 * @param msg a plaintext error message
287 * @internal
288 */
289void trace_set_err_out(libtrace_out_t *trace,int errcode,const char *msg,...)
290{
291        char buf[256];
292        va_list va;
293        va_start(va,msg);
294        assert(errcode != 0 && "An error occurred, but it is unknown what it is");
295        trace->err.err_num=errcode;
296        if (errcode>0) {
297                vsnprintf(buf,sizeof(buf),msg,va);
298                snprintf(trace->err.problem,sizeof(trace->err.problem),
299                                "%s: %s",buf,strerror(errno));
300        } else {
301                vsnprintf(trace->err.problem,sizeof(trace->err.problem),
302                                msg,va);
303        }
304        va_end(va);
305}
306
307uint64_t byteswap64(uint64_t num)
308{
309        return (byteswap32((num&0xFFFFFFFF00000000ULL)>>32))
310              |((uint64_t)byteswap32(num&0x00000000FFFFFFFFULL)<<32);
311}
312
313uint32_t byteswap32(uint32_t num)
314{
315        return ((num&0x000000FFU)<<24)
316                | ((num&0x0000FF00U)<<8)
317                | ((num&0x00FF0000U)>>8)
318                | ((num&0xFF000000U)>>24);
319}
320
321uint16_t byteswap16(uint16_t num)
322{
323        return ((num<<8)&0xFF00)|((num>>8)&0x00FF);
324}
325
Note: See TracBrowser for help on using the repository browser.