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