]> git.sur5r.net Git - openldap/blobdiff - libraries/libmdb/mdb.c
explain mdl_midl_sort() istack size
[openldap] / libraries / libmdb / mdb.c
index 7150d5062c27b35661693c75299c14fae2b7a752..b73541bd39934efa74b7c13509af984f09edd113 100644 (file)
@@ -48,6 +48,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <limits.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
 #include "mdb.h"
 #include "midl.h"
 
+#if (__BYTE_ORDER == __LITTLE_ENDIAN) == (__BYTE_ORDER == __BIG_ENDIAN)
+# error "Unknown or unsupported endianness (__BYTE_ORDER)"
+#elif (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF
+# error "Two's complement, reasonably sized integer types, please"
+#endif
+
 /** @defgroup internal MDB Internals
  *     @{
  */
@@ -243,7 +250,7 @@ typedef ULONG               pgno_t;
         */
 #define        DKEY(x) mdb_dkey(x, kbuf)
 #else
-#define        DKBUF
+#define        DKBUF   typedef int dummy_kbuf  /* so we can put ';' after */
 #define DKEY(x)
 #endif
 
@@ -268,7 +275,7 @@ typedef ULONG               pgno_t;
 #define        LAZY_RWLOCK_WRLOCK(x)
        /** Grab the DB table read lock */
 #define        LAZY_RWLOCK_RDLOCK(x)
-       /** Declare the DB table rwlock */
+       /** Declare the DB table rwlock.  Should not be followed by ';'. */
 #define        LAZY_RWLOCK_DEF(x)
        /** Initialize the DB table rwlock */
 #define        LAZY_RWLOCK_INIT(x,y)
@@ -533,10 +540,13 @@ typedef struct MDB_page {
 typedef struct MDB_node {
        /** lo and hi are used for data size on leaf nodes and for
         * child pgno on branch nodes. On 64 bit platforms, flags
-        * is also used for pgno. (branch nodes ignore flags)
+        * is also used for pgno. (Branch nodes have no flags).
+        * They are in in host byte order in case that lets some
+        * accesses be optimized into a 32-bit word access.
         */
-       unsigned short  mn_lo;
-       unsigned short  mn_hi;                  /**< part of dsize or pgno */
+#define mn_lo mn_offset[__BYTE_ORDER!=__LITTLE_ENDIAN]
+#define mn_hi mn_offset[__BYTE_ORDER==__LITTLE_ENDIAN] /**< part of dsize or pgno */
+       unsigned short  mn_offset[2];
        unsigned short  mn_flags;               /**< flags for special node types */
 #define F_BIGDATA       0x01                   /**< data put on overflow page */
 #define F_SUBDATA       0x02                   /**< data is a sub-database */
@@ -781,7 +791,7 @@ struct MDB_env {
        /** ID2L of pages that were written during a write txn */
        ID2                     me_dirty_list[MDB_IDL_UM_SIZE];
        /** rwlock for the DB tables, if #LAZY_LOCKS is false */
-       LAZY_RWLOCK_DEF(me_dblock);
+       LAZY_RWLOCK_DEF(me_dblock)
 #ifdef _WIN32
        HANDLE          me_rmutex;              /* Windows mutexes don't reside in shared mem */
        HANDLE          me_wmutex;
@@ -2316,8 +2326,8 @@ cintcmp(const MDB_val *a, const MDB_val *b)
        unsigned short *u, *c;
        int x;
 
-       u = a->mv_data + a->mv_size;
-       c = b->mv_data + a->mv_size;
+       u = (unsigned short *) ((char *) a->mv_data + a->mv_size);
+       c = (unsigned short *) ((char *) b->mv_data + a->mv_size);
        do {
                x = *--u - *--c;
        } while(!x && u > (unsigned short *)a->mv_data);
@@ -2330,45 +2340,44 @@ cintcmp(const MDB_val *a, const MDB_val *b)
 static int
 memncmp(const MDB_val *a, const MDB_val *b)
 {
-       int diff, len_diff;
+       int diff;
+       ssize_t len_diff;
        unsigned int len;
 
        len = a->mv_size;
-       len_diff = a->mv_size - b->mv_size;
-       if (len_diff > 0)
+       len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size;
+       if (len_diff > 0) {
                len = b->mv_size;
+               len_diff = 1;
+       }
+
        diff = memcmp(a->mv_data, b->mv_data, len);
-       return diff ? diff : len_diff;
+       return diff ? diff : len_diff<0 ? -1 : len_diff;
 }
 
 static int
 memnrcmp(const MDB_val *a, const MDB_val *b)
 {
        const unsigned char     *p1, *p2, *p1_lim;
-       int diff, len_diff;
+       ssize_t len_diff;
+       int diff;
 
-       if (b->mv_size == 0)
-               return a->mv_size != 0;
-       if (a->mv_size == 0)
-               return -1;
+       p1_lim = (const unsigned char *)a->mv_data;
+       p1 = (const unsigned char *)a->mv_data + a->mv_size;
+       p2 = (const unsigned char *)b->mv_data + b->mv_size;
 
-       p1 = (const unsigned char *)a->mv_data + a->mv_size - 1;
-       p2 = (const unsigned char *)b->mv_data + b->mv_size - 1;
-
-       len_diff = a->mv_size - b->mv_size;
-       if (len_diff < 0)
-               p1_lim = p1 - a->mv_size;
-       else
-               p1_lim = p1 - b->mv_size;
+       len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size;
+       if (len_diff > 0) {
+               p1_lim += len_diff;
+               len_diff = 1;
+       }
 
        while (p1 > p1_lim) {
-               diff = *p1 - *p2;
+               diff = *--p1 - *--p2;
                if (diff)
                        return diff;
-               p1--;
-               p2--;
        }
-       return len_diff;
+       return len_diff<0 ? -1 : len_diff;
 }
 
 /* Search for key within a leaf page, using binary search.