merged tdb changes from ctdb
authorAndrew Tridgell <tridge@samba.org>
Fri, 18 Jan 2008 04:33:57 +0000 (15:33 +1100)
committerAndrew Tridgell <tridge@samba.org>
Fri, 18 Jan 2008 04:33:57 +0000 (15:33 +1100)
source/lib/tdb/common/freelist.c
source/lib/tdb/common/tdb_private.h
source/lib/tdb/common/transaction.c

index c086c151fa686ceafd421c563313a734bf6d279f..2f2a4c379b0690399a9f4065b15960e667300bf0 100644 (file)
@@ -208,62 +208,61 @@ update:
 }
 
 
+
 /* 
    the core of tdb_allocate - called when we have decided which
    free list entry to use
+
+   Note that we try to allocate by grabbing data from the end of an existing record,
+   not the beginning. This is so the left merge in a free is more likely to be
+   able to free up the record without fragmentation
  */
-static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr,
-                               struct list_struct *rec, tdb_off_t last_ptr)
+static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, 
+                                 tdb_len_t length, tdb_off_t rec_ptr,
+                                 struct list_struct *rec, tdb_off_t last_ptr)
 {
-       struct list_struct newrec;
-       tdb_off_t newrec_ptr;
+#define MIN_REC_SIZE (sizeof(struct list_struct) + sizeof(tdb_off_t) + 8)
 
-       memset(&newrec, '\0', sizeof(newrec));
+       if (rec->rec_len < length + MIN_REC_SIZE) {
+               /* we have to grab the whole record */
 
-       /* found it - now possibly split it up  */
-       if (rec->rec_len > length + MIN_REC_SIZE) {
-               /* Length of left piece */
-               length = TDB_ALIGN(length, TDB_ALIGNMENT);
-               
-               /* Right piece to go on free list */
-               newrec.rec_len = rec->rec_len - (sizeof(*rec) + length);
-               newrec_ptr = rec_ptr + sizeof(*rec) + length;
-               
-               /* And left record is shortened */
-               rec->rec_len = length;
-       } else {
-               newrec_ptr = 0;
+               /* unlink it from the previous record */
+               if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) {
+                       return 0;
+               }
+
+               /* mark it not free */
+               rec->magic = TDB_MAGIC;
+               if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
+                       return 0;
+               }
+               return rec_ptr;
+       }
+
+       /* we're going to just shorten the existing record */
+       rec->rec_len -= (length + sizeof(*rec));
+       if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
+               return 0;
        }
-       
-       /* Remove allocated record from the free list */
-       if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) {
+       if (update_tailer(tdb, rec_ptr, rec) == -1) {
                return 0;
        }
-       
-       /* Update header: do this before we drop alloc
-          lock, otherwise tdb_free() might try to
-          merge with us, thinking we're free.
-          (Thanks Jeremy Allison). */
+
+       /* and setup the new record */
+       rec_ptr += sizeof(*rec) + rec->rec_len; 
+
+       memset(rec, '\0', sizeof(*rec));
+       rec->rec_len = length;
        rec->magic = TDB_MAGIC;
+
        if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
                return 0;
        }
-       
-       /* Did we create new block? */
-       if (newrec_ptr) {
-               /* Update allocated record tailer (we
-                  shortened it). */
-               if (update_tailer(tdb, rec_ptr, rec) == -1) {
-                       return 0;
-               }
-               
-               /* Free new record */
-               if (tdb_free(tdb, newrec_ptr, &newrec) == -1) {
-                       return 0;
-               }
+
+       if (update_tailer(tdb, rec_ptr, rec) == -1) {
+               return 0;
        }
-       
-       /* all done - return the new record offset */
+
        return rec_ptr;
 }
 
@@ -287,6 +286,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st
 
        /* Extra bytes required for tailer */
        length += sizeof(tdb_off_t);
+       length = TDB_ALIGN(length, TDB_ALIGNMENT);
 
  again:
        last_ptr = FREELIST_TOP;
@@ -343,7 +343,8 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st
                        goto fail;
                }
 
-               newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr);
+               newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, 
+                                             rec, bestfit.last_ptr);
                tdb_unlock(tdb, -1, F_WRLCK);
                return newrec_ptr;
        }
index 63a6d04e72d00db22f8c87c6cf3222963f1d1562..0d3f10582edbc50a01ad17764d645fe72e9f1b1a 100644 (file)
@@ -49,7 +49,6 @@ typedef uint32_t tdb_off_t;
 #define TDB_DEAD_MAGIC (0xFEE1DEAD)
 #define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
 #define TDB_ALIGNMENT 4
-#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT)
 #define DEFAULT_HASH_SIZE 131
 #define FREELIST_TOP (sizeof(struct tdb_header))
 #define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1))
index 0ecfb9b7ff610f9665ba7e53ae6eef78f71c98a3..ea0e3a93f3d46c2ccd835b95a3313afb3911f987 100644 (file)
@@ -316,25 +316,15 @@ static int transaction_write_existing(struct tdb_context *tdb, tdb_off_t off,
                return 0;
        }
 
-       /* overwrite part of an existing block */
-       if (buf == NULL) {
-               memset(tdb->transaction->blocks[blk] + off, 0, len);
-       } else {
-               memcpy(tdb->transaction->blocks[blk] + off, buf, len);
-       }
-       if (blk == tdb->transaction->num_blocks-1) {
-               if (len + off > tdb->transaction->last_block_size) {
-                       tdb->transaction->last_block_size = len + off;
-               }
+       if (blk == tdb->transaction->num_blocks-1 &&
+           off + len > tdb->transaction->last_block_size) {
+               len = tdb->transaction->last_block_size - off;
        }
 
-       return 0;
+       /* overwrite part of an existing block */
+       memcpy(tdb->transaction->blocks[blk] + off, buf, len);
 
-fail:
-       TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", 
-                (blk*tdb->transaction->block_size) + off, len));
-       tdb->transaction->transaction_error = 1;
-       return -1;
+       return 0;
 }