18#include "mdb_thread.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)
29# define lockf(handle, mode, nbytes) _locking(handle, mode, nbytes)
31# define usleep(usecs) Sleep(usecs / 1000)
35# if defined(__APPLE__)
38int lockf(
int filedes,
int function, off_t size);
42# if defined(BELOW_SOLARIS_56)
46typedef void (*OLD_SIG_FUNC)(int);
47static void usleep_alarm(
int x) {
51void usleep(
long usecs) {
59 v.it_value.tv_sec = usecs / 1000000;
60 v.it_value.tv_usec = usecs % 1000000;
62 v.it_interval.tv_sec = 0;
63 v.it_interval.tv_usec = 0;
65 old = signal(SIGALRM, usleep_alarm);
66 if (setitimer(ITIMER_REAL, &v, (
struct itimerval *)NULL) < 0)
78static struct tm *mdbmth_localtime(
const time_t *timep,
struct tm *result) {
80 return localtime_s(result, timep) == 0 ? result : NULL;
81#elif defined(_POSIX_VERSION) || defined(__unix__) || defined(__APPLE__)
82 return localtime_r(timep, result);
85 static MDB_THREAD_LOCK localtime_lock = MDB_THREAD_LOCK_INITIALIZER;
86 mdb_thread_lock(&localtime_lock);
87 tmp = localtime(timep);
90 mdb_thread_unlock(&localtime_lock);
91 return tmp ? result : NULL;
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"};
108 if (!mdbmth_localtime(&intTime, &tmBreakdown))
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);
128 double *ptrJulianDay,
double *ptrMonth,
129 double *ptrYear,
char **ptrTimeStamp) {
133 ptrMonth, ptrYear, ptrTimeStamp);
141 double theTime, hour;
147static const long daysInMonth[12] = {
174 double *ptrJulianDay,
double *ptrMonth,
double *ptrYear,
175 char **ptrTimeStamp) {
177 double Day, Hour, JulianDay, Year;
178 struct tm *tmBreakdown;
179 struct tm tmBreakdownData;
189 integerTime = (time_t)Time;
190 SubSeconds = Time - integerTime;
191 tmBreakdown = mdbmth_localtime(&integerTime, &tmBreakdownData);
196 Hour = (tmBreakdown->tm_min + (tmBreakdown->tm_sec + SubSeconds) / 60.0) / 60.0 + tmBreakdown->tm_hour;
201 Day = tmBreakdown->tm_mday + Hour / 24.0;
206 JulianDay = tmBreakdown->tm_yday + Hour / 24.0 + 1;
208 *ptrJulianDay = JulianDay;
212 tmBreakdown->tm_year += 1900;
213 if ((tmBreakdown->tm_year % 4 == 0 && tmBreakdown->tm_year % 100 != 0) || tmBreakdown->tm_year % 400 == 0)
215 Year = tmBreakdown->tm_year + (JulianDay - 1) / (365.0 + isLeap);
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));
233 struct tm *YearStart;
234 struct tm YearStartData;
238 YearStart = mdbmth_localtime(&intTime, &YearStartData);
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;
247 return (
double)timelocal(YearStart);
249 return (
double)mktime(YearStart);
254static MDB_THREAD_LOCK clock_gettime_oag_lock = MDB_THREAD_LOCK_INITIALIZER;
260# if defined(__MINGW32__)
261# define exp7 10000000LL
262# define exp9 1000000000LL
263# define w2ux 116444736000000000LL
265# define exp7 10000000i64
266# define exp9 1000000000i64
267# define w2ux 116444736000000000i64
270void unix_time(
struct timespecoag *spec) {
272 GetSystemTimeAsFileTime((FILETIME *)&wintime);
274 spec->tv_sec = wintime / exp7;
275 spec->tv_nsec = wintime % exp7 * 100;
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);
287 QueryPerformanceCounter((LARGE_INTEGER *)&startticks);
288 unix_time(&startspec);
289 ticks2nano = (double)exp9 / tps;
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)) {
297 spec->tv_nsec -= exp9;
299 mdb_thread_unlock(&clock_gettime_oag_lock);
310 struct timespecoag tp;
311 clock_gettime_oag(&tp);
312 return ((
double)tp.tv_sec) + ((double)tp.tv_nsec) * 1e-9;
315#if defined(__APPLE__)
316# include <sys/time.h>
318 gettimeofday(&tv, NULL);
319 return ((
double)tv.tv_sec) + ((double)tv.tv_usec) * 1e-6;
322#if !defined(_WIN32) && !defined(__APPLE__)
325 clock_gettime(CLOCK_REALTIME, &tp);
326 return ((
double)tp.tv_sec) + ((double)tp.tv_nsec) * 1e-9;
336 struct timespecoag tp;
337 clock_gettime_oag(&tp);
338 return ((
long double)tp.tv_sec) + ((
long double)tp.tv_nsec) * 1e-9L;
341#if defined(__APPLE__)
342# include <sys/time.h>
344 gettimeofday(&tv, NULL);
345 return ((
long double)tv.tv_sec) + ((
long double)tv.tv_usec) * 1e-6L;
348#if !defined(_WIN32) && !defined(__APPLE__)
351 clock_gettime(CLOCK_REALTIME, &tp);
352 return ((
long double)tp.tv_sec) + ((
long double)tp.tv_nsec) * 1e-9L;
365 char format[100], filename[1024], buffer[1100], *name, *ptr, *ptr1;
369 if (!rootname || strlen(rootname) == 0)
372 digits = DEFAULT_GENERATIONS_DIGITS;
374 if (lastFile && strlen(lastFile)) {
377 while ((ptr1 = strstr(ptr1, delimiter))) {
382 ptr += strlen(delimiter);
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);
391 sprintf(buffer,
"Error scanning name of last file: %s", lastFile);
392 fprintf(stderr,
"Error: %s\n", buffer);
399 sprintf(format,
"%%s%s%%0%ldld", delimiter, digits);
402 sprintf(filename, format, rootname, index);
404 if (!(fp = fopen(filename,
"r")))
406#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
407 if (lockf(fileno(fp), F_TEST, 0) == -1) {
410 sprintf(buffer,
"aborting--previous generation of %s (%s) is still active", rootname,
412 fprintf(stderr,
"Warning: %s\n", buffer);
418 if (!(name = malloc(
sizeof(*name) * (strlen(filename) + 1)))) {
419 fprintf(stderr,
"Error: memory allocation failure making generation filename\n");
422 return strcpy(name, filename);
440 fprintf(stderr,
"The rootname is not provided.\n");
446 now1 = mdbmth_localtime(&now, &nowData);
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);
454 if (!(name = malloc(
sizeof(*name) * (strlen(filename) + 1)))) {
455 fprintf(stderr,
"Error: memory allocation failure making generation filename\n");
458 return strcpy(name, filename);
473 char format[100], filename[1024], *name, *hourNow, match_date[1024];
476 double dayDbl, jDayDbl, monthDbl, yearDbl, theTime;
477 long day, jDay, month, year;
480 digits = DEFAULT_GENERATIONS_DIGITS;
482 makeTimeBreakdown(theTime, NULL, &dayDbl, NULL, &jDayDbl, &monthDbl, &yearDbl, NULL);
490 if (rootname && strlen(rootname) > 0)
491 sprintf(match_date,
"%s-%4ld-%03ld-%02ld%02ld", rootname, year, jDay, month, day);
493 sprintf(match_date,
"%4ld-%03ld-%02ld%02ld", year, jDay, month, day);
495 if (rootname && strlen(rootname) > 0)
496 sprintf(filename,
"%s-%4ld-%03ld-%02ld%02ld.%s", rootname,
497 year, jDay, month, day, hourNow);
499 sprintf(filename,
"%4ld-%03ld-%02ld%02ld.%s", year, jDay, month, day, hourNow);
502 if (rootname && strlen(rootname) > 0)
503 sprintf(filename,
"%s-%4ld-%03ld-%02ld%02ld", rootname, year, jDay, month, day);
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) {
511 sprintf(buffer,
"aborting--previous generation of %s is still active", filename);
512 fprintf(stderr,
"Warning: %s\n", buffer);
518 if (!delimiter || strlen(delimiter) == 0)
520 if (rootname && strlen(rootname) > 0)
521 sprintf(format,
"%s-%%4ld-%%03ld-%%02ld%%02ld%s%%0%ldld", rootname, delimiter, digits);
523 sprintf(format,
"%%4ld-%%03ld-%%02ld%%02ld%s%%0%ldld", delimiter, digits);
525 sprintf(filename, format, year, jDay, month, day, index);
527 if (!(fp = fopen(filename,
"r")))
530 makeTimeBreakdown(theTime, NULL, &dayDbl, NULL, &jDayDbl, &monthDbl, &yearDbl, NULL);
535#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
536 if (lockf(fileno(fp), F_TEST, 0) == -1) {
539 sprintf(buffer,
"aborting--previous generation of %s (%s) is still active", rootname,
541 fprintf(stderr,
"Warning: %s\n", buffer);
549 if (!(name = malloc(
sizeof(*name) * (strlen(filename) + 1)))) {
550 fprintf(stderr,
"Error: memory allocation failure making generation filename\n");
553 return strcpy(name, filename);
568 char format[100], filename[1024], *name, *hourNow, match_date[1024];
571 double dayDbl, jDayDbl, monthDbl, yearDbl, theTime;
575 digits = DEFAULT_GENERATIONS_DIGITS;
577 makeTimeBreakdown(theTime, NULL, &dayDbl, NULL, &jDayDbl, &monthDbl, &yearDbl, NULL);
583 if (rootname && strlen(rootname) > 0)
584 sprintf(match_date,
"%s-%4ld-%02ld", rootname, year, month);
586 sprintf(match_date,
"%4ld-%02ld", year, month);
588 if (rootname && strlen(rootname) > 0)
589 sprintf(filename,
"%s-%4ld-%02ld.%s", rootname,
590 year, month, hourNow);
592 sprintf(filename,
"%4ld-%02ld.%s", year, month, hourNow);
595 if (rootname && strlen(rootname) > 0)
596 sprintf(filename,
"%s-%4ld-%02ld", rootname, year, month);
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) {
604 sprintf(buffer,
"aborting--previous generation of %s is still active", filename);
605 fprintf(stderr,
"Warning: %s\n", buffer);
611 if (!delimiter || strlen(delimiter) == 0)
613 if (rootname && strlen(rootname) > 0)
614 sprintf(format,
"%s-%%4ld-%%02ld%s%%0%ldld", rootname, delimiter, digits);
616 sprintf(format,
"%%4ld-%%02ld%s%%0%ldld", delimiter, digits);
618 sprintf(filename, format, year, month, index);
620 if (!(fp = fopen(filename,
"r")))
626#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
627 if (lockf(fileno(fp), F_TEST, 0) == -1) {
630 sprintf(buffer,
"aborting--previous generation of %s (%s) is still active", rootname,
632 fprintf(stderr,
"Warning: %s\n", buffer);
640 if (!(name = malloc(
sizeof(*name) * (strlen(filename) + 1)))) {
641 fprintf(stderr,
"Error: memory allocation failure making generation filename\n");
644 return strcpy(name, filename);
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);
668 struct tm nowBreakdown;
669 static MDB_THREAD_LOCAL
char Hour[9];
672 if (!mdbmth_localtime(&now, &nowBreakdown))
674 snprintf(Hour,
sizeof(Hour),
"%02d:%02d:%02d",
675 nowBreakdown.tm_hour, nowBreakdown.tm_min, nowBreakdown.tm_sec);
684#if !defined(vxWorks) && !defined(__rtems__) && !defined(__CYGWIN__)
685 char comm[1024], filename[2048], buffer[1024];
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");
693 while (!feof(handle)) {
694 if (fgets(filename,
sizeof(filename), handle)) {
695 if (filename[strlen(filename) - 1] ==
'\n') {
696 filename[strlen(filename) - 1] = 0;
698 if (!(fp = fopen(filename,
"r")))
700 if (lockf(fileno(fp), F_TEST, 0) == -1) {
703 sprintf(buffer,
"aborting--previous generation %s is still active",
705 fprintf(stderr,
"Warning: %s\n", buffer);
720#if !defined(vxWorks) && !defined(__rtems__)
722 static FILE *fsh = NULL;
723 static MDB_THREAD_LOCK touch_file_lock = MDB_THREAD_LOCK_INITIALIZER;
725 mdb_thread_lock(&touch_file_lock);
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);
734 if ((fp = fopen(filename,
"r"))) {
736 fprintf(fsh,
"touch %s\n", filename);
740 mdb_thread_unlock(&touch_file_lock);
long fexists(const char *filename)
Checks if a file exists.
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.