]> git.sur5r.net Git - openldap/commitdiff
Add lutil_gettime() returning structured time with microseconds. Use
authorHoward Chu <hyc@openldap.org>
Fri, 2 Feb 2007 23:10:30 +0000 (23:10 +0000)
committerHoward Chu <hyc@openldap.org>
Fri, 2 Feb 2007 23:10:30 +0000 (23:10 +0000)
microseconds in CSNs. Omit microseconds from modifyTImestamp...

include/lutil.h
libraries/liblutil/csn.c
libraries/liblutil/utils.c
servers/slapd/add.c
servers/slapd/modify.c

index 6b2bf76beface0d086256eeb03d310d7aaf82516..c5b9c528cf4f51bdd90472b8027c10541df3f3cd 100644 (file)
@@ -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 );
 
index 51683f0466ee56db0c7be47ee0391f0561a2765a..647eabe4ec9ee03d28fee8793872b549f55bda5c 100644 (file)
@@ -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().
 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;
index 96271b4e1e463002a9e2e489c3519f21c4ffac6e..ee69a1baf06b5409d144dd258d5ce3eeebd49d30 100644 (file)
@@ -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,
index db9b809752342a1baf28f6fe5afdf6c8dadb1d6d..8d22d54afc255c11b7a4279192511b2cc75d4713 100644 (file)
@@ -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();
index ca53e0b9fa0e19284e31371351135341821a21f9..0cd1d039ab85b9bafd28040c07d578db28de7483 100644 (file)
@@ -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 {