SDDSlib
Loading...
Searching...
No Matches
logfile_gener.c
Go to the documentation of this file.
1/**
2 * @file logfile_gener.c
3 * @brief This file provides functions for creating time-based filenames, timestamps,
4 * and for breaking down and retrieving the current time in various formats.
5 *
6 * @copyright
7 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
8 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
9 *
10 * @license
11 * This file is distributed under the terms of the Software License Agreement
12 * found in the file LICENSE included with this distribution.
13 *
14 * @author M. Borland, R. Soliday
15 */
16
17#include "mdb.h"
18
19#ifdef _WIN32
20# include <windows.h>
21# include <io.h>
22# include <sys/locking.h>
23# include <sys/types.h>
24# include <sys/timeb.h>
25# if defined(__BORLANDC__)
26# define lockf(handle, mode, nbytes) locking(handle, mode, nbytes)
27# else
28# define lockf(handle, mode, nbytes) _locking(handle, mode, nbytes)
29# endif
30# define usleep(usecs) Sleep(usecs / 1000)
31# if !defined(__MINGW32__)
32# define popen(x, y) _popen(x, y)
33# endif
34# define F_TEST 3
35#else
36# include <unistd.h>
37# if defined(__APPLE__)
38# include <sys/time.h>
39/*lockf is not defined by unistd.h like it should be*/
40int lockf(int filedes, int function, off_t size);
41# endif
42#endif
43#ifdef SOLARIS
44# if defined(BELOW_SOLARIS_56)
45# include <signal.h>
46# include <sys/time.h>
47
48typedef void (*OLD_SIG_FUNC)(int);
49static void usleep_alarm(int x) {
50 return;
51}
52
53void usleep(long usecs) {
54 struct itimerval v;
55 OLD_SIG_FUNC old;
56 int rc = 0;
57
58 if (usecs < 1)
59 return;
60
61 v.it_value.tv_sec = usecs / 1000000;
62 v.it_value.tv_usec = usecs % 1000000;
63
64 v.it_interval.tv_sec = 0;
65 v.it_interval.tv_usec = 0;
66
67 old = signal(SIGALRM, usleep_alarm);
68 if (setitimer(ITIMER_REAL, &v, (struct itimerval *)NULL) < 0)
69 rc = -1;
70 else
71 pause();
72
73 signal(SIGALRM, old);
74}
75# endif
76#endif
77
78#include <time.h>
79/**
80 * @brief Create a human-readable timestamp from the given time in seconds since the Epoch.
81 * @param Time Time in seconds since the Epoch.
82 * @return Pointer to a static string containing the formatted timestamp.
83 */
84char *makeTimeStamp(double Time) {
85 time_t intTime;
86 char *TimeStamp;
87 intTime = Time;
88 TimeStamp = ctime(&intTime);
89 TimeStamp[strlen(TimeStamp) - 1] = 0; /* kill newline */
90 return TimeStamp;
91}
92
93/**
94 * @brief Retrieve detailed time breakdown (day, hour, julian day, month, year, and timestamp).
95 * @param ptrTime If not NULL, stores the time in seconds since the Epoch.
96 * @param ptrDay If not NULL, stores the day of the month (fractional).
97 * @param ptrHour If not NULL, stores the hour of the day (fractional).
98 * @param ptrJulianDay If not NULL, stores the Julian day (fractional).
99 * @param ptrMonth If not NULL, stores the month of the year (fractional).
100 * @param ptrYear If not NULL, stores the year (fractional).
101 * @param ptrTimeStamp If not NULL, stores a pointer to a timestamp string.
102 */
103void getTimeBreakdown(double *ptrTime, double *ptrDay, double *ptrHour,
104 double *ptrJulianDay, double *ptrMonth,
105 double *ptrYear, char **ptrTimeStamp) {
106 double theTime;
107 theTime = getTimeInSecs(); /* may get more precision than time() offers */
108 makeTimeBreakdown(theTime, ptrTime, ptrDay, ptrHour, ptrJulianDay,
109 ptrMonth, ptrYear, ptrTimeStamp);
110}
111
112/**
113 * @brief Get the current hour of the day (0-23, possibly fractional).
114 * @return Hour of the day.
115 */
116double getHourOfDay() {
117 double theTime, hour;
118 theTime = getTimeInSecs(); /* may get more precision than time() offers */
119 makeTimeBreakdown(theTime, NULL, NULL, &hour, NULL, NULL, NULL, NULL);
120 return hour;
121}
122
123static long daysInMonth[12] = {
124 31,
125 28,
126 31,
127 30,
128 31,
129 30,
130 31,
131 31,
132 30,
133 31,
134 30,
135 31,
136};
137
138/**
139 * @brief Break down a given time into multiple components (time, day, hour, Julian day, month, year, and timestamp).
140 * @param Time Time in seconds since the Epoch.
141 * @param ptrTime If not NULL, stores the input time value.
142 * @param ptrDay If not NULL, stores the day of the month (fractional).
143 * @param ptrHour If not NULL, stores the hour of the day (fractional).
144 * @param ptrJulianDay If not NULL, stores the Julian day (fractional).
145 * @param ptrMonth If not NULL, stores the month (fractional).
146 * @param ptrYear If not NULL, stores the year (fractional).
147 * @param ptrTimeStamp If not NULL, stores a timestamp string.
148 */
149void makeTimeBreakdown(double Time, double *ptrTime, double *ptrDay, double *ptrHour,
150 double *ptrJulianDay, double *ptrMonth, double *ptrYear,
151 char **ptrTimeStamp) {
152 double SubSeconds;
153 double Day, Hour, JulianDay, Year;
154 struct tm *tmBreakdown;
155 time_t integerTime;
156 long isLeap;
157
158 if (ptrTime)
159 *ptrTime = Time;
160 if (ptrTimeStamp)
161 *ptrTimeStamp = makeTimeStamp(Time);
162
163 /* get breakdown based on integer part of time */
164 integerTime = (time_t)Time;
165 SubSeconds = Time - integerTime;
166 tmBreakdown = localtime(&integerTime);
167
168 /* time since midnight in hours */
169 Hour = (tmBreakdown->tm_min + (tmBreakdown->tm_sec + SubSeconds) / 60.0) / 60.0 + tmBreakdown->tm_hour;
170 if (ptrHour)
171 *ptrHour = Hour;
172
173 /* time since beginning of month in days (includes partial days) */
174 Day = tmBreakdown->tm_mday + Hour / 24.0;
175 if (ptrDay)
176 *ptrDay = Day;
177
178 /* time since start of year in days (includes partial days) plus 1 day to give Julian convention */
179 JulianDay = tmBreakdown->tm_yday + Hour / 24.0 + 1;
180 if (ptrJulianDay)
181 *ptrJulianDay = JulianDay;
182
183 /* years since 0000 AD, including fractional years */
184 isLeap = 0;
185 tmBreakdown->tm_year += 1900;
186 if ((tmBreakdown->tm_year % 4 == 0 && tmBreakdown->tm_year % 100 != 0) || tmBreakdown->tm_year % 400 == 0)
187 isLeap = 1;
188 Year = tmBreakdown->tm_year + (JulianDay - 1) / (365.0 + isLeap);
189 if (ptrYear)
190 *ptrYear = Year;
191
192 /* time since start of year in 30-day months (includes partial days) */
193 if (ptrMonth) {
194 *ptrMonth = tmBreakdown->tm_mon + 1 +
195 +(1.0 * tmBreakdown->tm_mday - 1) / (daysInMonth[tmBreakdown->tm_mon] +
196 (isLeap && tmBreakdown->tm_mon == 1 ? 1 : 0));
197 }
198}
199
200/**
201 * @brief Compute the start time of the year for the given time.
202 * @param StartTime Time in seconds since the Epoch.
203 * @return Start-of-year time in seconds since the Epoch.
204 */
205double computeYearStartTime(double StartTime) {
206 struct tm *YearStart;
207 time_t intTime;
208
209 intTime = StartTime;
210 YearStart = localtime(&intTime);
211 YearStart->tm_sec = 0;
212 YearStart->tm_min = 0;
213 YearStart->tm_hour = 0;
214 YearStart->tm_mday = 1;
215 YearStart->tm_mon = 0;
216#if defined(SUNOS4)
217 return (double)timelocal(YearStart);
218#else
219 return (double)mktime(YearStart);
220#endif
221}
222
223#if defined(_WIN32)
224struct timespecoag {
225 long tv_sec;
226 long tv_nsec;
227}; /*header part */
228# if defined(__MINGW32__)
229# define exp7 10000000LL //1E+7 //C-file part
230# define exp9 1000000000LL //1E+9
231# define w2ux 116444736000000000LL //1.jan1601 to 1.jan1970
232# else
233# define exp7 10000000i64 //1E+7 //C-file part
234# define exp9 1000000000i64 //1E+9
235# define w2ux 116444736000000000i64 //1.jan1601 to 1.jan1970
236# endif
237
238void unix_time(struct timespecoag *spec) {
239 __int64 wintime;
240 GetSystemTimeAsFileTime((FILETIME *)&wintime);
241 wintime -= w2ux;
242 spec->tv_sec = wintime / exp7;
243 spec->tv_nsec = wintime % exp7 * 100;
244}
245
246int clock_gettime_oag(struct timespecoag *spec) {
247 static struct timespecoag startspec;
248 static double ticks2nano;
249 static __int64 startticks, tps = 0;
250 __int64 tmp, curticks;
251 QueryPerformanceFrequency((LARGE_INTEGER *)&tmp);
252 if (tps != tmp) {
253 tps = tmp;
254 QueryPerformanceCounter((LARGE_INTEGER *)&startticks);
255 unix_time(&startspec);
256 ticks2nano = (double)exp9 / tps;
257 }
258 QueryPerformanceCounter((LARGE_INTEGER *)&curticks);
259 curticks -= startticks;
260 spec->tv_sec = startspec.tv_sec + (curticks / tps);
261 spec->tv_nsec = startspec.tv_nsec + (double)(curticks % tps) * ticks2nano;
262 if (!(spec->tv_nsec < exp9)) {
263 spec->tv_sec++;
264 spec->tv_nsec -= exp9;
265 }
266 return 0;
267}
268#endif
269
270/**
271 * @brief Get the current time in seconds since the Epoch with high resolution.
272 * @return Current time in seconds.
273 */
275#if defined(_WIN32)
276 struct timespecoag tp;
277 clock_gettime_oag(&tp);
278 return ((double)tp.tv_sec) + ((double)tp.tv_nsec) * 1e-9;
279#endif
280
281#if defined(__APPLE__) /* This is only needed until I compile on MacOS 10.12 */
282# include <sys/time.h>
283 struct timeval tv;
284 gettimeofday(&tv, NULL);
285 return ((double)tv.tv_sec) + ((double)tv.tv_usec) * 1e-6;
286#endif
287
288#if !defined(_WIN32) && !defined(__APPLE__)
289# include <time.h>
290 struct timespec tp;
291 clock_gettime(CLOCK_REALTIME, &tp);
292 return ((double)tp.tv_sec) + ((double)tp.tv_nsec) * 1e-9;
293#endif
294}
295
296/**
297 * @brief Get the current time in seconds since the Epoch as a long double for higher precision.
298 * @return Current time in seconds as a long double.
299 */
301#if defined(_WIN32)
302 struct timespecoag tp;
303 clock_gettime_oag(&tp);
304 return ((long double)tp.tv_sec) + ((long double)tp.tv_nsec) * 1e-9L;
305#endif
306
307#if defined(__APPLE__) /* This is only needed until I compile on MacOS 10.12 */
308# include <sys/time.h>
309 struct timeval tv;
310 gettimeofday(&tv, NULL);
311 return ((long double)tv.tv_sec) + ((long double)tv.tv_usec) * 1e-6L;
312#endif
313
314#if !defined(_WIN32) && !defined(__APPLE__)
315# include <time.h>
316 struct timespec tp;
317 clock_gettime(CLOCK_REALTIME, &tp);
318 return ((long double)tp.tv_sec) + ((long double)tp.tv_nsec) * 1e-9L;
319#endif
320}
321
322/**
323 * @brief Generate a new filename with an incremented index based on a root name and delimiter.
324 * @param rootname Base name for the file.
325 * @param digits Number of digits to use for the index.
326 * @param delimiter Delimiter between root name and index.
327 * @param lastFile Last generated filename, used to determine the next index.
328 * @return Newly allocated string containing the generated filename.
329 */
330char *MakeGenerationFilename(char *rootname, long digits, char *delimiter, char *lastFile) {
331 char format[100], filename[1024], buffer[1024], *name, *ptr, *ptr1;
332 long index = 1;
333 FILE *fp;
334
335 if (!rootname || strlen(rootname) == 0)
336 return NULL;
337 if (digits < 1)
338 digits = DEFAULT_GENERATIONS_DIGITS;
339
340 if (lastFile && strlen(lastFile)) {
341 ptr1 = lastFile;
342 ptr = NULL;
343 while ((ptr1 = strstr(ptr1, delimiter))) {
344 ptr = ptr1;
345 ptr1 += 1;
346 }
347 if (ptr) {
348 ptr += strlen(delimiter);
349 while (*ptr == '0')
350 ptr++;
351 if (sscanf(ptr, "%ld", &index) != 1) {
352 sprintf(buffer, "Error scanning name of last file: %s", lastFile);
353 fprintf(stderr, "Error: %s\n", buffer);
354 exit(1);
355 }
356 } else {
357 sprintf(buffer, "Error scanning name of last file: %s", lastFile);
358 fprintf(stderr, "Error: %s\n", buffer);
359 exit(1);
360 }
361 if (!fexists(lastFile))
362 index += 1; /* avoids reuse of the file even if it has been deleted */
363 }
364
365 sprintf(format, "%%s%s%%0%ldld", delimiter, digits);
366
367 do {
368 sprintf(filename, format, rootname, index);
369 index++;
370 if (!(fp = fopen(filename, "r")))
371 break;
372#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
373 if (lockf(fileno(fp), F_TEST, 0) == -1) {
374 /* file exists and is locked */
375 fclose(fp);
376 sprintf(buffer, "aborting--previous generation of %s (%s) is still active", rootname,
377 filename);
378 fprintf(stderr, "Warning: %s\n", buffer);
379 exit(0);
380 }
381#endif
382 fclose(fp);
383 } while (1);
384 if (!(name = malloc(sizeof(*name) * (strlen(filename) + 1)))) {
385 fprintf(stderr, "Error: memory allocation failure making generation filename\n");
386 exit(1);
387 }
388 return strcpy(name, filename);
389}
390
391/**
392 * @brief Generate a new daily filename with a timestamp based on the current date and time.
393 * @param rootname Base name for the file.
394 * @return Newly allocated string containing the generated filename.
395 */
397 char buffer[1024];
398 char filename[1024];
399 char *name;
400 time_t now;
401 struct tm *now1;
402 FILE *fp;
403
404 if (!rootname) {
405 fprintf(stderr, "The rootname is not provided.\n");
406 exit(1);
407 }
408 /*generate a new file name */
409 do {
410 now = time(NULL);
411 now1 = localtime(&now);
412 strftime(buffer, 1024, "%Y-%j-%m%d-%H%M%S", now1);
413 sprintf(filename, "%s%s", rootname, buffer);
414 fp = fopen(filename, "r");
415 } while (fp != NULL);
416
417 if (!(name = malloc(sizeof(*name) * (strlen(filename) + 1)))) {
418 fprintf(stderr, "Error: memory allocation failure making generation filename\n");
419 exit(1);
420 }
421 return strcpy(name, filename);
422}
423
424/**
425 * @brief Generate a new daily filename. Can include a time tag or a numeric index.
426 * @param rootname Base name for the file.
427 * @param digits Number of digits for the index.
428 * @param delimiter Delimiter between parts of the filename.
429 * @param timetag If non-zero, includes a time tag in the filename.
430 * @return Newly allocated string containing the daily generated filename.
431 */
432char *MakeDailyGenerationFilename(char *rootname, long digits, char *delimiter, long timetag) {
433#if !defined(vxWorks)
434 char buffer[1024];
435#endif
436 char format[100], filename[1024], *name, *hourNow, match_date[1024];
437 long index = 1;
438 FILE *fp;
439 double dayDbl, jDayDbl, monthDbl, yearDbl, theTime;
440 long day, jDay, month, year;
441
442 if (digits < 0)
443 digits = DEFAULT_GENERATIONS_DIGITS;
444 theTime = getTimeInSecs();
445 makeTimeBreakdown(theTime, NULL, &dayDbl, NULL, &jDayDbl, &monthDbl, &yearDbl, NULL);
446 day = dayDbl;
447 jDay = jDayDbl;
448 month = monthDbl;
449 year = yearDbl;
450
451 if (timetag) {
452 hourNow = getHourMinuteSecond();
453 if (rootname && strlen(rootname) > 0)
454 sprintf(match_date, "%s-%4ld-%03ld-%02ld%02ld", rootname, year, jDay, month, day);
455 else
456 sprintf(match_date, "%4ld-%03ld-%02ld%02ld", year, jDay, month, day);
457 checkGenerationFileLocks(match_date);
458 if (rootname && strlen(rootname) > 0)
459 sprintf(filename, "%s-%4ld-%03ld-%02ld%02ld.%s", rootname,
460 year, jDay, month, day, hourNow);
461 else
462 sprintf(filename, "%4ld-%03ld-%02ld%02ld.%s", year, jDay, month, day, hourNow);
463 } else {
464 if (!digits) {
465 if (rootname && strlen(rootname) > 0)
466 sprintf(filename, "%s-%4ld-%03ld-%02ld%02ld", rootname, year, jDay, month, day);
467 else
468 sprintf(filename, "%4ld-%03ld-%02ld%02ld", year, jDay, month, day);
469 if ((fp = fopen(filename, "r"))) {
470#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
471 if (lockf(fileno(fp), F_TEST, 0) == -1) {
472 /* file exists and is locked */
473 fclose(fp);
474 sprintf(buffer, "aborting--previous generation of %s is still active", filename);
475 fprintf(stderr, "Warning: %s\n", buffer);
476 exit(0);
477 }
478#endif
479 }
480 } else {
481 if (!delimiter || strlen(delimiter) == 0)
482 return NULL;
483 if (rootname && strlen(rootname) > 0)
484 sprintf(format, "%s-%%4ld-%%03ld-%%02ld%%02ld%s%%0%ldld", rootname, delimiter, digits);
485 else
486 sprintf(format, "%%4ld-%%03ld-%%02ld%%02ld%s%%0%ldld", delimiter, digits);
487 do {
488 sprintf(filename, format, year, jDay, month, day, index);
489 index++;
490 if (!(fp = fopen(filename, "r")))
491 break;
492 theTime = getTimeInSecs();
493 makeTimeBreakdown(theTime, NULL, &dayDbl, NULL, &jDayDbl, &monthDbl, &yearDbl, NULL);
494 day = dayDbl;
495 jDay = jDayDbl;
496 month = monthDbl;
497 year = yearDbl;
498#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
499 if (lockf(fileno(fp), F_TEST, 0) == -1) {
500 /* file exists and is locked */
501 fclose(fp);
502 sprintf(buffer, "aborting--previous generation of %s (%s) is still active", rootname,
503 filename);
504 fprintf(stderr, "Warning: %s\n", buffer);
505 exit(0);
506 }
507#endif
508 fclose(fp);
509 } while (1);
510 }
511 }
512 if (!(name = malloc(sizeof(*name) * (strlen(filename) + 1)))) {
513 fprintf(stderr, "Error: memory allocation failure making generation filename\n");
514 exit(1);
515 }
516 return strcpy(name, filename);
517}
518
519/**
520 * @brief Generate a new monthly filename. Can include a time tag or a numeric index.
521 * @param rootname Base name for the file.
522 * @param digits Number of digits for the index.
523 * @param delimiter Delimiter between parts of the filename.
524 * @param timetag If non-zero, includes a time tag in the filename.
525 * @return Newly allocated string containing the monthly generated filename.
526 */
527char *MakeMonthlyGenerationFilename(char *rootname, long digits, char *delimiter, long timetag) {
528#if !defined(vxWorks)
529 char buffer[1024];
530#endif
531 char format[100], filename[1024], *name, *hourNow, match_date[1024];
532 long index = 1;
533 FILE *fp;
534 double dayDbl, jDayDbl, monthDbl, yearDbl, theTime;
535 long month, year;
536
537 if (digits < 0)
538 digits = DEFAULT_GENERATIONS_DIGITS;
539 theTime = getTimeInSecs();
540 makeTimeBreakdown(theTime, NULL, &dayDbl, NULL, &jDayDbl, &monthDbl, &yearDbl, NULL);
541 month = monthDbl;
542 year = yearDbl;
543
544 if (timetag) {
545 hourNow = getHourMinuteSecond();
546 if (rootname && strlen(rootname) > 0)
547 sprintf(match_date, "%s-%4ld-%02ld", rootname, year, month);
548 else
549 sprintf(match_date, "%4ld-%02ld", year, month);
550 checkGenerationFileLocks(match_date);
551 if (rootname && strlen(rootname) > 0)
552 sprintf(filename, "%s-%4ld-%02ld.%s", rootname,
553 year, month, hourNow);
554 else
555 sprintf(filename, "%4ld-%02ld.%s", year, month, hourNow);
556 } else {
557 if (!digits) {
558 if (rootname && strlen(rootname) > 0)
559 sprintf(filename, "%s-%4ld-%02ld", rootname, year, month);
560 else
561 sprintf(filename, "%4ld-%02ld", year, month);
562 if ((fp = fopen(filename, "r"))) {
563#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
564 if (lockf(fileno(fp), F_TEST, 0) == -1) {
565 /* file exists and is locked */
566 fclose(fp);
567 sprintf(buffer, "aborting--previous generation of %s is still active", filename);
568 fprintf(stderr, "Warning: %s\n", buffer);
569 exit(0);
570 }
571#endif
572 }
573 } else {
574 if (!delimiter || strlen(delimiter) == 0)
575 return NULL;
576 if (rootname && strlen(rootname) > 0)
577 sprintf(format, "%s-%%4ld-%%02ld%s%%0%ldld", rootname, delimiter, digits);
578 else
579 sprintf(format, "%%4ld-%%02ld%s%%0%ldld", delimiter, digits);
580 do {
581 sprintf(filename, format, year, month, index);
582 index++;
583 if (!(fp = fopen(filename, "r")))
584 break;
585 /* theTime = getTimeInSecs(); */
586 /* makeTimeBreakdown(theTime, NULL, &dayDbl, NULL, &jDayDbl, &monthDbl, &yearDbl, NULL); */
587 /* month = monthDbl; */
588 /* year = yearDbl; */
589#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
590 if (lockf(fileno(fp), F_TEST, 0) == -1) {
591 /* file exists and is locked */
592 fclose(fp);
593 sprintf(buffer, "aborting--previous generation of %s (%s) is still active", rootname,
594 filename);
595 fprintf(stderr, "Warning: %s\n", buffer);
596 exit(0);
597 }
598#endif
599 fclose(fp);
600 } while (1);
601 }
602 }
603 if (!(name = malloc(sizeof(*name) * (strlen(filename) + 1)))) {
604 fprintf(stderr, "Error: memory allocation failure making generation filename\n");
605 exit(1);
606 }
607 return strcpy(name, filename);
608}
609
610/**
611 * @brief Sleep for a given number of microseconds, system-independently.
612 * @param usec Number of microseconds to sleep.
613 */
614void usleepSystemIndependent(long usec) {
615#if defined(vxWorks) && !defined(__rtems__)
616 struct timespec rqtp;
617 rqtp.tv_sec = (long)(usec / 1000000);
618 rqtp.tv_nsec = usec % 1000000 * 1000;
619 nanosleep(&rqtp, NULL);
620#else
621 usleep(usec);
622#endif
623}
624
625/**
626 * @brief Get the current hour, minute, and second as a string.
627 * @return Pointer to a static string (e.g., "HH:MM:SS").
628 */
630 time_t now;
631 char *Hour, *ptr;
632 int i = 0;
633
634 now = time(NULL);
635 Hour = ctime(&now);
636 ptr = strtok(Hour, " ");
637 i++;
638 while (ptr != NULL) {
639 if (i == 4)
640 break;
641 ptr = strtok(NULL, " ");
642 i++;
643 }
644 return ptr;
645}
646
647/**
648 * @brief Check for matching date-based generation files and ensure none are locked.
649 * @param match_date Date pattern to match.
650 */
651void checkGenerationFileLocks(char *match_date) {
652#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
653 char comm[1024], filename[2048], buffer[1024];
654 FILE *handle, *fp;
655
656 sprintf(comm, "ls %s* 2> /dev/stdout", match_date);
657 if (!(handle = popen(comm, "r"))) {
658 fprintf(stderr, "Error: no data returned from popen call\n");
659 exit(1);
660 }
661 while (!feof(handle)) {
662 if (fgets(filename, sizeof(filename), handle)) {
663 if (filename[strlen(filename) - 1] == '\n') {
664 filename[strlen(filename) - 1] = 0;
665 }
666 if (!(fp = fopen(filename, "r")))
667 continue;
668 if (lockf(fileno(fp), F_TEST, 0) == -1) {
669 /* file exists and is locked */
670 fclose(fp);
671 sprintf(buffer, "aborting--previous generation %s is still active",
672 filename);
673 fprintf(stderr, "Warning: %s\n", buffer);
674 exit(0);
675 }
676 fclose(fp);
677 }
678 }
679#endif
680}
681
682/**
683 * @brief Update the modification timestamp of a file if it exists.
684 * @param filename File to "touch."
685 */
686void TouchFile(char *filename) {
687#if !defined(vxWorks) && !defined(__rtems__)
688 FILE *fp;
689 static FILE *fsh = NULL;
690
691 if (!fsh) {
692 if (!(fsh = popen("csh", "w"))) {
693 fprintf(stderr, "Error: unable to launch csh for touchFile operations\n");
694 exit(1);
695 }
696 }
697 if (filename) {
698 if ((fp = fopen(filename, "r"))) {
699 fclose(fp);
700 fprintf(fsh, "touch %s\n", filename);
701 fflush(fsh);
702 }
703 }
704#endif
705}
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27
double computeYearStartTime(double StartTime)
Compute the start time of the year for the given time.
char * makeTimeStamp(double Time)
Create a human-readable timestamp from the given time in seconds since the Epoch.
void makeTimeBreakdown(double Time, double *ptrTime, double *ptrDay, double *ptrHour, double *ptrJulianDay, double *ptrMonth, double *ptrYear, char **ptrTimeStamp)
Break down a given time into multiple components (time, day, hour, Julian day, month,...
void checkGenerationFileLocks(char *match_date)
Check for matching date-based generation files and ensure none are locked.
char * MakeDailyGenerationFilename(char *rootname, long digits, char *delimiter, long timetag)
Generate a new daily filename. Can include a time tag or a numeric index.
void usleepSystemIndependent(long usec)
Sleep for a given number of microseconds, system-independently.
double getHourOfDay()
Get the current hour of the day (0-23, possibly fractional).
char * getHourMinuteSecond()
Get the current hour, minute, and second as a string.
double getTimeInSecs()
Get the current time in seconds since the Epoch with high resolution.
char * MakeGenerationFilename(char *rootname, long digits, char *delimiter, char *lastFile)
Generate a new filename with an incremented index based on a root name and delimiter.
char * MakeSCRDailyTimeGenerationFilename(char *rootname)
Generate a new daily filename with a timestamp based on the current date and time.
void TouchFile(char *filename)
Update the modification timestamp of a file if it exists.
void getTimeBreakdown(double *ptrTime, double *ptrDay, double *ptrHour, double *ptrJulianDay, double *ptrMonth, double *ptrYear, char **ptrTimeStamp)
Retrieve detailed time breakdown (day, hour, julian day, month, year, and timestamp).
char * MakeMonthlyGenerationFilename(char *rootname, long digits, char *delimiter, long timetag)
Generate a new monthly filename. Can include a time tag or a numeric index.
long double getLongDoubleTimeInSecs()
Get the current time in seconds since the Epoch as a long double for higher precision.