LALPulsar 7.1.1.1-eeff03c
FstatToplist.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Bernd Machenschalk, Reinhard Prix
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20#include "config.h"
21
22#include "math.h"
23#ifdef HAVE_UNISTD_H
24#include <unistd.h>
25#endif
26
27#include <lal/StringInput.h>
28#include <lal/LALStdio.h>
29#include <lal/LogPrintf.h>
30#include <lal/LogPrintf.h>
31#include <lal/HeapToplist.h>
32
33#include "FstatToplist.h"
34
35/* MSC specifics */
36#ifdef _MSC_VER
37
38/* errno */
39extern int errno;
40extern int _doserrno;
41
42/* snprintf */
43#define snprintf _snprintf
44
45/* fsync */
46#define fsync _commit
47#define fileno _fileno
48
49#else /* MSC */
50
51/* errno */
52#include <errno.h>
53
54#endif /* MSC */
55
56
57
58/* define min macro if not already defined */
59#ifndef min
60#define min(a,b) ((a)<(b)?(a):(b))
61#endif
62
63/* maximum number of succesive failures before switching off syncing */
64#define SYNC_FAIL_LIMIT 5
65
66/* local prototypes */
68static int _atomic_write_fstat_toplist_to_file( toplist_t *l, const char *filename, UINT4 *checksum, int write_done );
69static int print_fstatline_to_str( FstatOutputEntry fline, char *buf, int buflen );
70
71
72/* ordering function for sorting the list */
73static int fstat_toplist_qsort_function( const void *a, const void *b )
74{
75 if ( ( ( const FstatOutputEntry * )a )->Freq < ( ( const FstatOutputEntry * )b )->Freq ) {
76 return -1;
77 } else if ( ( ( const FstatOutputEntry * )a )->Freq > ( ( const FstatOutputEntry * )b )->Freq ) {
78 return 1;
79 } else if ( ( ( const FstatOutputEntry * )a )->Alpha < ( ( const FstatOutputEntry * )b )->Alpha ) {
80 return -1;
81 } else if ( ( ( const FstatOutputEntry * )a )->Alpha > ( ( const FstatOutputEntry * )b )->Alpha ) {
82 return 1;
83 } else if ( ( ( const FstatOutputEntry * )a )->Delta < ( ( const FstatOutputEntry * )b )->Delta ) {
84 return -1;
85 } else if ( ( ( const FstatOutputEntry * )a )->Delta > ( ( const FstatOutputEntry * )b )->Delta ) {
86 return 1;
87 } else if ( ( ( const FstatOutputEntry * )a )->f1dot < ( ( const FstatOutputEntry * )b )->f1dot ) {
88 return -1;
89 } else if ( ( ( const FstatOutputEntry * )a )->f1dot > ( ( const FstatOutputEntry * )b )->f1dot ) {
90 return 1;
91 } else {
92 return 0;
93 }
94}
95
96/* ordering function defining the toplist */
97static int fstat_smaller( const void *a, const void *b )
98{
99 if ( ( ( const FstatOutputEntry * )a )->Fstat < ( ( const FstatOutputEntry * )b )->Fstat ) {
100 return ( 1 );
101 } else if ( ( ( const FstatOutputEntry * )a )->Fstat > ( ( const FstatOutputEntry * )b )->Fstat ) {
102 return ( -1 );
103 } else {
104 return ( fstat_toplist_qsort_function( a, b ) );
105 }
106}
107
108
109/* creates a toplist with length elements,
110 returns -1 on error (usually out of memory), else 0 */
112{
113 return ( create_toplist( tl, length, sizeof( FstatOutputEntry ), fstat_smaller ) );
114}
115
116
117/* frees the space occupied by the toplist */
119{
120 free_toplist( l );
121}
122
123
124/* Inserts an element in to the toplist either if there is space left
125 or the element is larger than the smallest element in the toplist.
126 In the latter case, remove the smallest element from the toplist and
127 look for the now smallest one.
128 Returns 1 if the element was actually inserted, 0 if not. */
130{
131 if ( !tl ) {
132 return 0;
133 } else {
134 return ( insert_into_toplist( tl, ( void * )&elem ) );
135 }
136}
137
138
139/* (q)sort the toplist according to the sorting function. */
141{
143}
144
145
146/* reads a (created!) toplist from an open filepointer
147 returns the number of bytes read,
148 0 if we found a %DONE marker at the end,
149 -1 if the file contained a syntax error,
150 -2 if given an improper toplist */
151int read_fstat_toplist_from_fp( toplist_t *l, FILE *fp, UINT4 *checksum, UINT4 maxbytes )
152{
153 CHAR line[256]; /* buffer for reading a line */
154 UINT4 items, lines; /* number of items read from a line, linecounter */
155 UINT4 len, chars = 0; /* length of a line, total characters read from the file */
156 UINT4 i; /* loop counter */
157 CHAR lastchar; /* last character of a line read, should be newline */
158 FstatOutputEntry FstatLine;
159 REAL8 epsilon = 1e-5;
160
161 /* basic check that the list argument is valid */
162 if ( !l ) {
163 return -2;
164 }
165
166 /* make sure the line buffer is terminated correctly */
167 XLAL_LAST_ELEM( line ) = '\0';
168
169 /* init the checksum if given */
170 if ( checksum ) {
171 *checksum = 0;
172 }
173
174 /* set maxbytes to maximum if zero */
175 if ( maxbytes == 0 ) {
176 maxbytes--;
177 }
178
179 lines = 1;
180 while ( fgets( line, sizeof( line ) - 1, fp ) ) {
181
182 if ( !strncmp( line, "%DONE\n", strlen( "%DONE\n" ) ) ) {
183 LogPrintf( LOG_NORMAL, "WARNING: found end marker - the task was already finished\n" );
184 return ( 0 );
185 }
186
187 len = strlen( line );
188 chars += len;
189
190 if ( len == 0 ) {
191 LogPrintf( LOG_CRITICAL, "Line %d is empty.\n", lines );
192 return -1;
193 } else if ( line[len - 1] != '\n' ) {
195 "Line %d is too long or has no NEWLINE. First %zu chars are:\n'%s'\n",
196 lines, sizeof( line ) - 1, line );
197 return -1;
198 }
199
200 items = sscanf( line,
205 " %" LAL_REAL8_FORMAT "%c",
206 &FstatLine.Freq,
207 &FstatLine.Alpha,
208 &FstatLine.Delta,
209 &FstatLine.f1dot,
210 &FstatLine.Fstat,
211 &lastchar );
212
213 /* check the values scanned */
214 if (
215 items != 6 ||
216
217 !isfinite( FstatLine.Freq ) ||
218 !isfinite( FstatLine.f1dot ) ||
219 !isfinite( FstatLine.Alpha ) ||
220 !isfinite( FstatLine.Delta ) ||
221 !isfinite( FstatLine.Fstat ) ||
222
223 FstatLine.Freq < 0.0 ||
224 FstatLine.Alpha < 0.0 - epsilon ||
225 FstatLine.Alpha > LAL_TWOPI + epsilon ||
226 FstatLine.Delta < -0.5 * LAL_PI - epsilon ||
227 FstatLine.Delta > 0.5 * LAL_PI + epsilon ||
228
229 lastchar != '\n'
230 ) {
232 "Line %d has invalid values.\n"
233 "First %zu chars are:\n"
234 "%s\n"
235 "All fields should be finite\n"
236 "1st field should be positive.\n"
237 "2nd field should lie between 0 and %1.15f.\n"
238 "3rd field should lie between %1.15f and %1.15f.\n",
239 lines, sizeof( line ) - 1, line,
240 ( double )LAL_TWOPI, ( double ) - LAL_PI / 2.0, ( double )LAL_PI / 2.0 );
241 return -1;
242 }
243
244 if ( checksum )
245 for ( i = 0; i < len; i++ ) {
246 *checksum += line[i];
247 }
248
249 insert_into_toplist( l, &FstatLine );
250 lines++;
251
252 /* NOTE: it *CAN* happen (and on Linux it DOES) that the fully buffered Fstat stream
253 * gets written to the File at program termination.
254 * This does not seem to happen on Mac though, most likely due to different
255 * exit()-calls used (_exit() vs exit() etc.....)
256 *
257 * The bottom-line is: the File-contents CAN legally extend beyond maxbytes,
258 * which is why we'll ensure here that we don't actually read more than
259 * maxbytes.
260 */
261 if ( chars == maxbytes ) {
262 LogPrintf( LOG_DEBUG, "Read exactly %d == maxbytes from Fstat-file, that's enough.\n",
263 chars );
264 break;
265 }
266 /* however, if we've read more than maxbytes, something is gone wrong */
267 if ( chars > maxbytes ) {
268 LogPrintf( LOG_CRITICAL, "Read %d bytes > maxbytes %d from Fstat-file ... corrupted.\n",
269 chars, maxbytes );
270 return -1;
271 }
272
273 } /* while (fgets() ) */
274
275 return chars;
276
277} /* read_fstat_toplist_from_fp() */
278
279
280/* Prints a Tooplist line to a string buffer.
281 Separate function to assure consistency of output and reduced precision for sorting */
282static int print_fstatline_to_str( FstatOutputEntry fline, char *buf, int buflen )
283{
284 return ( snprintf( buf, buflen,
285 /* output precision: choose by following (generous!) significant-digit constraints:
286 * Freq:1e-13
287 * Alpha,Delta:1e-7
288 * f1dot:1e-5
289 * F:1e-6
290 */
291 "%.13g %.7g %.7g %.5g %.6g\n",
292 fline.Freq,
293 fline.Alpha,
294 fline.Delta,
295 fline.f1dot,
296 fline.Fstat ) );
297}
298
299
300/* writes an FstatOutputEntry line to an open filepointer.
301 Returns the number of chars written, -1 if in error
302 Updates checksum if given */
304{
305 char linebuf[256];
306 UINT4 i;
307
308 UINT4 length = print_fstatline_to_str( fline, linebuf, sizeof( linebuf ) - 1 );
309
310 if ( length > sizeof( linebuf ) - 1 ) {
311 return -1;
312 }
313
314 if ( checksum )
315 for ( i = 0; i < length; i++ ) {
316 *checksum += linebuf[i];
317 }
318
319 XLAL_LAST_ELEM( linebuf ) = '\0';
320
321 return ( fprintf( fp, "%s", linebuf ) );
322}
323
324
325/* Reduces the precision of all elements in the toplist which influence the sorting order.
326 To be called before sorting and finally writing out the list */
328{
329 char linebuf[256];
330 print_fstatline_to_str( ( *( FstatOutputEntry * )line ), linebuf, sizeof( linebuf ) );
331 sscanf( linebuf,
336 "%*s\n",
337 &( ( *( FstatOutputEntry * )line ).Freq ),
338 &( ( *( FstatOutputEntry * )line ).Alpha ),
339 &( ( *( FstatOutputEntry * )line ).Delta ),
340 &( ( *( FstatOutputEntry * )line ).f1dot ) );
341}
342
344{
346}
347
348
349/* Writes the toplist to an (already open) filepointer
350 Returns the number of written charactes
351 Returns something <0 on error */
352int write_fstat_toplist_to_fp( toplist_t *tl, FILE *fp, UINT4 *checksum )
353{
354 UINT8 c = 0, i;
355 INT8 r;
356 if ( checksum ) {
357 *checksum = 0;
358 }
359 for ( i = 0; i < tl->elems; i++ )
360 if ( ( r = write_fstat_toplist_item_to_fp( *( ( FstatOutputEntry * )( void * )( tl->heap[i] ) ), fp, checksum ) ) < 0 ) {
361 LogPrintf( LOG_CRITICAL, "Failed to write toplistitem to output fp: %d: %s\n",
362 errno, strerror( errno ) );
363#ifdef _MSC_VER
364 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
365#endif
366 return ( r );
367 } else {
368 c += r;
369 }
370 return ( c );
371}
372
373
374/* writes the given toplitst to a temporary file, then renames the temporary file to filename.
375 The name of the temporary file is derived from the filename by appending ".tmp". Returns the
376 number of chars written or -1 if the temp file could not be opened.
377 This just calls _atomic_write_fstat_toplist_to_file() telling it not to write a %DONE marker*/
379{
380 return ( _atomic_write_fstat_toplist_to_file( l, filename, checksum, 0 ) );
381}
382
383/* function that does the actual work of atomic_write_fstat_toplist_to_file(),
384 appending a %DONE marker if specified (not when called from atomic_write_fstat_toplist_to_file().
385 NOTE that the checksum will be a little wrong when %DOME is appended, as this line is not counted */
386static int _atomic_write_fstat_toplist_to_file( toplist_t *l, const char *filename, UINT4 *checksum, int write_done )
387{
388 char *tempname;
389 INT4 length;
390 FILE *fpnew;
391 UINT4 s;
392
393#define TEMP_EXT ".tmp"
394 s = strlen( filename ) + strlen( TEMP_EXT ) + 1;
395 tempname = ( char * )malloc( s );
396 if ( !tempname ) {
397 LogPrintf( LOG_CRITICAL, "Could not allocate new filename\n" );
398 return ( -1 );
399 }
400 strcpy( tempname, filename );
401 strcat( tempname, TEMP_EXT );
402
403 fpnew = fopen( tempname, "wb" );
404 if ( !fpnew ) {
405 LogPrintf( LOG_CRITICAL, "Failed to open temp Fstat file \"%s\" for writing: %d: %s\n",
406 tempname, errno, strerror( errno ) );
407#ifdef _MSC_VER
408 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
409#endif
410 free( tempname );
411 return -1;
412 }
413 length = write_fstat_toplist_to_fp( l, fpnew, checksum );
414
415 if ( ( write_done ) && ( length >= 0 ) ) {
416 int ret;
417 ret = fprintf( fpnew, "%%DONE\n" );
418 if ( ret < 0 ) {
419 length = ret;
420 } else {
421 length += ret;
422 }
423 }
424
425 fclose( fpnew );
426
427 if ( length < 0 ) {
428 LogPrintf( LOG_CRITICAL, "Failed to write temp Fstat file \"%s\": %d: %s\n",
429 tempname, errno, strerror( errno ) );
430#ifdef _MSC_VER
431 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
432#endif
433 free( tempname );
434 return ( length );
435 }
436
437 if ( rename( tempname, filename ) ) {
438 LogPrintf( LOG_CRITICAL, "Failed to rename Fstat file to \"%s\": %d: %s\n",
439 filename, errno, strerror( errno ) );
440#ifdef _MSC_VER
441 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
442#endif
443 free( tempname );
444 return -1;
445 }
446
447 free( tempname );
448 return length;
449}
450
451
452/* meant for the final writing of the toplist
453 - reduces toplist precision
454 - sorts the toplist
455 - then calls atomic_write_fstat_toplist_to_file() */
457{
460 return ( atomic_write_fstat_toplist_to_file( l, filename, checksum ) );
461}
462
463
464
465
466/* sets up a FstatCheckpointFile from parameters */
468 CHAR *filename,
469 UINT4 bufsize,
470 UINT4 maxsize,
471 toplist_t *list )
472{
473
474 /* input sanity checks */
475 if ( ( cptf == NULL ) ||
476 ( *cptf != NULL ) ||
477 ( list == NULL ) ||
478 ( filename == NULL ) ||
479 ( strlen( filename ) == 0 ) ) {
480 LogPrintf( LOG_CRITICAL, "ERROR: error in input parameters (fstat_cpt_file_create)\n" );
481 return ( -1 );
482 }
483
484 /* allocation */
485 *cptf = LALMalloc( sizeof( FstatCheckpointFile ) );
486 if ( !( *cptf ) ) {
487 LogPrintf( LOG_CRITICAL, "ERROR: out of memeory (fstat_cpt_file_create)\n" );
488 return ( -1 );
489 }
490
491 ( *cptf )->filename = LALMalloc( strlen( filename ) + 1 );
492 if ( !( ( *cptf )->filename ) ) {
493 LogPrintf( LOG_CRITICAL, "ERROR: out of memeory (fstat_cpt_file_create)\n" );
494 LALFree( *cptf );
495 *cptf = NULL;
496 return ( -1 );
497 }
498
499 if ( bufsize > 0 ) {
500 ( *cptf )->buffer = LALMalloc( bufsize );
501 if ( !( ( *cptf )->buffer ) ) {
502 LogPrintf( LOG_CRITICAL, "ERROR: out of memeory (fstat_cpt_file_create)\n" );
503 LALFree( *cptf );
504 LALFree( ( *cptf )->filename );
505 *cptf = NULL;
506 return ( -1 );
507 }
508 }
509
510 /* initialization */
511 strcpy( ( *cptf )->filename, filename );
512
513 ( *cptf )->bytes = 0;
514 ( *cptf )->bufsize = bufsize;
515 ( *cptf )->maxsize = maxsize;
516 ( *cptf )->checksum = 0;
517 ( *cptf )->fp = NULL;
518 ( *cptf )->list = list;
519 return ( 0 );
520}
521
522
523
524/* destroys a FstatCheckpointFile structure */
526{
527 if ( !cptf ) {
528 LogPrintf( LOG_CRITICAL, "ERROR: FstatCheckpointFile is NULL\n" );
529 return ( -1 );
530 }
531 if ( ( *cptf )->filename ) {
532 LALFree( ( *cptf )->filename );
533 }
534 if ( ( *cptf )->buffer ) {
535 LALFree( ( *cptf )->buffer );
536 }
537 LALFree( *cptf );
538 *cptf = NULL;
539 return ( 0 );
540}
541
542
543
544/* opens the file named in the structure (for writing) and attaches an output buffer if specified */
546{
547 if ( !cptf ) {
548 LogPrintf( LOG_CRITICAL, "ERROR: FstatCheckpointFile is NULL\n" );
549 return ( -1 );
550 }
551 /* try open for appending if the file already exists */
552 cptf->fp = fopen( cptf->filename, "rb+" );
553 if ( !( cptf->fp ) ) {
554 LogPrintf( LOG_NORMAL, "WARNING: Couldn't open existing checkpointing toplist file %s\n", cptf->filename );
555 /* that didn't work,'s try opening a new file for writing */
556 cptf->fp = fopen( cptf->filename, "wb+" );
557 }
558 /* leave here if we couldn't open a checkpointed file at all */
559 if ( !( cptf->fp ) ) {
560 LogPrintf( LOG_CRITICAL, "ERROR: Couldn't open new checkpointing toplist file %s\n", cptf->filename );
561 return ( -1 );
562 }
563 /* attach a buffer large enough that no output is written to disk
564 * unless we fflush(). Policy is fully buffered. */
565 if ( cptf->bufsize > 0 ) {
566 setvbuf( cptf->fp, cptf->buffer, _IOFBF, cptf->bufsize );
567 }
568 return ( 0 );
569}
570
571
572
573/* flushes the checkpoint file (only useful if buffered) */
575{
576 if ( !cptf ) {
577 LogPrintf( LOG_CRITICAL, "ERROR: FstatCheckpointFile is NULL\n" );
578 return ( -1 );
579 }
580 if ( !( cptf->fp ) ) {
581 LogPrintf( LOG_CRITICAL, "ERROR: invalid checkpointing toplist file pointer\n" );
582 return ( -1 );
583 }
584 return ( fflush( cptf->fp ) );
585}
586
587
588
589/* returns information for checkpointing */
591 CHAR **filename, UINT4 *bytes, UINT4 *checksum )
592{
593 if ( !cptf ) {
594 LogPrintf( LOG_CRITICAL, "ERROR: FstatCheckpointFile is NULL\n" );
595 return ( -1 );
596 }
597 if ( filename ) {
598 *filename = cptf->filename;
599 }
600 if ( bytes ) {
601 *bytes = cptf->bytes;
602 }
603 if ( checksum ) {
604 *checksum = cptf->checksum;
605 }
606 return ( 0 );
607}
608
609
610/* closes and compacts the file */
612{
613 if ( !cptf ) {
614 LogPrintf( LOG_CRITICAL, "ERROR: FstatCheckpointFile is NULL\n" );
615 return ( -1 );
616 }
617 fclose( cptf->fp );
618
619 /* reduce the precision of the calculated values to the ones we may have
620 read in from a previous output (checkpoint) to achieve a proper sorting order */
622
623 /* completely sort the list before writing it (a heap is only partially sorted) */
624 sort_fstat_toplist( cptf->list );
625
626 /* write out the list a final time, this time with a %DONE marker at the end */
628 ( cptf->list, cptf->filename, &( cptf->checksum ), 1 ) );
629}
630
631
632/* adds an item to the toplist and keeps the file consistent, i.e.
633 adds the entry to the file if it was really inserted
634 returns 1 if the item was actually inserted, 0 if not,
635 -1 in case of an error
636 */
638{
639 int ret, bytes;
640
641 ret = insert_into_toplist( cptf->list, &line );
642 if ( ret ) {
643 bytes = write_fstat_toplist_item_to_fp( line, cptf->fp, &( cptf->checksum ) );
644 if ( bytes < 0 ) {
645 LogPrintf( LOG_CRITICAL, "Failed to write toplist item to file: %d: %s\n",
646 errno, strerror( errno ) );
647#ifdef _MSC_VER
648 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
649#endif
650 return ( -1 );
651 }
652 cptf->bytes += bytes;
653
654 if ( ( int )cptf->bytes != ftell( cptf->fp ) )
655 LogPrintf( LOG_DEBUG, "ERROR: bytecount mismatch: returned: %d, bytes: %u, file: %ld\n",
656 bytes, cptf->bytes, ftell( cptf->fp ) );
657 }
658
659 return ( ret );
660}
661
662
663/* reads a written checkpointed toplist back into a toplist
664 returns 0 if successfully read a list,
665 1 if we found a %DONE marker at the end,
666 -1 if the file contained a syntax error,
667 -2 if given an improper toplist */
668int fstat_cpt_file_read( FstatCheckpointFile *cptf, UINT4 checksum_should, UINT4 maxbytes )
669{
670 INT4 bytes;
671 UINT4 checksum_read;
672 if ( !cptf ) {
673 LogPrintf( LOG_CRITICAL, "ERROR: FstatCheckpointFile is NULL\n" );
674 return ( -1 );
675 }
676
677 /* the only actual call here, everything else is error handling */
678 bytes = read_fstat_toplist_from_fp( cptf->list, cptf->fp, &checksum_read, maxbytes );
679
680 LogPrintf( LOG_DEBUG, "DEBUG: read_fstat_toplist_from_fp() returned %d\n", bytes );
681
682 cptf->bytes = 0;
683 cptf->checksum = 0;
684
685 if ( bytes == 0 ) {
686 LogPrintf( LOG_DEBUG, "DEBUG: found %%DONE end marker\n" );
687 return ( 1 );
688 } else if ( bytes == -2 ) {
689 LogPrintf( LOG_CRITICAL, "ERROR: invalid toplist\n" );
690 return ( bytes );
691 } else if ( bytes == -1 ) {
692 LogPrintf( LOG_CRITICAL, "ERROR: format error in toplist\n" );
693 rewind( cptf->fp );
694 clear_toplist( cptf->list );
695 return ( bytes );
696 } else if ( checksum_read != checksum_should ) {
697 LogPrintf( LOG_CRITICAL, "ERROR: checksum error in toplist %d / %d\n",
698 checksum_should, checksum_read );
699 rewind( cptf->fp );
700 clear_toplist( cptf->list );
701 return ( -1 );
702 }
703
704 if ( ftell( cptf->fp ) > bytes ) {
705 LogPrintf( LOG_DEBUG, "ERROR: File length mismatch: bytes: %u, file: %li, fixing\n",
706 bytes, ftell( cptf->fp ) );
707 fseek( cptf->fp, bytes, SEEK_SET );
708 }
709 cptf->bytes = bytes;
710 cptf->checksum = checksum_read;
711
712 if ( ( int )( cptf->bytes ) != ftell( cptf->fp ) ) {
713 LogPrintf( LOG_DEBUG, "ERROR: read: %u, file: %ld\n", cptf->bytes, ftell( cptf->fp ) );
714 }
715
716 return ( 0 );
717}
718
719
720/* compacts a checkpointed toplist, i.e. re-writes it from scratch from memory */
722{
723 INT4 bytes;
724 UINT4 checksum;
725
726 LogPrintf( LOG_NORMAL, "Compacting toplist file\n" );
727 if ( cptf->fp ) {
728 fclose( cptf->fp );
729 } else {
730 LogPrintf( LOG_CRITICAL, "ERROR: Toplist filepointer is NULL\n" );
731 }
732
733 bytes = atomic_write_fstat_toplist_to_file( cptf->list, cptf->filename, &checksum );
734 if ( bytes < 0 ) {
735 return ( bytes );
736 }
737
738 fstat_cpt_file_open( cptf );
739 fseek( cptf->fp, 0L, SEEK_END );
740 cptf->bytes = bytes;
741 cptf->checksum = checksum;
742
743 return ( bytes );
744}
745
746
747
748/* New easier checkpointing - simply dump the whole toplist (plus a counter and
749 a checksum) into a binary file.
750 The heap structure array is hard to dump because it's based on pointers, so it
751 is restored after reding the data back in by sorting the list once.
752*/
753
754/** log an I/O error, i.e. source code line no., ferror, errno and strerror, and doserrno on Windows, too */
755#ifdef _MSC_VER
756#define LOGIOERROR(mess,filename) \
757 LogPrintf(LOG_CRITICAL, "ERROR: %s %s: line:%d, doserr:%d, ferr:%d, errno:%d: %s\n",\
758 mess,filename,__LINE__,_doserrno,((fp)?(ferror(fp)):0),errno,strerror(errno))
759#else
760#define LOGIOERROR(mess,filename) \
761 LogPrintf(LOG_CRITICAL, "ERROR: %s %s: line:%d, errno:%d: %s\n",\
762 mess,filename,__LINE__,errno,strerror(errno))
763#endif
764
765/* dumps toplist to a temporary file, then renames the file to filename */
766int write_hs_checkpoint( const char *filename, toplist_t *tl, UINT4 counter, BOOLEAN do_sync )
767{
768#define TMP_EXT ".tmp"
769 char *tmpfilename;
770 FILE *fp;
771 UINT4 len;
772 UINT4 checksum;
773 static UINT4 sync_fail_counter = 0;
774
775 /* construct temporary filename */
776 len = strlen( filename ) + strlen( TMP_EXT ) + 1;
777 tmpfilename = LALCalloc( len, sizeof( char ) );
778 if ( !tmpfilename ) {
779 LogPrintf( LOG_CRITICAL, "Couldn't allocate tmpfilename\n" );
780 return ( -2 );
781 }
782 strcpy( tmpfilename, filename );
783 strcat( tmpfilename, TMP_EXT );
784
785 /* calculate checksum */
786 checksum = 0;
787 for ( len = 0; len < sizeof( tl->elems ); len++ ) {
788 checksum += *( ( ( char * ) & ( tl->elems ) ) + len );
789 }
790 for ( len = 0; len < ( tl->elems * tl->size ); len++ ) {
791 checksum += *( ( ( char * )tl->data ) + len );
792 }
793 for ( len = 0; len < sizeof( counter ); len++ ) {
794 checksum += *( ( ( char * )&counter ) + len );
795 }
796
797 /* open tempfile */
798 fp = fopen( tmpfilename, "wb" );
799 if ( !fp ) {
800 LOGIOERROR( "Couldn't open", tmpfilename );
801 return ( -1 );
802 }
803
804 /* write number of elements */
805 len = fwrite( &( tl->elems ), sizeof( tl->elems ), 1, fp );
806 if ( len != 1 ) {
807 LOGIOERROR( "Couldn't write elems to", tmpfilename );
808 LogPrintf( LOG_CRITICAL, "fwrite() returned %d, length was %d\n", len, 1 );
809 if ( fclose( fp ) ) {
810 LOGIOERROR( "In addition: couldn't close", tmpfilename );
811 }
812 return ( -1 );
813 }
814
815 /* write data */
816 len = fwrite( tl->data, tl->size, tl->elems, fp );
817 if ( len != tl->elems ) {
818 LOGIOERROR( "Couldn't write data to", tmpfilename );
819 LogPrintf( LOG_CRITICAL, "fwrite() returned %d, length was %zu\n", len, tl->elems );
820 if ( fclose( fp ) ) {
821 LOGIOERROR( "In addition: couldn't close", tmpfilename );
822 }
823 return ( -1 );
824 }
825
826 /* write counter */
827 len = fwrite( &counter, sizeof( counter ), 1, fp );
828 if ( len != 1 ) {
829 LOGIOERROR( "Couldn't write counter to", tmpfilename );
830 LogPrintf( LOG_CRITICAL, "fwrite() returned %d, length was %i\n", len, 1 );
831 if ( fclose( fp ) ) {
832 LOGIOERROR( "In addition: couldn't close", tmpfilename );
833 }
834 return ( -1 );
835 }
836
837 /* write checksum */
838 len = fwrite( &checksum, sizeof( checksum ), 1, fp );
839 if ( len != 1 ) {
840 LOGIOERROR( "Couldn't write checksum to", tmpfilename );
841 LogPrintf( LOG_CRITICAL, "fwrite() returned %d, length was %i\n", len, 1 );
842 if ( fclose( fp ) ) {
843 LOGIOERROR( "In addition: couldn't close", tmpfilename );
844 }
845 return ( -1 );
846 }
847
848 if ( do_sync && ( sync_fail_counter < SYNC_FAIL_LIMIT ) ) {
849 /* make sure the data ends up on disk */
850 if ( fsync( fileno( fp ) ) ) {
851 LOGIOERROR( "Couldn't sync", tmpfilename );
852 sync_fail_counter++;
853 if ( sync_fail_counter >= SYNC_FAIL_LIMIT ) {
854 LogPrintf( LOG_NORMAL, "WARNING: syncing disabled\n" );
855 }
856 } else {
857 sync_fail_counter = 0;
858 }
859 }
860
861 /* close tempfile */
862 if ( fclose( fp ) ) {
863 LOGIOERROR( "Couldn't close", tmpfilename );
864 return ( -1 );
865 }
866
867 /* rename to filename */
868 if ( rename( tmpfilename, filename ) ) {
869 LOGIOERROR( "Couldn't rename\n", tmpfilename );
870 return ( -1 );
871 }
872
873 /* all went well */
874 return ( 0 );
875}
876
877
878int read_hs_checkpoint( const char *filename, toplist_t *tl, UINT4 *counter )
879{
880 FILE *fp;
881 UINT4 len;
882 UINT4 checksum;
883
884 /* counter should be 0 if we couldn't read a checkpoint */
885 *counter = 0;
886
887 /* try to open file */
888 fp = fopen( filename, "rb" );
889 if ( !fp ) {
890 LogPrintf( LOG_NORMAL, "INFO: Couldn't open checkpoint %s\n", filename );
891 clear_toplist( tl );
892 return ( 1 );
893 }
894
895 /* read number of elements */
896 len = fread( &( tl->elems ), sizeof( tl->elems ), 1, fp );
897 if ( len != 1 ) {
898 LOGIOERROR( "Couldn't read elems from", filename );
899 LogPrintf( LOG_CRITICAL, "fread() returned %d, length was %d\n", len, 1 );
900 if ( fclose( fp ) ) {
901 LOGIOERROR( "In addition: couldn't close", filename );
902 }
903 return ( -1 );
904 }
905 /* sanity check */
906 if ( tl->elems > tl->length ) {
908 "Number of elements read larger than length of toplist: %zu > %zu\n",
909 tl->elems, tl->length );
910 if ( fclose( fp ) ) {
911 LOGIOERROR( "In addition: couldn't close", filename );
912 }
913 return ( -2 );
914 }
915
916 /* read data */
917 len = fread( tl->data, tl->size, tl->elems, fp );
918 if ( len != tl->elems ) {
919 LOGIOERROR( "Couldn't read data from", filename );
920 LogPrintf( LOG_CRITICAL, "fread() returned %d, length was %zu\n", len, tl->elems );
921 if ( fclose( fp ) ) {
922 LOGIOERROR( "In addition: couldn't close", filename );
923 }
924 clear_toplist( tl );
925 return ( -1 );
926 }
927
928 /* read counter */
929 len = fread( counter, sizeof( *counter ), 1, fp );
930 if ( len != 1 ) {
931 LOGIOERROR( "Couldn't read counter from", filename );
932 LogPrintf( LOG_CRITICAL, "fread() returned %d, length was %d\n", len, 1 );
933 if ( fclose( fp ) ) {
934 LOGIOERROR( "In addition: couldn't close", filename );
935 }
936 clear_toplist( tl );
937 return ( -1 );
938 }
939
940 /* read checksum */
941 len = fread( &checksum, sizeof( checksum ), 1, fp );
942 if ( len != 1 ) {
943 LOGIOERROR( "Couldn't read checksum to", filename );
944 LogPrintf( LOG_CRITICAL, "fread() returned %d, length was %d\n", len, 1 );
945 if ( fclose( fp ) ) {
946 LOGIOERROR( "In addition: couldn't close", filename );
947 }
948 clear_toplist( tl );
949 return ( -1 );
950 }
951
952 /* close file */
953 if ( fclose( fp ) ) {
954 LOGIOERROR( "Couldn't close", filename );
955 clear_toplist( tl );
956 return ( -1 );
957 }
958
959 /* verify checksum */
960 for ( len = 0; len < sizeof( tl->elems ); len++ ) {
961 checksum -= *( ( ( char * ) & ( tl->elems ) ) + len );
962 }
963 for ( len = 0; len < ( tl->elems * tl->size ); len++ ) {
964 checksum -= *( ( ( char * )tl->data ) + len );
965 }
966 for ( len = 0; len < sizeof( *counter ); len++ ) {
967 checksum -= *( ( ( char * )counter ) + len );
968 }
969 if ( checksum ) {
970 LogPrintf( LOG_CRITICAL, "Checksum error: %d\n", checksum );
971 clear_toplist( tl );
972 return ( -2 );
973 }
974
975 /* restore Heap structure by sorting */
976 for ( len = 0; len < tl->elems; len++ ) {
977 tl->heap[len] = tl->data + len * tl->size;
978 }
980
981 /* all went well */
982 LogPrintf( LOG_DEBUG, "Successfully read checkpoint\n" );
983
984 return ( 0 );
985}
986
987
988int write_hs_oputput( const char *filename, toplist_t *tl )
989{
990 /* reduce the precision of the calculated values before doing the sort to
991 the precision we will write the result with. This should ensure a sorting
992 order that looks right to the validator, too */
994 sort_fstat_toplist( tl );
995 return ( _atomic_write_fstat_toplist_to_file( tl, filename, NULL, 1 ) );
996}
int read_fstat_toplist_from_fp(toplist_t *l, FILE *fp, UINT4 *checksum, UINT4 maxbytes)
reads a (created!) toplist from an open filepointer sets the checksum if non-NULL reads maximum maxby...
Definition: FstatToplist.c:151
void sort_fstat_toplist(toplist_t *l)
sorts the toplist with an internal sorting function, used before finally writing it
Definition: FstatToplist.c:140
void free_fstat_toplist(toplist_t **l)
frees the space occupied by the toplist
Definition: FstatToplist.c:118
int fstat_cpt_file_destroy(FstatCheckpointFile **cptf)
destroys a FstatCheckpointFile
Definition: FstatToplist.c:525
int final_write_fstat_toplist_to_file(toplist_t *l, const char *filename, UINT4 *checksum)
meant for the final writing of the toplist
Definition: FstatToplist.c:456
static int fstat_smaller(const void *a, const void *b)
Definition: FstatToplist.c:97
int write_fstat_toplist_item_to_fp(FstatOutputEntry fline, FILE *fp, UINT4 *checksum)
File IO.
Definition: FstatToplist.c:303
int fstat_cpt_file_flush(FstatCheckpointFile *cptf)
flushes the checkpoint file (only useful if buffered)
Definition: FstatToplist.c:574
int fstat_cpt_file_create(FstatCheckpointFile **cptf, CHAR *filename, UINT4 bufsize, UINT4 maxsize, toplist_t *list)
creates a FstatCheckpointFile
Definition: FstatToplist.c:467
int fstat_cpt_file_compact(FstatCheckpointFile *cptf)
compact a toplist file if the length has reached maxbytes
Definition: FstatToplist.c:721
int fstat_cpt_file_open(FstatCheckpointFile *cptf)
opens a file for checkpointing the desired toplist
Definition: FstatToplist.c:545
int fstat_cpt_file_close(FstatCheckpointFile *cptf)
closes the file, reduces the precision, sorts the toplist, finally rewrites the file (sorted and comp...
Definition: FstatToplist.c:611
int write_hs_oputput(const char *filename, toplist_t *tl)
write the final output file:
Definition: FstatToplist.c:988
int fstat_cpt_file_info(FstatCheckpointFile *cptf, CHAR **filename, UINT4 *bytes, UINT4 *checksum)
returns information for checkpointing
Definition: FstatToplist.c:590
int fstat_cpt_file_read(FstatCheckpointFile *cptf, UINT4 checksum_should, UINT4 maxbytes)
reads a written checkpointed toplist back into memory
Definition: FstatToplist.c:668
#define TEMP_EXT
int read_hs_checkpoint(const char *filename, toplist_t *tl, UINT4 *counter)
tries to read a checkpoint
Definition: FstatToplist.c:878
int create_fstat_toplist(toplist_t **tl, UINT8 length)
creates a toplist with length elements, returns -1 on error (usually out of memory),...
Definition: FstatToplist.c:111
static int print_fstatline_to_str(FstatOutputEntry fline, char *buf, int buflen)
Definition: FstatToplist.c:282
int atomic_write_fstat_toplist_to_file(toplist_t *l, const char *filename, UINT4 *checksum)
writes the given toplitst to a temporary file, then renames the temporary file to filename.
Definition: FstatToplist.c:378
static void reduce_fstatline_precision(void *line)
Definition: FstatToplist.c:327
int write_fstat_toplist_to_fp(toplist_t *tl, FILE *fp, UINT4 *checksum)
Writes the toplist to an (already open) filepointer Returns the number of written charactes sets the ...
Definition: FstatToplist.c:352
static int fstat_toplist_qsort_function(const void *a, const void *b)
Definition: FstatToplist.c:73
int insert_into_fstat_toplist(toplist_t *tl, FstatOutputEntry elem)
Inserts an element in to the toplist either if there is space left or the element is larger than the ...
Definition: FstatToplist.c:129
#define TMP_EXT
int write_hs_checkpoint(const char *filename, toplist_t *tl, UINT4 counter, BOOLEAN do_sync)
new, simpler checkpointing for HierarchicalSearch
Definition: FstatToplist.c:766
static void reduce_fstat_toplist_precision(toplist_t *l)
Definition: FstatToplist.c:343
#define SYNC_FAIL_LIMIT
Definition: FstatToplist.c:64
#define LOGIOERROR(mess, filename)
log an I/O error, i.e.
Definition: FstatToplist.c:760
static int _atomic_write_fstat_toplist_to_file(toplist_t *l, const char *filename, UINT4 *checksum, int write_done)
Definition: FstatToplist.c:386
int fstat_cpt_file_add(FstatCheckpointFile *cptf, FstatOutputEntry line)
adds an item to the toplist and keeps the file consistent, i.e.
Definition: FstatToplist.c:637
int create_toplist(toplist_t **list, size_t length, size_t size, int(*smaller)(const void *, const void *))
Definition: HeapToplist.c:101
void free_toplist(toplist_t **list)
Definition: HeapToplist.c:139
void qsort_toplist(toplist_t *list, int(*compare)(const void *, const void *))
Definition: HeapToplist.c:241
void qsort_toplist_r(toplist_t *list, int(*compare)(const void *, const void *))
Definition: HeapToplist.c:249
int insert_into_toplist(toplist_t *list, void *element)
Definition: HeapToplist.c:151
void go_through_toplist(toplist_t *list, void(*handle)(void *))
Definition: HeapToplist.c:177
void clear_toplist(toplist_t *list)
Definition: HeapToplist.c:132
#define LALCalloc(m, n)
#define LALMalloc(n)
#define LALFree(p)
#define c
#define L(i, j)
#define fprintf
int l
double e
#define LAL_PI
#define LAL_TWOPI
unsigned char BOOLEAN
uint64_t UINT8
double REAL8
#define XLAL_LAST_ELEM(x)
int64_t INT8
char CHAR
uint32_t UINT4
int32_t INT4
#define LAL_REAL8_FORMAT
void LogPrintf(LogLevel_t, const char *format,...) _LAL_GCC_PRINTF_FORMAT_(2
LOG_CRITICAL
LOG_DEBUG
LOG_NORMAL
static const INT4 r
static const INT4 a
a toplist as a checkpointed file
Definition: FstatToplist.h:118
CHAR * buffer
write buffer if needed
Definition: FstatToplist.h:120
FILE * fp
FILE* currently associated.
Definition: FstatToplist.h:125
CHAR * filename
name of the toplist file
Definition: FstatToplist.h:119
UINT4 bytes
counts the bytes in the file
Definition: FstatToplist.h:122
toplist_t * list
toplist this file reflects
Definition: FstatToplist.h:126
UINT4 bufsize
buffer size if needed
Definition: FstatToplist.h:121
UINT4 checksum
keeps the checksum
Definition: FstatToplist.h:124
Type to hold the fields that will be output in unclustered output file
Definition: FstatToplist.h:32
REAL8 Alpha
Skyposition: longitude in equatorial coords, radians.
Definition: FstatToplist.h:35
REAL8 Fstat
value of 2F
Definition: FstatToplist.h:37
REAL8 Delta
skyposition: latitude
Definition: FstatToplist.h:36
REAL8 Freq
Frequency at maximum (?) of the cluster.
Definition: FstatToplist.h:33
REAL8 f1dot
spindown value f1dot = df/dt
Definition: FstatToplist.h:34
char ** heap
Definition: HeapToplist.h:40
size_t length
Definition: HeapToplist.h:36
size_t elems
Definition: HeapToplist.h:37
size_t size
Definition: HeapToplist.h:38
char * data
Definition: HeapToplist.h:39