Wrapping indexer transactions inside a critical section seems to make it not deadlock
authorArt Cancro <ajc@citadel.org>
Wed, 30 Aug 2023 19:27:39 +0000 (15:27 -0400)
committerArt Cancro <ajc@citadel.org>
Wed, 30 Aug 2023 19:27:39 +0000 (15:27 -0400)
citadel/server/backends/berkeley_db/berkeley_db.c
citadel/server/citadel_defs.h
citadel/server/modules/fulltext/serv_fulltext.c
citadel/utils/loadtest.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) {
 
index a879c4631a76d48b40893df1942b17d3a5e445e5..6a16bfda8a894e878d69d32527b195d21bed2b66 100644 (file)
@@ -170,6 +170,7 @@ enum {
        S_IM_LOGS,
        S_OPENSSL,
        S_SMTPQUEUE,
+       S_INDEXER,
        MAX_SEMAPHORES
 };
 
index 994e856bbe716a4f42c959f81f07cbbe351d10de..caa5f17e76a00a7e1a1dc1942a0ff846e02ffd2f 100644 (file)
@@ -102,6 +102,7 @@ void ft_index_message(long msgnum, int op) {
        );
 
        if (array_len(tokens_in_this_message) > 0) {
+               begin_critical_section(S_INDEXER);
                cdb_begin_transaction();
                for (i=0; i<array_len(tokens_in_this_message); ++i) {
 
@@ -122,7 +123,6 @@ void ft_index_message(long msgnum, int op) {
                                memcpy(newbucket, cdb_bucket.ptr, cdb_bucket.len);
                                for (j=0; j<nmsgs; ++j) {
                                        if ((newbucket[j] == msgnum) || (newbucket[j] == 0)) {
-                                               fprintf(stderr, "removing %ld\n", newbucket[j]);
                                                memcpy(&newbucket[j], &newbucket[j+1], ((nmsgs-j)*sizeof(long)));
                                                --j;
                                                --nmsgs;
@@ -137,6 +137,7 @@ void ft_index_message(long msgnum, int op) {
                        if (server_shutting_down) break;
                }
                cdb_end_transaction();
+               end_critical_section(S_INDEXER);
                CtdlSetConfigLong("MMfulltext", msgnum);
        }
        array_free(tokens_in_this_message);
index 5cd8253dbd917560c03a1bee6c92f694a052b72e..c3acb05895afb1f6eadc976414fb7dcc3b3d3b6d 100644 (file)
@@ -292,7 +292,7 @@ void do_stuff(int serv_sock) {
 
        long ops = 0;
        while(1) {
-               alarm(30);
+               //alarm(30);
                perform_random_thing(serv_sock);
                printf("\033[%d;11H\033[33m%8ld\033[0m", 7+serv_sock, ++ops);
                fflush(stdout);