]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/open.c
tdb2: add TDB_ATTRIBUTE_TDB1_HASHSIZE
[ccan] / ccan / tdb2 / open.c
index 5ee2ed7844105d7c8e753e7e79d5b7885ba1d5e0..5d5eff1394b870233e90d22375438cc4be591cfc 100644 (file)
@@ -16,7 +16,6 @@
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 #include "private.h"
-#include <ccan/hash/hash.h>
 #include <assert.h>
 
 /* all tdbs, to detect double-opens (fcntl file don't nest!) */
@@ -210,6 +209,7 @@ enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb,
        case TDB_ATTRIBUTE_HASH:
        case TDB_ATTRIBUTE_SEED:
        case TDB_ATTRIBUTE_OPENHOOK:
+       case TDB_ATTRIBUTE_TDB1_HASHSIZE:
                return tdb->last_error
                        = tdb_logerr(tdb, TDB_ERR_EINVAL,
                                     TDB_LOG_USE_ERROR,
@@ -219,7 +219,9 @@ enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb,
                                     ? "TDB_ATTRIBUTE_HASH"
                                     : attr->base.attr == TDB_ATTRIBUTE_SEED
                                     ? "TDB_ATTRIBUTE_SEED"
-                                    : "TDB_ATTRIBUTE_OPENHOOK");
+                                    : attr->base.attr == TDB_ATTRIBUTE_OPENHOOK
+                                    ? "TDB_ATTRIBUTE_OPENHOOK"
+                                    : "TDB_ATTRIBUTE_TDB1_HASHSIZE");
        case TDB_ATTRIBUTE_STATS:
                return tdb->last_error
                        = tdb_logerr(tdb, TDB_ERR_EINVAL,
@@ -242,16 +244,6 @@ enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb,
        return TDB_SUCCESS;
 }
 
-static uint64_t jenkins_hash(const void *key, size_t length, uint64_t seed,
-                            void *unused)
-{
-       uint64_t ret;
-       /* hash64_stable assumes lower bits are more important; they are a
-        * slightly better hash.  We use the upper bits first, so swap them. */
-       ret = hash64_stable((const unsigned char *)key, length, seed);
-       return (ret >> 32) | (ret << 32);
-}
-
 enum TDB_ERROR tdb_get_attribute(struct tdb_context *tdb,
                                 union tdb_attribute *attr)
 {
@@ -287,6 +279,16 @@ enum TDB_ERROR tdb_get_attribute(struct tdb_context *tdb,
                attr->flock.unlock = tdb->unlock_fn;
                attr->flock.data = tdb->lock_data;
                break;
+       case TDB_ATTRIBUTE_TDB1_HASHSIZE:
+               if (!(tdb->flags & TDB_VERSION1))
+                       return tdb->last_error
+                               = tdb_logerr(tdb, TDB_ERR_EINVAL,
+                                            TDB_LOG_USE_ERROR,
+                                    "tdb_get_attribute:"
+                                    " cannot get TDB_ATTRIBUTE_TDB1_HASHSIZE"
+                                    " on TDB2 tdb.");
+               attr->tdb1_hashsize.hsize = tdb->tdb1.header.hash_size;
+               break;
        default:
                return tdb->last_error
                        = tdb_logerr(tdb, TDB_ERR_EINVAL,
@@ -311,11 +313,14 @@ void tdb_unset_attribute(struct tdb_context *tdb,
                break;
        case TDB_ATTRIBUTE_HASH:
        case TDB_ATTRIBUTE_SEED:
+       case TDB_ATTRIBUTE_TDB1_HASHSIZE:
                tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
                           "tdb_unset_attribute: cannot unset %s after opening",
                           type == TDB_ATTRIBUTE_HASH
                           ? "TDB_ATTRIBUTE_HASH"
-                          : "TDB_ATTRIBUTE_SEED");
+                          : type == TDB_ATTRIBUTE_SEED
+                          ? "TDB_ATTRIBUTE_SEED"
+                          : "TDB_ATTRIBUTE_TDB1_HASHSIZE");
                break;
        case TDB_ATTRIBUTE_STATS:
                tdb_logerr(tdb, TDB_ERR_EINVAL,
@@ -347,6 +352,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
        ssize_t rlen;
        struct tdb_header hdr;
        struct tdb_attribute_seed *seed = NULL;
+       struct tdb_attribute_tdb1_hashsize *hsize_attr = NULL;
        tdb_bool_err berr;
        enum TDB_ERROR ecode;
        int openlock;
@@ -363,22 +369,22 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
        } else {
                tdb->name = NULL;
        }
-       tdb->direct_access = 0;
        tdb->flags = tdb_flags;
        tdb->log_fn = NULL;
-       tdb->transaction = NULL;
-       tdb->access = NULL;
        tdb->open_flags = open_flags;
        tdb->last_error = TDB_SUCCESS;
        tdb->file = NULL;
        tdb->openhook = NULL;
        tdb->lock_fn = tdb_fcntl_lock;
        tdb->unlock_fn = tdb_fcntl_unlock;
-       tdb->hash_fn = jenkins_hash;
+       tdb->hash_fn = tdb_jenkins_hash;
        memset(&tdb->stats, 0, sizeof(tdb->stats));
        tdb->stats.base.attr = TDB_ATTRIBUTE_STATS;
        tdb->stats.size = sizeof(tdb->stats);
        tdb_io_init(tdb);
+       tdb->tdb2.direct_access = 0;
+       tdb->tdb2.transaction = NULL;
+       tdb->tdb2.access = NULL;
 
        while (attr) {
                switch (attr->base.attr) {
@@ -393,6 +399,9 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
                        tdb->openhook = attr->openhook.fn;
                        tdb->openhook_data = attr->openhook.data;
                        break;
+               case TDB_ATTRIBUTE_TDB1_HASHSIZE:
+                       hsize_attr = &attr->tdb1_hashsize;
+                       break;
                default:
                        /* These are set as normal. */
                        ecode = tdb_set_attribute(tdb, attr);
@@ -410,6 +419,18 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
                goto fail;
        }
 
+       if (hsize_attr) {
+               if (!(tdb_flags & TDB_VERSION1) ||
+                   (!(tdb_flags & TDB_INTERNAL) && !(open_flags & O_CREAT))) {
+                       ecode = tdb_logerr(tdb, TDB_ERR_EINVAL,
+                                          TDB_LOG_USE_ERROR,
+                                          "tdb_open: can only use"
+                                          " TDB_ATTRIBUTE_TDB1_HASHSIZE when"
+                                          " creating a TDB_VERSION1 tdb");
+                       goto fail;
+               }
+       }
+
        if ((open_flags & O_ACCMODE) == O_WRONLY) {
                ecode = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
                                   "tdb_open: can't open tdb %s write-only",
@@ -573,7 +594,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
        tdb_unlock_open(tdb, openlock);
 
        /* This make sure we have current map_size and mmap. */
-       ecode = tdb->methods->oob(tdb, tdb->file->map_size + 1, true);
+       ecode = tdb->tdb2.io->oob(tdb, tdb->file->map_size + 1, true);
        if (unlikely(ecode != TDB_SUCCESS))
                goto fail;
 
@@ -655,7 +676,7 @@ int tdb_close(struct tdb_context *tdb)
 
        tdb_trace(tdb, "tdb_close");
 
-       if (tdb->transaction) {
+       if (tdb->tdb2.transaction) {
                tdb_transaction_cancel(tdb);
        }
 
@@ -689,3 +710,13 @@ int tdb_close(struct tdb_context *tdb)
 
        return ret;
 }
+
+void tdb_foreach_(int (*fn)(struct tdb_context *, void *), void *p)
+{
+       struct tdb_context *i;
+
+       for (i = tdbs; i; i = i->next) {
+               if (fn(i, p) != 0)
+                       break;
+       }
+}