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:
parent
6aa72dae8f
commit
094ab60053
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user