diff --git a/lib/backend/sqlite.cc b/lib/backend/sqlite.cc index 7048d79615..f93d565c82 100644 --- a/lib/backend/sqlite.cc +++ b/lib/backend/sqlite.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -185,6 +186,20 @@ static int sqlite_init(rpmdb rdb, const char * dbhome) return rc; } +static long sqlite_free_space(sqlite3 * db) +{ + long result = 0; + sqlite3_stmt *s = NULL; + const char *cmd = "SELECT (freelist_count*page_size) as FreeSizeEstimate FROM pragma_freelist_count, pragma_page_size ;"; + if (sqlite3_prepare_v2(db, cmd, -1, &s, NULL) == SQLITE_OK) { + while (sqlite3_step(s) == SQLITE_ROW) { + result = sqlite3_column_int64(s, 0); + } + sqlite3_finalize(s); + } + return result; +} + static int sqlite_fini(rpmdb rdb) { int rc = 0; @@ -194,8 +209,19 @@ static int sqlite_fini(rpmdb rdb) rdb->db_opens--; } else { if (sqlite3_db_readonly(sdb, NULL) == 0) { + sqlexec(sdb, "PRAGMA optimize"); sqlexec(sdb, "PRAGMA wal_checkpoint = TRUNCATE"); + + int max_size = rpmExpandNumeric("%{?_sqlite_vacuum}"); + if (max_size <= 0) + max_size = 20*1024*1024; + int64_t free_space = sqlite_free_space(sdb); + + if (free_space > max_size) { + sqlexec(sdb, "VACUUM"); + rpmlog(RPMLOG_DEBUG, "Rpmdb Sqlite backend VACUUM maxfree: %i, free: %" PRIu64 " -> %" PRIu64 "\n", max_size, free_space, sqlite_free_space(sdb)); + } } rdb->db_dbenv = NULL; int xx = sqlite3_close(sdb); diff --git a/tests/rpmdb.at b/tests/rpmdb.at index 7c57f2bffe..7623ca210e 100644 --- a/tests/rpmdb.at +++ b/tests/rpmdb.at @@ -683,3 +683,20 @@ runroot rpm -q 'versiontest-1.0~2-1' []) RPMTEST_CLEANUP + +# ------------------------------ +AT_SETUP([rpmdb vacuum]) +AT_KEYWORDS([install rpmdb sqlite]) +RPMDB_INIT +RPMTEST_CHECK([ +runroot rpm -U --noscripts --nodeps --ignorearch --noverify \ + /data/RPMS/hello-1.0-1.i386.rpm +runroot rpm -D "_sqlite_vacuum 1024" -vv -U --noscripts --nodeps --ignorearch \ + /data/RPMS/hello-2.0-1.i686.rpm 2>&1 | grep VACUUM +], +[0], +[D: VACUUM: 0 +D: Rpmdb Sqlite backend VACUUM maxfree: 1024, free: 8192 -> 0 +], +[]) +RPMTEST_CLEANUP