Wietse Venema: > Dunk: > > Thanks, I have tested in on a low volume email server. > > Wietse Venema: > > The code is pretty clean, so I expect no surprises. I noticed that > > I have cleaned up the docs and code a little, and discovered that > the query interface does not support the query formatting and domain > matching features of the ldap, *sql* and memcache clients. > > This could (should) be similar to the memcache client implementation, > including the key_format feature. > > I can do that but it will take some time, and it is unlikley to be > part of the upcoming Postfix 3.6 release.
Attached is an updated patch, with some TODOs. I can implement those, that but it will take some time. Wietse
diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/conf/dynamicmaps.cf ./conf/dynamicmaps.cf --- /var/tmp/postfix-3.6-20210224/conf/dynamicmaps.cf 2014-05-30 07:38:33.000000000 -0400 +++ ./conf/dynamicmaps.cf 2021-03-11 18:07:16.529195712 -0500 @@ -5,5 +5,6 @@ mysql ${LIB_PREFIX}mysql${LIB_SUFFIX} dict_mysql_open pcre ${LIB_PREFIX}pcre${LIB_SUFFIX} dict_pcre_open pgsql ${LIB_PREFIX}pgsql${LIB_SUFFIX} dict_pgsql_open +redis ${LIB_PREFIX}redis${LIB_SUFFIX} dict_redis_open sdbm ${LIB_PREFIX}sdbm${LIB_SUFFIX} dict_sdbm_open mkmap_sdbm_open sqlite ${LIB_PREFIX}sqlite${LIB_SUFFIX} dict_sqlite_open diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/conf/postfix-files ./conf/postfix-files --- /var/tmp/postfix-3.6-20210224/conf/postfix-files 2019-01-29 17:24:42.000000000 -0500 +++ ./conf/postfix-files 2021-03-11 18:07:16.530195726 -0500 @@ -78,6 +78,7 @@ $shlib_directory/${LIB_PREFIX}mysql${LIB_SUFFIX}:f:root:-:755 $shlib_directory/${LIB_PREFIX}pcre${LIB_SUFFIX}:f:root:-:755 $shlib_directory/${LIB_PREFIX}pgsql${LIB_SUFFIX}:f:root:-:755 +$shlib_directory/${LIB_PREFIX}redis${LIB_SUFFIX}:f:root:-:755 $shlib_directory/${LIB_PREFIX}sdbm${LIB_SUFFIX}:f:root:-:755 $shlib_directory/${LIB_PREFIX}sqlite${LIB_SUFFIX}:f:root:-:755 $meta_directory/dynamicmaps.cf.d:d:root:-:755 @@ -200,6 +201,7 @@ $manpage_directory/man5/nisplus_table.5:f:root:-:644 $manpage_directory/man5/pcre_table.5:f:root:-:644 $manpage_directory/man5/pgsql_table.5:f:root:-:644 +$manpage_directory/man5/redis_table.5:f:root:-:644 $manpage_directory/man5/postconf.5:f:root:-:644 $manpage_directory/man5/postfix-wrapper.5:f:root:-:644 $manpage_directory/man5/regexp_table.5:f:root:-:644 @@ -307,6 +309,7 @@ $readme_directory/PACKAGE_README:f:root:-:644 $readme_directory/PCRE_README:f:root:-:644 $readme_directory/PGSQL_README:f:root:-:644 +$readme_directory/REDIS_README:f:root:-:644 $readme_directory/POSTSCREEN_README:f:root:-:644 $readme_directory/QMQP_README:f:root:-:644:o $readme_directory/QSHAPE_README:f:root:-:644 @@ -363,6 +366,7 @@ $html_directory/PACKAGE_README.html:f:root:-:644 $html_directory/PCRE_README.html:f:root:-:644 $html_directory/PGSQL_README.html:f:root:-:644 +$html_directory/REDIS_README.html:f:root:-:644 $html_directory/POSTSCREEN_README.html:f:root:-:644 $html_directory/QMQP_README.html:f:root:-:644:o $html_directory/QSHAPE_README.html:f:root:-:644 @@ -414,6 +418,7 @@ $html_directory/oqmgr.8.html:f:root:-:644 $html_directory/pcre_table.5.html:f:root:-:644 $html_directory/pgsql_table.5.html:f:root:-:644 +$html_directory/redis_table.5.html:f:root:-:644 $html_directory/pickup.8.html:f:root:-:644 $html_directory/pipe.8.html:f:root:-:644 $html_directory/postalias.1.html:f:root:-:644 diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/makedefs ./makedefs --- /var/tmp/postfix-3.6-20210224/makedefs 2020-09-30 17:22:49.000000000 -0400 +++ ./makedefs 2021-03-11 18:07:16.531195739 -0500 @@ -1165,7 +1165,7 @@ # Propagate AUXLIBS_FOO or merge them into global AUXLIBS (i.e. SYSLIBS). -PLUGGABLE_MAPS="CDB LDAP LMDB MYSQL PCRE PGSQL SDBM SQLITE" +PLUGGABLE_MAPS="CDB LDAP LMDB MYSQL PCRE PGSQL REDIS SDBM SQLITE" case "$dynamicmaps" in yes) for name in $PLUGGABLE_MAPS diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/proto/DATABASE_README.html ./proto/DATABASE_README.html --- /var/tmp/postfix-3.6-20210224/proto/DATABASE_README.html 2020-08-29 13:51:42.000000000 -0400 +++ ./proto/DATABASE_README.html 2021-03-13 17:14:36.642652892 -0500 @@ -421,6 +421,11 @@ as used in "sdbm:table" is the database file name without the ".dir" or ".pag" suffix. </dd> +<dt> <b>redis</b> (read-only) </dt> + +<dd> Redis database. Configuration details are given in redis_table(5). +</dd> + <dt> <b>socketmap</b> (read-only) </dt> <dd> Sendmail-style socketmap client. The name of the table is diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/proto/redis_table ./proto/redis_table --- /var/tmp/postfix-3.6-20210224/proto/redis_table 1969-12-31 19:00:00.000000000 -0500 +++ ./proto/redis_table 2021-03-13 17:01:09.830335391 -0500 @@ -0,0 +1,81 @@ +#++ +# NAME +# redis_table 5 +# SUMMARY +# Postfix Redis client configuration +# SYNOPSIS +# \fBpostmap -q "\fIprefix:string\fB" redis:/etc/postfix/\fIfilename\fR +# +# \fBpostmap -q - redis:/etc/postfix/\fIfilename\fB <\fIinputfile\fR +# DESCRIPTION +# The Postfix mail system uses optional tables for address +# rewriting or mail routing. These tables are usually in +# \fBdbm\fR or \fBdb\fR format. +# +# Alternatively, lookup tables can be specified as Redis +# databases. In order to use Redis lookups, define a Redis +# source as a lookup table in main.cf, for example: +# .nf +# virtual_alias_maps = redis:/etc/postfix/redis-valias-maps.cf +# .fi +# +# The file /etc/postfix/redis-valias-maps.cf has the same +# format as the Postfix main.cf file, and can specify the +# parameters described below. +# .IP "\fBhost\fR" +# The IP address of the host that Postfix will try to connect +# to and query from. +# .sp +# Example: +# .nf +# host = 127.0.0.1 +# .fi +# .IP "\fBport\fR" +# The TCP port that Postfix will connect to and query from. +# If not specified the default of \fB6379\fR will be used. +# .sp +# Example: +# .nf +# port = 6379 +# .fi +# .IP "\fBprefix\fR" +# This is the prefix that is added to the query from Postfix +# before it is passed to Redis for a lookup, allowing postfix +# to use simple key:value lookups from Redis. +# .sp +# Examples: +# .nf +# prefix = VALI +# prefix = LOCAL +# prefix = REV +# prefix = HELO +# .fi +# SEE ALSO +# .na +# .nf +# postmap(1), Postfix lookup table manager +# postconf(5), configuration parameters +# ldap_table(5), LDAP lookup tables +# mysql_table(5), MySQL lookup tables +# sqlite_table(5), SQLite lookup tables +# README FILES +# .ad +# .fi +# Use "\fBpostconf readme_directory\fR" or +# "\fBpostconf html_directory\fR" to locate this information. +# .na +# .nf +# DATABASE_README, Postfix lookup table overview +# REDIS_README, Postfix Redis client support +# LICENSE +# The Secure Mailer license must be distributed with this software. +# HISTORY +# Redis support was introduced with Postfix version 3.7. +# AUTHOR(S) +# Titus Jose +# titus.n...@gmail.com +# +# Updated by: +# Duncan Bellamy +# d...@denkimushi.com +#-- diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/src/global/dict_redis.c ./src/global/dict_redis.c --- /var/tmp/postfix-3.6-20210224/src/global/dict_redis.c 1969-12-31 19:00:00.000000000 -0500 +++ ./src/global/dict_redis.c 2021-03-13 17:29:03.371773960 -0500 @@ -0,0 +1,250 @@ +/*++ +/* NAME +/* dict_redis 3 +/* SUMMARY +/* dictionary manager interface to Redis databases +/* SYNOPSIS +/* #include <dict_redis.h> +/* +/* DICT *dict_redis_open(name, open_flags, dict_flags) +/* const char *name; +/* int open_flags; +/* int dict_flags; +/* DESCRIPTION +/* dict_redis_open() creates a dictionary of type 'redis'. This +/* dictionary is an interface for the postfix key->value mappings +/* to redis. The result is a pointer to the installed dictionary, +/* or a null pointer in case of problems. +/* .PP +/* Arguments: +/* .IP name +/* Either the path to the Redis configuration file (if it +/* starts with '/' or '.'), or the prefix which will be used to +/* obtain main.cf configuration parameters for this search. +/* +/* In the first case, the configuration parameters below are +/* specified in the file as \fIname\fR=\fIvalue\fR pairs. +/* +/* In the second case, the configuration parameters are +/* prefixed with the value of \fIname\fR and an underscore, +/* and they are specified in main.cf. For example, if this +/* value is \fIredisDB\fR, the parameters would look like +/* \fIredisDB_host\fR, \fIpredisDB_prefix\fR, and so on. +/* .IP other_name +/* reference for outside use. +/* .IP open_flags +/* unused. +/* .IP dict_flags +/* See dict_open(3). +/* +/* .PP +/* Configuration parameters: +/* .IP host +/* IP address of the redis server hosting the database. +/* .IP port +/* Port number to connect to the above. +/* .IP prefix +/* Prefix to add to the key when looking it up. +/* .PP +/* For example, if you want the map to reference databases on +/* redis host "127.0.0.1" and prefix the query with VDOM: +/* Then the configuration file +/* should read: +/* .PP +/* host = 127.0.0.1 +/* .br +/* port = 6379 +/* .br +/* prefix = VDOM: +/* .PP +/* SEE ALSO +/* dict(3) generic dictionary manager +/* HISTORY +/* .ad +/* .fi +/* This feature was introduced with Postfix 3.7. +/* AUTHOR(S) +/* Titus Jose +/* titus.n...@gmail.com +/* +/* Updated by: +/* Duncan Bellamy +/* d...@denkimushi.com +/*--*/ + +#include <sys_defs.h> + +#ifdef HAS_REDIS +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +/* Utility library. */ + +#include <msg.h> +#include <dict.h> +#include <mymalloc.h> +#include <vstring.h> +#include <stringops.h> + +/* Global library. */ + +#include <cfg_parser.h> + +/* Application-specific. */ + +#include <dict_redis.h> +#include <hiredis.h> + +typedef struct { + DICT dict; + CFG_PARSER *parser; + redisContext *c; + char *host; + int port; + char *prefix; + VSTRING *result; +} DICT_REDIS; + +/* internal function declarations */ +static const char *dict_redis_lookup(DICT *, const char *); +DICT *dict_redis_open(const char *, int, int); +static void dict_redis_close(DICT *); +static void redis_parse_config(DICT_REDIS *, const char *); + + +static const char *dict_redis_lookup(DICT *dict, const char *name) +{ + const char *myname = "dict_redis_lookup"; + DICT_REDIS *dict_redis = (DICT_REDIS *) dict; + redisReply *reply; + const char *r; + int error; + + dict->error = 0; + + if (msg_verbose) + msg_info("%s: Requesting key %s%s", dict_redis->host, dict_redis->prefix, name); + + /* + * Optionally fold the key. + */ + if (dict->flags & DICT_FLAG_FOLD_FIX) { + if (dict->fold_buf == 0) + dict->fold_buf = vstring_alloc(10); + vstring_strcpy(dict->fold_buf, name); + name = lowercase(vstring_str(dict->fold_buf)); + } + + /* + * TODO(wietse) domain match, substring query, and key format support as in + * memcache_table. + */ + reply = redisCommand(dict_redis->c, "GET %s%s", dict_redis->prefix, name); + error = dict->error; + if (reply->str) { + vstring_strcpy(dict_redis->result, reply->str); + r = vstring_str(dict_redis->result); + } else { + error = 1; + } + freeReplyObject(reply); + return ((error == 0 && *r) ? r : 0); +} + +/* redis_parse_config - parse redis configuration file */ + +static void redis_parse_config(DICT_REDIS *dict_redis, const char *rediscf) +{ + const char *myname = "redis_parse_config"; + CFG_PARSER *p = dict_redis->parser; + +#if 0 + + /* + * TODO(wietse) substring query and key format support as in + * memcache_table. + */ + dict_redis->key_format = cfg_get_str(p, "key_format", "%s", 0, 0); +#endif + dict_redis->port = cfg_get_int(p, "port", 6379, 0, 0); + dict_redis->host = cfg_get_str(p, "host", "127.0.0.1", 1, 0); + dict_redis->prefix = cfg_get_str(p, "prefix", "", 0, 0); + dict_redis->result = vstring_alloc(10); +} + +/* dict_redis_open - open redis data base */ + +DICT *dict_redis_open(const char *name, int open_flags, int dict_flags) +{ + DICT_REDIS *dict_redis; + CFG_PARSER *parser; + + /* + * Sanity check. + */ + if (open_flags != O_RDONLY) + return (dict_surrogate(DICT_TYPE_REDIS, name, open_flags, dict_flags, + "%s:%s map requires O_RDONLY access mode", + DICT_TYPE_REDIS, name)); + + /* + * Open the configuration file. + */ + if ((parser = cfg_parser_alloc(name)) == 0) + return (dict_surrogate(DICT_TYPE_REDIS, name, open_flags, dict_flags, + "open %s: %m", name)); + + dict_redis = (DICT_REDIS *) dict_alloc(DICT_TYPE_REDIS, name, + sizeof(DICT_REDIS)); + dict_redis->dict.lookup = dict_redis_lookup; + dict_redis->dict.close = dict_redis_close; + dict_redis->dict.flags = dict_flags; + dict_redis->parser = parser; + redis_parse_config(dict_redis, name); + dict_redis->dict.owner = cfg_get_owner(dict_redis->parser); + dict_redis->c = redisConnect(dict_redis->host, dict_redis->port); + if (dict_redis->c == 0 || dict_redis->c->err) { + msg_warn("%s:%s: Cannot connect to Redis server %s", + DICT_TYPE_REDIS, name, dict_redis->host); + dict_redis->dict.close((DICT *) dict_redis); + return (dict_surrogate(DICT_TYPE_REDIS, name, open_flags, dict_flags, + "open %s: %m", name)); + } +#if 0 + + /* + * TODO(wietse) domain match, substring query, and key format support as in + * memcache_table. + */ + dict_redis->dbc_ctxt = 0; + db_common_parse(&dict_redis->dict, &dict_redis->dbc_ctxt, + dict_redis->key_format, 1); + db_common_parse_domain(dict_redis->parser, dict_redis->dbc_ctxt); + if (db_common_dict_partial(dict_redis->dbc_ctxt)) + /* Breaks recipient delimiters */ + dict_redis->dict.flags |= DICT_FLAG_PATTERN; + else + dict_redis->dict.flags |= DICT_FLAG_FIXED; +#endif + return (DICT_DEBUG (&dict_redis->dict)); +} + +/* dict_redis_close - close redis database */ + +static void dict_redis_close(DICT *dict) +{ + DICT_REDIS *dict_redis = (DICT_REDIS *) dict; + + if (dict_redis->c) + redisFree(dict_redis->c); + cfg_parser_free(dict_redis->parser); + myfree(dict_redis->host); + myfree(dict_redis->prefix); + vstring_free(dict_redis->result); + if (dict->fold_buf) + vstring_free(dict->fold_buf); + dict_free(dict); +} + +#endif diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/src/global/dict_redis.h ./src/global/dict_redis.h --- /var/tmp/postfix-3.6-20210224/src/global/dict_redis.h 1969-12-31 19:00:00.000000000 -0500 +++ ./src/global/dict_redis.h 2021-03-13 16:47:47.025084145 -0500 @@ -0,0 +1,40 @@ +#ifndef _DICT_REDIS_H_INCLUDED_ +#define _DICT_REDIS_H_INCLUDED_ + +/*++ +/* NAME +/* dict_redis 3h +/* SUMMARY +/* dictionary manager interface to redis databases +/* SYNOPSIS +/* #include <dict_redis.h> +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include <dict.h> + + /* + * External interface. + */ +#define DICT_TYPE_REDIS "redis" +#endif /*SNAPSHOT */ + +extern DICT *dict_redis_open(const char *, int, int); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Titus Jose +/* titus.n...@gmail.com +/* +/* Updated by: +/* Duncan Bellamy +/* d...@denkimushi.com +/*--*/ + +#endif diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/src/global/mail_dict.c ./src/global/mail_dict.c --- /var/tmp/postfix-3.6-20210224/src/global/mail_dict.c 2014-06-21 20:42:55.000000000 -0400 +++ ./src/global/mail_dict.c 2021-03-11 18:07:16.532195753 -0500 @@ -45,6 +45,7 @@ #include <dict_ldap.h> #include <dict_mysql.h> #include <dict_pgsql.h> +#include <dict_redis.h> #include <dict_sqlite.h> #include <dict_memcache.h> #include <mail_dict.h> @@ -68,6 +69,9 @@ #ifdef HAS_PGSQL DICT_TYPE_PGSQL, dict_pgsql_open, #endif +#ifdef HAS_REDIS + DICT_TYPE_REDIS, dict_redis_open, +#endif #ifdef HAS_SQLITE DICT_TYPE_SQLITE, dict_sqlite_open, #endif diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/src/global/Makefile.in ./src/global/Makefile.in --- /var/tmp/postfix-3.6-20210224/src/global/Makefile.in 2021-01-09 16:24:11.000000000 -0500 +++ ./src/global/Makefile.in 2021-03-11 18:07:16.535195793 -0500 @@ -3,7 +3,7 @@ canon_addr.c cfg_parser.c cleanup_strerror.c cleanup_strflags.c \ clnt_stream.c conv_time.c db_common.c debug_peer.c debug_process.c \ defer.c deliver_completed.c deliver_flock.c deliver_pass.c \ - deliver_request.c dict_ldap.c dict_mysql.c dict_pgsql.c \ + deliver_request.c dict_ldap.c dict_mysql.c dict_pgsql.c dict_redis.c \ dict_proxy.c dict_sqlite.c domain_list.c dot_lockfile.c dot_lockfile_as.c \ dsb_scan.c dsn.c dsn_buf.c dsn_mask.c dsn_print.c dsn_util.c \ ehlo_mask.c ext_prop.c file_id.c flush_clnt.c header_opts.c \ @@ -80,13 +80,13 @@ # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. -MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o mkmap_cdb.o \ +MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_redis.o dict_sqlite.o mkmap_cdb.o \ mkmap_lmdb.o mkmap_sdbm.o HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \ conv_time.h db_common.h debug_peer.h debug_process.h defer.h \ deliver_completed.h deliver_flock.h deliver_pass.h deliver_request.h \ - dict_ldap.h dict_mysql.h dict_pgsql.h dict_proxy.h dict_sqlite.h domain_list.h \ + dict_ldap.h dict_mysql.h dict_pgsql.h dict_redis.h dict_proxy.h dict_sqlite.h domain_list.h \ dot_lockfile.h dot_lockfile_as.h dsb_scan.h dsn.h dsn_buf.h \ dsn_mask.h dsn_print.h dsn_util.h ehlo_mask.h ext_prop.h \ file_id.h flush_clnt.h header_opts.h header_token.h input_transp.h \ @@ -135,7 +135,7 @@ LIB_DIR = ../../lib INC_DIR = ../../include PLUGIN_MAP_SO = $(LIB_PREFIX)ldap$(LIB_SUFFIX) $(LIB_PREFIX)mysql$(LIB_SUFFIX) \ - $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) \ + $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)redis$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) \ $(LIB_PREFIX)lmdb$(LIB_SUFFIX) $(LIB_PREFIX)cdb$(LIB_SUFFIX) \ $(LIB_PREFIX)sdbm$(LIB_SUFFIX) MAKES = @@ -171,6 +171,9 @@ $(LIB_PREFIX)pgsql$(LIB_SUFFIX): dict_pgsql.o $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_pgsql.o $(AUXLIBS_PGSQL) +$(LIB_PREFIX)redis$(LIB_SUFFIX): dict_redis.o + $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_redis.o $(AUXLIBS_REDIS) + $(LIB_PREFIX)sqlite$(LIB_SUFFIX): dict_sqlite.o $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_sqlite.o $(AUXLIBS_SQLITE) @@ -535,6 +538,8 @@ echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict mysql:/xx read >>surrogate.tmp 2>&1 echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict pgsql:/xx write >>surrogate.tmp 2>&1 echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict pgsql:/xx read >>surrogate.tmp 2>&1 + echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict redis:/xx write >>surrogate.tmp 2>&1 + echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict redis:/xx read >>surrogate.tmp 2>&1 echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict sqlite:/xx write >>surrogate.tmp 2>&1 echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict sqlite:/xx read >>surrogate.tmp 2>&1 echo get foo| $(SHLIB_ENV) $(VALGRIND) ./mail_dict memcache:/xx read >>surrogate.tmp 2>&1 @@ -1231,6 +1236,17 @@ dict_pgsql.o: dict_pgsql.c dict_pgsql.o: dict_pgsql.h dict_pgsql.o: string_list.h +dict_redis.o: ../../include/dict.h +dict_redis.o: ../../include/msg.h +dict_redis.o: ../../include/mymalloc.h +dict_redis.o: ../../include/vbuf.h +dict_redis.o: ../../include/vstream.h +dict_redis.o: ../../include/vstring.h +dict_redis.o: ../../include/stringops.h +dict_redis.o: ../../include/sys_defs.h +dict_redis.o: cfg_parser.h +dict_redis.o: dict_redis.c +dict_redis.o: dict_redis.h dict_proxy.o: ../../include/argv.h dict_proxy.o: ../../include/attr.h dict_proxy.o: ../../include/check_arg.h @@ -1835,6 +1851,7 @@ mail_dict.o: dict_memcache.h mail_dict.o: dict_mysql.h mail_dict.o: dict_pgsql.h +mail_dict.o: dict_redis.h mail_dict.o: dict_proxy.h mail_dict.o: dict_sqlite.h mail_dict.o: dynamicmaps.h diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' '--exclude=INSTALL' '--exclude=.indent.pro' -r -ur --new-file /var/tmp/postfix-3.6-20210224/src/postconf/postconf.c ./src/postconf/postconf.c --- /var/tmp/postfix-3.6-20210224/src/postconf/postconf.c 2021-01-03 12:08:51.000000000 -0500 +++ ./src/postconf/postconf.c 2021-03-13 16:50:27.846333680 -0500 @@ -339,6 +339,10 @@ /* with support for SDBM databases. /* /* This feature is available with Postfix 2.2 and later. +/* .IP "\fBredis\fR (read-only)" +/* Redis database. This is described in \fBredis_table\fR(5). +/* +/* This feature is available with Postfix 3.7 and later. /* .IP "\fBsocketmap\fR (read-only)" /* Sendmail-style socketmap client. The table name is /* \fBinet\fR:\fIhost\fR:\fIport\fR:\fIname\fR for a TCP/IP