1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

tdb: tdb_repack() only when it's worthwhile.

tdb_repack() is expensive and consumes memory, so we can spend some
effort to see if it's worthwhile.  In particular, tdbbackup doesn't
need to repack: it started with an empty database!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2011-04-18 22:15:11 +09:30
parent 6aa72dae8f
commit 094ab60053

View File

@ -138,8 +138,8 @@ struct tdb_transaction {
/* old file size before transaction */
tdb_len_t old_map_size;
/* we should re-pack on commit */
bool need_repack;
/* did we expand in this transaction */
bool expanded;
};
@ -403,7 +403,7 @@ static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size,
return -1;
}
tdb->transaction->need_repack = true;
tdb->transaction->expanded = true;
return 0;
}
@ -983,6 +983,28 @@ _PUBLIC_ int tdb_transaction_prepare_commit(struct tdb_context *tdb)
return _tdb_transaction_prepare_commit(tdb);
}
/* A repack is worthwhile if the largest is less than half total free. */
static bool repack_worthwhile(struct tdb_context *tdb)
{
tdb_off_t ptr;
struct tdb_record rec;
tdb_len_t total = 0, largest = 0;
if (tdb_ofs_read(tdb, FREELIST_TOP, &ptr) == -1) {
return false;
}
while (ptr != 0 && tdb_rec_free_read(tdb, ptr, &rec) == 0) {
total += rec.rec_len;
if (rec.rec_len > largest) {
largest = rec.rec_len;
}
ptr = rec.next;
}
return total > largest * 2;
}
/*
commit the current transaction
*/
@ -990,7 +1012,7 @@ _PUBLIC_ int tdb_transaction_commit(struct tdb_context *tdb)
{
const struct tdb_methods *methods;
int i;
bool need_repack;
bool need_repack = false;
if (tdb->transaction == NULL) {
TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n"));
@ -1058,6 +1080,11 @@ _PUBLIC_ int tdb_transaction_commit(struct tdb_context *tdb)
SAFE_FREE(tdb->transaction->blocks[i]);
}
/* Do this before we drop lock or blocks. */
if (tdb->transaction->expanded) {
need_repack = repack_worthwhile(tdb);
}
SAFE_FREE(tdb->transaction->blocks);
tdb->transaction->num_blocks = 0;
@ -1081,8 +1108,6 @@ _PUBLIC_ int tdb_transaction_commit(struct tdb_context *tdb)
utime(tdb->name, NULL);
#endif
need_repack = tdb->transaction->need_repack;
/* use a transaction cancel to free memory and remove the
transaction locks */
_tdb_transaction_cancel(tdb);