Postfix3.3.1
qmgr_feedback.c
[詳解]
1 /*++
2 /* NAME
3 /* qmgr_feedback 3
4 /* SUMMARY
5 /* delivery agent feedback management
6 /* SYNOPSIS
7 /* #include "qmgr.h"
8 /*
9 /* void qmgr_feedback_init(fbck_ctl, name_prefix, name_tail,
10 /* def_name, def_value)
11 /* QMGR_FEEDBACK *fbck_ctl;
12 /* const char *name_prefix;
13 /* const char *name_tail;
14 /* const char *def_name;
15 /* const char *def_value;
16 /*
17 /* double QMGR_FEEDBACK_VAL(fbck_ctl, concurrency)
18 /* QMGR_FEEDBACK *fbck_ctl;
19 /* const int concurrency;
20 /* DESCRIPTION
21 /* Upon completion of a delivery request, a delivery agent
22 /* provides a hint that the scheduler should dedicate fewer or
23 /* more resources to a specific destination.
24 /*
25 /* qmgr_feedback_init() looks up transport-dependent positive
26 /* or negative concurrency feedback control information from
27 /* main.cf, and converts it to internal form.
28 /*
29 /* QMGR_FEEDBACK_VAL() computes a concurrency adjustment based
30 /* on a preprocessed feedback control information and the
31 /* current concurrency window. This is an "unsafe" macro that
32 /* evaluates some arguments multiple times.
33 /*
34 /* Arguments:
35 /* .IP fbck_ctl
36 /* Pointer to QMGR_FEEDBACK structure where the result will
37 /* be stored.
38 /* .IP name_prefix
39 /* Mail delivery transport name, used as the initial portion
40 /* of a transport-dependent concurrency feedback parameter
41 /* name.
42 /* .IP name_tail
43 /* The second, and fixed, portion of a transport-dependent
44 /* concurrency feedback parameter.
45 /* .IP def_name
46 /* The name of a default feedback parameter.
47 /* .IP def_val
48 /* The value of the default feedback parameter.
49 /* .IP concurrency
50 /* Delivery concurrency for concurrency-dependent feedback calculation.
51 /* DIAGNOSTICS
52 /* Warning: configuration error or unreasonable input. The program
53 /* uses name_tail feedback instead.
54 /* Panic: consistency check failure.
55 /* LICENSE
56 /* .ad
57 /* .fi
58 /* The Secure Mailer license must be distributed with this software.
59 /* AUTHOR(S)
60 /* Wietse Venema
61 /* IBM T.J. Watson Research
62 /* P.O. Box 704
63 /* Yorktown Heights, NY 10598, USA
64 /*--*/
65 
66 /* System library. */
67 
68 #include <sys_defs.h>
69 #include <stdlib.h>
70 #include <limits.h> /* INT_MAX */
71 #include <stdio.h> /* sscanf() */
72 #include <string.h>
73 
74 /* Utility library. */
75 
76 #include <msg.h>
77 #include <name_code.h>
78 #include <stringops.h>
79 #include <mymalloc.h>
80 
81 /* Global library. */
82 
83 #include <mail_params.h>
84 #include <mail_conf.h>
85 
86 /* Application-specific. */
87 
88 #include "qmgr.h"
89 
90  /*
91  * Lookup tables for main.cf feedback method names.
92  */
95 #ifdef QMGR_FEEDBACK_IDX_SQRT_WIN
96  CONC_FDBACK_NAME_SQRT_WIN, QMGR_FEEDBACK_IDX_SQRT_WIN,
97 #endif
99 };
100 
101 /* qmgr_feedback_init - initialize feedback control */
102 
104  const char *name_prefix,
105  const char *name_tail,
106  const char *def_name,
107  const char *def_val)
108 {
109  double enum_val;
110  char denom_str[30 + 1];
111  double denom_val;
112  char slash;
113  char junk;
114  char *fbck_name;
115  char *fbck_val;
116 
117  /*
118  * Look up the transport-dependent feedback value.
119  */
120  fbck_name = concatenate(name_prefix, name_tail, (char *) 0);
121  fbck_val = get_mail_conf_str(fbck_name, def_val, 1, 0);
122 
123  /*
124  * We allow users to express feedback as 1/8, as a more user-friendly
125  * alternative to 0.125 (or worse, having users specify the number of
126  * events in a feedback hysteresis cycle).
127  *
128  * We use some sscanf() fu to parse the value into numerator and optional
129  * "/" followed by denominator. We're doing this only a few times during
130  * the process life time, so we strive for convenience instead of speed.
131  */
132 #define INCLUSIVE_BOUNDS(val, low, high) ((val) >= (low) && (val) <= (high))
133 
134  fb->hysteresis = 1; /* legacy */
135  fb->base = -1; /* assume error */
136 
137  switch (sscanf(fbck_val, "%lf %1[/] %30s%c",
138  &enum_val, &slash, denom_str, &junk)) {
139  case 1:
141  fb->base = enum_val;
142  break;
143  case 3:
144  if ((fb->index = name_code(qmgr_feedback_map, NAME_CODE_FLAG_NONE,
145  denom_str)) != QMGR_FEEDBACK_IDX_NONE) {
146  fb->base = enum_val;
147  } else if (INCLUSIVE_BOUNDS(enum_val, 0, INT_MAX)
148  && sscanf(denom_str, "%lf%c", &denom_val, &junk) == 1
149  && INCLUSIVE_BOUNDS(denom_val, 1.0 / INT_MAX, INT_MAX)) {
150  fb->base = enum_val / denom_val;
151  }
152  break;
153  }
154 
155  /*
156  * Sanity check. If input is bad, we just warn and use a reasonable
157  * default.
158  */
159  if (!INCLUSIVE_BOUNDS(fb->base, 0, 1)) {
160  msg_warn("%s: ignoring malformed or unreasonable feedback: %s",
161  strcmp(fbck_val, def_val) ? fbck_name : def_name, fbck_val);
163  fb->base = 1;
164  }
165 
166  /*
167  * Performance debugging/analysis.
168  */
170  msg_info("%s: %s feedback type %d value at %d: %g",
171  name_prefix, strcmp(fbck_val, def_val) ?
172  fbck_name : def_name, fb->index, var_init_dest_concurrency,
174 
175  myfree(fbck_name);
176  myfree(fbck_val);
177 }
void myfree(void *ptr)
Definition: mymalloc.c:207
const NAME_CODE qmgr_feedback_map[]
Definition: qmgr_feedback.c:93
#define QMGR_FEEDBACK_IDX_WIN
Definition: qmgr.h:120
int var_init_dest_concurrency
Definition: qmgr.c:417
void qmgr_feedback_init(QMGR_FEEDBACK *fb, const char *name_prefix, const char *name_tail, const char *def_name, const char *def_val)
#define QMGR_FEEDBACK_VAL(fb, win)
Definition: qmgr.h:132
bool var_conc_feedback_debug
Definition: qmgr.c:430
#define CONC_FDBACK_NAME_WIN
Definition: mail_params.h:3507
void msg_warn(const char *fmt,...)
Definition: msg.c:215
#define NAME_CODE_FLAG_NONE
Definition: name_code.h:22
int name_code(const NAME_CODE *table, int flags, const char *name)
Definition: name_code.c:65
char * concatenate(const char *arg0,...)
Definition: concatenate.c:42
double base
Definition: qmgr.h:115
int hysteresis
Definition: qmgr.h:114
int index
Definition: qmgr.h:116
#define CONC_FDBACK_NAME_SQRT_WIN
Definition: mail_params.h:3508
#define QMGR_FEEDBACK_IDX_NONE
Definition: qmgr.h:119
char * get_mail_conf_str(const char *, const char *, int, int)
#define INCLUSIVE_BOUNDS(val, low, high)
void msg_info(const char *fmt,...)
Definition: msg.c:199