]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/transaction.c
tdb2: use counters to decide when to coalesce records.
[ccan] / ccan / tdb2 / transaction.c
index d15db10691eb7d17c489a54d4211ccaa5cb16535..f1414391abe42caa7b81504dede1ea3700291c1b 100644 (file)
@@ -110,7 +110,7 @@ struct tdb_transaction {
        /* when inside a transaction we need to keep track of any
           nested tdb_transaction_start() calls, as these are allowed,
           but don't create a new transaction */
-       int nesting;
+       unsigned int nesting;
 
        /* set when a prepare has already occurred */
        bool prepared;
@@ -531,11 +531,15 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
 
        /* cope with nested tdb_transaction_start() calls */
        if (tdb->transaction != NULL) {
-               return tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO,
-                                                   TDB_LOG_USE_ERROR,
-                                                   "tdb_transaction_start:"
-                                                   " already inside"
-                                                   " transaction");
+               if (!(tdb->flags & TDB_ALLOW_NESTING)) {
+                       return tdb->last_error
+                               = tdb_logerr(tdb, TDB_ERR_IO,
+                                            TDB_LOG_USE_ERROR,
+                                            "tdb_transaction_start:"
+                                            " already inside transaction");
+               }
+               tdb->transaction->nesting++;
+               return 0;
        }
 
        if (tdb_has_hash_locks(tdb)) {
@@ -682,9 +686,10 @@ static enum TDB_ERROR tdb_recovery_allocate(struct tdb_context *tdb,
           us an area that is being currently used (as of the start of
           the transaction) */
        if (recovery_head != 0) {
-               add_stat(tdb, frees, 1);
+               tdb->stats.frees++;
                ecode = add_free_record(tdb, recovery_head,
-                                       sizeof(rec) + rec.max_len);
+                                       sizeof(rec) + rec.max_len,
+                                       TDB_LOCK_WAIT, true);
                if (ecode != TDB_SUCCESS) {
                        return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
                                          "tdb_recovery_allocate:"
@@ -696,10 +701,11 @@ static enum TDB_ERROR tdb_recovery_allocate(struct tdb_context *tdb,
        /* the tdb_free() call might have increased the recovery size */
        *recovery_size = tdb_recovery_size(tdb);
 
-       /* round up to a multiple of page size */
+       /* round up to a multiple of page size. Overallocate, since each
+        * such allocation forces us to expand the file. */
        *recovery_max_size
-               = (((sizeof(rec) + *recovery_size) + PAGESIZE-1)
-                  & ~(PAGESIZE-1))
+               = (((sizeof(rec) + *recovery_size + *recovery_size / 2)
+                   + PAGESIZE-1) & ~(PAGESIZE-1))
                - sizeof(rec);
        *recovery_offset = tdb->file->map_size;
        recovery_head = *recovery_offset;
@@ -907,7 +913,6 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb)
 
 
        if (tdb->transaction->nesting != 0) {
-               tdb->transaction->nesting--;
                return TDB_SUCCESS;
        }