summaryrefslogtreecommitdiffstats
path: root/src/enq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/enq.c')
-rw-r--r--src/enq.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/enq.c b/src/enq.c
new file mode 100644
index 0000000..f7f8c9c
--- /dev/null
+++ b/src/enq.c
@@ -0,0 +1,123 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) The Exim Maintainers 2021 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* Functions concerned with serialization. */
+
+
+#include "exim.h"
+
+
+
+
+/*************************************************
+* Test for host or ETRN 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 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, unsigned lim)
+{
+dbdata_serialize *serial_record;
+dbdata_serialize new_record;
+open_db dbblock;
+open_db *dbm_file;
+
+DEBUG(D_transport) debug_printf("check serialized: %s\n", key);
+
+/* Open and lock the waiting information database. The absence of O_CREAT is
+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. */
+
+if (!(dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, 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_enforce_length(dbm_file, key, sizeof(dbdata_serialize));
+if (serial_record && time(NULL) - serial_record->time_stamp < 6*60*60)
+ {
+ 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. */
+
+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;
+}
+
+
+
+/*************************************************
+* Release serialization *
+*************************************************/
+
+/* This function is called when a serialized host's connection or serialized
+ETRN queue run ends. We open the relevant database and delete its record.
+
+Arguments:
+ key the serialization key
+
+Returns: nothing
+*/
+
+void
+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);
+
+if ( !(dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE))
+ || !(serial_record = dbfn_read_enforce_length(dbm_file, key, sizeof(dbdata_serialize)))
+ )
+ 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);
+}
+
+/* End of enq.c */