]> code.citadel.org Git - citadel.git/blobdiff - citadel/server/backends/berkeley_db/berkeley_db.c
Wrapping indexer transactions inside a critical section seems to make it not deadlock
[citadel.git] / citadel / server / backends / berkeley_db / berkeley_db.c
index b025f0953c5d90cf5614d700a313fc3ad01772ee..b36c3c1058459969d7873bd717c3c300a4392b3c 100644 (file)
@@ -420,17 +420,21 @@ int bdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen)
                bdb_begin_transaction();                // create our own for this operation.
        }
 
-       ret = bdb_table[cdb]->put(bdb_table[cdb],       // db
-                           TSD->tid,                   // transaction ID
-                           &dkey,                      // key
-                           &ddata,                     // data
-                           0                           // flags
-       );
-
-       if (ret) {
-               syslog(LOG_ERR, "bdb: bdb_store(%02x): %s", cdb, db_strerror(ret));
-               bdb_abort();
-       }
+       do {
+               ret = bdb_table[cdb]->put(bdb_table[cdb],       // db
+                               TSD->tid,                       // transaction ID
+                               &dkey,                  // key
+                               &ddata,                 // data
+                               0                               // flags
+               );
+               if ((ret != 0) && (ret != DB_LOCK_DEADLOCK)) {
+                       syslog(LOG_ERR, "bdb: bdb_store(%02x): error %d: %s", cdb, ret, db_strerror(ret));
+                       bdb_abort();
+               }
+               if (ret == DB_LOCK_DEADLOCK) {
+                       syslog(LOG_DEBUG, "bdb: bdb_store(%02x): would deadlock, trying again", cdb);
+               }
+       } while (ret == DB_LOCK_DEADLOCK);
 
        if (!existing_txn) {
                bdb_end_transaction();
@@ -497,12 +501,14 @@ struct cdbdata bdb_fetch(int cdb, const void *key, int keylen) {
        dkey.data = (void *) key;
 
        TSD->dbdata[cdb].flags = DB_DBT_REALLOC;
-       ret = bdb_table[cdb]->get(bdb_table[cdb], TSD->tid, &dkey, &TSD->dbdata[cdb], 0);
 
-       if ((ret != 0) && (ret != DB_NOTFOUND)) {
-               syslog(LOG_ERR, "bdb: bdb_fetch(%d): %s", cdb, db_strerror(ret));
-               bdb_abort();
-       }
+       do {
+               ret = bdb_table[cdb]->get(bdb_table[cdb], TSD->tid, &dkey, &TSD->dbdata[cdb], 0);
+               if ((ret != 0) && (ret != DB_NOTFOUND) && (ret != DB_LOCK_DEADLOCK)) {
+                       syslog(LOG_ERR, "bdb: bdb_fetch(%d): error %d: %s", cdb, ret, db_strerror(ret));
+                       bdb_abort();
+               }
+       } while (ret == DB_LOCK_DEADLOCK);
 
        if (ret == 0) {
                bdb_decompress_if_necessary(&TSD->dbdata[cdb]);
@@ -635,7 +641,6 @@ void bdb_tick(void) {
        }
 }
 
-
 // Calling this function activates the Berkeley DB back end.
 void bdb_init_backend(void) {