]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/open.c
tdb2: don't cancel transaction when tdb_transaction_prepare_commit fails
[ccan] / ccan / tdb2 / open.c
index 6d930be14f6f4b14faeb44e0beae7dbc3a59b1e1..f358d0322d1d494ab05d826568b6f32f90b981b2 100644 (file)
@@ -101,12 +101,13 @@ static enum TDB_ERROR tdb_new_database(struct tdb_context *tdb,
        else
                newdb.hdr.hash_seed = random_number(tdb);
        newdb.hdr.hash_test = TDB_HASH_MAGIC;
-       newdb.hdr.hash_test = tdb->khash(&newdb.hdr.hash_test,
-                                        sizeof(newdb.hdr.hash_test),
-                                        newdb.hdr.hash_seed,
-                                        tdb->hash_priv);
+       newdb.hdr.hash_test = tdb->hash_fn(&newdb.hdr.hash_test,
+                                          sizeof(newdb.hdr.hash_test),
+                                          newdb.hdr.hash_seed,
+                                          tdb->hash_data);
        newdb.hdr.recovery = 0;
        newdb.hdr.features_used = newdb.hdr.features_offered = TDB_FEATURE_MASK;
+       newdb.hdr.seqnum = 0;
        memset(newdb.hdr.reserved, 0, sizeof(newdb.hdr.reserved));
        /* Initial hashes are empty. */
        memset(newdb.hdr.hashtable, 0, sizeof(newdb.hdr.hashtable));
@@ -192,6 +193,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_openhook *openhook = NULL;
        tdb_bool_err berr;
        enum TDB_ERROR ecode;
 
@@ -204,10 +206,11 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
        tdb->name = NULL;
        tdb->direct_access = 0;
        tdb->flags = tdb_flags;
-       tdb->logfn = NULL;
+       tdb->log_fn = NULL;
        tdb->transaction = NULL;
        tdb->stats = NULL;
        tdb->access = NULL;
+       tdb->last_error = TDB_SUCCESS;
        tdb->file = NULL;
        tdb_hash_init(tdb);
        tdb_io_init(tdb);
@@ -215,12 +218,12 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
        while (attr) {
                switch (attr->base.attr) {
                case TDB_ATTRIBUTE_LOG:
-                       tdb->logfn = attr->log.log_fn;
-                       tdb->log_private = attr->log.log_private;
+                       tdb->log_fn = attr->log.fn;
+                       tdb->log_data = attr->log.data;
                        break;
                case TDB_ATTRIBUTE_HASH:
-                       tdb->khash = attr->hash.hash_fn;
-                       tdb->hash_priv = attr->hash.hash_private;
+                       tdb->hash_fn = attr->hash.fn;
+                       tdb->hash_data = attr->hash.data;
                        break;
                case TDB_ATTRIBUTE_SEED:
                        seed = &attr->seed;
@@ -231,6 +234,9 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
                        if (tdb->stats->size > sizeof(attr->stats))
                                tdb->stats->size = sizeof(attr->stats);
                        break;
+               case TDB_ATTRIBUTE_OPENHOOK:
+                       openhook = &attr->openhook;
+                       break;
                default:
                        ecode = tdb_logerr(tdb, TDB_ERR_EINVAL,
                                           TDB_LOG_USE_ERROR,
@@ -243,7 +249,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
        }
 
        if (tdb_flags & ~(TDB_INTERNAL | TDB_NOLOCK | TDB_NOMMAP | TDB_CONVERT
-                         | TDB_NOSYNC)) {
+                         | TDB_NOSYNC | TDB_SEQNUM)) {
                ecode = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
                                   "tdb_open: unknown flags %u", tdb_flags);
                goto fail;
@@ -276,6 +282,16 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
                if (ecode != TDB_SUCCESS) {
                        goto fail;
                }
+               if (name) {
+                       tdb->name = strdup(name);
+                       if (!tdb->name) {
+                               ecode = tdb_logerr(tdb, TDB_ERR_OOM,
+                                                  TDB_LOG_ERROR,
+                                                  "tdb_open: failed to"
+                                                  " allocate name");
+                               goto fail;
+                       }
+               }
                tdb_convert(tdb, &hdr.hash_seed, sizeof(hdr.hash_seed));
                tdb->hash_seed = hdr.hash_seed;
                tdb_ftable_init(tdb);
@@ -327,6 +343,17 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
                goto fail;
        }
 
+       /* call their open hook if they gave us one. */
+       if (openhook) {
+               ecode = openhook->fn(tdb->file->fd, openhook->data);
+               if (ecode != TDB_SUCCESS) {
+                       tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
+                                  "tdb_open: open hook failed");
+                       goto fail;
+               }
+               open_flags |= O_CREAT;
+       }
+
        /* If they used O_TRUNC, read will return 0. */
        rlen = pread(tdb->file->fd, &hdr, sizeof(hdr), 0);
        if (rlen == 0 && (open_flags & O_CREAT)) {
@@ -442,9 +469,9 @@ fail_errno:
 #ifdef TDB_TRACE
        close(tdb->tracefd);
 #endif
-       free((char *)tdb->name);
+       free(cast_const(char *, tdb->name));
        if (tdb->file) {
-               tdb_unlock_all(tdb);
+               tdb_lock_cleanup(tdb);
                if (--tdb->file->refcnt == 0) {
                        assert(tdb->file->num_lockrecs == 0);
                        if (tdb->file->map_ptr) {
@@ -483,11 +510,11 @@ int tdb_close(struct tdb_context *tdb)
                else
                        tdb_munmap(tdb->file);
        }
-       free((char *)tdb->name);
+       free(cast_const(char *, tdb->name));
        if (tdb->file) {
                struct tdb_file **i;
 
-               tdb_unlock_all(tdb);
+               tdb_lock_cleanup(tdb);
                if (--tdb->file->refcnt == 0) {
                        ret = close(tdb->file->fd);