1 | |
---|
2 | /* file copy_recs.c |
---|
3 | * =========== |
---|
4 | * |
---|
5 | * version 20, 6-Feb-2007 |
---|
6 | * v 10: 14-Aug-96, include jukebox reading |
---|
7 | * v 11: 14-Aug-97, include 2nd jukebox |
---|
8 | * v 12: 21-Aug-97 correct call of jk_bugfix_loop.csh |
---|
9 | * v 13: 13-Mar-98, check for locked data windows (CdDataLocked) |
---|
10 | * v 14: 13-Oct-98, convert string data to uppercase in record header |
---|
11 | * v 15: 11-Jan-00, variable record length |
---|
12 | * v 16: 14-Jan-00, fix output of CD name, change size output from recs to kB |
---|
13 | * v 17: 04-Feb-00, Y2K bug in standard_name |
---|
14 | * v 18: 09-Oct-02, write Netcode GR if qualifier -net=GR is given |
---|
15 | * v 19: 09-Mar-06, remove bugfix loop, no more CD jukeboxes used |
---|
16 | * v 20: 06-Feb-07, add GpReadParams and -defaultnet qualifier |
---|
17 | * |
---|
18 | * Counts kB in a stream within a given time window |
---|
19 | * if an output file is specified the records are copied to this file. |
---|
20 | * If the record length changes during data read a new output file is written. |
---|
21 | * This file gets a new standard name or the specified name extended by |
---|
22 | * a counter (*.1, *.2, ...). |
---|
23 | * Implementation: reads record by record and counts until end time is reached. |
---|
24 | * K. Stammler, 18-Nov-94 |
---|
25 | */ |
---|
26 | |
---|
27 | |
---|
28 | #include <stdio.h> |
---|
29 | #include <string.h> |
---|
30 | #include BASECNST |
---|
31 | #include BC_SYSBASE |
---|
32 | #include BC_CPAR |
---|
33 | #include BC_TCUSRDEF |
---|
34 | #include BC_ERUSRDEF |
---|
35 | #include "seedcfg.h" |
---|
36 | #include "seed_lib.h" |
---|
37 | #include "seed_cd.h" |
---|
38 | |
---|
39 | |
---|
40 | |
---|
41 | /* prototypes of local routines */ |
---|
42 | static void standard_name( char stream[], char start[], char name[] ); |
---|
43 | |
---|
44 | |
---|
45 | |
---|
46 | int main( int argc, char *argv[] ) |
---|
47 | { |
---|
48 | /* local variables */ |
---|
49 | STATUS status; /* return status */ |
---|
50 | SeedSbyteT *seedrec; /* pointer to SEED record */ |
---|
51 | SeedDataHeaderT *seedhdr; /* pointer to seed data header */ |
---|
52 | int reclth; /* SEED record length */ |
---|
53 | int last_reclth; /* length of last record */ |
---|
54 | char sfdfile[cBcFileLth+1]; /* sfd file name */ |
---|
55 | char stream[cBcShortStrLth+1]; /* stream name */ |
---|
56 | char t_start[cBcTimeLth+1]; /* start time */ |
---|
57 | char t_end[cBcTimeLth+1]; /* end time */ |
---|
58 | char act_start[cBcTimeLth+1]; /* actual start time */ |
---|
59 | char outfile[cBcFileLth+1]; /* name of output file */ |
---|
60 | int outfile_lth; /* length of outfile name */ |
---|
61 | char timestr[cBcTimeLth+1]; /* time string */ |
---|
62 | NTIME recstime, recetime; /* start & end time of record */ |
---|
63 | NTIME p_recstime, p_recetime; /* start & end time of previous record */ |
---|
64 | NTIME endntime; /* end time */ |
---|
65 | int rec_cnt; /* record counter */ |
---|
66 | int gap_cnt; /* gap counter */ |
---|
67 | BOOLEAN hdr_swapped; /* header was swapped */ |
---|
68 | FILE *out; /* pointer to output file */ |
---|
69 | SeedSbyteT ctmp; /* scratch */ |
---|
70 | BOOLEAN work_quiet; /* print less error messages */ |
---|
71 | BOOLEAN exact; /* cut 1st and last recs to exact times*/ |
---|
72 | BOOLEAN swap; /* swap bytes (only imp. for -exact) */ |
---|
73 | BOOLEAN no_negative_gaps; /* ignore negative gap records */ |
---|
74 | BOOLEAN negative_gap; /* negative time gap found */ |
---|
75 | float tdiff; /* time difference */ |
---|
76 | float gapdiff; /* gap time difference */ |
---|
77 | float dt; /* sample distance in sec */ |
---|
78 | BOOLEAN read_jukebox; /* read from jukebox */ |
---|
79 | BOOLEAN overwrite_netcode=FALSE; /* overwrite netcode */ |
---|
80 | char cdlabel[cBcShortStrLth+1]; /* CD label */ |
---|
81 | char cdmagic[cBcLineLth+1]; /* magic string of CD */ |
---|
82 | char jkpath[cBcLineLth+1]; /* jukebox root path */ |
---|
83 | int i; /* counter */ |
---|
84 | int bytesize; /* total size in bytes */ |
---|
85 | int fcnt; /* file counter */ |
---|
86 | char netcode[cBcShortStrLth+1]; /* network code */ |
---|
87 | char pathcache[cBcFileLth+1]; /* path cache file */ |
---|
88 | |
---|
89 | /* executable code */ |
---|
90 | |
---|
91 | GpReadParfile(); |
---|
92 | status = BC_NOERROR; |
---|
93 | work_quiet = FALSE; |
---|
94 | swap = TRUE; |
---|
95 | exact = FALSE; |
---|
96 | no_negative_gaps = FALSE; |
---|
97 | p_recstime.year = 0; |
---|
98 | p_recetime.year = 0; |
---|
99 | dt = 0.0; |
---|
100 | strcpy( cdlabel, "online" ); |
---|
101 | reclth = last_reclth = 0; |
---|
102 | bytesize = 0; |
---|
103 | *pathcache = '\0'; |
---|
104 | |
---|
105 | pa_init( argc, argv ); |
---|
106 | if (pa_pnumber() < 4 || pa_pnumber() > 5) { |
---|
107 | fprintf( stderr, |
---|
108 | "Usage: %s <sfdfile> <stream> <start> <end> [<outfile>]\n", |
---|
109 | pa_progname() ); |
---|
110 | return 1; |
---|
111 | } /*endif*/ |
---|
112 | strcpy( sfdfile, pa_pvalue(1) ); |
---|
113 | strcpy( stream, pa_pvalue(2) ); |
---|
114 | strcpy( t_start, pa_pvalue(3) ); |
---|
115 | strcpy( t_end, pa_pvalue(4) ); |
---|
116 | *outfile = '\0'; |
---|
117 | if (pa_pnumber() >= 5) strcpy( outfile, pa_pvalue(5) ); |
---|
118 | if (pa_qspecified("-quiet")) work_quiet = TRUE; |
---|
119 | if (pa_qspecified("-exact")) exact = TRUE; |
---|
120 | if (pa_qspecified("-noexact")) exact = FALSE; |
---|
121 | if (pa_qspecified("-swap")) swap = TRUE; |
---|
122 | if (pa_qspecified("-noswap")) swap = FALSE; |
---|
123 | if (pa_qspecified("-neggaps")) no_negative_gaps = FALSE; |
---|
124 | if (pa_qspecified("-noneggaps")) no_negative_gaps = TRUE; |
---|
125 | if (pa_qspecified("-invhdr")) SeedSetInvertSwapHeader( TRUE ); |
---|
126 | *netcode = '\0'; |
---|
127 | if (pa_qspecified("-net")) { |
---|
128 | strcpy( netcode, pa_qvalue("-net") ); |
---|
129 | overwrite_netcode = TRUE; |
---|
130 | } /*endif*/ |
---|
131 | if (pa_qspecified("-defaultnet")) { |
---|
132 | strcpy( netcode, pa_qvalue("-defaultnet") ); |
---|
133 | overwrite_netcode = FALSE; |
---|
134 | } /*endif*/ |
---|
135 | if (pa_qspecified("-pathcache")) { |
---|
136 | strcpy( pathcache, pa_qvalue("-pathcache") ); |
---|
137 | SqlPathcacheFile( pathcache ); |
---|
138 | } /*endif*/ |
---|
139 | read_jukebox = (strcmp(sfdfile,"JK:") == 0); |
---|
140 | |
---|
141 | /* open output file if requested */ |
---|
142 | fcnt = 0; |
---|
143 | out = NULL; |
---|
144 | if (*outfile != '\0') { |
---|
145 | if (strcmp(outfile,"standard") == 0) { |
---|
146 | standard_name( stream, t_start, outfile ); |
---|
147 | } else { |
---|
148 | fcnt = 1; /* fcnt > 0 means keep given name as prefix */ |
---|
149 | } /*endif*/ |
---|
150 | outfile_lth = strlen( outfile ); |
---|
151 | out = fopen( outfile, "wb" ); |
---|
152 | if (out == NULL) { |
---|
153 | fprintf( stderr, "%s: output file %s couldn't be opened\n", |
---|
154 | pa_progname(), outfile ); |
---|
155 | return 1; |
---|
156 | } /*endif*/ |
---|
157 | } /*endif*/ |
---|
158 | |
---|
159 | tc_t2n( t_end, &endntime, &status ); |
---|
160 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
161 | |
---|
162 | /* get other parameters */ |
---|
163 | SeedLibInitialize( &status ); |
---|
164 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
165 | |
---|
166 | /* allocate memory for SEED record */ |
---|
167 | seedrec = (SeedSbyteT *)sy_allocmem( 1, Seed_C_MAX_RECLTH, &status ); |
---|
168 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
169 | |
---|
170 | /* if reading from jukebox get name of sfdfile */ |
---|
171 | if (read_jukebox) { |
---|
172 | tdiff = tc_tdiff( t_end, t_start, &status ); |
---|
173 | if (SySevere(&status)) err_writemsg( status, "", TRUE ); |
---|
174 | if (CdDataLocked(stream,t_start,tdiff,&status)) { |
---|
175 | fprintf( stderr, "%s: %s is locked at %s. Abort.\n", |
---|
176 | pa_progname(), stream, t_start ); |
---|
177 | return 1; |
---|
178 | } /*endif*/ |
---|
179 | CdFindLabel( stream, t_start, jkpath, cdlabel, cdmagic, &status ); |
---|
180 | if (SySevere(&status)) err_writemsg( status, "", TRUE ); |
---|
181 | sprintf( sfdfile, "%s/%s/sfdfile.sfd", jkpath, cdlabel ); |
---|
182 | } /*endif*/ |
---|
183 | |
---|
184 | SeedSearchPosition( 0, sfdfile, stream, t_start, act_start, &status ); |
---|
185 | if (status == SeedERR_NEXTTIMEPOS) { |
---|
186 | if (!work_quiet) |
---|
187 | fprintf( stderr, "%s: stream %s, pos %s instead of %s\n", |
---|
188 | pa_progname(), stream, act_start, t_start ); |
---|
189 | status = BC_NOERROR; |
---|
190 | } /*endif*/ |
---|
191 | if (Severe(&status)) { |
---|
192 | if (!work_quiet) { |
---|
193 | fprintf( stderr, "%s: time %s on stream %s not found\n", |
---|
194 | pa_progname(), t_start, stream ); |
---|
195 | err_writemsg( status, "", TRUE ); |
---|
196 | } /*endif*/ |
---|
197 | printf( "0 kB found (CD %s)\n", cdlabel ); |
---|
198 | return 0; |
---|
199 | } /*endif*/ |
---|
200 | |
---|
201 | negative_gap = FALSE; |
---|
202 | rec_cnt = gap_cnt = 0; |
---|
203 | seedhdr = (SeedDataHeaderT *)seedrec; |
---|
204 | do { |
---|
205 | status = cBcNoError; |
---|
206 | /* read next record */ |
---|
207 | SeedReadNextRecord( 0, (SeedSbyteT *)seedrec, &hdr_swapped, &status ); |
---|
208 | if (status == SeedERR_NEXTTIMEPOS) status = BC_NOERROR; |
---|
209 | if (Severe(&status)) { |
---|
210 | if (!work_quiet) { |
---|
211 | fprintf( stderr, "%s: stream %s, error reading next record\n", |
---|
212 | pa_progname(), stream ); |
---|
213 | err_writemsg( status, "", FALSE ); |
---|
214 | } /*endif*/ |
---|
215 | status = BC_NOERROR; |
---|
216 | break; |
---|
217 | } /*endif*/ |
---|
218 | reclth = SeedGetReclth( seedhdr, FALSE ); |
---|
219 | /* get start and end time */ |
---|
220 | SeedRecordTime( seedrec, &recstime, &recetime, &status ); |
---|
221 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
222 | /* if start time of record is out of requested window, return */ |
---|
223 | if (tc_ndiff(&endntime,&recstime,&status) < 0.0) break; |
---|
224 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
225 | /* change network code if requested */ |
---|
226 | if (*netcode != '\0') { |
---|
227 | if (overwrite_netcode || seedhdr->network[0] <= ' ') { |
---|
228 | seedhdr->network[0] = netcode[0]; |
---|
229 | seedhdr->network[1] = netcode[1]; |
---|
230 | } /*endif*/ |
---|
231 | } /*endif*/ |
---|
232 | /* get dt on first time */ |
---|
233 | if (dt == 0.0) dt = SeedGetSampleDist( seedhdr ); |
---|
234 | if (rec_cnt == 0 && exact) { |
---|
235 | SeedCutStartRecord( seedrec, t_start, swap, &status ); |
---|
236 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
237 | if (seedhdr->no_of_samples == 0) continue; |
---|
238 | } /*endif*/ |
---|
239 | tdiff = tc_ndiff( &endntime, &recetime, &status ); |
---|
240 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
241 | ctmp = seedrec[6]; |
---|
242 | sprintf( (char *)seedrec, "%06d", ++rec_cnt ); |
---|
243 | seedrec[6] = ctmp; |
---|
244 | bytesize += reclth; |
---|
245 | /* check for data gaps */ |
---|
246 | if (p_recstime.year != 0) { |
---|
247 | gapdiff = tc_ndiff( &p_recetime, &recstime, &status ); |
---|
248 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
249 | if (Abs(gapdiff) > dt/2.0) gap_cnt++; |
---|
250 | negative_gap = (gapdiff < -dt/2.0); |
---|
251 | if (negative_gap && no_negative_gaps) |
---|
252 | /* do not write record out and do not copy record times */ |
---|
253 | /* to p_recsttime and p_recetime */ |
---|
254 | continue; |
---|
255 | } /*endif*/ |
---|
256 | if (out != NULL) { |
---|
257 | if (tdiff <= 0.0 && exact) { |
---|
258 | SeedCutEndRecord( seedrec, t_end, swap, &status ); |
---|
259 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
260 | if (seedhdr->no_of_samples == 0) { |
---|
261 | rec_cnt--; |
---|
262 | bytesize -= reclth; |
---|
263 | break; |
---|
264 | } /*endif*/ |
---|
265 | } /*endif*/ |
---|
266 | /* convert string data to uppercase */ |
---|
267 | for (i=0; i<5; i++) |
---|
268 | seedhdr->statcode[i] = Cap( seedhdr->statcode[i] ); |
---|
269 | for (i=0; i<3; i++) |
---|
270 | seedhdr->channel[i] = Cap( seedhdr->channel[i] ); |
---|
271 | /* write out data */ |
---|
272 | reclth = SeedGetReclth( seedhdr, TRUE ); |
---|
273 | if (last_reclth == 0) last_reclth = reclth; |
---|
274 | if (last_reclth != reclth) { |
---|
275 | /* open new file */ |
---|
276 | fclose( out ); |
---|
277 | if (fcnt > 0) { |
---|
278 | /* use given name and append counter */ |
---|
279 | sprintf( outfile+outfile_lth, ".%d", fcnt++ ); |
---|
280 | } else { |
---|
281 | /* new standard name */ |
---|
282 | tc_n2t( &recstime, timestr, &status ); |
---|
283 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
284 | standard_name( stream, timestr, outfile ); |
---|
285 | } /*endif*/ |
---|
286 | out = fopen( outfile, "wb" ); |
---|
287 | if (out == NULL) { |
---|
288 | fprintf( stderr, "%s: output file %s couldn't be opened\n", |
---|
289 | pa_progname(), outfile ); |
---|
290 | return 1; |
---|
291 | } /*endif*/ |
---|
292 | } /*endif*/ |
---|
293 | if (fwrite((char *)seedrec,reclth,1,out) != 1) { |
---|
294 | fprintf( stderr, "%s: write error on file %s\n", |
---|
295 | pa_progname(), outfile ); |
---|
296 | fclose( out ); |
---|
297 | return 1; |
---|
298 | } /*endif*/ |
---|
299 | last_reclth = reclth; |
---|
300 | } /*endif*/ |
---|
301 | p_recstime = recstime; |
---|
302 | p_recetime = recetime; |
---|
303 | } while (tdiff > 0.0); |
---|
304 | if (Severe(&status)) err_writemsg( status, "", TRUE ); |
---|
305 | |
---|
306 | printf( "%d kB found (%d records, %d gaps) on stream %s (CD %s)\n", |
---|
307 | bytesize/1024, rec_cnt, gap_cnt, stream, cdlabel ); |
---|
308 | |
---|
309 | if (out != NULL) fclose( out ); |
---|
310 | |
---|
311 | return 0; |
---|
312 | |
---|
313 | } /* end of main */ |
---|
314 | |
---|
315 | |
---|
316 | |
---|
317 | |
---|
318 | /*---------------------------------------------------------------------------*/ |
---|
319 | |
---|
320 | |
---|
321 | |
---|
322 | static void standard_name( char stream[], char start[], char name[] ) |
---|
323 | |
---|
324 | /* computes standard name for output file |
---|
325 | * |
---|
326 | * parameters of routine |
---|
327 | * char stream[]; input; stream string |
---|
328 | * char start[]; input; start time |
---|
329 | * char name[]; output; name of file |
---|
330 | */ |
---|
331 | { |
---|
332 | /* local variables */ |
---|
333 | char lstream[BC_SHORTSTRLTH+1]; /* local stream copy */ |
---|
334 | char station[BC_SHORTSTRLTH+1]; /* name of station */ |
---|
335 | char channel[BC_SHORTSTRLTH+1]; /* name of channel */ |
---|
336 | char cmpstr[BC_SHORTSTRLTH+1]; /* component */ |
---|
337 | char *cptr; /* moving pointer */ |
---|
338 | NTIME ntime; /* numeric time */ |
---|
339 | STATUS locstat; /* local status */ |
---|
340 | |
---|
341 | /* executable code */ |
---|
342 | |
---|
343 | if (strlen(stream) > BC_SHORTSTRLTH) { |
---|
344 | strcpy( name, "stream-too-long" ); |
---|
345 | return; |
---|
346 | } /*endif*/ |
---|
347 | |
---|
348 | strcpy( lstream, stream ); |
---|
349 | cptr = lstream; |
---|
350 | while (*cptr != '\0') { |
---|
351 | if (*cptr == '-') *cptr = ' '; |
---|
352 | cptr++; |
---|
353 | } /*endwhile*/ |
---|
354 | sscanf( lstream, "%s %s %s", station, channel, cmpstr ); |
---|
355 | |
---|
356 | locstat = BC_NOERROR; |
---|
357 | tc_t2n( start, &ntime, &locstat ); |
---|
358 | if (Severe(&locstat)) { |
---|
359 | strcpy( name, "illegal-start-time" ); |
---|
360 | return; |
---|
361 | } /*endif*/ |
---|
362 | if (ntime.year > 1900) ntime.year -= 1900; |
---|
363 | if (ntime.year >= 100) ntime.year -= 100; |
---|
364 | |
---|
365 | sprintf( name, "%s_%02d%02d%02d_%02d%02d.%s%c", station, |
---|
366 | ntime.year, ntime.month, ntime.day, ntime.hour, ntime.min, |
---|
367 | channel, *cmpstr ); |
---|
368 | |
---|
369 | } /* end of standard_name */ |
---|
370 | |
---|
371 | |
---|
372 | |
---|
373 | /*---------------------------------------------------------------------------*/ |
---|