Merge of changes from HEAD branch.
authorTim Potter <tpot@samba.org>
Tue, 29 Feb 2000 22:52:28 +0000 (22:52 +0000)
committerTim Potter <tpot@samba.org>
Tue, 29 Feb 2000 22:52:28 +0000 (22:52 +0000)
source/tdb/.cvsignore
source/tdb/README
source/tdb/tdb.c
source/tdb/tdbtool.c

index af9d6be961b213ad27e2ea901773923583dde142..0480bc977f9637f198ed482a173f2fd1150b9c1d 100644 (file)
@@ -1 +1,7 @@
-*.lo
\ No newline at end of file
+*.lo
+tdbtool
+tdbtest
+tdbtorture
+test.db
+test.gdbm
+test.tdb
index 3b070bdc4005eadf5ea15c3c105984e422036a55..9eef521075acd1295f11cae10bdab142d73ede2e 100644 (file)
@@ -65,6 +65,11 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
    possible tdb_flags are:
     TDB_CLEAR_IF_FIRST - clear database if we are the only one with it open
 
+----------------------------------------------------------------------
+char *tdb_error(TDB_CONTEXT *tdb);
+
+     return a error string for the last tdb error
+
 ----------------------------------------------------------------------
 int tdb_close(TDB_CONTEXT *tdb);
 
@@ -96,9 +101,10 @@ int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
 
 ----------------------------------------------------------------------
 int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb,
-                 TDB_DATA key, TDB_DATA dbuf));
+                 TDB_DATA key, TDB_DATA dbuf, void *state), void *state);
 
-   traverse the entire database - calling fn(tdb, key, data) on each element.
+   traverse the entire database - calling fn(tdb, key, data, state) on each 
+   element.
 
    return -1 on error or the record count traversed
 
index a754c583e60e6638bdcccf986ac80f6c5c7e42b8..c7b70aa15338f3d9058ae2d17e8d6a13dd84b2cb 100644 (file)
@@ -92,6 +92,8 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
 #else
        struct flock fl;
 
+        if (tdb->fd == -1) return 0;   /* for in memory tdb */
+
        if (tdb->read_only) return -1;
 
        fl.l_type = set==LOCK_SET?rw_type:F_UNLCK;
@@ -194,7 +196,7 @@ static tdb_off tdb_hash_top(TDB_CONTEXT *tdb, unsigned hash)
 static int tdb_oob(TDB_CONTEXT *tdb, tdb_off offset)
 {
        struct stat st;
-       if (offset <= tdb->map_size) return 0;
+       if ((offset <= tdb->map_size) || (tdb->fd == -1)) return 0;
 
        fstat(tdb->fd, &st);
        if (st.st_size <= (ssize_t)offset) {
@@ -337,8 +339,10 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off length)
        length = ((tdb->map_size + length + TDB_PAGE_SIZE) & ~(TDB_PAGE_SIZE - 1)) - tdb->map_size;
 
        /* expand the file itself */
-       lseek(tdb->fd, tdb->map_size + length - 1, SEEK_SET);
-       if (write(tdb->fd, &b, 1) != 1) goto fail;
+        if (tdb->fd != -1) {
+            lseek(tdb->fd, tdb->map_size + length - 1, SEEK_SET);
+            if (write(tdb->fd, &b, 1) != 1) goto fail;
+        }
 
        /* form a new freelist record */
        offset = FREELIST_TOP;
@@ -349,7 +353,7 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off length)
        }
 
 #if HAVE_MMAP
-       if (tdb->map_ptr) {
+       if (tdb->fd != -1 && tdb->map_ptr) {
                munmap(tdb->map_ptr, tdb->map_size);
                tdb->map_ptr = NULL;
        }
@@ -357,6 +361,10 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off length)
 
        tdb->map_size += length;
 
+        if (tdb->fd == -1) {
+            tdb->map_ptr = realloc(tdb->map_ptr, tdb->map_size);
+        }
+
        /* write it out */
        if (rec_write(tdb, tdb->map_size - length, &rec) == -1) {
                goto fail;
@@ -367,10 +375,13 @@ static int tdb_expand(TDB_CONTEXT *tdb, tdb_off length)
        if (ofs_write(tdb, offset, &ptr) == -1) goto fail;
 
 #if HAVE_MMAP
-       tdb->map_ptr = (void *)mmap(NULL, tdb->map_size, 
-                                  PROT_READ|PROT_WRITE,
-                                  MAP_SHARED | MAP_FILE, tdb->fd, 0);
+        if (tdb->fd != -1) {
+            tdb->map_ptr = (void *)mmap(NULL, tdb->map_size, 
+                                        PROT_READ|PROT_WRITE,
+                                        MAP_SHARED | MAP_FILE, tdb->fd, 0);
+        }
 #endif
+
        tdb_unlock(tdb, -1);
        return 0;
 
@@ -478,37 +489,52 @@ static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size)
 {
        struct tdb_header header;
        tdb_off offset;
-       int i;
+       int i, size = 0;
        tdb_off buf[16];
 
-       /* create the header */
-       memset(&header, 0, sizeof(header));
-       memcpy(header.magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
-       header.version = TDB_VERSION;
-       header.hash_size = hash_size;
-       lseek(tdb->fd, 0, SEEK_SET);
-       ftruncate(tdb->fd, 0);
-
-       if (write(tdb->fd, &header, sizeof(header)) != sizeof(header)) {
-               tdb->ecode = TDB_ERR_IO;
-               return -1;
-       }
+        /* create the header */
+        memset(&header, 0, sizeof(header));
+        memcpy(header.magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
+        header.version = TDB_VERSION;
+        header.hash_size = hash_size;
+        lseek(tdb->fd, 0, SEEK_SET);
+        ftruncate(tdb->fd, 0);
+        
+        if (tdb->fd != -1 && write(tdb->fd, &header, sizeof(header)) != 
+            sizeof(header)) {
+            tdb->ecode = TDB_ERR_IO;
+            return -1;
+        } else size += sizeof(header);
        
-       /* the freelist and hash pointers */
-       offset = 0;
-       memset(buf, 0, sizeof(buf));
-       for (i=0;(hash_size+1)-i >= 16; i += 16) {
-               if (write(tdb->fd, buf, sizeof(buf)) != sizeof(buf)) {
-                       tdb->ecode = TDB_ERR_IO;
-                       return -1;
-               }
-       }
-       for (;i<hash_size+1; i++) {
-               if (write(tdb->fd, buf, sizeof(tdb_off)) != sizeof(tdb_off)) {
-                       tdb->ecode = TDB_ERR_IO;
-                       return -1;
-               }
-       }
+        /* the freelist and hash pointers */
+        offset = 0;
+        memset(buf, 0, sizeof(buf));
+
+        for (i=0;(hash_size+1)-i >= 16; i += 16) {
+            if (tdb->fd != -1 && write(tdb->fd, buf, sizeof(buf)) != 
+                sizeof(buf)) {
+                tdb->ecode = TDB_ERR_IO;
+                return -1;
+            } else size += sizeof(buf);
+        }
+
+        for (;i<hash_size+1; i++) {
+            if (tdb->fd != -1 && write(tdb->fd, buf, sizeof(tdb_off)) != 
+                sizeof(tdb_off)) {
+                tdb->ecode = TDB_ERR_IO;
+                return -1;
+            } else size += sizeof(tdb_off);
+        }
+
+        if (tdb->fd == -1) {
+            tdb->map_ptr = calloc(size, 1);
+            tdb->map_size = size;
+            if (tdb->map_ptr == NULL) {
+                tdb->ecode = TDB_ERR_IO;
+                return -1;
+            }
+            memcpy(&tdb->header, &header, sizeof(header));
+        }
 
 #if TDB_DEBUG
        printf("initialised database of hash_size %u\n", 
@@ -597,6 +623,13 @@ int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf)
        tdb_off rec_ptr;
        int ret = -1;
 
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_update() called with null context\n");
+#endif
+            return -1;
+        }
+
        /* find which hash bucket it is in */
        hash = tdb_hash(&key);
 
@@ -634,6 +667,13 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
        struct list_struct rec;
        TDB_DATA ret = null_data;
 
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_fetch() called with null context\n");
+#endif
+            return null_data;
+        }
+
        /* find which hash bucket it is in */
        hash = tdb_hash(&key);
 
@@ -687,6 +727,13 @@ int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, TDB_DATA key, TDB
        char *data;
        TDB_DATA key, dbuf;
 
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_traverse() called with null context\n");
+#endif
+            return -1;
+        }
+
        /* loop over all hash chains */
        for (h = 0; h < tdb->header.hash_size; h++) {
                tdb_lock(tdb, BUCKET(h));
@@ -749,6 +796,13 @@ TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb)
        unsigned hash;
        TDB_DATA ret;
 
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_firstkey() called with null context\n");
+#endif
+            return null_data;
+        }
+
        /* look for a non-empty hash chain */
        for (hash = 0, rec_ptr = 0; 
             hash < tdb->header.hash_size;
@@ -794,6 +848,13 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key)
        struct list_struct rec;
        TDB_DATA ret;
 
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_nextkey() called with null context\n");
+#endif
+            return null_data;
+        }
+
        /* find which hash bucket it is in */
        hash = tdb_hash(&key);
        hbucket = BUCKET(hash);
@@ -842,6 +903,13 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
        struct list_struct rec, lastrec;
        char *data = NULL;
 
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_delete() called with null context\n");
+#endif
+            return -1;
+        }
+
        /* find which hash bucket it is in */
        hash = tdb_hash(&key);
 
@@ -940,6 +1008,13 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
        tdb_off rec_ptr, offset;
        char *p = NULL;
 
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_store() called with null context\n");
+#endif
+            return -1;
+        }
+
        /* find which hash bucket it is in */
        hash = tdb_hash(&key);
 
@@ -1033,6 +1108,8 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
        TDB_CONTEXT tdb, *ret;
        struct stat st;
 
+       memset(&tdb, 0, sizeof(tdb));
+
        tdb.fd = -1;
        tdb.name = NULL;
        tdb.map_ptr = NULL;
@@ -1043,14 +1120,14 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
 
        if (hash_size == 0) hash_size = DEFAULT_HASH_SIZE;
 
-       memset(&tdb, 0, sizeof(tdb));
-
        tdb.read_only = ((open_flags & O_ACCMODE) == O_RDONLY);
 
-       tdb.fd = open(name, open_flags, mode);
-       if (tdb.fd == -1) {
+        if (name != NULL) {
+            tdb.fd = open(name, open_flags, mode);
+            if (tdb.fd == -1) {
                goto fail;
-       }
+            }
+        }
 
        /* ensure there is only one process initialising at once */
        tdb_brlock(&tdb, GLOBAL_LOCK, LOCK_SET, F_WRLCK, F_SETLKW);
@@ -1077,23 +1154,32 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
                if (tdb_new_database(&tdb, hash_size) == -1) goto fail;
 
                lseek(tdb.fd, 0, SEEK_SET);
-               if (read(tdb.fd, &tdb.header, sizeof(tdb.header)) != sizeof(tdb.header)) goto fail;
+               if (tdb.fd != -1 && read(tdb.fd, &tdb.header, 
+                                         sizeof(tdb.header)) != 
+                                         sizeof(tdb.header)) 
+                    goto fail;
        }
 
-       fstat(tdb.fd, &st);
+        if (tdb.fd != -1) {
+            fstat(tdb.fd, &st);
+
+            /* map the database and fill in the return structure */
+            tdb.name = (char *)strdup(name);
+            tdb.map_size = st.st_size;
+        }
+
+        tdb.locked = (int *)calloc(tdb.header.hash_size+1, 
+                                   sizeof(tdb.locked[0]));
+        if (!tdb.locked) {
+            goto fail;
+        }
 
-       /* map the database and fill in the return structure */
-       tdb.name = (char *)strdup(name);
-       tdb.locked = (int *)calloc(tdb.header.hash_size+1, 
-                                  sizeof(tdb.locked[0]));
-       if (!tdb.locked) {
-               goto fail;
-       }
-       tdb.map_size = st.st_size;
 #if HAVE_MMAP
-       tdb.map_ptr = (void *)mmap(NULL, st.st_size, 
-                                 tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
-                                 MAP_SHARED | MAP_FILE, tdb.fd, 0);
+        if (tdb.fd != -1) {
+            tdb.map_ptr = (void *)mmap(NULL, st.st_size, 
+                                       tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
+                                       MAP_SHARED | MAP_FILE, tdb.fd, 0);
+        }
 #endif
 
        ret = (TDB_CONTEXT *)malloc(sizeof(tdb));
@@ -1110,7 +1196,7 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
        return ret;
 
  fail:
-       if (tdb.name) free(tdb.name);
+        if (tdb.name) free(tdb.name);
        if (tdb.fd != -1) close(tdb.fd);
        if (tdb.map_ptr) munmap(tdb.map_ptr, tdb.map_size);
 
@@ -1124,9 +1210,16 @@ int tdb_close(TDB_CONTEXT *tdb)
 
        if (tdb->name) free(tdb->name);
        if (tdb->fd != -1) close(tdb->fd);
-       if (tdb->map_ptr) munmap(tdb->map_ptr, tdb->map_size);
        if (tdb->locked) free(tdb->locked);
 
+       if (tdb->map_ptr) {
+            if (tdb->fd != -1) {
+                munmap(tdb->map_ptr, tdb->map_size);
+            } else {
+                free(tdb->map_ptr);
+            }
+        }
+
        memset(tdb, 0, sizeof(*tdb));
        free(tdb);
 
@@ -1136,12 +1229,26 @@ int tdb_close(TDB_CONTEXT *tdb)
 /* lock the database. If we already have it locked then don't do anything */
 int tdb_writelock(TDB_CONTEXT *tdb)
 {
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_writelock() called with null context\n");
+#endif
+            return -1;
+        }
+
        return tdb_lock(tdb, -1);
 }
 
 /* unlock the database. */
 int tdb_writeunlock(TDB_CONTEXT *tdb)
 {
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_writeunlock() called with null context\n");
+#endif
+            return -1;
+        }
+
        return tdb_unlock(tdb, -1);
 }
 
@@ -1149,6 +1256,13 @@ int tdb_writeunlock(TDB_CONTEXT *tdb)
    contention - it cannot guarantee how many records will be locked */
 int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key)
 {
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_lockchain() called with null context\n");
+#endif
+            return -1;
+        }
+
        return tdb_lock(tdb, BUCKET(tdb_hash(&key)));
 }
 
@@ -1156,5 +1270,12 @@ int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key)
 /* unlock one hash chain */
 int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key)
 {
+        if (tdb == NULL) {
+#ifdef TDB_DEBUG
+            printf("tdb_unlockchain() called with null context\n");
+#endif
+            return -1;
+        }
+
        return tdb_unlock(tdb, BUCKET(tdb_hash(&key)));
 }
index 43c7faf2bf1f4f6de3a0c6e66c21057ee3062f7c..317ad9b4fc5a53c69c796e7517671183230c25bb 100644 (file)
@@ -134,12 +134,7 @@ static void delete_tdb(void)
        }
 }
 
-static int del_rec(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void*)
-{
-       tdb_delete(tdb, key);
-}
-
-static int print_rec(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void*)
+static int print_rec(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
 {
        printf("%*.*s : %*.*s\n", 
               (int)key.dsize, (int)key.dsize, key.dptr, 
@@ -149,7 +144,7 @@ static int print_rec(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void*)
 
 static int total_bytes;
 
-static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void*)
+static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
 {
        total_bytes += dbuf.dsize;
        return 0;
@@ -175,6 +170,12 @@ static char *getline(char *prompt)
        return p?line:NULL;
 }
 
+static int do_delete_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf,
+                     void *state)
+{
+    return tdb_delete(tdb, key);
+}
+
 int main(int argc, char *argv[])
 {
        char *line;
@@ -204,7 +205,7 @@ int main(int argc, char *argv[])
                } else if (strcmp(tok,"show") == 0) {
                        show_tdb();
                } else if (strcmp(tok,"erase") == 0) {
-                       tdb_traverse(tdb, del_rec, NULL);
+                       tdb_traverse(tdb, do_delete_fn, NULL);
                } else if (strcmp(tok,"delete") == 0) {
                        delete_tdb();
                } else if (strcmp(tok,"dump") == 0) {