Skip to content
Snippets Groups Projects
Commit 4b1bb814 authored by Howard Chu's avatar Howard Chu
Browse files

Add lutil_gettime() returning structured time with microseconds. Use

microseconds in CSNs. Omit microseconds from modifyTImestamp...
parent 5afd693a
No related branches found
No related tags found
No related merge requests found
......@@ -166,14 +166,20 @@ typedef struct lutil_timet {
unsigned int tt_usec; /* microseconds */
} lutil_timet;
/* Parse a timestamp string into a structure */
LDAP_LUTIL_F( int )
lutil_parsetime LDAP_P((
char *atm, struct lutil_tm * ));
/* Convert structured time to time in seconds since 1900 */
LDAP_LUTIL_F( int )
lutil_tm2time LDAP_P((
struct lutil_tm *, struct lutil_timet * ));
/* Get current time as a structured time */
LDAP_LUTIL_F( void )
lutil_gettime LDAP_P(( struct lutil_tm * ));
#ifdef _WIN32
LDAP_LUTIL_F( void )
lutil_slashpath LDAP_P(( char* path ));
......@@ -290,6 +296,7 @@ lutil_atoulx( unsigned long *v, const char *s, int x );
#define lutil_atol(v, s) lutil_atolx((v), (s), 10)
#define lutil_atoul(v, s) lutil_atoulx((v), (s), 10)
/* Parse and unparse time intervals */
LDAP_LUTIL_F (int)
lutil_parse_time( const char *in, unsigned long *tp );
......
......@@ -35,8 +35,8 @@
* where s is a counter of operations within a timeslice, r is
* the replica id (normally zero), and c is a counter of
* modifications within this operation. s, r, and c are
* represented in hex and zero padded to lengths of 6, 2, and
* 6, respectively.
* represented in hex and zero padded to lengths of 6, 3, and
* 6, respectively. (In previous implementations r was only 2 digits.)
*
* Calls to this routine MUST be serialized with other calls
* to gmtime().
......@@ -51,33 +51,26 @@
size_t
lutil_csnstr(char *buf, size_t len, unsigned int replica, unsigned int mod)
{
static time_t csntime;
struct lutil_tm tm;
static unsigned int csnop;
static int prev_sec, prev_usec;
time_t t;
unsigned int op;
struct tm *ltm;
#ifdef HAVE_GMTIME_R
struct tm ltm_buf;
#endif
int n;
time( &t );
if ( t > csntime ) {
csntime = t;
lutil_gettime( &tm );
if ( tm.tm_usec != prev_usec || tm.tm_sec != prev_sec ) {
prev_sec = tm.tm_sec;
prev_usec = tm.tm_usec;
csnop = 0;
}
op = csnop++;
#ifdef HAVE_GMTIME_R
ltm = gmtime_r( &t, &ltm_buf );
#else
ltm = gmtime( &t );
#endif
n = snprintf( buf, len,
"%4d%02d%02d%02d%02d%02dZ#%06x#%02x#%06x",
ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour,
ltm->tm_min, ltm->tm_sec, op, replica, mod );
"%4d%02d%02d%02d%02d%02d.%06dZ#%06x#%03x#%06x",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
tm.tm_min, tm.tm_sec, tm.tm_usec, op, replica, mod );
if( n < 0 ) return 0;
return ( (size_t) n < len ) ? n : 0;
......
......@@ -27,6 +27,9 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#include "lutil.h"
#include "ldap_defaults.h"
......@@ -269,6 +272,89 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm )
return -1;
}
/* return a broken out time, with microseconds */
#ifdef _WIN32
/* Windows SYSTEMTIME only has 10 millisecond resolution, so we
* also need to use a high resolution timer to get microseconds.
* This is pretty clunky.
*/
void
lutil_gettime( struct lutil_tm *tm )
{
static LARGE_INTEGER cFreq;
static int offset;
LARGE_INTEGER count;
SYSTEMTIME st;
GetSystemTime( &st );
QueryPerformanceCounter( &count );
/* We assume Windows has at least a vague idea of
* when a second begins. So we align our microsecond count
* with the Windows millisecond count using this offset.
* We retain the submillisecond portion of our own count.
*/
if ( !cFreq.QuadPart ) {
long long t;
int usec;
QueryPerformanceFrequency( &cFreq );
t = count.QuadPart * 1000000;
t /= cFreq.QuadPart;
usec = t % 10000000;
usec /= 1000;
offset = ( usec - st.wMilliseconds ) * 1000;
}
/* convert to microseconds */
count.QuadPart *= 1000000;
count.QuadPart /= cFreq.QuadPart;
count.QuadPart -= offset;
tm->tm_usec = count.QuadPart % 1000000;
printf("tm_usec %d, msec %d\n", tm->tm_usec, st.wMilliseconds);
/* any difference larger than microseconds is
* already reflected in st
*/
tm->tm_sec = st.wSecond;
tm->tm_min = st.wMinute;
tm->tm_hour = st.wHour;
tm->tm_mday = st.wDay;
tm->tm_mon = st.wMonth - 1;
tm->tm_year = st.wYear - 1900;
}
#else
void
lutil_gettime( struct lutil_tm *ltm )
{
struct timeval tv;
#ifdef HAVE_GMTIME_R
struct tm tm_buf;
#endif
struct tm *tm;
time_t t;
gettimeofday( &tv, NULL );
t = tv.tv_sec;
#ifdef HAVE_GMTIME_R
tm = gmtime_r( &t, &tm_buf );
#else
tm = gmtime( &t );
#endif
ltm->tm_sec = tm->tm_sec;
ltm->tm_min = tm->tm_min;
ltm->tm_hour = tm->tm_hour;
ltm->tm_mday = tm->tm_mday;
ltm->tm_mon = tm->tm_mon;
ltm->tm_year = tm->tm_year;
ltm->tm_usec = tv.tv_usec;
}
#endif
/* strcopy is like strcpy except it returns a pointer to the trailing NUL of
* the result string. This allows fast construction of catenated strings
* without the overhead of strlen/strcat.
......@@ -316,7 +402,6 @@ int mkstemp( char * template )
#endif
#ifdef _MSC_VER
#include <windows.h>
struct dirent {
char *d_name;
};
......@@ -491,6 +576,7 @@ lutil_atoulx( unsigned long *v, const char *s, int x )
static char time_unit[] = "dhms";
/* Used to parse and unparse time intervals, not timestamps */
int
lutil_parse_time(
const char *in,
......
......@@ -608,10 +608,9 @@ int slap_add_opattrs(
}
ptr = ber_bvchr( &csn, '#' );
if ( ptr ) {
timestamp.bv_len = ptr - csn.bv_val;
if ( timestamp.bv_len >= sizeof(timebuf) ) /* ?!? */
timestamp.bv_len = sizeof(timebuf) - 1;
timestamp.bv_len = STRLENOF("YYYYMMDDHHMMSSZ");
AC_MEMCPY( timebuf, csn.bv_val, timestamp.bv_len );
timebuf[timestamp.bv_len-1] = 'Z';
timebuf[timestamp.bv_len] = '\0';
} else {
time_t now = slap_get_time();
......
......@@ -924,11 +924,9 @@ void slap_mods_opattrs(
ptr = ber_bvchr( &csn, '#' );
if ( ptr ) {
timestamp.bv_len = ptr - csn.bv_val;
if ( timestamp.bv_len >= sizeof( timebuf ) ) { /* ?!? */
timestamp.bv_len = sizeof( timebuf ) - 1;
}
timestamp.bv_len = STRLENOF("YYYYMMDDHHMMSSZ");
AC_MEMCPY( timebuf, csn.bv_val, timestamp.bv_len );
timebuf[timestamp.bv_len-1] = 'Z';
timebuf[timestamp.bv_len] = '\0';
} else {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment