00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00033 #include <string.h>
00034 #include <stdlib.h>
00035 #include <stdint.h>
00036 #include <arpa/inet.h>
00037 #include "eventlog.h"
00038
00039 #define MAGIC ((int32_t) 0xEDA1DA01L)
00040
00041 static inline int fread32(FILE *f, int32_t *v32)
00042 {
00043 int32_t v;
00044 if (fread(&v, 4, 1, f) != 1)
00045 return -1;
00046 *v32 = ntohl(v);
00047 return 0;
00048 }
00049
00050 static inline int fread64(FILE *f, int64_t *v64)
00051 {
00052 int32_t v1, v2;
00053 if (fread32(f, &v1))
00054 return -1;
00055 if (fread32(f, &v2))
00056 return -1;
00057 *v64 = (((int64_t) v1)<<32) | (((int64_t) v2)&0xffffffff);
00058 return 0;
00059 }
00060
00061 lcm_eventlog_t *lcm_eventlog_create(const char *path, const char *mode)
00062 {
00063 if(strcmp(mode, "r")) return NULL;
00064 lcm_eventlog_t *l = (lcm_eventlog_t*) calloc(1, sizeof(lcm_eventlog_t));
00065 l->f = fopen(path, mode);
00066 if (l->f == NULL) {
00067 free (l);
00068 return NULL;
00069 }
00070 l->eventcount = 0;
00071 return l;
00072 }
00073
00074 void lcm_eventlog_destroy(lcm_eventlog_t *l)
00075 {
00076 fclose(l->f);
00077 free(l);
00078 }
00079
00080 lcm_eventlog_event_t *lcm_eventlog_read_next_event(lcm_eventlog_t *l)
00081 {
00082 lcm_eventlog_event_t *le =
00083 (lcm_eventlog_event_t*) calloc(1, sizeof(lcm_eventlog_event_t));
00084
00085 int32_t magic = 0;
00086
00087 do {
00088 int r = fgetc(l->f);
00089 if (r < 0) goto eof;
00090 magic = (magic << 8) | r;
00091 } while( magic != MAGIC );
00092
00093 fread64(l->f, &le->eventnum);
00094 fread64(l->f, &le->timestamp);
00095 fread32(l->f, &le->channellen);
00096 fread32(l->f, &le->datalen);
00097
00098 if (l->eventcount != le->eventnum) {
00099 l->eventcount = le->eventnum;
00100 }
00101
00102 le->channel = (char*)calloc(1, le->channellen+1);
00103 if (fread(le->channel, 1, le->channellen, l->f) != (size_t) le->channellen)
00104 goto eof;
00105
00106 le->data = calloc(1, le->datalen+1);
00107 if (fread(le->data, 1, le->datalen, l->f) != (size_t) le->datalen)
00108 goto eof;
00109
00110 l->eventcount++;
00111
00112 return le;
00113
00114 eof:
00115 return NULL;
00116 }
00117
00118 void lcm_eventlog_free_event(lcm_eventlog_event_t *le)
00119 {
00120 if (le->data) free(le->data);
00121 if (le->channel) free(le->channel);
00122 memset(le,0,sizeof(lcm_eventlog_event_t));
00123 free(le);
00124 }
00125
00126 static int64_t get_event_time(lcm_eventlog_t *l)
00127 {
00128 int32_t magic = 0;
00129 int r;
00130
00131 do {
00132 r = fgetc(l->f);
00133 if (r < 0) goto eof;
00134 magic = (magic << 8) | r;
00135 } while( magic != MAGIC );
00136
00137 int64_t event_num;
00138 int64_t timestamp;
00139 if (0 != fread64(l->f, &event_num)) return -1;
00140 if (0 != fread64(l->f, ×tamp)) return -1;
00141 fseeko (l->f, -20, SEEK_CUR);
00142
00143 l->eventcount = event_num;
00144
00145 return timestamp;
00146
00147 eof:
00148 return -1;
00149 }
00150
00151 int lcm_eventlog_seek_to_timestamp(lcm_eventlog_t *l, int64_t timestamp)
00152 {
00153 fseeko (l->f, 0, SEEK_END);
00154 off_t file_len = ftello(l->f);
00155
00156 int64_t cur_time;
00157 double frac1 = 0;
00158 double frac2 = 1;
00159 double prev_frac = -1;
00160 double frac;
00161
00162 while (1) {
00163 frac = 0.5*(frac1+frac2);
00164 off_t offset = (off_t)(frac*file_len);
00165 fseeko (l->f, offset, SEEK_SET);
00166 cur_time = get_event_time (l);
00167 if (cur_time < 0)
00168 return -1;
00169
00170 frac = (double)ftello (l->f)/file_len;
00171 if ((frac > frac2) || (frac < frac1) || (frac1>=frac2))
00172 break;
00173
00174 double df = frac-prev_frac;
00175 if (df < 0)
00176 df = -df;
00177 if (df < 1e-12)
00178 break;
00179
00180 if (cur_time == timestamp)
00181 break;
00182
00183 if (cur_time < timestamp)
00184 frac1 = frac;
00185 else
00186 frac2 = frac;
00187
00188 prev_frac = frac;
00189 }
00190
00191 return 0;
00192 }