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