From db6d957330d03f3c369001c0fb91e6dec8d5651d Mon Sep 17 00:00:00 2001 From: Nagy Gabor <ngaba@bibl.u-szeged.hu> Date: Thu, 27 Mar 2008 18:55:52 +0100 Subject: [PATCH] Keep pkgcaches and dbs in sync Ref.: http://www.archlinux.org/pipermail/pacman-dev/2007-September/009429.html http://bugs.frugalware.org/index.php?do=details&task_id=2533 This patch based on the work of Vajna Miklos (vmiklos) from pacman-g2. It's time to fix this issue, since we have upcoming GUIs. Briefly, the problem is that pkgcache can become outdated. The trivial fix would be: reload pkgcache immediately after db lock. We follow a more sophisticated approach to minimize overhead: 1. Each dbs on HDD have a "fingerprint": .lastupdate (patch extends this to localdb too) 2. After pkgcache load this fingerprint is recorded to the new fingerprint field of pmdb_t 3. New _alpm_db_refrech_pkgcache was introduced to reload cache, if it outdated. (Note: fingerprint treats transaction atomic.) Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu> --- lib/libalpm/cache.c | 17 +++++++++++++++++ lib/libalpm/cache.h | 1 + lib/libalpm/db.h | 1 + lib/libalpm/trans.c | 11 +++++++++++ 4 files changed, 30 insertions(+), 0 deletions(-) diff --git a/lib/libalpm/cache.c b/lib/libalpm/cache.c index 7fa2405..8922dca 100644 --- a/lib/libalpm/cache.c +++ b/lib/libalpm/cache.c @@ -67,6 +67,7 @@ int _alpm_db_load_pkgcache(pmdb_t *db) } db->pkgcache = alpm_list_msort(db->pkgcache, count, _alpm_pkg_cmp); + db->fingerprint = _alpm_db_getlastupdate(db); return(0); } @@ -90,6 +91,22 @@ void _alpm_db_free_pkgcache(pmdb_t *db) } } +/* Reload pkgcache if it is outdated + */ +int _alpm_db_refresh_pkgcache(pmdb_t *db) { + ALPM_LOG_FUNC; + + if(db == NULL) { + return(-1); + } + + if(!db->pkgcache || (db->fingerprint != _alpm_db_getlastupdate(db))) { + return(_alpm_db_load_pkgcache(db)); + } + + return(0); +} + alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db) { ALPM_LOG_FUNC; diff --git a/lib/libalpm/cache.h b/lib/libalpm/cache.h index 915896e..4569b70 100644 --- a/lib/libalpm/cache.h +++ b/lib/libalpm/cache.h @@ -27,6 +27,7 @@ /* packages */ int _alpm_db_load_pkgcache(pmdb_t *db); void _alpm_db_free_pkgcache(pmdb_t *db); +int _alpm_db_refresh_pkgcache(pmdb_t *db); int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg); int _alpm_db_remove_pkgfromcache(pmdb_t *db, pmpkg_t *pkg); alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db); diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 8c8c9bd..cd362d5 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -45,6 +45,7 @@ struct __pmdb_t { alpm_list_t *pkgcache; alpm_list_t *grpcache; alpm_list_t *servers; + time_t fingerprint; /* of pkgcache */ }; /* db.c, database general calls */ diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index 3edbbac..f425147 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -65,6 +65,7 @@ int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags, alpm_trans_cb_progress progress) { ALPM_LOG_FUNC; + alpm_list_t *i; /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); @@ -77,6 +78,12 @@ int SYMEXPORT alpm_trans_init(pmtranstype_t type, pmtransflag_t flags, RET_ERR(PM_ERR_HANDLE_LOCK, -1); } + /* ensure dbs and pkgcaches are in sync */ + _alpm_db_refresh_pkgcache(handle->db_local); + for(i = handle->dbs_sync; i; i = i->next) { + _alpm_db_refresh_pkgcache(i->data); + } + handle->trans = _alpm_trans_new(); if(handle->trans == NULL) { RET_ERR(PM_ERR_MEMORY, -1); @@ -203,6 +210,10 @@ int SYMEXPORT alpm_trans_release() _alpm_trans_free(trans); handle->trans = NULL; + time_t fingerprint = time(NULL); + _alpm_db_setlastupdate(handle->db_local, fingerprint); + handle->db_local->fingerprint = fingerprint; + /* unlock db */ if(handle->lckfd != -1) { close(handle->lckfd); -- 1.5.3.8