Allow max-sockets in use to a particular target to be configured.
authorAdam Dickmeiss <adam@indexdata.dk>
Wed, 19 Mar 2008 17:03:27 +0000 (18:03 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Wed, 19 Mar 2008 17:03:27 +0000 (18:03 +0100)
The per-target setting 'max-sockets' allows number of sockets to be in
use. If reached and HTTP is in use a HTTP response with status code 500
is returned.

doc/reference.xml
etc/config.xml
include/yazproxy/proxy.h
src/proxyp.h
src/yaz-proxy-config.cpp
src/yaz-proxy.cpp

index 5fa7146..158f97d 100644 (file)
     <para>
      The proxy config file must have a root element called
      <literal>proxy</literal> and scoped within namespace
-     <literal> xmlns="http://indexdata.dk/yazproxy/schema/0.9/</literal>.
+     <literal> xmlns="http://indexdata.dk/yazproxy/schema/0.9/"</literal>.
      All information except an optional XML header must be stored
      within the <literal>proxy</literal> element.
     </para>
      equivalent to command line option <literal>-t</literal>.
     </para>
     <para>
-     <screen>
-     &lt;?xml version="1.0"?>
-     &lt;proxy xmlns="http://indexdata.dk/yazproxy/schema/0.9/">
-      &lt;target name="server1" default="1">
-       &lt;!-- description of server1 .. -->
-      &lt;/target>
-      &lt;target name="server2">
-       &lt;!-- description of server2 .. -->
-      &lt;/target>
-     &lt;/proxy>
+      <screen><![CDATA[
+     <?xml version="1.0"?>
+     <proxy xmlns="http://indexdata.dk/yazproxy/schema/0.9/">
+      <target name="server1" default="1">
+       <!-- description of server1 .. -->
+      </target>
+      <target name="server2">
+       <!-- description of server2 .. -->
+      </target>
+     </proxy>
+      ]]>
      </screen>
     </para>
    </section>
     </para>
    </section>
 
+   <section id="proxy-config-max-sockets">
+    <title>client-timeout</title>
+    <para>
+     The element <literal>max-sockets</literal> is the child of element
+     <literal>target</literal> and specifies the maximum number of sockets
+     to use for the target for all sessions using it. In other words: maximum
+     number of Z39.50 session to the target.
+    </para>
+   </section>
+
    <section id="proxy-config-keepalive">
     <title>keepalive</title>
     <para>The <literal>keepalive</literal> element holds information about
      <xs:element ref="url" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element ref="target-timeout" minOccurs="0"/>
      <xs:element ref="client-timeout" minOccurs="0"/>
+     <xs:element ref="max-sockets" minOccurs="0"/>
      <xs:element ref="keepalive" minOccurs="0"/>
      <xs:element ref="limit" minOccurs="0"/>
      <xs:element ref="attribute" minOccurs="0" maxOccurs="unbounded"/>
  <xs:element name="url" type="xs:string"/>
  <xs:element name="target-timeout" type="xs:integer"/>
  <xs:element name="client-timeout" type="xs:integer"/>
+ <xs:element name="max-sockets" type="xs:integer"/>
  <xs:element name="bandwidth" type="xs:integer"/>
  <xs:element name="pdu" type="xs:integer"/>
  <xs:element name="retrieve" type="xs:integer"/>
index ca243e0..3c84edb 100644 (file)
@@ -10,6 +10,7 @@
     <url>localhost:9999</url>
     <target-timeout>60</target-timeout>
     <client-timeout>20</client-timeout>
+    <max-sockets>8</max-sockets>
     <!-- <target-authentication type="open">a/b</target-authentication> -->
     <keepalive>
       <bandwidth>100000</bandwidth>
@@ -42,7 +43,7 @@
     </syntax>
     
     <syntax type="*" error="238"/>
-    <preinit>2</preinit>
+    <preinit>0</preinit>
     <xi:include href="explain.xml"/>
     <target-charset>iso-8859-1</target-charset>
     <cql2rpn>pqf.properties</cql2rpn>
index 25ef079..0357948 100644 (file)
@@ -69,8 +69,9 @@ class YAZ_EXPORT Yaz_Proxy : public yazpp_1::Z_Assoc {
     void HTTP_Forwarded(Z_GDU *z_gdu);
     void connect_stat(bool &block, int &reduce);
     Yaz_ProxyClient *get_client(Z_APDU *apdu, const char *cookie,
-                                const char *proxy_host);
+                                const char *proxy_host, int *http_code);
     void srw_get_client(const char *db, const char **backend_db);
+    int get_number_of_connections();
     Z_APDU *result_set_optimize(Z_APDU *apdu);
     void releaseClient();
     Yaz_ProxyClient *m_client;
@@ -85,6 +86,7 @@ class YAZ_EXPORT Yaz_Proxy : public yazpp_1::Z_Assoc {
     int m_keepalive_limit_pdu;
     int m_client_idletime;
     int m_target_idletime;
+    int m_max_sockets;
     int m_debug_mode;
     char *m_proxyTarget;
     char *m_default_target;
index f87ec92..cc19d99 100644 (file)
@@ -115,6 +115,7 @@ public:
                          int *limit_bw, int *limit_pdu, int *limit_req,
                          int *limit_search,
                          int *target_idletime, int *client_idletime,
+                         int *max_sockets,
                          int *max_clients,
                          int *keepalive_limit_bw, int *keepalive_limit_pdu,
                          int *pre_init,
index b59d88a..edd5d85 100644 (file)
@@ -42,6 +42,7 @@ class Yaz_ProxyConfigP {
                             int *limit_bw, int *limit_pdu, int *limit_req,
                             int *limit_search,
                             int *target_idletime, int *client_idletime,
+                            int *max_sockets,
                             int *keepalive_limit_bw, int *keepalive_limit_pdu,
                             int *pre_init, const char **cql2rpn,
                             const char **negotiation_charset,
@@ -231,6 +232,7 @@ void Yaz_ProxyConfigP::return_target_info(xmlNodePtr ptr,
                                           int *limit_search,
                                           int *target_idletime,
                                           int *client_idletime,
+                                          int *max_sockets,
                                           int *keepalive_limit_bw,
                                           int *keepalive_limit_pdu,
                                           int *pre_init,
@@ -297,6 +299,15 @@ void Yaz_ProxyConfigP::return_target_info(xmlNodePtr ptr,
             }
         }
         if (ptr->type == XML_ELEMENT_NODE
+            && !strcmp((const char *) ptr->name, "max-sockets"))
+        {
+            const char *t = get_text(ptr);
+            if (t && max_sockets)
+            {
+                *max_sockets = atoi(t);
+            }
+        }
+        if (ptr->type == XML_ELEMENT_NODE
             && !strcmp((const char *) ptr->name, "cql2rpn"))
         {
             const char *t = get_text(ptr);
@@ -1018,6 +1029,7 @@ int Yaz_ProxyConfig::get_target_no(int no,
                     limit_bw, limit_pdu, limit_req,
                     limit_search,
                     target_idletime, client_idletime,
+                    0,
                     keepalive_limit_bw, keepalive_limit_pdu,
                     pre_init, cql2rpn,
                     negotiation_charset, negotiation_lang, target_charset,
@@ -1297,6 +1309,7 @@ void Yaz_ProxyConfig::get_target_info(const char *name,
                                       int *limit_search,
                                       int *target_idletime,
                                       int *client_idletime,
+                                      int *max_sockets,
                                       int *max_clients,
                                       int *keepalive_limit_bw,
                                       int *keepalive_limit_pdu,
@@ -1341,6 +1354,7 @@ void Yaz_ProxyConfig::get_target_info(const char *name,
         m_cp->return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
                                  limit_search,
                                  target_idletime, client_idletime,
+                                 max_sockets,
                                  keepalive_limit_bw, keepalive_limit_pdu,
                                  pre_init, cql2rpn,
                                  negotiation_charset, negotiation_lang,
index 258c5b4..147d066 100644 (file)
@@ -1,5 +1,5 @@
 /* $Id: yaz-proxy.cpp,v 1.78 2008-02-21 09:33:23 adam Exp $
-   Copyright (c) 1998-2007, Index Data.
+   Copyright (c) 1998-2008, Index Data.
 
 This file is part of the yazproxy.
 
@@ -220,6 +220,7 @@ Yaz_Proxy::Yaz_Proxy(IPDU_Observable *the_PDU_Observable,
     m_seed = time(0);
     m_client_idletime = 600;
     m_target_idletime = 600;
+    m_max_sockets = 1024;
     m_optimize = xstrdup ("1");
     strcpy(m_session_str, "0 ");
     m_session_no = 0;
@@ -546,8 +547,27 @@ const char *Yaz_Proxy::load_balance(const char **url)
     return ret_min;
 }
 
+int Yaz_Proxy::get_number_of_connections()
+{
+    int no_connections = 0;
+    Yaz_ProxyClient *c;
+
+    for (c = m_parent->m_clientPool; c; c = c->m_next)
+    {
+        assert(c->m_prev);
+        assert(*c->m_prev == c);
+        if (!strcmp(m_proxyTarget, c->get_hostname()))
+        {
+            no_connections++;
+        }
+    }
+    yaz_log (YLOG_LOG, "%sExisting %s connections: %d", m_session_str, m_proxyTarget,
+        no_connections);
+    return no_connections;
+}
+
 Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie,
-                                       const char *proxy_host)
+                                       const char *proxy_host, int *http_code)
 {
     assert (m_parent);
     Yaz_Proxy *parent = m_parent;
@@ -584,6 +604,7 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie,
                                  &m_pdu_max, &m_max_record_retrieve,
                                  &m_search_max,
                                  &m_target_idletime, &client_idletime,
+                                 &m_max_sockets,
                                  &parent->m_max_clients,
                                  &m_keepalive_limit_bw,
                                  &m_keepalive_limit_pdu,
@@ -679,7 +700,7 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie,
         {
             assert(c->m_prev);
             assert(*c->m_prev == c);
-            if (c->m_server == 0 && c->m_cookie == 0 &&  c->m_waiting == 0 
+            if (c->m_server == 0 && c->m_cookie == 0 && c->m_waiting == 0 
                 && c->compare_idAuthentication(apdu)
                 && c->compare_charset(apdu)
                 && !strcmp(m_proxyTarget, c->get_hostname()))
@@ -710,6 +731,16 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie,
         if (apdu->which != Z_APDU_initRequest)
         {
             yaz_log (YLOG_LOG, "%sno init request as first PDU", m_session_str);
+            *http_code = 500;
+            return 0;
+        }
+
+        int no_in_use = get_number_of_connections();
+        if (no_in_use >= m_max_sockets)
+        {
+            yaz_log (YLOG_LOG, "%smax sockets reached %d", m_session_str,
+                m_max_sockets);
+            *http_code = 500;
             return 0;
         }
         // go through list of clients - and find the lowest/oldest one.
@@ -769,6 +800,7 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie,
         }
         else
         {
+
             yaz_log (YLOG_LOG, "%sNEW %d %s",
                      m_session_str, parent->m_seqno, m_proxyTarget);
             c = new Yaz_ProxyClient(m_PDU_Observable->clone(), parent);
@@ -2798,8 +2830,6 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq)
             else
             {
                 // Use _client_ IP as shown in the log entries...!
-                yaz_log(YLOG_LOG, "No authorization_str present: use client IP: %s\n", m_peername);
-                
                 auth = (Z_IdAuthentication *) odr_malloc(m_s2z_odr_init, sizeof(Z_IdAuthentication));
                    auth->which = Z_IdAuthentication_idPass;
                    auth->u.idPass = (Z_IdPass *) odr_malloc(m_s2z_odr_init, sizeof(Z_IdPass));
@@ -3249,12 +3279,13 @@ void Yaz_Proxy::handle_incoming_Z_PDU(Z_APDU *apdu)
     // Determine our client.
     Z_OtherInformation **oi;
     get_otherInfoAPDU(apdu, &oi);
-    m_client = get_client(apdu, get_cookie(oi), get_proxy(oi));
+    int http_code = 404;
+    m_client = get_client(apdu, get_cookie(oi), get_proxy(oi), &http_code);
     if (!m_client)
     {
         if (m_http_version)
         {   // HTTP. Send not found
-            send_http_response(404);
+            send_http_response(http_code);
             return;
         }
         else