X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/d7d7b7b91dd75cec636fc144da7e27eed860f971..1d28cc061677bd07d9bed48dd84bd5c590247043:/src/src/enq.c diff --git a/src/src/enq.c b/src/src/enq.c index aa44e1c50..43f53a585 100644 --- a/src/src/enq.c +++ b/src/src/enq.c @@ -1,11 +1,11 @@ -/* $Cambridge: exim/src/src/enq.c,v 1.3 2006/02/07 11:19:00 ph10 Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2006 */ +/* Copyright (c) University of Cambridge 1995 - 2015 */ +/* Copyright (c) The Exim Maintainers 2021 */ /* See the file NOTICE for conditions of use and distribution. */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* Functions concerned with serialization. */ @@ -22,17 +22,20 @@ /* 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 +49,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, 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) +serial_record = dbfn_read_enforce_length(dbm_file, key, sizeof(dbdata_serialize)); +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 +99,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, 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); }