]> git.sur5r.net Git - openldap/blobdiff - libraries/liblutil/utils.c
ITS#5129 fix alock_close with Quick mode
[openldap] / libraries / liblutil / utils.c
index bffeef84a4c3f1ad3e845fab4f719aba7b016471..2cd105ed92cf6dd4ddbb4f1c6ea1a7713b24a0dc 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2007 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -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,117 @@ int lutil_parsetime( char *atm, struct lutil_tm *tm )
        return -1;
 }
 
+/* return a broken out time, with microseconds
+ * Must be mutex-protected.
+ */
+#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 LARGE_INTEGER prevCount;
+       static int subs;
+       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;
+       }
+
+       /* It shouldn't ever go backwards, but multiple CPUs might
+        * be able to hit in the same tick.
+        */
+       if ( count.QuadPart <= prevCount.QuadPart ) {
+               subs++;
+       } else {
+               subs = 0;
+               prevCount = count;
+       }
+
+       tm->tm_usub = subs;
+
+       /* convert to microseconds */
+       count.QuadPart *= 1000000;
+       count.QuadPart /= cFreq.QuadPart;
+       count.QuadPart -= offset;
+
+       tm->tm_usec = count.QuadPart % 1000000;
+
+       /* 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;
+       static struct timeval prevTv;
+       static int subs;
+
+#ifdef HAVE_GMTIME_R
+       struct tm tm_buf;
+#endif
+       struct tm *tm;
+       time_t t;
+
+       gettimeofday( &tv, NULL );
+       t = tv.tv_sec;
+
+       if ( tv.tv_sec < prevTv.tv_sec
+               || ( tv.tv_sec == prevTv.tv_sec && tv.tv_usec == prevTv.tv_usec )) {
+               subs++;
+       } else {
+               subs = 0;
+               prevTv = tv;
+       }
+
+       ltm->tm_usub = subs;
+
+#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 +430,6 @@ int mkstemp( char * template )
 #endif
 
 #ifdef _MSC_VER
-#include <windows.h>
 struct dirent {
        char *d_name;
 };
@@ -491,6 +604,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,
@@ -572,154 +686,3 @@ lutil_unparse_time(
        return 0;
 }
 
-/*
- * lutil_bisect_find
- *
- * args:
- *     v:      array of length n (in)
- *     n:      length of array v (in)
- *     id:     value to look for (in)
- *     idxp:   pointer to location of value/insert point
- *
- * return:
- *     0:      not found
- *     1:      found
- *     -1:     error
- */
-int
-lutil_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp )
-{
-       int             begin,
-                       end,
-                       i,
-                       rc = 0;
-
-       assert( n >= 0 );
-       assert( id >= 0 );
-
-       begin = 0;
-       end = n - 1;
-
-       if ( n > 0 ) {
-               if ( id < v[ begin ] ) {
-                       *idxp = 0;
-
-               } else if ( id > v[ end ] ) {
-                       *idxp = n;
-
-               } else {
-                       int             pos;
-                       ber_int_t       curid;
-       
-                       while ( end >= begin ) {
-                               pos = (begin + end)/2;
-                               curid = v[ pos ];
-       
-                               if ( id < curid ) {
-                                       end = pos - 1;
-       
-                               } else if ( id > curid ) {
-                                       begin = pos + 1;
-       
-                               } else {
-                                       /* already abandoned? */
-                                       *idxp = pos;
-                                       rc = 1;
-                                       break;
-                               }
-                       }
-       
-                       if ( rc == 0 ) {
-                               *idxp = pos + ( id > curid ? 1 : 0 );
-                       }
-               }
-
-       } else {
-               *idxp = 0;
-       }
-
-       return rc;
-}
-
-/*
- * lutil_bisect_insert
- *
- * args:
- *     vp:     pointer to array of length *np (in/out)
- *     np:     pointer to length of array *vp (in/out)
- *     id:     value to insert (in)
- *     idx:    location of insert point (as computed by lutil_bosect_find())
- *
- * return:
- *     0:      inserted
- *     -1:     error
- */
-int
-lutil_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx )
-{
-       ber_int_t       *v;
-       ber_len_t       n;
-       int             i;
-
-       assert( vp != NULL );
-       assert( np != NULL );
-       assert( *np >= 0 );
-       assert( idx >= 0 );
-       assert( idx <= *np );
-
-       n = *np;
-
-       v = ber_memrealloc( *vp, sizeof( ber_int_t ) * ( n + 1 ) );
-       if ( v == NULL ) {
-               return -1;
-       }
-       *vp = v;
-
-       for ( i = n; i > idx; i-- ) {
-               v[ i ] = v[ i - 1 ];
-       }
-       v[ idx ] = id;
-       ++(*np);
-
-       return 0;
-}
-
-/*
- * lutil_bisect_delete
- *
- * args:
- *     vp:     pointer to array of length *np (in/out)
- *     np:     pointer to length of array *vp (in/out)
- *     id:     value to delete (in)
- *     idx:    location of value to delete (as computed by lutil_bosect_find())
- *
- * return:
- *     0:      deleted
- */
-int
-lutil_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx )
-{
-       ber_int_t       *v;
-       ber_len_t       n;
-       int             i;
-
-       assert( vp != NULL );
-       assert( np != NULL );
-       assert( *np >= 0 );
-       assert( idx >= 0 );
-       assert( idx < *np );
-
-       v = *vp;
-
-       assert( v[ idx ] == id );
-
-       --(*np);
-       n = *np;
-
-       for ( i = idx; i < n; i++ ) {
-               v[ i ] = v[ i + 1 ];
-       }
-
-       return 0;
-}
-