]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/tdb1_open.c
tdb2: approximate INCOMPATIBLE_HASH flag with tdb1_incompatible_hash()
[ccan] / ccan / tdb2 / tdb1_open.c
index e1f16053666537eb91ba8501ab7c151fe8d35994..f53a32b5befa977bc2a927dee37ec6da26f9bb81 100644 (file)
@@ -34,11 +34,11 @@ static struct tdb1_context *tdb1s = NULL;
 void tdb1_header_hash(struct tdb1_context *tdb,
                     uint32_t *magic1_hash, uint32_t *magic2_hash)
 {
-       TDB1_DATA hash_key;
+       TDB_DATA hash_key;
        uint32_t tdb1_magic = TDB1_MAGIC;
 
-       hash_key.dptr = (unsigned char *)TDB1_MAGIC_FOOD;
-       hash_key.dsize = sizeof(TDB1_MAGIC_FOOD);
+       hash_key.dptr = (unsigned char *)TDB_MAGIC_FOOD;
+       hash_key.dsize = sizeof(TDB_MAGIC_FOOD);
        *magic1_hash = tdb->hash_fn(&hash_key);
 
        hash_key.dptr = (unsigned char *)TDB1_CONV(tdb1_magic);
@@ -72,7 +72,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
 
        /* Make sure older tdbs (which don't check the magic hash fields)
         * will refuse to open this TDB. */
-       if (tdb->flags & TDB1_INCOMPATIBLE_HASH)
+       if (tdb->hash_fn == tdb1_incompatible_hash)
                newdb->rwlocks = TDB1_HASH_RWLOCK_MAGIC;
 
        if (tdb->flags & TDB1_INTERNAL) {
@@ -93,7 +93,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
        TDB1_CONV(*newdb);
        memcpy(&tdb->header, newdb, sizeof(tdb->header));
        /* Don't endian-convert the magic food! */
-       memcpy(newdb->magic_food, TDB1_MAGIC_FOOD, strlen(TDB1_MAGIC_FOOD)+1);
+       memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
        /* we still have "ret == -1" here */
        if (tdb1_write_all(tdb->fd, newdb, size))
                ret = 0;
@@ -135,25 +135,28 @@ struct tdb1_context *tdb1_open(const char *name, int hash_size, int tdb1_flags,
        return tdb1_open_ex(name, hash_size, tdb1_flags, open_flags, mode, NULL, NULL);
 }
 
-static bool check_header_hash(struct tdb1_context *tdb,
-                             bool default_hash, uint32_t *m1, uint32_t *m2)
+static bool hash_correct(struct tdb1_context *tdb,
+                        uint32_t *m1, uint32_t *m2)
 {
        tdb1_header_hash(tdb, m1, m2);
-       if (tdb->header.magic1_hash == *m1 &&
-           tdb->header.magic2_hash == *m2) {
-               return true;
-       }
+       return (tdb->header.magic1_hash == *m1 &&
+               tdb->header.magic2_hash == *m2);
+}
 
-       /* If they explicitly set a hash, always respect it. */
-       if (!default_hash)
-               return false;
+static bool check_header_hash(struct tdb1_context *tdb,
+                             uint32_t *m1, uint32_t *m2)
+{
+       if (hash_correct(tdb, m1, m2))
+               return true;
 
-       /* Otherwise, try the other inbuilt hash. */
+       /* If they use one inbuilt, try the other inbuilt hash. */
        if (tdb->hash_fn == tdb1_old_hash)
-               tdb->hash_fn = tdb1_jenkins_hash;
-       else
+               tdb->hash_fn = tdb1_incompatible_hash;
+       else if (tdb->hash_fn == tdb1_incompatible_hash)
                tdb->hash_fn = tdb1_old_hash;
-       return check_header_hash(tdb, false, m1, m2);
+       else
+               return false;
+       return hash_correct(tdb, m1, m2);
 }
 
 struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flags,
@@ -216,15 +219,13 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
 
        if (hash_fn) {
                tdb->hash_fn = hash_fn;
-               hash_alg = "the user defined";
+               if (hash_fn == tdb1_incompatible_hash)
+                       hash_alg = "tdb1_incompatible_hash";
+               else
+                       hash_alg = "the user defined";
        } else {
-               /* This controls what we use when creating a tdb. */
-               if (tdb->flags & TDB1_INCOMPATIBLE_HASH) {
-                       tdb->hash_fn = tdb1_jenkins_hash;
-               } else {
-                       tdb->hash_fn = tdb1_old_hash;
-               }
-               hash_alg = "either default";
+               tdb->hash_fn = tdb1_old_hash;
+               hash_alg = "default";
        }
 
        /* cache the page size */
@@ -293,7 +294,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
         fcntl(tdb->fd, F_SETFD, v | FD_CLOEXEC);
 
        /* ensure there is only one process initialising at once */
-       if (tdb1_nest_lock(tdb, TDB1_OPEN_LOCK, F_WRLCK, TDB1_LOCK_WAIT) == -1) {
+       if (tdb1_nest_lock(tdb, TDB1_OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) {
                tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
                           "tdb1_open_ex: failed to get open lock on %s: %s",
                           name, strerror(errno));
@@ -303,7 +304,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
        /* we need to zero database if we are the only one with it open */
        if ((tdb1_flags & TDB1_CLEAR_IF_FIRST) &&
            (!tdb->read_only) &&
-           (locked = (tdb1_nest_lock(tdb, TDB1_ACTIVE_LOCK, F_WRLCK, TDB1_LOCK_NOWAIT|TDB1_LOCK_PROBE) == 0))) {
+           (locked = (tdb1_nest_lock(tdb, TDB1_ACTIVE_LOCK, F_WRLCK, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE) == 0))) {
                open_flags |= O_CREAT;
                if (ftruncate(tdb->fd, 0) == -1) {
                        tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
@@ -316,7 +317,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
 
        errno = 0;
        if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
-           || strcmp(tdb->header.magic_food, TDB1_MAGIC_FOOD) != 0) {
+           || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0) {
                if (!(open_flags & O_CREAT) || tdb1_new_database(tdb, hash_size) == -1) {
                        if (errno == 0) {
                                errno = EIO; /* ie bad format or something */
@@ -353,7 +354,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
        if ((tdb->header.magic1_hash == 0) && (tdb->header.magic2_hash == 0)) {
                /* older TDB without magic hash references */
                tdb->hash_fn = tdb1_old_hash;
-       } else if (!check_header_hash(tdb, !hash_fn, &magic1, &magic2)) {
+       } else if (!check_header_hash(tdb, &magic1, &magic2)) {
                tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_USE_ERROR,
                           "tdb1_open_ex: "
                           "%s was not created with %s hash function we are using\n"
@@ -401,7 +402,7 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
 
        if (tdb1_flags & TDB1_CLEAR_IF_FIRST) {
                /* leave this lock in place to indicate it's in use */
-               if (tdb1_nest_lock(tdb, TDB1_ACTIVE_LOCK, F_RDLCK, TDB1_LOCK_WAIT) == -1) {
+               if (tdb1_nest_lock(tdb, TDB1_ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
                        goto fail;
                }
        }