From 333efba249dd9c42c63c78174203193fba5619d9 Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <gray@Pirx.gnu.org.ua>
Date: Fri, 12 Jun 2009 17:24:07 +0300
Subject: [PATCH] Configurable max. number of threads in pmilter.

* include/sm/pmfapi.h (include/sm/pmfapi.h): New members pmfi_thrmax_s,
pmfi_thrmax_h, pmfi_fdmax. Tailor pmfi_unused.
* libpmilter/pmilter_init.c (sm_pmilt_init1): Set arguments to
evthr_init from the new struct pmilter_S members.
* doc/README.tex: Document changes.
---
 doc/README.tex            |   39 ++++++++++++++++++++++++++++++++++++++-
 libpmilter/pmilter_init.c |   14 ++++++++------
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/doc/README.tex b/doc/README.tex
index 174e2a6..c22c20f 100644
--- a/doc/README.tex
+++ b/doc/README.tex
@@ -1610,6 +1610,19 @@ the pathname of the Unix domain socket
 port for inet socket
 (type {\tt socket} only).
 \item
+\verb|min_connections|\index{min_connections}:
+minumum number of simultaneously open connections
+(type {\tt socket} only). Default is 1. See below for
+a description.
+\item
+\verb|max_connections|\index{min_connections}:
+maximum number of simultaneously open connections
+(type {\tt socket} only).
+\item
+\verb|timeout|\index{timeout}:
+time to wait for the answer from the socket map.
+Default is 5 seconds (type {\tt socket} only).
+\item
 \verb|maps|\index{maps}:
 list of map names to use in the map
 (type {\tt sequence} only).
@@ -1619,7 +1632,7 @@ Note:
 for {\tt socket} maps either
 a Unix domain socket (\verb|path|)
 or an inet socket (\verb|address| and \verb|port|)
-must be specified.
+must be specified. 
 
 Example:
 
@@ -1631,6 +1644,30 @@ map seq1 { type = sequence; maps = { localusers, otherusers }; }
 map seq2 { type = sequence; maps = { password, otherusers }; }
 \end{verbatim}
 
+By default, SMAR opens a single connection to each socket map
+configured, which means that accesses to this map are serialized. As a
+result, each incoming connection waits in a queue while all
+previous connections are served. This may create intolerable
+delays on loaded servers. To avoid this, use {\tt min\_connections}
+and {\tt max\_connections} to create a spool of map connections, e.g.:
+
+\begin{verbatim}
+map userdb {
+    type = socket;
+    path = "/var/spool/meta1/smap/userdb";
+    mapname = userdb;
+    min_connections = 10;
+    max_connections = 512;
+}
+\end{verbatim}
+
+This way, when a need to consult the map arrives, SMAR looks
+for the first free connection among the opened ones and uses it. If
+there are no more free connections and the number of opened
+connections is less than {\tt max\_connections}, SMAR will create a
+new connection to serve the request. Otherwise, if the maximum number
+of connections is reached, SMAR will wait until any of them becomes
+available again.
 
 \subsection{Configuration Options for SMAR}
 \label{ConfigurationOptionsforSMAR}
diff --git a/libpmilter/pmilter_init.c b/libpmilter/pmilter_init.c
index 20b9dfe..5f4b58c 100644
--- a/libpmilter/pmilter_init.c
+++ b/libpmilter/pmilter_init.c
@@ -111,7 +111,7 @@ sm_pmilt_init1(pmg_ctx_P pmg_ctx)
 	ret = thr_init();
 	if (sm_is_err(ret)) {
 		sm_io_fprintf(smioerr,
-			"sev=ERROR, func=sm_pmilt_init, thr_init=%x\n", ret);
+			"sev=ERROR, func=sm_pmilt_init, thr_init=%m\n", ret);
 		goto error;
 	}
 
@@ -119,17 +119,19 @@ sm_pmilt_init1(pmg_ctx_P pmg_ctx)
 	if (i != 0) {
 		ret = sm_error_perm(SM_EM_Q, i);
 		sm_io_fprintf(smioerr,
-			"sev=ERROR, func=sm_pmilt_init, mutex_init=%m\n", i);
+			"sev=ERROR, func=sm_pmilt_init, mutex_init=%m\n", ret);
 		goto error;
 	}
 
 	/* initialize event threads system */
 #define SM_PMFI_DEF_VAL(val, dfl) (((val) > 0) ? (val) : dfl)
 	ret = evthr_init(&pmg_ctx->pmg_ev_ctx,
-		     SM_PMFI_DEF_VAL(pmg_ctx->pmg_pmilter->pmfi_thrmax_s, 2),
-		     SM_PMFI_DEF_VAL(pmg_ctx->pmg_pmilter->pmfi_thrmax_h, 6),
-		     SM_PMFI_DEF_VAL(pmg_ctx->pmg_pmilter->pmfi_fdmax, 10));
-	if (sm_is_err(ret)) {
+		       SM_PMFI_DEF_VAL(pmg_ctx->pmg_pmilter->pmfi_thrmax_s, 2),
+		       SM_PMFI_DEF_VAL(pmg_ctx->pmg_pmilter->pmfi_thrmax_h, 6),
+		       SM_PMFI_DEF_VAL(pmg_ctx->pmg_pmilter->pmfi_fdmax, 10));
+
+	if (sm_is_err(ret))
+	{
 		sm_io_fprintf(smioerr,
 			"sev=ERROR, func=sm_pmilt_init, evthr_init=%m\n", ret);
 		goto error;
-- 
1.6.0.3

