~ubuntu-branches/ubuntu/vivid/postfix/vivid-proposed

« back to all changes in this revision

Viewing changes to src/global/dict_proxy.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2012-03-20 13:47:16 UTC
  • mfrom: (1.1.33)
  • mto: This revision was merged to the branch mainline in revision 44.
  • Revision ID: package-import@ubuntu.com-20120320134716-v7ab94fmor2z9pvp
Tags: upstream-2.9.1
ImportĀ upstreamĀ versionĀ 2.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
/*      int     open_flags;
12
12
/*      int     dict_flags;
13
13
/* DESCRIPTION
14
 
/*      dict_proxy_open() relays read-only operations through
15
 
/*      the Postfix proxymap server.
 
14
/*      dict_proxy_open() relays read-only or read-write operations
 
15
/*      through the Postfix proxymap server.
16
16
/*
17
17
/*      The \fIopen_flags\fR argument must specify O_RDONLY
18
 
/*      or O_RDWR|O_CREAT. Depending on this, the client
 
18
/*      or O_RDWR. Depending on this, the client
19
19
/*      connects to the proxymap multiserver or to the
20
20
/*      proxywrite single updater.
21
21
/*
72
72
    DICT    dict;                       /* generic members */
73
73
    CLNT_STREAM *clnt;                  /* client handle (shared) */
74
74
    const char *service;                /* service name */
75
 
    int     in_flags;                   /* caller-specified flags */
 
75
    int     inst_flags;                 /* saved dict flags */
 
76
    VSTRING *reskey;                    /* result key storage */
76
77
    VSTRING *result;                    /* storage */
77
78
} DICT_PROXY;
78
79
 
88
89
static CLNT_STREAM *proxymap_stream;    /* read-only maps */
89
90
static CLNT_STREAM *proxywrite_stream;  /* read-write maps */
90
91
 
 
92
/* dict_proxy_sequence - find first/next entry */
 
93
 
 
94
static int dict_proxy_sequence(DICT *dict, int function,
 
95
                                       const char **key, const char **value)
 
96
{
 
97
    const char *myname = "dict_proxy_sequence";
 
98
    DICT_PROXY *dict_proxy = (DICT_PROXY *) dict;
 
99
    VSTREAM *stream;
 
100
    int     status;
 
101
    int     count = 0;
 
102
    int     request_flags;
 
103
 
 
104
    /*
 
105
     * The client and server live in separate processes that may start and
 
106
     * terminate independently. We cannot rely on a persistent connection,
 
107
     * let alone on persistent state (such as a specific open table) that is
 
108
     * associated with a specific connection. Each lookup needs to specify
 
109
     * the table and the flags that were specified to dict_proxy_open().
 
110
     */
 
111
    VSTRING_RESET(dict_proxy->reskey);
 
112
    VSTRING_TERMINATE(dict_proxy->reskey);
 
113
    VSTRING_RESET(dict_proxy->result);
 
114
    VSTRING_TERMINATE(dict_proxy->result);
 
115
    request_flags = dict_proxy->inst_flags
 
116
        | (dict->flags & DICT_FLAG_RQST_MASK);
 
117
    for (;;) {
 
118
        stream = clnt_stream_access(dict_proxy->clnt);
 
119
        errno = 0;
 
120
        count += 1;
 
121
        if (attr_print(stream, ATTR_FLAG_NONE,
 
122
                       ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE,
 
123
                       ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict->name,
 
124
                       ATTR_TYPE_INT, MAIL_ATTR_FLAGS, request_flags,
 
125
                       ATTR_TYPE_INT, MAIL_ATTR_FUNC, function,
 
126
                       ATTR_TYPE_END) != 0
 
127
            || vstream_fflush(stream)
 
128
            || attr_scan(stream, ATTR_FLAG_STRICT,
 
129
                         ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
 
130
                         ATTR_TYPE_STR, MAIL_ATTR_KEY, dict_proxy->reskey,
 
131
                         ATTR_TYPE_STR, MAIL_ATTR_VALUE, dict_proxy->result,
 
132
                         ATTR_TYPE_END) != 3) {
 
133
            if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
 
134
                msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
 
135
        } else {
 
136
            if (msg_verbose)
 
137
                msg_info("%s: table=%s flags=%s func=%d -> status=%d key=%s val=%s",
 
138
                         myname, dict->name, dict_flags_str(request_flags),
 
139
                         function, status, STR(dict_proxy->reskey),
 
140
                         STR(dict_proxy->result));
 
141
            switch (status) {
 
142
            case PROXY_STAT_BAD:
 
143
                msg_fatal("%s sequence failed for table \"%s\" function %d: "
 
144
                          "invalid request",
 
145
                          dict_proxy->service, dict->name, function);
 
146
            case PROXY_STAT_DENY:
 
147
                msg_fatal("%s service is not configured for table \"%s\"",
 
148
                          dict_proxy->service, dict->name);
 
149
            case PROXY_STAT_OK:
 
150
                *key = STR(dict_proxy->reskey);
 
151
                *value = STR(dict_proxy->result);
 
152
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS);
 
153
            case PROXY_STAT_NOKEY:
 
154
                *key = *value = 0;
 
155
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL);
 
156
            case PROXY_STAT_RETRY:
 
157
                *key = *value = 0;
 
158
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_RETRY, DICT_STAT_ERROR);
 
159
            default:
 
160
                msg_warn("%s sequence failed for table \"%s\" function %d: "
 
161
                         "unexpected reply status %d",
 
162
                         dict_proxy->service, dict->name, function, status);
 
163
            }
 
164
        }
 
165
        clnt_stream_recover(dict_proxy->clnt);
 
166
        sleep(1);                               /* XXX make configurable */
 
167
    }
 
168
}
 
169
 
91
170
/* dict_proxy_lookup - find table entry */
92
171
 
93
172
static const char *dict_proxy_lookup(DICT *dict, const char *key)
108
187
     */
109
188
    VSTRING_RESET(dict_proxy->result);
110
189
    VSTRING_TERMINATE(dict_proxy->result);
111
 
    request_flags = (dict_proxy->in_flags & DICT_FLAG_RQST_MASK)
 
190
    request_flags = dict_proxy->inst_flags
112
191
        | (dict->flags & DICT_FLAG_RQST_MASK);
113
192
    for (;;) {
114
193
        stream = clnt_stream_access(dict_proxy->clnt);
142
221
                msg_fatal("%s service is not configured for table \"%s\"",
143
222
                          dict_proxy->service, dict->name);
144
223
            case PROXY_STAT_OK:
145
 
                return (STR(dict_proxy->result));
 
224
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, STR(dict_proxy->result));
146
225
            case PROXY_STAT_NOKEY:
147
 
                dict_errno = 0;
148
 
                return (0);
 
226
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, (char *) 0);
149
227
            case PROXY_STAT_RETRY:
150
 
                dict_errno = DICT_ERR_RETRY;
151
 
                return (0);
 
228
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_RETRY, (char *) 0);
152
229
            default:
153
230
                msg_warn("%s lookup failed for table \"%s\" key \"%s\": "
154
231
                         "unexpected reply status %d",
162
239
 
163
240
/* dict_proxy_update - update table entry */
164
241
 
165
 
static void dict_proxy_update(DICT *dict, const char *key, const char *value)
 
242
static int dict_proxy_update(DICT *dict, const char *key, const char *value)
166
243
{
167
244
    const char *myname = "dict_proxy_update";
168
245
    DICT_PROXY *dict_proxy = (DICT_PROXY *) dict;
178
255
     * associated with a specific connection. Each lookup needs to specify
179
256
     * the table and the flags that were specified to dict_proxy_open().
180
257
     */
181
 
    request_flags = (dict_proxy->in_flags & DICT_FLAG_RQST_MASK)
 
258
    request_flags = dict_proxy->inst_flags
182
259
        | (dict->flags & DICT_FLAG_RQST_MASK);
183
260
    for (;;) {
184
261
        stream = clnt_stream_access(dict_proxy->clnt);
211
288
                msg_fatal("%s update access is not configured for table \"%s\"",
212
289
                          dict_proxy->service, dict->name);
213
290
            case PROXY_STAT_OK:
214
 
                return;
 
291
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS);
 
292
            case PROXY_STAT_NOKEY:
 
293
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL);
 
294
            case PROXY_STAT_RETRY:
 
295
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_RETRY, DICT_STAT_ERROR);
215
296
            default:
216
297
                msg_warn("%s update failed for table \"%s\" key \"%s\": "
217
298
                         "unexpected reply status %d",
241
322
     * associated with a specific connection. Each lookup needs to specify
242
323
     * the table and the flags that were specified to dict_proxy_open().
243
324
     */
244
 
    request_flags = (dict_proxy->in_flags & DICT_FLAG_RQST_MASK)
 
325
    request_flags = dict_proxy->inst_flags
245
326
        | (dict->flags & DICT_FLAG_RQST_MASK);
246
327
    for (;;) {
247
328
        stream = clnt_stream_access(dict_proxy->clnt);
274
355
                msg_fatal("%s update access is not configured for table \"%s\"",
275
356
                          dict_proxy->service, dict->name);
276
357
            case PROXY_STAT_OK:
277
 
                return 0;
 
358
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS);
278
359
            case PROXY_STAT_NOKEY:
279
 
                return 1;
 
360
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL);
 
361
            case PROXY_STAT_RETRY:
 
362
                DICT_ERR_VAL_RETURN(dict, DICT_ERR_RETRY, DICT_STAT_ERROR);
280
363
            default:
281
364
                msg_warn("%s delete failed for table \"%s\" key \"%s\": "
282
365
                         "unexpected reply status %d",
294
377
{
295
378
    DICT_PROXY *dict_proxy = (DICT_PROXY *) dict;
296
379
 
 
380
    vstring_free(dict_proxy->reskey);
297
381
    vstring_free(dict_proxy->result);
298
382
    dict_free(dict);
299
383
}
334
418
    if (open_flags == O_RDONLY) {
335
419
        pstream = &proxymap_stream;
336
420
        service = var_proxymap_service;
337
 
    } else if (open_flags == (O_RDWR | O_CREAT)) {
 
421
    } else if ((open_flags & O_RDWR) == O_RDWR) {
338
422
        pstream = &proxywrite_stream;
339
423
        service = var_proxywrite_service;
340
424
    } else
341
 
        msg_fatal("%s: %s map open requires O_RDONLY or O_RDWR|O_CREAT mode",
 
425
        msg_fatal("%s: %s map open requires O_RDONLY or O_RDWR mode",
342
426
                  map, DICT_TYPE_PROXY);
343
427
 
344
428
    if (*pstream == 0) {
364
448
    dict_proxy->dict.lookup = dict_proxy_lookup;
365
449
    dict_proxy->dict.update = dict_proxy_update;
366
450
    dict_proxy->dict.delete = dict_proxy_delete;
 
451
    dict_proxy->dict.sequence = dict_proxy_sequence;
367
452
    dict_proxy->dict.close = dict_proxy_close;
368
 
    dict_proxy->in_flags = dict_flags;
 
453
    dict_proxy->inst_flags = (dict_flags & DICT_FLAG_INST_MASK);
 
454
    dict_proxy->reskey = vstring_alloc(10);
369
455
    dict_proxy->result = vstring_alloc(10);
370
456
    dict_proxy->clnt = *pstream;
371
457
    dict_proxy->service = service;
381
467
        if (attr_print(stream, ATTR_FLAG_NONE,
382
468
                       ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_OPEN,
383
469
                       ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict_proxy->dict.name,
384
 
                       ATTR_TYPE_INT, MAIL_ATTR_FLAGS, dict_proxy->in_flags,
 
470
                     ATTR_TYPE_INT, MAIL_ATTR_FLAGS, dict_proxy->inst_flags,
385
471
                       ATTR_TYPE_END) != 0
386
472
            || vstream_fflush(stream)
387
473
            || attr_scan(stream, ATTR_FLAG_STRICT,
403
489
                msg_fatal("%s service is not configured for table \"%s\"",
404
490
                          dict_proxy->service, dict_proxy->dict.name);
405
491
            case PROXY_STAT_OK:
406
 
                dict_proxy->dict.flags = dict_proxy->in_flags
 
492
                dict_proxy->dict.flags = (dict_flags & ~DICT_FLAG_IMPL_MASK)
407
493
                    | (server_flags & DICT_FLAG_IMPL_MASK);
408
494
                return (DICT_DEBUG (&dict_proxy->dict));
409
495
            default: