r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation
[tprouty/samba.git] / source / tdb / tdb.c
index 0ebbc8b21ebdeca1eb543928026d5b35356fc88c..45895d2ec71bc4a84d53a7a40729415db385a553 100644 (file)
 #include "spinlock.h"
 #else
 #include "includes.h"
+
+#if defined(PARANOID_MALLOC_CHECKER)
+#ifdef malloc
+#undef malloc
+#endif
+
+#ifdef realloc
+#undef realloc
+#endif
+
+#ifdef calloc
+#undef calloc
+#endif
+
+#ifdef strdup
+#undef strdup
+#endif
+
+#ifdef strndup
+#undef strndup
+#endif
+
+#endif
+
 #endif
 
 #define TDB_MAGIC_FOOD "TDB file\n"
@@ -276,7 +300,7 @@ static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype)
        if (tdb->locked[list+1].count == 0) {
                if (!tdb->read_only && tdb->header.rwlocks) {
                        if (tdb_spinlock(tdb, list, ltype)) {
-                               TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list ltype=%d\n", 
+                               TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n", 
                                           list, ltype));
                                return -1;
                        }
@@ -476,7 +500,7 @@ static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec)
        if (rec->magic == TDB_MAGIC) {
                /* this happens when a app is showdown while deleting a record - we should
                   not completely fail when this happens */
-               TDB_LOG((tdb, 0,"rec_free_read non-free magic at offset=%d - fixing\n", 
+               TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", 
                         rec->magic, off));
                rec->magic = TDB_FREE_MAGIC;
                if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
@@ -1007,26 +1031,12 @@ static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash,
        return TDB_ERRCODE(TDB_ERR_NOEXIST, 0);
 }
 
-/* If they do lockkeys, check that this hash is one they locked */
-static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash)
-{
-       u32 i;
-       if (!tdb->lockedkeys)
-               return 1;
-       for (i = 0; i < tdb->lockedkeys[0]; i++)
-               if (tdb->lockedkeys[i+1] == hash)
-                       return 1;
-       return TDB_ERRCODE(TDB_ERR_NOLOCK, 0);
-}
-
 /* As tdb_find, but if you succeed, keep the lock */
 static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype,
                             struct list_struct *rec)
 {
        u32 rec_ptr;
 
-       if (!tdb_keylocked(tdb, hash))
-               return 0;
        if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
                return 0;
        if (!(rec_ptr = tdb_find(tdb, key, hash, rec)))
@@ -1228,10 +1238,6 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock,
 {
        int want_next = (tlock->off != 0);
 
-       /* No traversal allows if you've called tdb_lockkeys() */
-       if (tdb->lockedkeys)
-               return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
-
        /* Lock each chain from the start one. */
        for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
                if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1)
@@ -1463,8 +1469,6 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
 
        /* find which hash bucket it is in */
        hash = tdb->hash_fn(&key);
-       if (!tdb_keylocked(tdb, hash))
-               return -1;
        if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
                return -1;
 
@@ -1581,8 +1585,6 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
 
        /* find which hash bucket it is in */
        hash = tdb->hash_fn(&key);
-       if (!tdb_keylocked(tdb, hash))
-               return -1;
        if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
                return -1;
 
@@ -1689,11 +1691,6 @@ static u32 default_tdb_hash(TDB_DATA *key)
        return (1103515243 * value + 12345);  
 }
 
-void tdb_set_hash_function(TDB_CONTEXT *tdb, tdb_hash_func fn)
-{
-       tdb->hash_fn = fn;
-}
-
 /* open the database, creating it if necessary 
 
    The open_flags and mode are passed straight to the open call on the
@@ -1707,13 +1704,14 @@ void tdb_set_hash_function(TDB_CONTEXT *tdb, tdb_hash_func fn)
 TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
                      int open_flags, mode_t mode)
 {
-       return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL);
+       return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
 }
 
 
 TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
                         int open_flags, mode_t mode,
-                        tdb_log_func log_fn)
+                        tdb_log_func log_fn,
+                        tdb_hash_func hash_fn)
 {
        TDB_CONTEXT *tdb;
        struct stat st;
@@ -1729,11 +1727,10 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
        tdb->fd = -1;
        tdb->name = NULL;
        tdb->map_ptr = NULL;
-       tdb->lockedkeys = NULL;
        tdb->flags = tdb_flags;
        tdb->open_flags = open_flags;
        tdb->log_fn = log_fn;
-       tdb->hash_fn = default_tdb_hash;
+       tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
 
        if ((open_flags & O_ACCMODE) == O_WRONLY) {
                TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n",
@@ -1815,7 +1812,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
        if (tdb_already_open(st.st_dev, st.st_ino)) {
                TDB_LOG((tdb, 2, "tdb_open_ex: "
                         "%s (%d,%d) is already open in this process\n",
-                        name, st.st_dev, st.st_ino));
+                        name, (int)st.st_dev, (int)st.st_ino));
                errno = EBUSY;
                goto fail;
        }
@@ -1917,7 +1914,6 @@ int tdb_close(TDB_CONTEXT *tdb)
        if (tdb->fd != -1)
                ret = close(tdb->fd);
        SAFE_FREE(tdb->locked);
-       SAFE_FREE(tdb->lockedkeys);
 
        /* Remove from contexts list */
        for (i = &tdbs; *i; i = &(*i)->next) {
@@ -1941,8 +1937,6 @@ int tdb_lockall(TDB_CONTEXT *tdb)
        /* There are no locks on read-only dbs */
        if (tdb->read_only)
                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-       if (tdb->lockedkeys)
-               return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
        for (i = 0; i < tdb->header.hash_size; i++) 
                if (tdb_lock(tdb, i, F_WRLCK))
                        break;
@@ -1965,51 +1959,6 @@ void tdb_unlockall(TDB_CONTEXT *tdb)
                tdb_unlock(tdb, i, F_WRLCK);
 }
 
-int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[])
-{
-       u32 i, j, hash;
-
-       /* Can't lock more keys if already locked */
-       if (tdb->lockedkeys)
-               return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
-       if (!(tdb->lockedkeys = malloc(sizeof(u32) * (number+1))))
-               return TDB_ERRCODE(TDB_ERR_OOM, -1);
-       /* First number in array is # keys */
-       tdb->lockedkeys[0] = number;
-
-       /* Insertion sort by bucket */
-       for (i = 0; i < number; i++) {
-               hash = tdb->hash_fn(&keys[i]);
-               for (j = 0; j < i && BUCKET(tdb->lockedkeys[j+1]) < BUCKET(hash); j++);
-                       memmove(&tdb->lockedkeys[j+2], &tdb->lockedkeys[j+1], sizeof(u32) * (i-j));
-               tdb->lockedkeys[j+1] = hash;
-       }
-       /* Finally, lock in order */
-       for (i = 0; i < number; i++)
-               if (tdb_lock(tdb, i, F_WRLCK))
-                       break;
-
-       /* If error, release locks we have... */
-       if (i < number) {
-               for ( j = 0; j < i; j++)
-                       tdb_unlock(tdb, j, F_WRLCK);
-               SAFE_FREE(tdb->lockedkeys);
-               return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
-       }
-       return 0;
-}
-
-/* Unlock the keys previously locked by tdb_lockkeys() */
-void tdb_unlockkeys(TDB_CONTEXT *tdb)
-{
-       u32 i;
-       if (!tdb->lockedkeys)
-               return;
-       for (i = 0; i < tdb->lockedkeys[0]; i++)
-               tdb_unlock(tdb, tdb->lockedkeys[i+1], F_WRLCK);
-       SAFE_FREE(tdb->lockedkeys);
-}
-
 /* lock/unlock one hash chain. This is meant to be used to reduce
    contention - it cannot guarantee how many records will be locked */
 int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key)