Changeset 0d57541


Ignore:
Timestamp:
02/28/06 13:44:36 (15 years ago)
Author:
Perry Lorier <perry@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
5b66921
Parents:
c26ca86
Message:

Add preliminary seek support

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • lib/common.h

    r3d4d52d r0d57541  
    2020#  define LIBTRACE_WRITE(file,buf,len) gzwrite(file,buf,len)
    2121#  define LIBTRACE_FILE gzFile*
     22#  define LIBTRACE_SEEK(file,offset,whence) gzseek(file,offset,whence)
     23#  define LIBTRACE_TELL(file) gztell(file)
    2224#else
    2325#  define LIBTRACE_READ(file,buf,len) read(file,buf,len)
     
    2729#  define LIBTRACE_WRITE(file,buf,len) write(file,buf,len)
    2830#  define LIBTRACE_FILE int
     31#  define LIBTRACE_SEEK(file,offset,whence) lseek(file,offset,whence)
     32#  define LIBTRACE_TELL(file) tell(file,0,SEEK_CUR)
    2933#endif
    3034
  • lib/format_erf.c

    r5fb2251 r0d57541  
    9595        } input;
    9696
     97        struct {
     98                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
     99                LIBTRACE_FILE index;
     100                off_t index_len;
     101        } seek;
     102
    97103#if HAVE_DAG
    98104        struct {
     
    142148} libtrace_packet_status_t;
    143149
     150typedef struct erf_index_t {
     151        uint64_t timestamp;
     152        uint64_t offset;
     153} erf_index_t;
    144154
    145155#ifdef HAVE_DAG
     
    205215}
    206216
    207 static int erf_start_input(struct libtrace_t *libtrace)
     217static int erf_start_input(libtrace_t *libtrace)
    208218{
    209219        INPUT.file = trace_open_file(libtrace);
     
    213223
    214224        return 0; /* success */
     225}
     226
     227/* Binary search through the index to find the closest point before
     228 * the packet.  Consider in future having a btree index perhaps?
     229 */
     230static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
     231{
     232        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
     233        size_t min_off = 0;
     234        off_t current;
     235        erf_index_t record;
     236        do {
     237                current=(max_off+min_off)>>2;
     238
     239                LIBTRACE_SEEK(DATA(libtrace)->seek.index,
     240                                current*sizeof(record),
     241                                SEEK_SET);
     242                LIBTRACE_READ(DATA(libtrace)->seek.index,
     243                                &record,sizeof(record));
     244                if (record.timestamp < erfts) {
     245                        min_off=current;
     246                }
     247                if (record.timestamp > erfts) {
     248                        max_off=current;
     249                }
     250                if (record.timestamp == erfts)
     251                        break;
     252        } while(min_off<max_off);
     253
     254        /* If we've passed it, seek backwards.  This loop shouldn't
     255         * execute more than twice.
     256         */
     257        do {
     258                LIBTRACE_SEEK(DATA(libtrace)->seek.index,
     259                                current*sizeof(record),SEEK_SET);
     260                LIBTRACE_READ(DATA(libtrace)->seek.index,
     261                                &record,sizeof(record));
     262                current--;
     263        } while(record.timestamp>erfts);
     264
     265        /* We've found our location in the trace, now use it. */
     266        LIBTRACE_SEEK(INPUT.file,record.offset,SEEK_SET);
     267
     268        return 0; /* success */
     269}
     270
     271/* There is no index.  Seek through the entire trace from the start, nice
     272 * and slowly.
     273 */
     274static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts)
     275{
     276        if (INPUT.file) {
     277                LIBTRACE_CLOSE(INPUT.file);
     278        }
     279        INPUT.file = trace_open_file(libtrace);
     280        if (!INPUT.file)
     281                return -1;
     282        return 0;
     283}
     284
     285static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
     286{
     287        libtrace_packet_t *packet;
     288        off_t off = 0;
     289
     290        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
     291                char buffer[PATH_MAX];
     292                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
     293                DATA(libtrace)->seek.index=LIBTRACE_OPEN(buffer,"r");
     294                if (DATA(libtrace)->seek.index) {
     295                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
     296                }
     297                else {
     298                        DATA(libtrace)->seek.exists=INDEX_NONE;
     299                }
     300        }
     301
     302        /* If theres an index, use it to find the nearest packet that isn't
     303         * after the time we're looking for.  If there is no index we need
     304         * to seek slowly through the trace from the beginning.  Sigh.
     305         */
     306        switch(DATA(libtrace)->seek.exists) {
     307                case INDEX_EXISTS:
     308                        erf_fast_seek_start(libtrace,erfts);
     309                        break;
     310                case INDEX_NONE:
     311                        erf_slow_seek_start(libtrace,erfts);
     312                        break;
     313                case INDEX_UNKNOWN:
     314                        assert(0);
     315                        break;
     316        }
     317
     318        /* Now seek forward looking for the correct timestamp */
     319        packet=trace_create_packet();
     320        do {
     321                trace_read_packet(libtrace,packet);
     322                if (trace_get_erf_timestamp(packet)==erfts)
     323                        break;
     324                off=LIBTRACE_TELL(INPUT.file);
     325        } while(trace_get_erf_timestamp(packet)<erfts);
     326
     327        LIBTRACE_SEEK(INPUT.file,off,SEEK_SET);
     328
     329        return 0;
    215330}
    216331
     
    350465
    351466#if HAVE_DAG
     467/* FIXME: dag_read_packet shouldn't update the pointers, dag_fin_packet
     468 * should do that.
     469 */
    352470static int dag_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
    353471        int numbytes;
     
    791909        NULL,                           /* get_timeval */
    792910        NULL,                           /* get_seconds */
    793         NULL,                           /* seek_erf */
     911        erf_seek_erf,                   /* seek_erf */
    794912        NULL,                           /* seek_timeval */
    795913        NULL,                           /* seek_seconds */
  • lib/format_helper.c

    r0ea3526 r0d57541  
    8080        struct timeval stv;
    8181
    82         if (!trace->event.packet.buffer) {
    83                 trace->event.packet.buffer = (void *)malloc(4096);
    84                 trace->event.packet.size=
    85                         trace_read_packet(trace,packet);
    86                 event.size = trace->event.packet.size = \
    87                              trace->event.packet.size;
    88                 if (trace->event.packet.size > 0 ) {
    89                         memcpy(trace->event.packet.buffer,
    90                                         packet->buffer,
    91                                         trace->event.packet.size);
    92                 } else {
     82        if (!trace->event.packet) {
     83                trace->event.packet = trace_create_packet();
     84                trace->event.psize=
     85                        trace_read_packet(trace,trace->event.packet);
     86                if (trace->event.psize<1) {
    9387                        /* return here, the test for
    9488                         * event.size will sort out the error
     
    9993        }
    10094
    101         ts=trace_get_seconds(packet);
     95        ts=trace_get_seconds(trace->event.packet);
    10296        if (trace->event.tdelta!=0) {
    10397                /* Get the adjusted current time */
     
    108102                now -= trace->event.tdelta;
    109103
    110                 /*if the trace timestamp is still in the
    111                 //future, return a SLEEP event,
    112                 //otherwise fire the packet
     104                /* if the trace timestamp is still in the
     105                 * future, return a SLEEP event,
     106                 * otherwise fire the packet
    113107                 */
    114108                if (ts > now) {
     
    121115                gettimeofday(&stv, NULL);
    122116                /* work out the difference between the
    123                 // start of trace replay, and the first
    124                 // packet in the trace
     117                 * start of trace replay, and the first
     118                 * packet in the trace
    125119                 */
    126120                trace->event.tdelta = stv.tv_sec +
     
    130124
    131125        /* This is the first packet, so just fire away. */
    132         memcpy(packet->buffer,
    133                         trace->event.packet.buffer,
    134                         trace->event.packet.size);
    135         free(trace->event.packet.buffer);
    136         trace->event.packet.buffer = 0;
     126        /* TODO: finalise packet */
     127        *packet = *trace->event.packet;
     128        trace->event.packet = NULL;
     129
    137130        event.type = TRACE_EVENT_PACKET;
    138131
     
    140133
    141134        return event;
    142        
    143135}
    144136
  • lib/libtrace.h

    rd8f02df r0d57541  
    743743int trace_seek_timeval(libtrace_t *trace, struct timeval tv);
    744744
     745/** Seek within a trace
     746 * @param trace         trace to seek
     747 * @param ts            erf timestamp
     748 * @return 0 on success.
     749 * Make the next packet read to be the first packet to occur at or after the
     750 * time searched for.  This must be called in the configuration state (ie,
     751 * before trace_start() or after trace_pause().
     752 * @note This function may be extremely slow.
     753 */
     754int trace_seek_erf_timestamp(libtrace_t *trace, uint64_t ts);
     755
    745756/*@}*/
    746757
  • lib/libtrace_int.h

    rd5879cc r0d57541  
    8080
    8181struct libtrace_event_t {
    82         struct {
    83                 void *buffer;
    84                 int size;
    85         } packet;
     82        libtrace_packet_t *packet;
     83        int psize;
    8684        double tdelta;
    8785        double trace_last_ts;
  • lib/trace.c

    rd8f02df r0d57541  
    16681668        return err;
    16691669}
     1670
     1671int trace_seek_erf_timestamp(libtrace_t *trace, uint64_t ts)
     1672{
     1673        if (trace->format->seek_erf) {
     1674                return trace->format->seek_erf(trace,ts);
     1675        }
     1676        else {
     1677                /*FIXME: can this be transmuted into seek_seconds, or
     1678                 * seek_timeval?
     1679                 */
     1680                trace_set_err(trace,
     1681                                TRACE_ERR_OPTION_UNAVAIL,
     1682                                "Feature unimplemented");
     1683                return -1;
     1684        }
     1685}
     1686
  • test/Makefile

    rc6a6c3a r0d57541  
    1010
    1111BINS = test1 test2 test-pcap test-pcap-bpf test-erf-write test-erf-to-pcap \
    12         test-pcap-to-erf test-wtf test-rtclient test-event test-time
     12        test-pcap-to-erf test-wtf test-rtclient test-event test-time \
     13        test-seek
    1314.PHONY: all clean distclean install depend test
    1415
Note: See TracChangeset for help on using the changeset viewer.