/* $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
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
#include "lutil.h"
#include "ldap_defaults.h"
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.
#endif
#ifdef _MSC_VER
-#include <windows.h>
struct dirent {
char *d_name;
};
static char time_unit[] = "dhms";
+/* Used to parse and unparse time intervals, not timestamps */
int
lutil_parse_time(
const char *in,
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;
-}
-