[pacman-dev] [PATCH] Keep pkgcaches and dbs in sync (resubmit)

Nagy Gabor ngaba at bibl.u-szeged.hu
Thu Mar 27 14:51:14 EDT 2008


From 6631713f5bd54953ba60555b07b8e3ec5e4cfb81 Mon Sep 17 00:00:00 2001
From: Nagy Gabor <ngaba at bibl.u-szeged.hu>
Date: Thu, 27 Mar 2008 19:48:49 +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 is 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 is outdated.
(Note: fingerprint treats transaction atomic.)

[Resubmit: move fingerprint creation to the begining of load_pkgcache]
Signed-off-by: Nagy Gabor <ngaba at 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..8b5c335 100644
--- a/lib/libalpm/cache.c
+++ b/lib/libalpm/cache.c
@@ -54,6 +54,7 @@ int _alpm_db_load_pkgcache(pmdb_t *db)
 
 	_alpm_log(PM_LOG_DEBUG, "loading package cache for repository '%s'\n",
 	          db->treename);
+	db->fingerprint = _alpm_db_getlastupdate(db);
 
 	_alpm_db_rewind(db);
 	while((info = _alpm_db_scan(db, NULL)) != NULL) {
@@ -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






More information about the pacman-dev mailing list