1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2015 */
6 /* Copyright (c) The Exim Maintainers 2021 */
7 /* See the file NOTICE for conditions of use and distribution. */
9 /* Functions concerned with serialization. */
17 /*************************************************
18 * Test for host or ETRN serialization *
19 *************************************************/
21 /* This function is called when a host is listed for serialization of
22 connections. It is also called when ETRN is listed for serialization. We open
23 the misc database and look for a record, which implies an existing connection
24 or ETRN run. If increasing the count would take us past the given limit
25 value return FALSE. If not, bump it and return TRUE. If not found, create
26 one with value 1 and return TRUE.
29 key string on which to serialize
32 Returns: TRUE if OK to proceed; FALSE otherwise
37 enq_start(uschar *key, unsigned lim)
39 dbdata_serialize *serial_record;
40 dbdata_serialize new_record;
44 DEBUG(D_transport) debug_printf("check serialized: %s\n", key);
46 /* Open and lock the waiting information database. The absence of O_CREAT is
47 deliberate; the dbfn_open() function - which is an Exim function - always tries
48 to create if it can't open a read/write file. It expects only O_RDWR or
49 O_RDONLY as its argument. */
51 if (!(dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE)))
54 /* See if there is a record for this host or queue run; if there is, we cannot
55 proceed with the connection unless the record is very old. */
57 serial_record = dbfn_read_enforce_length(dbm_file, key, sizeof(dbdata_serialize));
58 if (serial_record && time(NULL) - serial_record->time_stamp < 6*60*60)
60 if (serial_record->count >= lim)
63 DEBUG(D_transport) debug_printf("outstanding serialization record for %s\n",
67 new_record.count = serial_record->count + 1;
72 /* We can proceed - insert a new record or update the old one. */
74 DEBUG(D_transport) debug_printf("write serialization record for %s val %d\n",
75 key, new_record.count);
76 dbfn_write(dbm_file, key, &new_record, (int)sizeof(dbdata_serialize));
83 /*************************************************
84 * Release serialization *
85 *************************************************/
87 /* This function is called when a serialized host's connection or serialized
88 ETRN queue run ends. We open the relevant database and delete its record.
91 key the serialization key
101 dbdata_serialize *serial_record;
103 DEBUG(D_transport) debug_printf("end serialized: %s\n", key);
105 if ( !(dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE))
106 || !(serial_record = dbfn_read_enforce_length(dbm_file, key, sizeof(dbdata_serialize)))
109 if (--serial_record->count > 0)
111 DEBUG(D_transport) debug_printf("write serialization record for %s val %d\n",
112 key, serial_record->count);
113 dbfn_write(dbm_file, key, serial_record, (int)sizeof(dbdata_serialize));
117 DEBUG(D_transport) debug_printf("remove serialization record for %s\n", key);
118 dbfn_delete(dbm_file, key);
120 dbfn_close(dbm_file);