mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-04-06 15:00:40 +08:00
Add lutil_gettime() returning structured time with microseconds. Use
microseconds in CSNs. Omit microseconds from modifyTImestamp...
This commit is contained in:
parent
5afd693a6d
commit
4b1bb81452
@ -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, <m_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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user