diff options
author | Andrew Tridgell <tridge@samba.org> | 2006-02-01 10:50:26 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:51:42 -0500 |
commit | b9e07af8227a59932e0da1dda1749d490eba958c (patch) | |
tree | 4b9f87a43b814fb9707fce9edd897ad107340169 /source4/lib/tdb | |
parent | 5bb38cf7e6b1647a88b0f2233bf5a513f8b4c881 (diff) | |
download | samba-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.c | 37 |
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: |