Changeset View
Standalone View
contrib/tzcode/stdtime/localtime.c
Show First 20 Lines • Show All 164 Lines • ▼ Show 20 Lines | |||||
#define JULIAN_DAY 0 /* Jn - Julian day */ | #define JULIAN_DAY 0 /* Jn - Julian day */ | ||||
#define DAY_OF_YEAR 1 /* n - day of year */ | #define DAY_OF_YEAR 1 /* n - day of year */ | ||||
#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ | #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ | ||||
/* | /* | ||||
** Prototypes for static functions. | ** Prototypes for static functions. | ||||
*/ | */ | ||||
static int check_tz_change(int is_lcl_set); | |||||
static long detzcode(const char * codep); | static long detzcode(const char * codep); | ||||
static time_t detzcode64(const char * codep); | static time_t detzcode64(const char * codep); | ||||
static int differ_by_repeat(time_t t1, time_t t0); | static int differ_by_repeat(time_t t1, time_t t0); | ||||
static const char * getzname(const char * strp) ATTRIBUTE_PURE; | static const char * getzname(const char * strp) ATTRIBUTE_PURE; | ||||
static const char * getqzname(const char * strp, const int delim) | static const char * getqzname(const char * strp, const int delim) | ||||
ATTRIBUTE_PURE; | ATTRIBUTE_PURE; | ||||
static const char * getnum(const char * strp, int * nump, int min, | static const char * getnum(const char * strp, int * nump, int min, | ||||
int max); | int max); | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
#define lclptr (&lclmem) | #define lclptr (&lclmem) | ||||
#define gmtptr (&gmtmem) | #define gmtptr (&gmtmem) | ||||
#endif /* State Farm */ | #endif /* State Farm */ | ||||
#ifndef TZ_STRLEN_MAX | #ifndef TZ_STRLEN_MAX | ||||
#define TZ_STRLEN_MAX 255 | #define TZ_STRLEN_MAX 255 | ||||
#endif /* !defined TZ_STRLEN_MAX */ | #endif /* !defined TZ_STRLEN_MAX */ | ||||
#define TZ_FILENAME "/etc/localtime" | |||||
#define MAX_CHECK_COUNT 10 | |||||
julian: nominal defaults. don't do the work every time you get called.. that could be a lot. Maybe… | |||||
impUnsubmitted Not Done Inline ActionsThis seems tailor made for a kqueue thing... imp: This seems tailor made for a kqueue thing... | |||||
julianAuthorUnsubmitted Not Done Inline Actionsdo you think adding a kqueue infrastructure is worth it? if you are in syslogd then yes you are running a long time I guess you could make it only do it if the user has bothered to set the env variable. which suggests he plans on sticking around.. I'll have to think about that idea. julian: do you think adding a kqueue infrastructure is worth it?
if you are in syslogd then yes you… | |||||
#define CHECK_INTERVAL 10 | |||||
static char lcl_TZname[TZ_STRLEN_MAX + 1]; | static char lcl_TZname[TZ_STRLEN_MAX + 1]; | ||||
static int lcl_is_set; | static int lcl_is_set; | ||||
static int done_env_read = 0; | |||||
static int watch_changes = 1; /* Always starts off taking notice */ | |||||
static time_t tzfile_ctime = (time_t)0; /* will always want the first check */ | |||||
static time_t last_check_time = (time_t)0; /* It's time to check immediately */ | |||||
static int check_times; | |||||
static pthread_once_t gmt_once = PTHREAD_ONCE_INIT; | static pthread_once_t gmt_once = PTHREAD_ONCE_INIT; | ||||
static pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER; | static pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER; | ||||
static pthread_once_t gmtime_once = PTHREAD_ONCE_INIT; | static pthread_once_t gmtime_once = PTHREAD_ONCE_INIT; | ||||
static pthread_key_t gmtime_key; | static pthread_key_t gmtime_key; | ||||
static int gmtime_key_error; | static int gmtime_key_error; | ||||
static pthread_once_t localtime_once = PTHREAD_ONCE_INIT; | static pthread_once_t localtime_once = PTHREAD_ONCE_INIT; | ||||
static pthread_key_t localtime_key; | static pthread_key_t localtime_key; | ||||
static int localtime_key_error; | static int localtime_key_error; | ||||
Show All 17 Lines | |||||
time_t timezone = 0; | time_t timezone = 0; | ||||
int daylight = 0; | int daylight = 0; | ||||
#endif /* defined USG_COMPAT */ | #endif /* defined USG_COMPAT */ | ||||
#ifdef ALTZONE | #ifdef ALTZONE | ||||
time_t altzone = 0; | time_t altzone = 0; | ||||
#endif /* defined ALTZONE */ | #endif /* defined ALTZONE */ | ||||
static int | |||||
check_tz_change(int is_lcl_set) | |||||
{ | |||||
int is_change = 0; | |||||
if ( watch_changes ) { | |||||
impUnsubmitted Not Done Inline Actionsextra space here and other places, and those extra spaces aren't file wide, so please clean up to KNF. imp: extra space here and other places, and those extra spaces aren't file wide, so please clean up… | |||||
julianAuthorUnsubmitted Not Done Inline Actionswill have a cleanup pass.. julian: will have a cleanup pass.. | |||||
struct stat buf; | |||||
time_t current_time = time(NULL); | |||||
if ( ! done_env_read ) { | |||||
char *env_ptr; | |||||
env_ptr = getenv("ZONEINFO_WATCH_CHANGES"); | |||||
done_env_read = 1; | |||||
if (env_ptr == NULL) { | |||||
watch_changes = 1; /* default value */ | |||||
julianAuthorUnsubmitted Not Done Inline ActionsI would commit this a 0.. we use it as 1 at $JOB as we always want everything to notice when /etc/localtime changes. julian: I would commit this a 0.. we use it as 1 at $JOB as we always want everything to notice when… | |||||
} else { | |||||
if (strncmp("yes", env_ptr, 3)) { | |||||
impUnsubmitted Not Done Inline ActionsAdd a != 0 here because of strcmp interface. imp: Add a != 0 here because of strcmp interface.
| |||||
watch_changes = 0; | |||||
} else { | |||||
watch_changes = 1; | |||||
} | |||||
impUnsubmitted Not Done Inline ActionsThis is the long way to say watch_changes = (env_ptr = getenv("ZONEINFO_WATCH_CHANGES") && strncmp(env_ptr, "yes", 3) ==0) imp: This is the long way to say
watch_changes = (env_ptr = getenv("ZONEINFO_WATCH_CHANGES") &&… | |||||
julianAuthorUnsubmitted Not Done Inline ActionsOr you could say that watch_changes = (env_ptr = getenv("ZONEINFO_WATCH_CHANGES") && strncmp(env_ptr, "yes", 3) ==0) is the unreadable way of saying it the other way.. julian: Or you could say that watch_changes = (env_ptr = getenv("ZONEINFO_WATCH_CHANGES") && strncmp… | |||||
} | |||||
} | |||||
if (check_times++ % MAX_CHECK_COUNT == 0 || | |||||
impUnsubmitted Not Done Inline Actionswhat does this accomplish? Seems totally redundant. imp: what does this accomplish? Seems totally redundant. | |||||
julianAuthorUnsubmitted Not Done Inline Actionsyou could say "only check once a minute, but what if the time is set backwards or forwards. a count of calls is a catch-all.. you could also say We have several hundred logs per second and don't want to wait a minute. I agree there's duplication but not redundancy. julian: you could say "only check once a minute, but what if the time is set backwards or forwards. a… | |||||
(current_time - last_check_time > CHECK_INTERVAL)) { | |||||
if (fstatat(AT_FDCWD, TZ_FILENAME, &buf, AT_SYMLINK_NOFOLLOW ) == 0) { | |||||
impUnsubmitted Not Done Inline ActionsThis is wrong. imp: This is wrong.
You should default to TZ_FILENAME if no TZ variable is set, otherwise you should… | |||||
julianAuthorUnsubmitted Not Done Inline Actionswell that depends. If you think it's important then it can be done.. we just don't need it, so it's extra. julian: well that depends.
I'm not watching for someone updating the definition of America/Podunk, but… | |||||
cgull_glup.orgUnsubmitted Not Done Inline ActionsWell, what if the timezone files themselves change? freebsd-update might do that without a reboot, for instance. That might be another case you want to handle, though I think it makes monitoring more complex, because then you have to watch both the symlink and its target. I don't know that this is a must-do but it does seem a little inconsistent to update on symlink changes but not on file changes. (I work for another appliance vendor, but I don't think this actually is an issue for us, so this is a somewhat theoretical observation) cgull_glup.org: Well, what if the timezone files themselves change? freebsd-update might do that without a… | |||||
if (tzfile_ctime != buf.st_ctime) { | |||||
tzfile_ctime = buf.st_ctime; | |||||
is_change = 1; | |||||
} | |||||
} else { | |||||
if (tzfile_ctime != 0) { | |||||
/* it went away.. do whatever we do with no TZ */ | |||||
is_change = 1; | |||||
tzfile_ctime = (time_t)0; | |||||
} | |||||
} | |||||
check_times = 0; | |||||
last_check_time = current_time; | |||||
} | |||||
} | |||||
if (is_lcl_set == 0 && is_change == 0) { | |||||
julianAuthorUnsubmitted Not Done Inline Actionsthis bit may change if I can wrap my head around what lcl_is_set is trying to do julian: this bit may change if I can wrap my head around what lcl_is_set is trying to do | |||||
if ( lcl_is_set >= 0 ) { | |||||
is_change = 1; | |||||
} | |||||
} else if (is_lcl_set == 1 && is_change == 0) { | |||||
if ( lcl_is_set <= 0) { | |||||
is_change = 1; | |||||
} | |||||
} | |||||
return is_change; | |||||
} | |||||
static long | static long | ||||
detzcode(const char *const codep) | detzcode(const char *const codep) | ||||
{ | { | ||||
long result; | long result; | ||||
int i; | int i; | ||||
result = (codep[0] & 0x80) ? ~0L : 0; | result = (codep[0] & 0x80) ? ~0L : 0; | ||||
for (i = 0; i < 4; ++i) | for (i = 0; i < 4; ++i) | ||||
▲ Show 20 Lines • Show All 940 Lines • ▼ Show 20 Lines | if (tzload(gmt, sp, TRUE) != 0) | ||||
(void) tzparse(gmt, sp, TRUE); | (void) tzparse(gmt, sp, TRUE); | ||||
} | } | ||||
static void | static void | ||||
tzsetwall_basic(int rdlocked) | tzsetwall_basic(int rdlocked) | ||||
{ | { | ||||
if (!rdlocked) | if (!rdlocked) | ||||
_RWLOCK_RDLOCK(&lcl_rwlock); | _RWLOCK_RDLOCK(&lcl_rwlock); | ||||
if (lcl_is_set < 0) { | if ((check_tz_change(0) == 0)) { | ||||
if (!rdlocked) | if (!rdlocked) | ||||
_RWLOCK_UNLOCK(&lcl_rwlock); | _RWLOCK_UNLOCK(&lcl_rwlock); | ||||
return; | return; | ||||
} | } | ||||
_RWLOCK_UNLOCK(&lcl_rwlock); | _RWLOCK_UNLOCK(&lcl_rwlock); | ||||
_RWLOCK_WRLOCK(&lcl_rwlock); | _RWLOCK_WRLOCK(&lcl_rwlock); | ||||
lcl_is_set = -1; | lcl_is_set = -1; | ||||
Show All 33 Lines | tzset_basic(int rdlocked) | ||||
name = getenv("TZ"); | name = getenv("TZ"); | ||||
if (name == NULL) { | if (name == NULL) { | ||||
tzsetwall_basic(rdlocked); | tzsetwall_basic(rdlocked); | ||||
return; | return; | ||||
} | } | ||||
if (!rdlocked) | if (!rdlocked) | ||||
_RWLOCK_RDLOCK(&lcl_rwlock); | _RWLOCK_RDLOCK(&lcl_rwlock); | ||||
if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) { | if (strcmp(lcl_TZname, name) == 0 && check_tz_change(1) == 0 ) { | ||||
if (!rdlocked) | if (!rdlocked) | ||||
_RWLOCK_UNLOCK(&lcl_rwlock); | _RWLOCK_UNLOCK(&lcl_rwlock); | ||||
return; | return; | ||||
} | } | ||||
_RWLOCK_UNLOCK(&lcl_rwlock); | _RWLOCK_UNLOCK(&lcl_rwlock); | ||||
_RWLOCK_WRLOCK(&lcl_rwlock); | _RWLOCK_WRLOCK(&lcl_rwlock); | ||||
lcl_is_set = strlen(name) < sizeof lcl_TZname; | lcl_is_set = strlen(name) < sizeof lcl_TZname; | ||||
▲ Show 20 Lines • Show All 955 Lines • Show Last 20 Lines |
nominal defaults. don't do the work every time you get called.. that could be a lot. Maybe once a minute or every 100 messages (which ever happens first) would be enough.
I'm unhappy about doing a time() each time, but maybe we can pass it down from callers if they already have it?