Blob Blame Raw
commit 918b2892b46036ac46f07c3156ed78b45e4e2ee2
Author: Panu Matilainen <pmatilai@redhat.com>
Date:   Tue Feb 5 10:11:19 2013 +0200

    Check for stale db locks when opening write-cursors
    
    - During long-running transactions its entirely possible for some
      other player to come and go leaving stale locks behind and cause
      the transaction to get stuck until the cavalry comes along in the
      form of somebody else opening the rpmdb, clearing the blockage.
    - Presumably dbenv->failchk() is not entirely free of cost so we only
      do this for writes which are way more critical and also more prone to
      getting stuck.
    - dbenv->failchk() could return DB_RUNRECOVER in which case we should
      abort everything but we lack a mechanism to do it... just add
      a reminder comment for now.
    
    (cherry picked from commit 29e7c4b3bd1e67f9de1eaaf9fecf82cae281a7e6)

diff --git a/lib/backend/db3.c b/lib/backend/db3.c
index bbf9577..ed2a5f8 100644
--- a/lib/backend/db3.c
+++ b/lib/backend/db3.c
@@ -244,7 +244,7 @@ dbiCursor dbiCursorInit(dbiIndex dbi, unsigned int flags)
 	DB * db = dbi->dbi_db;
 	DBC * cursor;
 	int cflags;
-	int rc;
+	int rc = 0;
 	uint32_t eflags = db_envflags(db);
 	
        /* DB_WRITECURSOR requires CDB and writable db */
@@ -255,8 +255,23 @@ dbiCursor dbiCursorInit(dbiIndex dbi, unsigned int flags)
 	} else
 	    cflags = 0;
 
-	rc = db->cursor(db, NULL, &cursor, cflags);
-	rc = cvtdberr(dbi, "db->cursor", rc, _debug);
+	/*
+	 * Check for stale locks which could block writes "forever".
+	 * XXX: Should we also do this on reads? Reads are less likely
+	 *      to get blocked so it seems excessive...
+	 * XXX: On DB_RUNRECOVER, we should abort everything. Now
+	 *      we'll just fail to open a cursor again and again and again.
+	 */
+	if (cflags & DB_WRITECURSOR) {
+	    DB_ENV *dbenv = db->get_env(db);
+	    rc = dbenv->failchk(dbenv, 0);
+	    rc = cvtdberr(dbi, "dbenv->failchk", rc, _debug);
+	}
+
+	if (rc == 0) {
+	    rc = db->cursor(db, NULL, &cursor, cflags);
+	    rc = cvtdberr(dbi, "db->cursor", rc, _debug);
+	}
 
 	if (rc == 0) {
 	    dbc = xcalloc(1, sizeof(*dbc));