Rev 713: cleanup the new freelist code in http://samba.org/~tridge/ctdb

tridge at samba.org tridge at samba.org
Sat Jan 5 01:09:00 GMT 2008


------------------------------------------------------------
revno: 713
revision-id:tridge at samba.org-20080105010900-5c7uv6cs1f761q1g
parent: tridge at samba.org-20080105010841-n49gmcacwn2x1fdc
committer: Andrew Tridgell <tridge at samba.org>
branch nick: tridge.stable
timestamp: Sat 2008-01-05 12:09:00 +1100
message:
  cleanup the new freelist code
modified:
  lib/tdb/common/freelist.c      freelist.c-20070220022425-m1wibgjq7n5hahs6-4
=== modified file 'lib/tdb/common/freelist.c'
--- a/lib/tdb/common/freelist.c	2008-01-04 01:12:02 +0000
+++ b/lib/tdb/common/freelist.c	2008-01-05 01:09:00 +0000
@@ -27,6 +27,12 @@
 
 #include "tdb_private.h"
 
+/* 'right' merges can involve O(n^2) cost when combined with a
+   traverse, so they are disabled until we find a way to do them in 
+   O(1) time
+*/
+#define USE_RIGHT_MERGES 0
+
 /* read a freelist record and check for simple errors */
 int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
 {
@@ -56,7 +62,7 @@
 }
 
 
-
+#if USE_RIGHT_MERGES
 /* Remove an element from the freelist.  Must have alloc lock. */
 static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next)
 {
@@ -75,6 +81,7 @@
 	TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off));
 	return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
 }
+#endif
 
 
 /* update a record tailer (must hold allocation lock) */
@@ -93,8 +100,6 @@
    neccessary. */
 int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
 {
-	tdb_off_t right, left;
-
 	/* Allocation and tailer lock */
 	if (tdb_lock(tdb, -1, F_WRLCK) != 0)
 		return -1;
@@ -105,13 +110,10 @@
 		goto fail;
 	}
 
-#if 0
-	/* (tridge) disable 'right' merges for now as they give rise to a O(n^2) behaviour during
-	   traverse which is freeing old dead records */
-
+#if USE_RIGHT_MERGES
 	/* Look right first (I'm an Australian, dammit) */
-	right = offset + sizeof(*rec) + rec->rec_len;
-	if (right + sizeof(*rec) <= tdb->map_size) {
+	if (offset + sizeof(*rec) + rec->rec_len + sizeof(*rec) <= tdb->map_size) {
+		tdb_off_t right = offset + sizeof(*rec) + rec->rec_len;
 		struct list_struct r;
 
 		if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
@@ -126,14 +128,18 @@
 				goto left;
 			}
 			rec->rec_len += sizeof(r) + r.rec_len;
+			if (update_tailer(tdb, offset, rec) == -1) {
+				TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset));
+				goto fail;
+			}
 		}
 	}
-#endif
-
 left:
+#endif
+
 	/* Look left */
-	left = offset - sizeof(tdb_off_t);
-	if (left > TDB_DATA_START(tdb->header.hash_size)) {
+	if (offset - sizeof(tdb_off_t) >= TDB_DATA_START(tdb->header.hash_size)) {
+		tdb_off_t left = offset - sizeof(tdb_off_t);
 		struct list_struct l;
 		tdb_off_t leftsize;
 		
@@ -150,7 +156,11 @@
 
 		left = offset - leftsize;
 
-		/* Now read in record */
+		if (left < TDB_DATA_START(tdb->header.hash_size)) {
+			goto update;
+		}
+
+		/* Now read in the left record */
 		if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) {
 			TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize));
 			goto update;
@@ -158,7 +168,6 @@
 
 		/* If it's free, expand to include it. */
 		if (l.magic == TDB_FREE_MAGIC) {
-#if 1
 			/* we now merge the new record into the left record, rather than the other 
 			   way around. This makes the operation O(1) instead of O(n). This change
 			   prevents traverse from being O(n^2) after a lot of deletes */
@@ -171,26 +180,12 @@
 				TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset));
 				goto fail;
 			}
-			/* we're done. */
 			tdb_unlock(tdb, -1, F_WRLCK);
-			return 0;			
-#else
-			if (remove_from_freelist(tdb, left, l.next) == -1) {
-				TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left free failed at %u\n", left));
-				goto update;
-			} else {
-				offset = left;
-				rec->rec_len += leftsize;
-			}
-#endif
+			return 0;
 		}
 	}
 
 update:
-	if (update_tailer(tdb, offset, rec) == -1) {
-		TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset));
-		goto fail;
-	}
 
 	/* Now, prepend to free list */
 	rec->magic = TDB_FREE_MAGIC;



More information about the samba-cvs mailing list