Lookups: fix pgsql multiple-row, single-column return
[users/heiko/exim.git] / src / src / enq.c
index dc9be759c6145d1ad968e3fe2066fb8a40d65c94..573fc00ca4833cca78c0d20d44d6f6a0a1d54b07 100644 (file)
@@ -1,10 +1,8 @@
-/* $Cambridge: exim/src/src/enq.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with serialization. */
 /* This function is called when a host is listed for serialization of
 connections. It is also called when ETRN is listed for serialization. We open
 the misc database and look for a record, which implies an existing connection
-or ETRN run. If not found, create one and return TRUE.
+or ETRN run. If increasing the count would take us past the given limit
+value return FALSE.  If not, bump it and return TRUE.  If not found, create
+one with value 1 and return TRUE.
 
 Arguments:
   key            string on which to serialize
+  lim            parallelism limit
 
 Returns:         TRUE if OK to proceed; FALSE otherwise
 */
 
 
 BOOL
-enq_start(uschar *key)
+enq_start(uschar *key, unsigned lim)
 {
 dbdata_serialize *serial_record;
 dbdata_serialize new_record;
@@ -46,25 +47,31 @@ deliberate; the dbfn_open() function - which is an Exim function - always tries
 to create if it can't open a read/write file. It expects only O_RDWR or
 O_RDONLY as its argument. */
 
-dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE);
-if (dbm_file == NULL) return FALSE;
+if (!(dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE)))
+  return FALSE;
 
 /* See if there is a record for this host or queue run; if there is, we cannot
 proceed with the connection unless the record is very old. */
 
 serial_record = dbfn_read(dbm_file, key);
-if (serial_record != NULL && time(NULL) - serial_record->time_stamp < 6*60*60)
+if (serial_record && time(NULL) - serial_record->time_stamp < 6*60*60)
   {
-  dbfn_close(dbm_file);
-  DEBUG(D_transport) debug_printf("outstanding serialization record for %s\n",
-    key);
-  return FALSE;
+  if (serial_record->count >= lim)
+    {
+    dbfn_close(dbm_file);
+    DEBUG(D_transport) debug_printf("outstanding serialization record for %s\n",
+      key);
+    return FALSE;
+    }
+  new_record.count = serial_record->count + 1;
   }
+else
+  new_record.count = 1;
 
-/* We can proceed - insert a new record or update the old one. At present
-the count field is not used; just set it to 1. */
+/* We can proceed - insert a new record or update the old one. */
 
-new_record.count = 1;
+DEBUG(D_transport) debug_printf("write serialization record for %s val %d\n",
+      key, new_record.count);
 dbfn_write(dbm_file, key, &new_record, (int)sizeof(dbdata_serialize));
 dbfn_close(dbm_file);
 return TRUE;
@@ -90,12 +97,25 @@ enq_end(uschar *key)
 {
 open_db dbblock;
 open_db *dbm_file;
+dbdata_serialize *serial_record;
 
 DEBUG(D_transport) debug_printf("end serialized: %s\n", key);
 
-dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE);
-if (dbm_file == NULL) return;
-dbfn_delete(dbm_file, key);
+if (  !(dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE))
+   || !(serial_record = dbfn_read(dbm_file, key))
+   )
+  return;
+if (--serial_record->count > 0)
+  {
+  DEBUG(D_transport) debug_printf("write serialization record for %s val %d\n",
+      key, serial_record->count);
+  dbfn_write(dbm_file, key, serial_record, (int)sizeof(dbdata_serialize));
+  }
+else
+  {
+  DEBUG(D_transport) debug_printf("remove serialization record for %s\n", key);
+  dbfn_delete(dbm_file, key);
+  }
 dbfn_close(dbm_file);
 }