]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb/transaction.c
Fix sequence numbers when tracing transaction.
[ccan] / ccan / tdb / transaction.c
index 6a34c4526993d73d25a13778474739a3afa0b971..a23bb60427c574a5ac9c7f25ef7c82f32c9c6e0c 100644 (file)
@@ -398,6 +398,58 @@ static const struct tdb_methods transaction_methods = {
        transaction_brlock
 };
 
        transaction_brlock
 };
 
+int tdb_transaction_cancel_internal(struct tdb_context *tdb)
+{
+       int i;
+
+       if (tdb->transaction == NULL) {
+               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n"));
+               return -1;
+       }
+
+       if (tdb->transaction->nesting != 0) {
+               tdb->transaction->transaction_error = 1;
+               tdb->transaction->nesting--;
+               return 0;
+       }               
+
+       tdb->map_size = tdb->transaction->old_map_size;
+
+       /* free all the transaction blocks */
+       for (i=0;i<tdb->transaction->num_blocks;i++) {
+               if (tdb->transaction->blocks[i] != NULL) {
+                       free(tdb->transaction->blocks[i]);
+               }
+       }
+       SAFE_FREE(tdb->transaction->blocks);
+
+       /* remove any global lock created during the transaction */
+       if (tdb->global_lock.count != 0) {
+               tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size);
+               tdb->global_lock.count = 0;
+       }
+
+       /* remove any locks created during the transaction */
+       if (tdb->num_locks != 0) {
+               for (i=0;i<tdb->num_lockrecs;i++) {
+                       tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list,
+                                  F_UNLCK,F_SETLKW, 0, 1);
+               }
+               tdb->num_locks = 0;
+               tdb->num_lockrecs = 0;
+               SAFE_FREE(tdb->lockrecs);
+       }
+
+       /* restore the normal io methods */
+       tdb->methods = tdb->transaction->io_methods;
+
+       tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
+       tdb_transaction_unlock(tdb);
+       SAFE_FREE(tdb->transaction->hash_heads);
+       SAFE_FREE(tdb->transaction);
+       
+       return 0;
+}
 
 /*
   start a tdb transaction. No token is returned, as only a single
 
 /*
   start a tdb transaction. No token is returned, as only a single
@@ -414,13 +466,14 @@ int tdb_transaction_start(struct tdb_context *tdb)
 
        /* cope with nested tdb_transaction_start() calls */
        if (tdb->transaction != NULL) {
 
        /* cope with nested tdb_transaction_start() calls */
        if (tdb->transaction != NULL) {
+               tdb_trace(tdb, "tdb_transaction_start");
                if (!tdb->flags & TDB_NO_NESTING) {
                        tdb->transaction->nesting++;
                        TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", 
                                 tdb->transaction->nesting));
                        return 0;
                } else {
                if (!tdb->flags & TDB_NO_NESTING) {
                        tdb->transaction->nesting++;
                        TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", 
                                 tdb->transaction->nesting));
                        return 0;
                } else {
-                       tdb_transaction_cancel(tdb);
+                       tdb_transaction_cancel_internal(tdb);
                        TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: cancelling previous transaction\n"));
                }
        }
                        TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: cancelling previous transaction\n"));
                }
        }
@@ -495,6 +548,8 @@ int tdb_transaction_start(struct tdb_context *tdb)
        tdb->transaction->io_methods = tdb->methods;
        tdb->methods = &transaction_methods;
 
        tdb->transaction->io_methods = tdb->methods;
        tdb->methods = &transaction_methods;
 
+       /* Trace at the end, so we get sequence number correct. */
+       tdb_trace(tdb, "tdb_transaction_start");
        return 0;
        
 fail:
        return 0;
        
 fail:
@@ -512,57 +567,9 @@ fail:
 */
 int tdb_transaction_cancel(struct tdb_context *tdb)
 {      
 */
 int tdb_transaction_cancel(struct tdb_context *tdb)
 {      
-       int i;
-
-       if (tdb->transaction == NULL) {
-               TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n"));
-               return -1;
-       }
-
-       if (tdb->transaction->nesting != 0) {
-               tdb->transaction->transaction_error = 1;
-               tdb->transaction->nesting--;
-               return 0;
-       }               
-
-       tdb->map_size = tdb->transaction->old_map_size;
-
-       /* free all the transaction blocks */
-       for (i=0;i<tdb->transaction->num_blocks;i++) {
-               if (tdb->transaction->blocks[i] != NULL) {
-                       free(tdb->transaction->blocks[i]);
-               }
-       }
-       SAFE_FREE(tdb->transaction->blocks);
-
-       /* remove any global lock created during the transaction */
-       if (tdb->global_lock.count != 0) {
-               tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size);
-               tdb->global_lock.count = 0;
-       }
-
-       /* remove any locks created during the transaction */
-       if (tdb->num_locks != 0) {
-               for (i=0;i<tdb->num_lockrecs;i++) {
-                       tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list,
-                                  F_UNLCK,F_SETLKW, 0, 1);
-               }
-               tdb->num_locks = 0;
-               tdb->num_lockrecs = 0;
-               SAFE_FREE(tdb->lockrecs);
-       }
-
-       /* restore the normal io methods */
-       tdb->methods = tdb->transaction->io_methods;
-
-       tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
-       tdb_transaction_unlock(tdb);
-       SAFE_FREE(tdb->transaction->hash_heads);
-       SAFE_FREE(tdb->transaction);
-       
-       return 0;
+       tdb_trace(tdb, "tdb_transaction_cancel");
+       return tdb_transaction_cancel_internal(tdb);
 }
 }
-
 /*
   sync to disk
 */
 /*
   sync to disk
 */
@@ -845,6 +852,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
        uint32_t zero = 0;
        int i;
 
        uint32_t zero = 0;
        int i;
 
+       tdb_trace(tdb, "tdb_transaction_commit");
        if (tdb->transaction == NULL) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n"));
                return -1;
        if (tdb->transaction == NULL) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n"));
                return -1;
@@ -852,7 +860,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
 
        if (tdb->transaction->transaction_error) {
                tdb->ecode = TDB_ERR_IO;
 
        if (tdb->transaction->transaction_error) {
                tdb->ecode = TDB_ERR_IO;
-               tdb_transaction_cancel(tdb);
+               tdb_transaction_cancel_internal(tdb);
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n"));
                return -1;
        }
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n"));
                return -1;
        }
@@ -865,7 +873,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
 
        /* check for a null transaction */
        if (tdb->transaction->blocks == NULL) {
 
        /* check for a null transaction */
        if (tdb->transaction->blocks == NULL) {
-               tdb_transaction_cancel(tdb);
+               tdb_transaction_cancel_internal(tdb);
                return 0;
        }
 
                return 0;
        }
 
@@ -876,7 +884,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
        if (tdb->num_locks || tdb->global_lock.count) {
                tdb->ecode = TDB_ERR_LOCK;
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n"));
        if (tdb->num_locks || tdb->global_lock.count) {
                tdb->ecode = TDB_ERR_LOCK;
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n"));
-               tdb_transaction_cancel(tdb);
+               tdb_transaction_cancel_internal(tdb);
                return -1;
        }
 
                return -1;
        }
 
@@ -884,7 +892,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
        if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n"));
                tdb->ecode = TDB_ERR_LOCK;
        if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n"));
                tdb->ecode = TDB_ERR_LOCK;
-               tdb_transaction_cancel(tdb);
+               tdb_transaction_cancel_internal(tdb);
                return -1;
        }
 
                return -1;
        }
 
@@ -893,7 +901,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
        if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n"));
                tdb->ecode = TDB_ERR_LOCK;
        if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n"));
                tdb->ecode = TDB_ERR_LOCK;
-               tdb_transaction_cancel(tdb);
+               tdb_transaction_cancel_internal(tdb);
                return -1;
        }
 
                return -1;
        }
 
@@ -902,7 +910,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
                if (transaction_setup_recovery(tdb, &magic_offset) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n"));
                        tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
                if (transaction_setup_recovery(tdb, &magic_offset) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n"));
                        tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
-                       tdb_transaction_cancel(tdb);
+                       tdb_transaction_cancel_internal(tdb);
                        return -1;
                }
        }
                        return -1;
                }
        }
@@ -915,7 +923,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
                        tdb->ecode = TDB_ERR_IO;
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n"));
                        tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
                        tdb->ecode = TDB_ERR_IO;
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n"));
                        tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
-                       tdb_transaction_cancel(tdb);
+                       tdb_transaction_cancel_internal(tdb);
                        return -1;
                }
                tdb->map_size = tdb->transaction->old_map_size;
                        return -1;
                }
                tdb->map_size = tdb->transaction->old_map_size;
@@ -946,7 +954,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
                        tdb->methods = methods;
                        tdb_transaction_recover(tdb); 
 
                        tdb->methods = methods;
                        tdb_transaction_recover(tdb); 
 
-                       tdb_transaction_cancel(tdb);
+                       tdb_transaction_cancel_internal(tdb);
                        tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
 
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n"));
                        tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
 
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n"));
@@ -989,13 +997,13 @@ int tdb_transaction_commit(struct tdb_context *tdb)
           not be backed up (as tdb rounding to block sizes means that
           file size changes are quite rare too). The following forces
           mtime changes when a transaction completes */
           not be backed up (as tdb rounding to block sizes means that
           file size changes are quite rare too). The following forces
           mtime changes when a transaction completes */
-#ifdef HAVE_UTIME
+#if HAVE_UTIME
        utime(tdb->name, NULL);
 #endif
 
        /* use a transaction cancel to free memory and remove the
           transaction locks */
        utime(tdb->name, NULL);
 #endif
 
        /* use a transaction cancel to free memory and remove the
           transaction locks */
-       tdb_transaction_cancel(tdb);
+       tdb_transaction_cancel_internal(tdb);
 
        return 0;
 }
 
        return 0;
 }