]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/transaction.c
tdb2: cleanup oob handling.
[ccan] / ccan / tdb2 / transaction.c
index 805ea0948aad0e0ddfa11289aadc26334cfc8a44..eda65c520842240e871ed3439378432f102a4d9c 100644 (file)
@@ -348,15 +348,14 @@ static void transaction_write_existing(struct tdb_context *tdb, tdb_off_t off,
 static enum TDB_ERROR transaction_oob(struct tdb_context *tdb, tdb_off_t len,
                                      bool probe)
 {
-       if (len <= tdb->file->map_size) {
+       if (len <= tdb->file->map_size || probe) {
                return TDB_SUCCESS;
        }
-       if (!probe) {
-               tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
-                          "tdb_oob len %lld beyond transaction size %lld",
-                          (long long)len,
-                          (long long)tdb->file->map_size);
-       }
+
+       tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                  "tdb_oob len %lld beyond transaction size %lld",
+                  (long long)len,
+                  (long long)tdb->file->map_size);
        return TDB_ERR_IO;
 }
 
@@ -387,15 +386,17 @@ static void *transaction_direct(struct tdb_context *tdb, tdb_off_t off,
 
        /* Can only do direct if in single block and we've already copied. */
        if (write_mode) {
-               if (blk != end_blk)
-                       return NULL;
-               if (blk >= tdb->transaction->num_blocks)
-                       return NULL;
-               if (tdb->transaction->blocks[blk] == NULL)
+               tdb->stats.transaction_write_direct++;
+               if (blk != end_blk
+                   || blk >= tdb->transaction->num_blocks
+                   || tdb->transaction->blocks[blk] == NULL) {
+                       tdb->stats.transaction_write_direct_fail++;
                        return NULL;
+               }
                return tdb->transaction->blocks[blk] + off % PAGESIZE;
        }
 
+       tdb->stats.transaction_read_direct++;
        /* Single which we have copied? */
        if (blk == end_blk
            && blk < tdb->transaction->num_blocks
@@ -406,8 +407,10 @@ static void *transaction_direct(struct tdb_context *tdb, tdb_off_t off,
        while (blk <= end_blk) {
                if (blk >= tdb->transaction->num_blocks)
                        break;
-               if (tdb->transaction->blocks[blk])
+               if (tdb->transaction->blocks[blk]) {
+                       tdb->stats.transaction_read_direct_fail++;
                        return NULL;
+               }
                blk++;
        }
        return tdb->transaction->io_methods->direct(tdb, off, len, false);
@@ -438,7 +441,7 @@ static enum TDB_ERROR transaction_sync(struct tdb_context *tdb,
        }
 #ifdef MS_SYNC
        if (tdb->file->map_ptr) {
-               tdb_off_t moffset = offset & ~(PAGESIZE-1);
+               tdb_off_t moffset = offset & ~(getpagesize()-1);
                if (msync(moffset + (char *)tdb->file->map_ptr,
                          length + (offset - moffset), MS_SYNC) != 0) {
                        return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
@@ -505,7 +508,7 @@ static void _tdb_transaction_cancel(struct tdb_context *tdb)
        tdb_transaction_unlock(tdb, F_WRLCK);
 
        if (tdb_has_open_lock(tdb))
-               tdb_unlock_open(tdb);
+               tdb_unlock_open(tdb, F_WRLCK);
 
        SAFE_FREE(tdb->transaction);
 }
@@ -518,6 +521,7 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
 {
        enum TDB_ERROR ecode;
 
+       tdb->stats.transactions++;
        /* some sanity checks */
        if (tdb->read_only || (tdb->flags & TDB_INTERNAL)) {
                return tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
@@ -538,6 +542,7 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
                                             " already inside transaction");
                }
                tdb->transaction->nesting++;
+               tdb->stats.transaction_nest++;
                return 0;
        }
 
@@ -603,6 +608,7 @@ fail_allrecord_lock:
 */
 void tdb_transaction_cancel(struct tdb_context *tdb)
 {
+       tdb->stats.transaction_cancel++;
        _tdb_transaction_cancel(tdb);
 }
 
@@ -824,6 +830,7 @@ static tdb_off_t create_recovery_area(struct tdb_context *tdb,
        addition = (tdb->file->map_size - tdb->transaction->old_map_size) +
                sizeof(*rec) + rec->max_len;
        tdb->file->map_size = tdb->transaction->old_map_size;
+       tdb->stats.transaction_expand_file++;
        ecode = methods->expand_file(tdb, addition);
        if (ecode != TDB_SUCCESS) {
                return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
@@ -997,7 +1004,7 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb)
 
        /* get the open lock - this prevents new users attaching to the database
           during the commit */
-       ecode = tdb_lock_open(tdb, TDB_LOCK_WAIT|TDB_LOCK_NOCHECK);
+       ecode = tdb_lock_open(tdb, F_WRLCK, TDB_LOCK_WAIT|TDB_LOCK_NOCHECK);
        if (ecode != TDB_SUCCESS) {
                return ecode;
        }