Mercurial > hg > nginx-vendor-current
view src/core/ngx_times.c @ 196:8759b346e431 NGINX_0_3_45
nginx 0.3.45
*) Feature: the "ssl_verify_client", "ssl_verify_depth", and
"ssl_client_certificate" directives.
*) Change: the $request_method variable now returns the main request
method.
*) Change: the ° symbol codes were changed in koi-win conversion
table.
*) Feature: the euro и N symbols were added to koi-win conversion table.
*) Bugfix: if nginx distributed the requests among several backends and
some backend failed, then requests intended for this backend was
directed to one live backend only instead of being distributed among
the rest.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Sat, 06 May 2006 00:00:00 +0400 |
parents | 408f195b3482 |
children | e0b1d0a6c629 |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev */ #include <ngx_config.h> #include <ngx_core.h> /* * The time may be updated by signal handler or by several threads. * The time update operations are rare and require to hold the ngx_time_lock. * The time read operations are frequent, so they are lock-free and get time * values and strings from the current slot. Thus thread may get the corrupted * values only if it is preempted while copying and then it is not scheduled * to run more than NGX_TIME_SLOTS seconds. */ #define NGX_TIME_SLOTS 64 static ngx_uint_t slot = NGX_TIME_SLOTS; static ngx_atomic_t ngx_time_lock; volatile ngx_msec_t ngx_current_msec; volatile ngx_time_t *ngx_cached_time; volatile ngx_str_t ngx_cached_err_log_time; volatile ngx_str_t ngx_cached_http_time; volatile ngx_str_t ngx_cached_http_log_time; static ngx_time_t cached_time[NGX_TIME_SLOTS]; static u_char cached_err_log_time[NGX_TIME_SLOTS] [sizeof("1970/09/28 12:00:00")]; static u_char cached_http_time[NGX_TIME_SLOTS] [sizeof("Mon, 28 Sep 1970 06:00:00 GMT")]; static u_char cached_http_log_time[NGX_TIME_SLOTS] [sizeof("28/Sep/1970:12:00:00 +0600")]; static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; void ngx_time_init(void) { ngx_cached_err_log_time.len = sizeof("1970/09/28 12:00:00") - 1; ngx_cached_http_time.len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1; ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1; ngx_cached_time = &cached_time[0]; #if !(NGX_WIN32) tzset(); #endif ngx_time_update(0, 0); } void ngx_time_update(time_t sec, ngx_uint_t msec) { u_char *p0, *p1, *p2; ngx_tm_t tm, gmt; ngx_time_t *tp; struct timeval tv; if (!ngx_trylock(&ngx_time_lock)) { return; } if (slot == NGX_TIME_SLOTS) { slot = 0; } else { slot++; } if (sec == 0) { ngx_gettimeofday(&tv); sec = tv.tv_sec; msec = tv.tv_usec / 1000; } ngx_current_msec = (ngx_msec_t) sec * 1000 + msec; tp = &cached_time[slot]; tp->msec = msec; if (tp->sec == sec) { ngx_unlock(&ngx_time_lock); return; } tp->sec = sec; ngx_gmtime(sec, &gmt); p0 = cached_http_time[slot]; (void) ngx_sprintf(p0, "%s, %02d %s %4d %02d:%02d:%02d GMT", week[gmt.ngx_tm_wday], gmt.ngx_tm_mday, months[gmt.ngx_tm_mon - 1], gmt.ngx_tm_year, gmt.ngx_tm_hour, gmt.ngx_tm_min, gmt.ngx_tm_sec); #if (NGX_HAVE_GETTIMEZONE) tp->gmtoff = ngx_gettimezone(); ngx_gmtime(sec + tp->gmtoff * 60, &tm); #elif (NGX_HAVE_GMTOFF) ngx_localtime(sec, &tm); tp->gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60); #else ngx_localtime(sec, &tm); tp->gmtoff = ngx_timezone(tm.ngx_tm_isdst); #endif p1 = cached_err_log_time[slot]; (void) ngx_sprintf(p1, "%4d/%02d/%02d %02d:%02d:%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); p2 = cached_http_log_time[slot]; (void) ngx_sprintf(p2, "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec, tp->gmtoff < 0 ? '-' : '+', ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60)); ngx_memory_barrier(); ngx_cached_time = tp; ngx_cached_http_time.data = p0; ngx_cached_err_log_time.data = p1; ngx_cached_http_log_time.data = p2; ngx_unlock(&ngx_time_lock); } u_char * ngx_http_time(u_char *buf, time_t t) { ngx_tm_t tm; ngx_gmtime(t, &tm); return ngx_sprintf(buf, "%s, %02d %s %4d %02d:%02d:%02d GMT", week[tm.ngx_tm_wday], tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); } u_char * ngx_http_cookie_time(u_char *buf, time_t t) { ngx_tm_t tm; ngx_gmtime(t, &tm); /* * Netscape 3.x does not understand 4-digit years at all and * 2-digit years more than "37" */ return ngx_sprintf(buf, (tm.ngx_tm_year > 2037) ? "%s, %02d-%s-%d %02d:%02d:%02d GMT": "%s, %02d-%s-%02d %02d:%02d:%02d GMT", week[tm.ngx_tm_wday], tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], (tm.ngx_tm_year > 2037) ? tm.ngx_tm_year: tm.ngx_tm_year % 100, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); } void ngx_gmtime(time_t t, ngx_tm_t *tp) { ngx_int_t sec, min, hour, mday, mon, year, wday, yday, days; days = t / 86400; /* Jaunary 1, 1970 was Thursday */ wday = (4 + days) % 7; t %= 86400; hour = t / 3600; t %= 3600; min = t / 60; sec = t % 60; /* the algorithm based on Gauss's formula */ days = days - (31 + 28) + 719527; year = days * 400 / (365 * 400 + 100 - 4 + 1); yday = days - (365 * year + year / 4 - year / 100 + year / 400); mon = (yday + 31) * 12 / 367; mday = yday - (mon * 367 / 12 - 31); mon += 2; if (yday >= 306) { /* * there is no "yday" in Win32 SYSTEMTIME * * yday -= 306; */ year++; mon -= 12; if (mday == 0) { /* Jaunary 31 */ mon = 1; mday = 31; } else if (mon == 2) { if ((year % 4 == 0) && (year % 100 || (year % 400 == 0))) { if (mday > 29) { mon = 3; mday -= 29; } } else if (mday > 28) { mon = 3; mday -= 28; } } /* * there is no "yday" in Win32 SYSTEMTIME * * } else { * yday += 31 + 28; * * if ((year % 4 == 0) && (year % 100 || (year % 400 == 0))) { * yday++; * } */ } tp->ngx_tm_sec = (ngx_tm_sec_t) sec; tp->ngx_tm_min = (ngx_tm_min_t) min; tp->ngx_tm_hour = (ngx_tm_hour_t) hour; tp->ngx_tm_mday = (ngx_tm_mday_t) mday; tp->ngx_tm_mon = (ngx_tm_mon_t) mon; tp->ngx_tm_year = (ngx_tm_year_t) year; tp->ngx_tm_wday = (ngx_tm_wday_t) wday; }