summaryrefslogtreecommitdiffstats
path: root/source4/lib/tdb
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2006-02-01 10:50:26 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:51:42 -0500
commitb9e07af8227a59932e0da1dda1749d490eba958c (patch)
tree4b9f87a43b814fb9707fce9edd897ad107340169 /source4/lib/tdb
parent5bb38cf7e6b1647a88b0f2233bf5a513f8b4c881 (diff)
downloadsamba-b9e07af8227a59932e0da1dda1749d490eba958c.tar.gz
samba-b9e07af8227a59932e0da1dda1749d490eba958c.tar.xz
samba-b9e07af8227a59932e0da1dda1749d490eba958c.zip
r13283: added two optimisations to the tdb transactions code. The first is to
more agressively coalesce entries in the linked list of the undo log. The second is to ensure that writes during a transaction into the hash table don't cause the size of the undo log linked list to grow. These optimisations don't affect Samba much, but they make a huge difference to the use of ldb in kde (This used to be commit a37d9434d1fa181fd3d060ad032ee4ec5135fc52)
Diffstat (limited to 'source4/lib/tdb')
-rw-r--r--source4/lib/tdb/common/transaction.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/source4/lib/tdb/common/transaction.c b/source4/lib/tdb/common/transaction.c
index becc6cd059..ace4aa51a6 100644
--- a/source4/lib/tdb/common/transaction.c
+++ b/source4/lib/tdb/common/transaction.c
@@ -195,7 +195,7 @@ fail:
static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
const void *buf, tdb_len_t len)
{
- struct tdb_transaction_el *el;
+ struct tdb_transaction_el *el, *best_el=NULL;
if (len == 0) {
return 0;
@@ -213,6 +213,10 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
for (el=tdb->transaction->elements_last;el;el=el->prev) {
tdb_len_t partial;
+ if (best_el == NULL && off == el->offset+el->length) {
+ best_el = el;
+ }
+
if (off+len <= el->offset) {
continue;
}
@@ -248,6 +252,28 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
return 0;
}
+ /* see if we can append the new entry to an existing entry */
+ if (best_el && best_el->offset + best_el->length == off &&
+ (off+len < tdb->transaction->old_map_size ||
+ off > tdb->transaction->old_map_size)) {
+ unsigned char *data = best_el->data;
+ el = best_el;
+ el->data = realloc(el->data, el->length + len);
+ if (el->data == NULL) {
+ tdb->ecode = TDB_ERR_OOM;
+ tdb->transaction->transaction_error = 1;
+ el->data = data;
+ return -1;
+ }
+ if (buf) {
+ memcpy(el->data + el->length, buf, len);
+ } else {
+ memset(el->data + el->length, TDB_PAD_BYTE, len);
+ }
+ el->length += len;
+ return 0;
+ }
+
/* add a new entry at the end of the list */
el = malloc(sizeof(*el));
if (el == NULL) {
@@ -433,6 +459,15 @@ int tdb_transaction_start(struct tdb_context *tdb)
tdb->transaction->io_methods = tdb->methods;
tdb->methods = &transaction_methods;
+ /* by calling this transaction write here, we ensure that we don't grow the
+ transaction linked list due to hash table updates */
+ if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
+ TDB_HASHTABLE_SIZE(tdb)) != 0) {
+ TDB_LOG((tdb, 0, "tdb_transaction_start: failed to prime hash table\n"));
+ tdb->ecode = TDB_ERR_IO;
+ goto fail;
+ }
+
return 0;
fail: