Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
CrossCorrToplist.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2010 Christine Chung (based closely on CrossCorrToplist.c)
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#include <stdio.h>
24#ifdef HAVE_UNISTD_H
25#include <unistd.h>
26#endif
27
28#include <lal/StringInput.h>
29#include <lal/LALConstants.h>
30#include <lal/LALStdio.h>
31#include <lal/LogPrintf.h>
32#include <lal/HeapToplist.h>
33
34#include "CrossCorrToplist.h"
35
36/* Windows specifics */
37#ifdef _WIN32
38#include <io.h>
39
40/* errno */
41extern int errno;
42extern int _doserrno;
43
44/* snprintf */
45#define snprintf _snprintf
46
47/* fsync */
48#define fsync _commit
49#define fileno _fileno
50
51#else /* WIN32 */
52
53/* errno */
54#include <errno.h>
55
56#endif /* WIN32 */
57
58
59
60
61
62/* define min macro if not already defined */
63#ifndef min
64#define min(a,b) ((a)<(b)?(a):(b))
65#endif
66
67/* maximum number of succesive failures before switching off syncing */
68#define SYNC_FAIL_LIMIT 5
69
70/* local prototypes */
72static int _atomic_write_crossCorr_toplist_to_file( toplist_t *l, const char *filename, UINT4 *checksum, int write_done );
73static int _atomic_write_crossCorrBinary_toplist_to_file( toplist_t *l, const char *filename, UINT4 *checksum, int write_done );
74
75static int print_crossCorrline_to_str( CrossCorrOutputEntry fline, char *buf, int buflen );
76static int print_crossCorrBinaryline_to_str( CrossCorrBinaryOutputEntry fline, char *buf, int buflen );
77
78
79/* ordering function for sorting the list */
80static int crossCorr_toplist_qsort_function( const void *a, const void *b )
81{
82 if ( ( ( const CrossCorrOutputEntry * )a )->Freq < ( ( const CrossCorrOutputEntry * )b )->Freq ) {
83 return -1;
84 } else if ( ( ( const CrossCorrOutputEntry * )a )->Freq > ( ( const CrossCorrOutputEntry * )b )->Freq ) {
85 return 1;
86 }
87 if ( ( ( const CrossCorrOutputEntry * )a )->Q1 < ( ( const CrossCorrOutputEntry * )b )->Q1 ) {
88 return -1;
89 } else if ( ( ( const CrossCorrOutputEntry * )a )->Q1 > ( ( const CrossCorrOutputEntry * )b )->Q1 ) {
90 return 1;
91 }
92 if ( ( ( const CrossCorrOutputEntry * )a )->Q2 < ( ( const CrossCorrOutputEntry * )b )->Q2 ) {
93 return -1;
94 } else if ( ( ( const CrossCorrOutputEntry * )a )->Q2 > ( ( const CrossCorrOutputEntry * )b )->Q2 ) {
95 return 1;
96 }
97 if ( ( ( const CrossCorrOutputEntry * )a )->BrakingIndex < ( ( const CrossCorrOutputEntry * )b )->BrakingIndex ) {
98 return -1;
99 } else if ( ( ( const CrossCorrOutputEntry * )a )->BrakingIndex > ( ( const CrossCorrOutputEntry * )b )->BrakingIndex ) {
100 return 1;
101 } else if ( ( ( const CrossCorrOutputEntry * )a )->Alpha < ( ( const CrossCorrOutputEntry * )b )->Alpha ) {
102 return -1;
103 } else if ( ( ( const CrossCorrOutputEntry * )a )->Alpha > ( ( const CrossCorrOutputEntry * )b )->Alpha ) {
104 return 1;
105 } else if ( ( ( const CrossCorrOutputEntry * )a )->Delta < ( ( const CrossCorrOutputEntry * )b )->Delta ) {
106 return -1;
107 } else if ( ( ( const CrossCorrOutputEntry * )a )->Delta > ( ( const CrossCorrOutputEntry * )b )->Delta ) {
108 return 1;
109 } else {
110 return 0;
111 }
112}
113
114
115/* ordering function for sorting the list */
116static int crossCorrBinary_toplist_qsort_function( const void *a, const void *b )
117{
118 if ( ( ( const CrossCorrBinaryOutputEntry * )a )->freq < ( ( const CrossCorrBinaryOutputEntry * )b )->freq ) {
119 return -1;
120 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->freq > ( ( const CrossCorrBinaryOutputEntry * )b )->freq ) {
121 return 1;
122 }
123 if ( ( ( const CrossCorrBinaryOutputEntry * )a )->tp < ( ( const CrossCorrBinaryOutputEntry * )b )->tp ) {
124 return -1;
125 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->tp > ( ( const CrossCorrBinaryOutputEntry * )b )->tp ) {
126 return 1;
127 }
128 if ( ( ( const CrossCorrBinaryOutputEntry * )a )->argp < ( ( const CrossCorrBinaryOutputEntry * )b )->argp ) {
129 return -1;
130 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->argp > ( ( const CrossCorrBinaryOutputEntry * )b )->argp ) {
131 return 1;
132 }
133 if ( ( ( const CrossCorrBinaryOutputEntry * )a )->asini < ( ( const CrossCorrBinaryOutputEntry * )b )->asini ) {
134 return -1;
135 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->asini > ( ( const CrossCorrBinaryOutputEntry * )b )->asini ) {
136 return 1;
137 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->ecc < ( ( const CrossCorrBinaryOutputEntry * )b )->ecc ) {
138 return -1;
139 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->ecc > ( ( const CrossCorrBinaryOutputEntry * )b )->ecc ) {
140 return 1;
141 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->period < ( ( const CrossCorrBinaryOutputEntry * )b )->period ) {
142 return -1;
143 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->period > ( ( const CrossCorrBinaryOutputEntry * )b )->period ) {
144 return 1;
145 } else {
146 return 0;
147 }
148}
149
150
151/* ordering function defining the toplist */
152static int crossCorr_smaller( const void *a, const void *b )
153{
154 if ( ( ( const CrossCorrOutputEntry * )a )->Rho < ( ( const CrossCorrOutputEntry * )b )->Rho ) {
155 return ( 1 );
156 } else if ( ( ( const CrossCorrOutputEntry * )a )->Rho > ( ( const CrossCorrOutputEntry * )b )->Rho ) {
157 return ( -1 );
158 } else {
159 return ( crossCorr_toplist_qsort_function( a, b ) );
160 }
161}
162
163
164static int crossCorrBinary_smaller( const void *a, const void *b )
165{
166 if ( ( ( const CrossCorrBinaryOutputEntry * )a )->rho < ( ( const CrossCorrBinaryOutputEntry * )b )->rho ) {
167 return ( 1 );
168 } else if ( ( ( const CrossCorrBinaryOutputEntry * )a )->rho > ( ( const CrossCorrBinaryOutputEntry * )b )->rho ) {
169 return ( -1 );
170 } else {
172 }
173}
174
175
176
177/* creates a toplist with length elements,
178 returns -1 on error (usually out of memory), else 0 */
180{
181 return ( create_toplist( tl, length, sizeof( CrossCorrOutputEntry ), crossCorr_smaller ) );
182}
183
185{
186 return ( create_toplist( tl, length, sizeof( CrossCorrBinaryOutputEntry ), crossCorrBinary_smaller ) );
187}
188
189
190/* frees the space occupied by the toplist */
192{
193 free_toplist( l );
194}
195
196
197/* Inserts an element in to the toplist either if there is space left
198 or the element is larger than the smallest element in the toplist.
199 In the latter case, remove the smallest element from the toplist and
200 look for the now smallest one.
201 Returns 1 if the element was actually inserted, 0 if not. */
203{
204 if ( !tl ) {
205 return 0;
206 } else {
207 return ( insert_into_toplist( tl, ( void * )&elem ) );
208 }
209}
210
211
213{
214 if ( !tl ) {
215 return 0;
216 } else {
217 return ( insert_into_toplist( tl, ( void * )&elem ) );
218 }
219}
220
221
222
223
224/* (q)sort the toplist according to the sorting function. */
226{
228}
229
230
232{
234}
235
236/* /\* reads a (created!) toplist from an open filepointer */
237/* returns the number of bytes read, */
238/* 0 if we found a %DONE marker at the end, */
239/* -1 if the file contained a syntax error, */
240/* -2 if given an improper toplist *\/ */
241/* int read_crossCorr_toplist_from_fp(toplist_t*l, FILE*fp, UINT4*checksum, UINT4 maxbytes) { */
242/* CHAR line[256]; /\* buffer for reading a line *\/ */
243/* UINT4 items, lines; /\* number of items read from a line, linecounter *\/ */
244/* UINT4 len, chars = 0; /\* length of a line, total characters read from the file *\/ */
245/* UINT4 i; /\* loop counter *\/ */
246/* CHAR lastchar; /\* last character of a line read, should be newline *\/ */
247/* CrossCorrOutputEntry CrossCorrLine; */
248/* REAL8 epsilon=1e-5; */
249
250/* /\* basic check that the list argument is valid *\/ */
251/* if(!l) */
252/* return -2; */
253
254/* /\* make sure the line buffer is terminated correctly *\/ */
255/* XLAL_LAST_ELEM(line)='\0'; */
256
257/* /\* init the checksum if given *\/ */
258/* if(checksum) */
259/* *checksum = 0; */
260
261/* /\* set maxbytes to maximum if zero *\/ */
262/* if (maxbytes == 0) */
263/* maxbytes--; */
264
265/* lines=1; */
266/* while(fgets(line,sizeof(line)-1, fp)) { */
267
268/* if (!strncmp(line,"%DONE\n",strlen("%DONE\n"))) { */
269/* LogPrintf(LOG_NORMAL,"WARNING: found end marker - the task was already finished\n"); */
270/* return(0); */
271/* } */
272
273/* len = strlen(line); */
274/* chars += len; */
275
276/* if (len==0) { */
277/* LogPrintf (LOG_CRITICAL, "Line %d is empty.\n", lines); */
278/* return -1; */
279/* } */
280/* else if (line[len-1] != '\n') { */
281/* LogPrintf (LOG_CRITICAL, */
282/* "Line %d is too long or has no NEWLINE. First %d chars are:\n'%s'\n", */
283/* lines,sizeof(line)-1, line); */
284/* return -1; */
285/* } */
286
287/* items = sscanf (line, */
288/* "%" LAL_REAL8_FORMAT */
289/* " %" LAL_REAL8_FORMAT */
290/* " %" LAL_REAL8_FORMAT */
291/* " %" LAL_REAL8_FORMAT */
292/* " %" LAL_REAL8_FORMAT */
293/* " %" LAL_REAL8_FORMAT */
294/* " %" LAL_REAL8_FORMAT */
295/* " %" LAL_REAL8_FORMAT "%c", */
296/* &CrossCorrLine.Freq, */
297/* &CrossCorrLine.Q1, */
298/* &CrossCorrLine.Q2, */
299/* &CrossCorrLine.BrakingIndex, */
300/* &CrossCorrLine.Alpha, */
301/* &CrossCorrLine.Delta, */
302/* &CrossCorrLine.Rho, */
303/* &lastchar); */
304
305/* /\* check the values scanned *\/ */
306/* if ( */
307/* items != 7 || */
308
309/* !isfinite(CrossCorrLine.Freq) || */
310/* !isfinite(CrossCorrLine.Q1) || */
311/* !isfinite(CrossCorrLine.Q2) || */
312/* !isfinite(CrossCorrLine.BrakingIndex) || */
313/* !isfinite(CrossCorrLine.Alpha) || */
314/* !isfinite(CrossCorrLine.Delta) || */
315/* !isfinite(CrossCorrLine.Rho) || */
316
317/* CrossCorrLine.Freq < 0.0 || */
318/* CrossCorrLine.Alpha < 0.0 - epsilon || */
319/* CrossCorrLine.Alpha > LAL_TWOPI + epsilon || */
320/* CrossCorrLine.Delta < -0.5*LAL_PI - epsilon || */
321/* CrossCorrLine.Delta > 0.5*LAL_PI + epsilon || */
322
323/* lastchar != '\n' */
324/* ) { */
325/* LogPrintf (LOG_CRITICAL, */
326/* "Line %d has invalid values.\n" */
327/* "First %d chars are:\n" */
328/* "%s\n" */
329/* "All fields should be finite\n" */
330/* "1st field should be positive.\n" */
331/* "2nd field should lie between 0 and %1.15f.\n" */
332/* "3rd field should lie between %1.15f and %1.15f.\n", */
333/* lines, sizeof(line)-1, line, */
334/* (double)LAL_TWOPI, (double)-LAL_PI/2.0, (double)LAL_PI/2.0); */
335/* return -1; */
336/* } */
337
338/* if (checksum) */
339/* for(i=0;i<len;i++) */
340/* *checksum += line[i]; */
341
342/* insert_into_toplist(l, &CrossCorrLine); */
343/* lines++; */
344
345/* /\* NOTE: it *CAN* happen (and on Linux it DOES) that the fully buffered CrossCorr stream */
346/* * gets written to the File at program termination. */
347/* * This does not seem to happen on Mac though, most likely due to different */
348/* * exit()-calls used (_exit() vs exit() etc.....) */
349/* * */
350/* * The bottom-line is: the File-contents CAN legally extend beyond maxbytes, */
351/* * which is why we'll ensure here that we don't actually read more than */
352/* * maxbytes. */
353/* *\/ */
354/* if ( chars == maxbytes ) */
355/* { */
356/* LogPrintf (LOG_DEBUG, "Read exactly %d == maxbytes from CrossCorr-file, that's enough.\n", */
357/* chars); */
358/* break; */
359/* } */
360/* /\* however, if we've read more than maxbytes, something is gone wrong *\/ */
361/* if ( chars > maxbytes ) */
362/* { */
363/* LogPrintf (LOG_CRITICAL, "Read %d bytes > maxbytes %d from CrossCorr-file ... corrupted.\n", */
364/* chars, maxbytes ); */
365/* return -1; */
366/* } */
367
368/* } /\* while (fgets() ) *\/ */
369
370/* return chars; */
371
372/* } /\* read_crossCorr_toplist_from_fp() *\/ */
373
374
375/* int read_crossCorrBinary_toplist_from_fp(toplist_t*l, FILE*fp, UINT4*checksum, UINT4 maxbytes) { */
376/* CHAR line[256]; /\* buffer for reading a line *\/ */
377/* UINT4 items, lines; /\* number of items read from a line, linecounter *\/ */
378/* UINT4 len, chars = 0; /\* length of a line, total characters read from the file *\/ */
379/* UINT4 i; /\* loop counter *\/ */
380/* CHAR lastchar; /\* last character of a line read, should be newline *\/ */
381/* CrossCorrBinaryOutputEntry CrossCorrLine; */
382/* REAL8 epsilon=1e-5; */
383
384/* /\* basic check that the list argument is valid *\/ */
385/* if(!l) */
386/* return -2; */
387
388/* /\* make sure the line buffer is terminated correctly *\/ */
389/* XLAL_LAST_ELEM(line)='\0'; */
390
391/* /\* init the checksum if given *\/ */
392/* if(checksum) */
393/* *checksum = 0; */
394
395/* /\* set maxbytes to maximum if zero *\/ */
396/* if (maxbytes == 0) */
397/* maxbytes--; */
398
399/* lines=1; */
400/* while(fgets(line,sizeof(line)-1, fp)) { */
401
402/* if (!strncmp(line,"%DONE\n",strlen("%DONE\n"))) { */
403/* LogPrintf(LOG_NORMAL,"WARNING: found end marker - the task was already finished\n"); */
404/* return(0); */
405/* } */
406
407/* len = strlen(line); */
408/* chars += len; */
409
410/* if (len==0) { */
411/* LogPrintf (LOG_CRITICAL, "Line %d is empty.\n", lines); */
412/* return -1; */
413/* } */
414/* else if (line[len-1] != '\n') { */
415/* LogPrintf (LOG_CRITICAL, */
416/* "Line %d is too long or has no NEWLINE. First %d chars are:\n'%s'\n", */
417/* lines,sizeof(line)-1, line); */
418/* return -1; */
419/* } */
420
421/* items = sscanf (line, */
422/* "%" LAL_REAL8_FORMAT */
423/* " %" LAL_REAL8_FORMAT */
424/* " %" LAL_REAL8_FORMAT */
425/* " %" LAL_REAL8_FORMAT */
426/* " %" LAL_REAL8_FORMAT */
427/* " %" LAL_REAL8_FORMAT "%c", */
428/* &CrossCorrBinaryLine.freq, */
429/* &CrossCorrBinaryLine.tp, */
430/* &CrossCorrBinaryLine.argp, */
431/* &CrossCorrBinaryLine.asini, */
432/* &CrossCorrBinaryLine.ecc, */
433/* &CrossCorrBinaryLine.period, */
434/* &CrossCorrBinaryLine.rho, */
435/* &lastchar); */
436
437/* /\* check the values scanned *\/ */
438/* if ( */
439/* items != 7 || */
440
441/* !isfinite(CrossCorrBinaryLine.freq) || */
442/* !isfinite(CrossCorrBinaryLine.tp) || */
443/* !isfinite(CrossCorrBinaryLine.argp) || */
444/* !isfinite(CrossCorrBinaryLine.asini) || */
445/* !isfinite(CrossCorrBinaryLine.ecc) || */
446/* !isfinite(CrossCorrBinaryLine.period) || */
447/* !isfinite(CrossCorrBinaryLine.rho) || */
448
449/* CrossCorrBinaryLine.Freq < 0.0 || */
450
451/* lastchar != '\n' */
452/* ) { */
453/* LogPrintf (LOG_CRITICAL, "Line %d has invalid values.\n",lines); */
454/* return -1; */
455/* } */
456
457/* if (checksum) */
458/* for(i=0;i<len;i++) */
459/* *checksum += line[i]; */
460
461/* insert_into_toplist(l, &CrossCorrBinaryLine); */
462/* lines++; */
463
464/* /\* NOTE: it *CAN* happen (and on Linux it DOES) that the fully buffered CrossCorr stream */
465/* * gets written to the File at program termination. */
466/* * This does not seem to happen on Mac though, most likely due to different */
467/* * exit()-calls used (_exit() vs exit() etc.....) */
468/* * */
469/* * The bottom-line is: the File-contents CAN legally extend beyond maxbytes, */
470/* * which is why we'll ensure here that we don't actually read more than */
471/* * maxbytes. */
472/* *\/ */
473/* if ( chars == maxbytes ) */
474/* { */
475/* LogPrintf (LOG_DEBUG, "Read exactly %d == maxbytes from CrossCorr-file, that's enough.\n", */
476/* chars); */
477/* break; */
478/* } */
479/* /\* however, if we've read more than maxbytes, something is gone wrong *\/ */
480/* if ( chars > maxbytes ) */
481/* { */
482/* LogPrintf (LOG_CRITICAL, "Read %d bytes > maxbytes %d from CrossCorr-file ... corrupted.\n", */
483/* chars, maxbytes ); */
484/* return -1; */
485/* } */
486
487/* } /\* while (fgets() ) *\/ */
488
489/* return chars; */
490
491/* } /\* read_crossCorr_toplist_from_fp() *\/ */
492
493
494
495
496/* Prints a Toplist line to a string buffer.
497 Separate function to assure consistency of output and reduced precision for sorting */
498static int print_crossCorrline_to_str( CrossCorrOutputEntry fline, char *buf, int buflen )
499{
500 return ( snprintf( buf, buflen,
501 /* output precision: choose by following (generous!) significant-digit constraints:
502 * Freq, Q1, Q2:1e-13
503 * BrakingIndex: 1e-5 (?)
504 * Alpha,Delta:1e-7
505 * Rho:1e-7
506 */
507 "%.13g %.13g %.13g %.5g %.7g %.7g %.7g\n",
508 fline.Freq,
509 fline.Q1,
510 fline.Q2,
511 fline.BrakingIndex,
512 fline.Alpha,
513 fline.Delta,
514 fline.Rho ) );
515}
516
517
518static int print_crossCorrBinaryline_to_str( CrossCorrBinaryOutputEntry fline, char *buf, int buflen )
519{
520 return ( snprintf( buf, buflen,
521 /* output precision: choose to 10 for no real reason -- FIXME:
522 */
523 "%.10f %.10f %.10g %.10f %.10g %.5f %.10g %.10g %.10g\n",
524 fline.freq,
525 fline.tp,
526 fline.argp,
527 fline.asini,
528 fline.ecc,
529 fline.period,
530 fline.estSens,
531 fline.evSquared,
532 fline.rho ) );
533}
534
535
536/* writes an CrossCorrOutputEntry line to an open filepointer.
537 Returns the number of chars written, -1 if in error
538 Updates checksum if given */
540{
541 char linebuf[256];
542 UINT4 i;
543
544 UINT4 length = print_crossCorrline_to_str( fline, linebuf, sizeof( linebuf ) - 1 );
545
546 if ( length > sizeof( linebuf ) - 1 ) {
547 return -1;
548 }
549
550 if ( checksum )
551 for ( i = 0; i < length; i++ ) {
552 *checksum += linebuf[i];
553 }
554
555 XLAL_LAST_ELEM( linebuf ) = '\0';
556
557 return ( fprintf( fp, "%s", linebuf ) );
558}
559
560
562{
563 char linebuf[256];
564 UINT4 i;
565
566 UINT4 length = print_crossCorrBinaryline_to_str( fline, linebuf, sizeof( linebuf ) - 1 );
567
568 if ( length > sizeof( linebuf ) - 1 ) {
569 return -1;
570 }
571
572 if ( checksum )
573 for ( i = 0; i < length; i++ ) {
574 *checksum += linebuf[i];
575 }
576
577 XLAL_LAST_ELEM( linebuf ) = '\0';
578
579 return ( fprintf( fp, "%s", linebuf ) );
580}
581
582/* Reduces the precision of all elements in the toplist which influence the sorting order.
583 To be called before sorting and finally writing out the list */
585{
586 char linebuf[256];
587 print_crossCorrline_to_str( ( *( CrossCorrOutputEntry * )line ), linebuf, sizeof( linebuf ) );
588 sscanf( linebuf,
595 "%*s\n",
596 &( ( *( CrossCorrOutputEntry * )line ).Freq ),
597 &( ( *( CrossCorrOutputEntry * )line ).Q1 ),
598 &( ( *( CrossCorrOutputEntry * )line ).Q2 ),
599 &( ( *( CrossCorrOutputEntry * )line ).BrakingIndex ),
600 &( ( *( CrossCorrOutputEntry * )line ).Alpha ),
601 &( ( *( CrossCorrOutputEntry * )line ).Delta ) );
602}
603
605{
606 char linebuf[256];
607 print_crossCorrBinaryline_to_str( ( *( CrossCorrBinaryOutputEntry * )line ), linebuf, sizeof( linebuf ) );
608 sscanf( linebuf,
615 "%*s\n",
616 &( ( *( CrossCorrBinaryOutputEntry * )line ).freq ),
617 &( ( *( CrossCorrBinaryOutputEntry * )line ).tp ),
618 &( ( *( CrossCorrBinaryOutputEntry * )line ).argp ),
619 &( ( *( CrossCorrBinaryOutputEntry * )line ).asini ),
620 &( ( *( CrossCorrBinaryOutputEntry * )line ).ecc ),
621 &( ( *( CrossCorrBinaryOutputEntry * )line ).period ) );
622}
623
624
626{
628}
629
630
632{
634}
635
636
637/* Writes the toplist to an (already open) filepointer
638 Returns the number of written charactes
639 Returns something <0 on error */
641{
642 UINT8 c = 0, i;
643 INT8 r;
644 if ( checksum ) {
645 *checksum = 0;
646 }
647 for ( i = 0; i < tl->elems; i++ )
648 if ( ( r = write_crossCorr_toplist_item_to_fp( *( ( CrossCorrOutputEntry * )( void * )( tl->heap[i] ) ), fp, checksum ) ) < 0 ) {
649 LogPrintf( LOG_CRITICAL, "Failed to write toplistitem to output fp: %d: %s\n",
650 errno, strerror( errno ) );
651#ifdef _MSC_VER
652 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
653#endif
654 return ( r );
655 } else {
656 c += r;
657 }
658 return ( c );
659}
660
661
663{
664 UINT8 c = 0, i;
665 INT8 r;
666 if ( checksum ) {
667 *checksum = 0;
668 }
669 for ( i = 0; i < tl->elems; i++ )
670 if ( ( r = write_crossCorrBinary_toplist_item_to_fp( *( ( CrossCorrBinaryOutputEntry * )( void * )( tl->heap[i] ) ), fp, checksum ) ) < 0 ) {
671 LogPrintf( LOG_CRITICAL, "Failed to write toplistitem to output fp: %d: %s\n",
672 errno, strerror( errno ) );
673#ifdef _MSC_VER
674 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
675#endif
676 return ( r );
677 } else {
678 c += r;
679 }
680 return ( c );
681}
682
683
684/* writes the given toplitst to a temporary file, then renames the temporary file to filename.
685 The name of the temporary file is derived from the filename by appending ".tmp". Returns the
686 number of chars written or -1 if the temp file could not be opened.
687 This just calls _atomic_write_crossCorr_toplist_to_file() telling it not to write a %DONE marker*/
689{
690 return ( _atomic_write_crossCorr_toplist_to_file( l, filename, checksum, 0 ) );
691}
692
694{
695 return ( _atomic_write_crossCorrBinary_toplist_to_file( l, filename, checksum, 0 ) );
696}
697
698/* function that does the actual work of atomic_write_crossCorr_toplist_to_file(),
699 appending a %DONE marker if specified (not when called from atomic_write_crossCorr_toplist_to_file().
700 NOTE that the checksum will be a little wrong when %DOME is appended, as this line is not counted */
701static int _atomic_write_crossCorr_toplist_to_file( toplist_t *l, const char *filename, UINT4 *checksum, int write_done )
702{
703 char *tempname;
704 INT4 length;
705 FILE *fpnew;
706 UINT4 s;
707
708#define TEMP_EXT ".tmp"
709 s = strlen( filename ) + strlen( TEMP_EXT ) + 1;
710 tempname = ( char * )malloc( s );
711 if ( !tempname ) {
712 LogPrintf( LOG_CRITICAL, "Could not allocate new filename\n" );
713 return ( -1 );
714 }
715 strcpy( tempname, filename );
716 strcat( tempname, TEMP_EXT );
717
718 fpnew = fopen( tempname, "wb" );
719 if ( !fpnew ) {
720 LogPrintf( LOG_CRITICAL, "Failed to open temp CrossCorr file \"%s\" for writing: %d: %s\n",
721 tempname, errno, strerror( errno ) );
722#ifdef _MSC_VER
723 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
724#endif
725 free( tempname );
726 return -1;
727 }
728 length = write_crossCorr_toplist_to_fp( l, fpnew, checksum );
729
730 if ( ( write_done ) && ( length >= 0 ) ) {
731 int ret;
732 ret = fprintf( fpnew, "%%DONE\n" );
733 if ( ret < 0 ) {
734 length = ret;
735 } else {
736 length += ret;
737 }
738 }
739
740 fclose( fpnew );
741
742 if ( length < 0 ) {
743 LogPrintf( LOG_CRITICAL, "Failed to write temp CrossCorr file \"%s\": %d: %s\n",
744 tempname, errno, strerror( errno ) );
745#ifdef _MSC_VER
746 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
747#endif
748 free( tempname );
749 return ( length );
750 }
751
752 if ( rename( tempname, filename ) ) {
753 LogPrintf( LOG_CRITICAL, "Failed to rename CrossCorr file to \"%s\": %d: %s\n",
754 filename, errno, strerror( errno ) );
755#ifdef _MSC_VER
756 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
757#endif
758 free( tempname );
759 return -1;
760 }
761
762 free( tempname );
763 return length;
764}
765
766
767static int _atomic_write_crossCorrBinary_toplist_to_file( toplist_t *l, const char *filename, UINT4 *checksum, int write_done )
768{
769 char *tempname;
770 INT4 length;
771 FILE *fpnew;
772 UINT4 s;
773
774#define TEMP_EXT ".tmp"
775 s = strlen( filename ) + strlen( TEMP_EXT ) + 1;
776 tempname = ( char * )malloc( s );
777 if ( !tempname ) {
778 LogPrintf( LOG_CRITICAL, "Could not allocate new filename\n" );
779 return ( -1 );
780 }
781 strcpy( tempname, filename );
782 strcat( tempname, TEMP_EXT );
783
784 fpnew = fopen( tempname, "wb" );
785 if ( !fpnew ) {
786 LogPrintf( LOG_CRITICAL, "Failed to open temp CrossCorr file \"%s\" for writing: %d: %s\n",
787 tempname, errno, strerror( errno ) );
788#ifdef _MSC_VER
789 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
790#endif
791 free( tempname );
792 return -1;
793 }
794 length = write_crossCorrBinary_toplist_to_fp( l, fpnew, checksum );
795
796 if ( ( write_done ) && ( length >= 0 ) ) {
797 int ret;
798 ret = fprintf( fpnew, "%%DONE\n" );
799 if ( ret < 0 ) {
800 length = ret;
801 } else {
802 length += ret;
803 }
804 }
805
806 fclose( fpnew );
807
808 if ( length < 0 ) {
809 LogPrintf( LOG_CRITICAL, "Failed to write temp CrossCorr file \"%s\": %d: %s\n",
810 tempname, errno, strerror( errno ) );
811#ifdef _MSC_VER
812 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
813#endif
814 free( tempname );
815 return ( length );
816 }
817
818 if ( rename( tempname, filename ) ) {
819 LogPrintf( LOG_CRITICAL, "Failed to rename CrossCorr file to \"%s\": %d: %s\n",
820 filename, errno, strerror( errno ) );
821#ifdef _MSC_VER
822 LogPrintf( LOG_CRITICAL, "Windows system call returned: %d\n", _doserrno );
823#endif
824 free( tempname );
825 return -1;
826 }
827
828 free( tempname );
829 return length;
830}
831
832
833
834/* meant for the final writing of the toplist
835 - reduces toplist precision
836 - sorts the toplist
837 - then calls atomic_write_crossCorr_toplist_to_file() */
839{
842 return ( atomic_write_crossCorr_toplist_to_file( l, filename, checksum ) );
843}
844
845
847{
851}
852
853
854/* New easier checkpointing - simply dump the whole toplist (plus a counter and
855 a checksum) into a binary file.
856 The heap structure array is hard to dump because it's based on pointers, so it
857 is restored after reding the data back in by sorting the list once.
858*/
859
860/** log an I/O error, i.e. source code line no., ferror, errno and strerror, and doserrno on Windows, too */
861#ifndef __func__
862#ifdef __FUNCTION__
863#define __func__ __FUNCTION__
864#else
865#define __func__ ""
866#endif
867#endif
868
869#ifdef _WIN32
870#define LOGIOERROR(mess,filename) \
871 LogPrintf(LOG_CRITICAL, "ERROR: %s %s: %s (%s:%d): doserr:%d, errno:%d: %s\n",\
872 mess,filename,__func__,__FILE__,__LINE__,_doserrno,errno,strerror(errno))
873#else
874#define LOGIOERROR(mess,filename) \
875 LogPrintf(LOG_CRITICAL, "ERROR: %s %s: %s (%s:%d): errno:%d: %s\n",\
876 mess,filename,__func__,__FILE__,__LINE__,errno,strerror(errno))
877#endif
878
879/* dumps toplist to a temporary file, then renames the file to filename */
880int write_cc_checkpoint( const char *filename, toplist_t *tl, UINT4 counter, BOOLEAN do_sync )
881{
882#define TMP_EXT ".tmp"
883 char *tmpfilename;
884 FILE *fp;
885 UINT4 len;
886 UINT4 checksum;
887 static UINT4 sync_fail_counter = 0;
888
889 /* construct temporary filename */
890 len = strlen( filename ) + strlen( TMP_EXT ) + 1;
891 tmpfilename = LALCalloc( len, sizeof( char ) );
892 if ( !tmpfilename ) {
893 LogPrintf( LOG_CRITICAL, "Couldn't allocate tmpfilename\n" );
894 return ( -2 );
895 }
896 strcpy( tmpfilename, filename );
897 strcat( tmpfilename, TMP_EXT );
898
899 /* calculate checksum */
900 checksum = 0;
901 for ( len = 0; len < sizeof( tl->elems ); len++ ) {
902 checksum += *( ( ( char * ) & ( tl->elems ) ) + len );
903 }
904 for ( len = 0; len < ( tl->elems * tl->size ); len++ ) {
905 checksum += *( ( ( char * )tl->data ) + len );
906 }
907 for ( len = 0; len < sizeof( counter ); len++ ) {
908 checksum += *( ( ( char * )&counter ) + len );
909 }
910
911 /* open tempfile */
912 fp = fopen( tmpfilename, "wb" );
913 if ( !fp ) {
914 LOGIOERROR( "Couldn't open", tmpfilename );
915 return ( -1 );
916 }
917
918 /* write number of elements */
919 len = fwrite( &( tl->elems ), sizeof( tl->elems ), 1, fp );
920 if ( len != 1 ) {
921 LOGIOERROR( "Couldn't write elems to", tmpfilename );
922 LogPrintf( LOG_CRITICAL, "fwrite() returned %d, length was %d\n", len, 1 );
923 if ( fclose( fp ) ) {
924 LOGIOERROR( "In addition: couldn't close", tmpfilename );
925 }
926 return ( -1 );
927 }
928
929 /* write data */
930 len = fwrite( tl->data, tl->size, tl->elems, fp );
931 if ( len != tl->elems ) {
932 LOGIOERROR( "Couldn't write data to", tmpfilename );
933 LogPrintf( LOG_CRITICAL, "fwrite() returned %d, length was %zu\n", len, tl->elems );
934 if ( fclose( fp ) ) {
935 LOGIOERROR( "In addition: couldn't close", tmpfilename );
936 }
937 return ( -1 );
938 }
939
940 /* write counter */
941 len = fwrite( &counter, sizeof( counter ), 1, fp );
942 if ( len != 1 ) {
943 LOGIOERROR( "Couldn't write counter to", tmpfilename );
944 LogPrintf( LOG_CRITICAL, "fwrite() returned %d, length was %d\n", len, 1 );
945 if ( fclose( fp ) ) {
946 LOGIOERROR( "In addition: couldn't close", tmpfilename );
947 }
948 return ( -1 );
949 }
950
951 /* write checksum */
952 len = fwrite( &checksum, sizeof( checksum ), 1, fp );
953 if ( len != 1 ) {
954 LOGIOERROR( "Couldn't write checksum to", tmpfilename );
955 LogPrintf( LOG_CRITICAL, "fwrite() returned %d, length was %d\n", len, 1 );
956 if ( fclose( fp ) ) {
957 LOGIOERROR( "In addition: couldn't close", tmpfilename );
958 }
959 return ( -1 );
960 }
961
962 if ( do_sync && ( sync_fail_counter < SYNC_FAIL_LIMIT ) ) {
963 /* make sure the data ends up on disk */
964 if ( fsync( fileno( fp ) ) ) {
965 LOGIOERROR( "Couldn't sync", tmpfilename );
966 sync_fail_counter++;
967 if ( sync_fail_counter >= SYNC_FAIL_LIMIT ) {
968 LogPrintf( LOG_NORMAL, "WARNING: syncing disabled\n" );
969 }
970 } else {
971 sync_fail_counter = 0;
972 }
973 }
974
975 /* close tempfile */
976 if ( fclose( fp ) ) {
977 LOGIOERROR( "Couldn't close", tmpfilename );
978 return ( -1 );
979 }
980
981 /* rename to filename */
982 if ( rename( tmpfilename, filename ) ) {
983 LOGIOERROR( "Couldn't rename\n", tmpfilename );
984 return ( -1 );
985 }
986
987 /* all went well */
988 return ( 0 );
989}
990
991
992int read_cc_checkpoint( const char *filename, toplist_t *tl, UINT4 *counter )
993{
994 FILE *fp;
995 UINT4 len;
996 UINT4 checksum;
997
998 /* counter should be 0 if we couldn't read a checkpoint */
999 *counter = 0;
1000
1001 /* try to open file */
1002 fp = fopen( filename, "rb" );
1003 if ( !fp ) {
1004 if ( errno == ENOENT ) {
1005 LogPrintf( LOG_NORMAL, "INFO: No checkpoint %s found - starting from scratch\n", filename );
1006 clear_toplist( tl );
1007 return ( 1 );
1008 } else {
1009 LOGIOERROR( "Checkpoint found but couldn't open", filename );
1010 clear_toplist( tl );
1011 return ( -1 );
1012 }
1013 }
1014
1015 /* read number of elements */
1016 len = fread( &( tl->elems ), sizeof( tl->elems ), 1, fp );
1017 if ( len != 1 ) {
1018 LOGIOERROR( "Couldn't read elems from", filename );
1019 LogPrintf( LOG_CRITICAL, "fread() returned %d, length was %d\n", len, 1 );
1020 if ( fclose( fp ) ) {
1021 LOGIOERROR( "In addition: couldn't close", filename );
1022 }
1023 return ( -1 );
1024 }
1025 /* sanity check */
1026 if ( tl->elems > tl->length ) {
1028 "Number of elements read larger than length of toplist: %zu > %zu\n",
1029 tl->elems, tl->length );
1030 if ( fclose( fp ) ) {
1031 LOGIOERROR( "In addition: couldn't close", filename );
1032 }
1033 return ( -2 );
1034 }
1035
1036 /* read data */
1037 len = fread( tl->data, tl->size, tl->elems, fp );
1038 if ( len != tl->elems ) {
1039 LOGIOERROR( "Couldn't read data from", filename );
1040 LogPrintf( LOG_CRITICAL, "fread() returned %d, length was %zu\n", len, tl->elems );
1041 if ( fclose( fp ) ) {
1042 LOGIOERROR( "In addition: couldn't close", filename );
1043 }
1044 clear_toplist( tl );
1045 return ( -1 );
1046 }
1047
1048 /* read counter */
1049 len = fread( counter, sizeof( *counter ), 1, fp );
1050 if ( len != 1 ) {
1051 LOGIOERROR( "Couldn't read counter from", filename );
1052 LogPrintf( LOG_CRITICAL, "fread() returned %d, length was %d\n", len, 1 );
1053 if ( fclose( fp ) ) {
1054 LOGIOERROR( "In addition: couldn't close", filename );
1055 }
1056 clear_toplist( tl );
1057 return ( -1 );
1058 }
1059
1060 /* read checksum */
1061 len = fread( &checksum, sizeof( checksum ), 1, fp );
1062 if ( len != 1 ) {
1063 LOGIOERROR( "Couldn't read checksum to", filename );
1064 LogPrintf( LOG_CRITICAL, "fread() returned %d, length was %d\n", len, 1 );
1065 if ( fclose( fp ) ) {
1066 LOGIOERROR( "In addition: couldn't close", filename );
1067 }
1068 clear_toplist( tl );
1069 return ( -1 );
1070 }
1071
1072 /* close file */
1073 if ( fclose( fp ) ) {
1074 LOGIOERROR( "Couldn't close", filename );
1075 clear_toplist( tl );
1076 return ( -1 );
1077 }
1078
1079 /* verify checksum */
1080 for ( len = 0; len < sizeof( tl->elems ); len++ ) {
1081 checksum -= *( ( ( char * ) & ( tl->elems ) ) + len );
1082 }
1083 for ( len = 0; len < ( tl->elems * tl->size ); len++ ) {
1084 checksum -= *( ( ( char * )tl->data ) + len );
1085 }
1086 for ( len = 0; len < sizeof( *counter ); len++ ) {
1087 checksum -= *( ( ( char * )counter ) + len );
1088 }
1089 if ( checksum ) {
1090 LogPrintf( LOG_CRITICAL, "Checksum error: %d\n", checksum );
1091 clear_toplist( tl );
1092 return ( -2 );
1093 }
1094
1095 /* restore Heap structure by sorting */
1096 for ( len = 0; len < tl->elems; len++ ) {
1097 tl->heap[len] = tl->data + len * tl->size;
1098 }
1100
1101 /* all went well */
1102 LogPrintf( LOG_DEBUG, "Successfully read checkpoint\n" );
1103
1104 return ( 0 );
1105}
1106
1107
1108int write_cc_output( const char *filename, toplist_t *tl )
1109{
1110 /* reduce the precision of the calculated values before doing the sort to
1111 the precision we will write the result with. This should ensure a sorting
1112 order that looks right to the validator, too */
1115 return ( _atomic_write_crossCorr_toplist_to_file( tl, filename, NULL, 1 ) );
1116}
void sort_crossCorrBinary_toplist(toplist_t *l)
static int crossCorr_toplist_qsort_function(const void *a, const void *b)
int write_crossCorr_toplist_item_to_fp(CrossCorrOutputEntry fline, FILE *fp, UINT4 *checksum)
File IO.
static void reduce_crossCorrline_precision(void *line)
static void reduce_crossCorrBinary_toplist_precision(toplist_t *l)
int final_write_crossCorr_toplist_to_file(toplist_t *l, const char *filename, UINT4 *checksum)
meant for the final writing of the toplist
static int crossCorrBinary_toplist_qsort_function(const void *a, const void *b)
static void reduce_crossCorr_toplist_precision(toplist_t *l)
int write_cc_checkpoint(const char *filename, toplist_t *tl, UINT4 counter, BOOLEAN do_sync)
writes a checkpoint:
int atomic_write_crossCorr_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.
void sort_crossCorr_toplist(toplist_t *l)
reads a (created!) toplist from an open filepointer sets the checksum if non-NULL reads maximum maxby...
#define TEMP_EXT
int atomic_write_crossCorrBinary_toplist_to_file(toplist_t *l, const char *filename, UINT4 *checksum)
int write_crossCorrBinary_toplist_item_to_fp(CrossCorrBinaryOutputEntry fline, FILE *fp, UINT4 *checksum)
int write_crossCorr_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 ...
static int _atomic_write_crossCorrBinary_toplist_to_file(toplist_t *l, const char *filename, UINT4 *checksum, int write_done)
void free_crossCorr_toplist(toplist_t **l)
frees the space occupied by the toplist
static int print_crossCorrBinaryline_to_str(CrossCorrBinaryOutputEntry fline, char *buf, int buflen)
int final_write_crossCorrBinary_toplist_to_file(toplist_t *l, const char *filename, UINT4 *checksum)
int create_crossCorr_toplist(toplist_t **tl, UINT8 length)
creates a toplist with length elements, returns -1 on error (usually out of memory),...
int create_crossCorrBinary_toplist(toplist_t **tl, UINT8 length)
static int crossCorrBinary_smaller(const void *a, const void *b)
static void reduce_crossCorrBinaryline_precision(void *line)
static int _atomic_write_crossCorr_toplist_to_file(toplist_t *l, const char *filename, UINT4 *checksum, int write_done)
int write_cc_output(const char *filename, toplist_t *tl)
write the final output file:
int insert_into_crossCorrBinary_toplist(toplist_t *tl, CrossCorrBinaryOutputEntry elem)
static int crossCorr_smaller(const void *a, const void *b)
#define TMP_EXT
static int print_crossCorrline_to_str(CrossCorrOutputEntry fline, char *buf, int buflen)
int read_cc_checkpoint(const char *filename, toplist_t *tl, UINT4 *counter)
tries to read a checkpoint
int insert_into_crossCorr_toplist(toplist_t *tl, CrossCorrOutputEntry elem)
Inserts an element in to the toplist either if there is space left or the element is larger than the ...
#define SYNC_FAIL_LIMIT
#define LOGIOERROR(mess, filename)
int write_crossCorrBinary_toplist_to_fp(toplist_t *tl, FILE *fp, UINT4 *checksum)
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 c
#define fprintf
int l
unsigned char BOOLEAN
uint64_t UINT8
#define XLAL_LAST_ELEM(x)
int64_t INT8
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
Type to hold the fields that will be kept in a "toplist" – for a directed binary search.
REAL8 ecc
eccentricity
REAL8 argp
argument of periapse
REAL8 estSens
average template E[rho]/h0^2)^2
REAL8 period
bperiod
REAL8 evSquared
E[rho]/h0^2)^2.
REAL8 tp
time of periapse passage
REAL8 rho
Crosscorr statistic.
REAL8 freq
Frequency.
REAL8 asini
projected semi-major axis
Type to hold the fields that will be kept in a "toplist"
REAL8 Q1
Q1.
REAL8 BrakingIndex
braking index
REAL8 Freq
Frequency.
REAL8 Rho
Crosscorr statistic.
REAL8 Q2
Q2.
REAL8 Delta
skyposition: latitude
REAL8 Alpha
Skyposition: longitude in equatorial coords, radians.
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