On Tue, 2011-10-04 at 18:59 +0100, Andrew Beverley wrote:
> However, I'm now having problems with multiple instances of the session
> helper writing to the same database. I thought I had fixed this with the
> ->sync option, but it appears not. If I open multiple instances of
> ext_session_acl in terminal windows on the same database, then I do not
> get consistent results between each process. If I do a "LOGIN" on one,
> then I can still get "No session available" on the other. Any ideas why
> this might be? Is it a bug with db-185? Debugging shows that the key
> does not exist in the second process, despite having been written in the
> first.

After further investigation, the problem appears to be that the *read*
database process is being cached (I'm not sure where). So even if the
writing process syncs its changes to the DB file, these aren't reflected
in the process that is reading the DB file.

After a lot of Googling, the only way I can see to fix this is to close
and re-open the database on every read. This is very messy, but does
anyone have any better suggestions?

> I also found another bug with the session helper when used in active
> mode (which might have been created by me). I'll submit a patch once
> I've got a way ahead with the DB.

The problem here was that the "LOGIN" was being written to the database,
as well as the desired key (even though the correct string length was
specified). So it was never actually matching a subsequent query.

Please find attached a patch that fixes both of these. The fix for the
first is messy; the fix for the second is simple, just using strtok
instead of strrchr, so as to force the key to be correctly truncated.

Andy

This patch fixes two problems with the session helper:

1. When using multiple processes with the DB, it did not properly re-read the
database file when the other process makes a change.

2. Active mode was not properly working, due to the wrong key being written to
the database after a login.

=== modified file 'helpers/external_acl/session/ext_session_acl.cc'
--- helpers/external_acl/session/ext_session_acl.cc	2011-09-21 00:19:19 +0000
+++ helpers/external_acl/session/ext_session_acl.cc	2011-10-04 22:10:31 +0000
@@ -79,11 +79,16 @@
     DBT key, data;
     key.data = (void *)details;
     key.size = len;
+    /* This is very messy, but appears to be the only way to force a reload of the DB.
+       Failure to do this causes sync problems when multiple helper processes are running. */
+    shutdown_db();
+    init_db();   
     if (db->get(db, &key, &data, 0) == 0) {
         time_t timestamp;
         if (data.size != sizeof(timestamp)) {
             fprintf(stderr, "ERROR: %s: CORRUPTED DATABASE (%s)\n", program_name, details);
             db->del(db, &key, 0);
+            db->sync(db, 0);
             return 0;
         }
         memcpy(&timestamp, data.data, sizeof(timestamp));
@@ -111,6 +116,7 @@
     key.data = (void *)details;
     key.size = len;
     db->del(db, &key, 0);
+    db->sync(db, 0);
 }
 
 static void usage(void)
@@ -156,21 +162,19 @@
     while (fgets(request, HELPER_INPUT_BUFFER, stdin)) {
         int action = 0;
         const char *channel_id = strtok(request, " ");
-        const char *detail = strtok(NULL, "\n");
+        const char *detail = strtok(NULL, " \n");
         if (detail == NULL) {
             // Only 1 paramater supplied. We are expecting at least 2 (including the channel ID)
             fprintf(stderr, "FATAL: %s is concurrent and requires the concurrency option to be specified.\n", program_name);
             exit(1);
         }
-        const char *lastdetail = strrchr(detail, ' ');
+        const char *lastdetail = strtok(NULL, " \n");
         size_t detail_len = strlen(detail);
         if (lastdetail) {
-            if (strcmp(lastdetail, " LOGIN") == 0) {
+            if (strcmp(lastdetail, "LOGIN") == 0) {
                 action = 1;
-                detail_len = (size_t)(lastdetail-detail);
-            } else if (strcmp(lastdetail, " LOGOUT") == 0) {
+            } else if (strcmp(lastdetail, "LOGOUT") == 0) {
                 action = -1;
-                detail_len = (size_t)(lastdetail-detail);
             }
         }
         if (action == -1) {

Reply via email to