summaryrefslogtreecommitdiffstats
path: root/src/oqmgr/qmgr_scan.c
blob: 0665a23ce8bfa5b1e8b29301b59f6bd39a4b948d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*++
/* NAME
/*	qmgr_scan 3
/* SUMMARY
/*	queue scanning
/* SYNOPSIS
/*	#include "qmgr.h"
/*
/*	QMGR_SCAN *qmgr_scan_create(queue_name)
/*	const char *queue_name;
/*
/*	char	*qmgr_scan_next(scan_info)
/*	QMGR_SCAN *scan_info;
/*
/*	void	qmgr_scan_request(scan_info, flags)
/*	QMGR_SCAN *scan_info;
/*	int	flags;
/* DESCRIPTION
/*	This module implements queue scans. A queue scan always runs
/*	to completion, so that all files get a fair chance. The caller
/*	can request that a queue scan be restarted once it completes.
/*
/*	qmgr_scan_create() creates a context for scanning the named queue,
/*	but does not start a queue scan.
/*
/*	qmgr_scan_next() returns the base name of the next queue file.
/*	A null pointer means that no file was found. qmgr_scan_next()
/*	automagically restarts a queue scan when a scan request had
/*	arrived while the scan was in progress.
/*
/*	qmgr_scan_request() records a request for the next queue scan. The
/*	flags argument is the bit-wise OR of zero or more of the following,
/*	unrecognized flags being ignored:
/* .IP QMGR_FLUSH_ONCE
/*	Forget state information about dead hosts or transports.
/*	This request takes effect immediately.
/* .IP QMGR_FLUSH_DFXP
/*	Override the defer_transports setting. This takes effect
/*	immediately when a queue scan is in progress, and affects
/*	the next queue scan.
/* .IP QMGR_SCAN_ALL
/*	Ignore queue file time stamps. This takes effect immediately
/*	when a queue scan is in progress, and affects the next queue
/*	scan.
/* .IP QMGR_SCAN_START
/*	Start a queue scan when none is in progress, or restart the
/*	current scan upon completion.
/* DIAGNOSTICS
/*	Fatal: out of memory.
/*	Panic: interface violations, internal consistency errors.
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System library. */

#include <sys_defs.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <scan_dir.h>

/* Global library. */

#include <mail_scan_dir.h>

/* Application-specific. */

#include "qmgr.h"

/* qmgr_scan_start - start queue scan */

static void qmgr_scan_start(QMGR_SCAN *scan_info)
{
    const char *myname = "qmgr_scan_start";

    /*
     * Sanity check.
     */
    if (scan_info->handle)
	msg_panic("%s: %s queue scan in progress",
		  myname, scan_info->queue);

    /*
     * Give the poor tester a clue.
     */
    if (msg_verbose)
	msg_info("%s: %sstart %s queue scan",
		 myname,
		 scan_info->nflags & QMGR_SCAN_START ? "re" : "",
		 scan_info->queue);

    /*
     * Start or restart the scan.
     */
    scan_info->flags = scan_info->nflags;
    scan_info->nflags = 0;
    scan_info->handle = scan_dir_open(scan_info->queue);
}

/* qmgr_scan_request - request for future scan */

void    qmgr_scan_request(QMGR_SCAN *scan_info, int flags)
{

    /*
     * Apply "forget all dead destinations" requests immediately. Throttle
     * dead transports and queues at the earliest opportunity: preferably
     * during an already ongoing queue scan, otherwise the throttling will
     * have to wait until a "start scan" trigger arrives.
     * 
     * The QMGR_FLUSH_ONCE request always comes with QMGR_FLUSH_DFXP, and
     * sometimes it also comes with QMGR_SCAN_ALL. It becomes a completely
     * different story when a flush request is encoded in file permissions.
     */
    if (flags & QMGR_FLUSH_ONCE)
	qmgr_enable_all();

    /*
     * Apply "ignore time stamp" requests also towards the scan that is
     * already in progress.
     */
    if (scan_info->handle != 0 && (flags & QMGR_SCAN_ALL))
	scan_info->flags |= QMGR_SCAN_ALL;

    /*
     * Apply "override defer_transports" requests also towards the scan that
     * is already in progress.
     */
    if (scan_info->handle != 0 && (flags & QMGR_FLUSH_DFXP))
	scan_info->flags |= QMGR_FLUSH_DFXP;

    /*
     * If a scan is in progress, just record the request.
     */
    scan_info->nflags |= flags;
    if (scan_info->handle == 0 && (flags & QMGR_SCAN_START) != 0) {
	scan_info->nflags &= ~QMGR_SCAN_START;
	qmgr_scan_start(scan_info);
    }
}

/* qmgr_scan_next - look for next queue file */

char   *qmgr_scan_next(QMGR_SCAN *scan_info)
{
    char   *path = 0;

    /*
     * Restart the scan if we reach the end and a queue scan request has
     * arrived in the mean time.
     */
    if (scan_info->handle && (path = mail_scan_dir_next(scan_info->handle)) == 0) {
	scan_info->handle = scan_dir_close(scan_info->handle);
	if (msg_verbose && (scan_info->nflags & QMGR_SCAN_START) == 0)
	    msg_info("done %s queue scan", scan_info->queue);
    }
    if (!scan_info->handle && (scan_info->nflags & QMGR_SCAN_START)) {
	qmgr_scan_start(scan_info);
	path = mail_scan_dir_next(scan_info->handle);
    }
    return (path);
}

/* qmgr_scan_create - create queue scan context */

QMGR_SCAN *qmgr_scan_create(const char *queue)
{
    QMGR_SCAN *scan_info;

    scan_info = (QMGR_SCAN *) mymalloc(sizeof(*scan_info));
    scan_info->queue = mystrdup(queue);
    scan_info->flags = scan_info->nflags = 0;
    scan_info->handle = 0;
    return (scan_info);
}