Happy new year
[pazpar2-moved-to-github.git] / src / connection.c
index 93b9020..80d6ec0 100644 (file)
@@ -103,28 +103,16 @@ struct connection {
 
 static int connection_connect(struct connection *con, iochan_man_t iochan_man);
 
-static int connection_is_idle(struct connection *co)
-{
-    ZOOM_connection link = co->link;
-    int event;
-
-    if (co->state != Conn_Open || !link)
-        return 0;
-
-    if (!ZOOM_connection_is_idle(link))
-        return 0;
-    event = ZOOM_connection_peek_event(link);
-    if (event == ZOOM_EVENT_NONE)
-        return 1;
-    else
-        return 0;
-}
-
 ZOOM_connection connection_get_link(struct connection *co)
 {
     return co->link;
 }
 
+void connection_mark_dead(struct connection *co)
+{ 
+    iochan_settimeout(co->iochan, 1);
+}
+
 // Close connection and recycle structure
 static void connection_destroy(struct connection *co)
 {
@@ -156,6 +144,7 @@ static struct connection *connection_create(struct client *cl,
                                             iochan_man_t iochan_man)
 {
     struct connection *co;
+    int ret;
 
     co = xmalloc(sizeof(*co));
 
@@ -171,9 +160,13 @@ static struct connection *connection_create(struct client *cl,
     co->operation_timeout = operation_timeout;
     co->session_timeout = session_timeout;
 
-    connection_connect(co, iochan_man);
-
+    ret = connection_connect(co, iochan_man);
     connection_use(1);
+    if (ret)
+    {   /* error */
+        connection_destroy(co);
+        co = 0;
+    }
     return co;
 }
 
@@ -206,8 +199,10 @@ static void non_block_events(struct connection *co)
                 int err;
                 if ((err = ZOOM_connection_error(link, &error, &addinfo)))
                 {
-                    yaz_log(YLOG_LOG, "Error %s from %s",
-                            error, client_get_id(cl));
+                    struct session *se = client_get_session(cl);
+
+                    session_log(se, YLOG_WARN, "%s: Error %s (%s)",
+                                client_get_id(cl), error, addinfo);
                     client_set_diagnostic(cl, err, error, addinfo);
                     client_set_state(cl, Client_Error);
                 }
@@ -231,7 +226,6 @@ static void non_block_events(struct connection *co)
         case ZOOM_EVENT_RECV_APDU:
             break;
         case ZOOM_EVENT_CONNECT:
-            yaz_log(YLOG_LOG, "Connected to %s", client_get_id(cl));
             co->state = Conn_Open;
             break;
         case ZOOM_EVENT_RECV_SEARCH:
@@ -252,10 +246,20 @@ static void non_block_events(struct connection *co)
     {
         struct client *cl = co->client;
         if (cl)
-        {
-            client_check_preferred_watch(cl);
             client_got_records(cl);
-        }
+    }
+}
+
+static void iochan_update(struct connection *co)
+{
+    if (co->link)
+    {
+        int m = ZOOM_connection_get_mask(co->link);
+
+        if (m == 0)
+            m = ZOOM_SELECT_READ;
+        iochan_setflags(co->iochan, m);
+        iochan_setfd(co->iochan, ZOOM_connection_get_socket(co->link));
     }
 }
 
@@ -271,10 +275,7 @@ void connection_continue(struct connection *co)
         client_unlock(cl);
     }
     else
-    {
-        iochan_setflags(co->iochan, ZOOM_connection_get_mask(co->link));
-        iochan_setfd(co->iochan, ZOOM_connection_get_socket(co->link));
-    }
+        iochan_update(co);
 }
 
 static void connection_handler(IOCHAN iochan, int event)
@@ -302,6 +303,11 @@ static void connection_handler(IOCHAN iochan, int event)
     }
     else
     {
+        if (ZOOM_connection_is_idle(co->link))
+        {
+            connection_destroy(co);
+            return;
+        }
         client_lock(cl);
         non_block_events(co);
 
@@ -310,23 +316,12 @@ static void connection_handler(IOCHAN iochan, int event)
         non_block_events(co);
         client_unlock(cl);
 
-        if (co->link)
-        {
-            iochan_setflags(iochan, ZOOM_connection_get_mask(co->link));
-            iochan_setfd(iochan, ZOOM_connection_get_socket(co->link));
-        }
+        iochan_update(co);
     }
 }
 
-
-// Disassociate connection from client
-static void connection_release(struct connection *co)
+void connection_release2(struct connection *co)
 {
-    struct client *cl = co->client;
-
-    if (!cl)
-        return;
-    client_set_connection(cl, 0);
     co->client = 0;
 }
 
@@ -338,11 +333,15 @@ static int connection_connect(struct connection *con, iochan_man_t iochan_man)
     const char *sru;
     const char *sru_version = 0;
     const char *value;
+    int r = 0;
     WRBUF w;
 
-    struct session_database *sdb = client_get_database(con->client);
+    struct client *cl = con->client;
+    struct session_database *sdb = client_get_database(cl);
     const char *apdulog = session_setting_oneval(sdb, PZ_APDULOG);
+    struct session *se = client_get_session(cl);
     const char *memcached = session_setting_oneval(sdb, PZ_MEMCACHED);
+    const char *redis = session_setting_oneval(sdb, PZ_REDIS);
 
     assert(con);
 
@@ -354,6 +353,8 @@ static int connection_connect(struct connection *con, iochan_man_t iochan_man)
         ZOOM_options_set(zoptions, "charset", charset);
     if (memcached && *memcached)
         ZOOM_options_set(zoptions, "memcached", memcached);
+    if (redis && *redis)
+        ZOOM_options_set(zoptions, "redis", redis);
 
     if (con->zproxy)
     {
@@ -403,7 +404,8 @@ static int connection_connect(struct connection *con, iochan_man_t iochan_man)
 
     if (!(con->link = ZOOM_connection_create(zoptions)))
     {
-        yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create ZOOM Connection");
+        session_log(se, YLOG_WARN, "%s: ZOOM_connection_create failed",
+                    client_get_id(cl));
         ZOOM_options_destroy(zoptions);
         return -1;
     }
@@ -425,12 +427,22 @@ static int connection_connect(struct connection *con, iochan_man_t iochan_man)
     con->state = Conn_Connecting;
     iochan_settimeout(con->iochan, con->operation_timeout);
     iochan_setdata(con->iochan, con);
-    iochan_add(iochan_man, con->iochan);
-
-    client_set_state(con->client, Client_Connecting);
+    if (iochan_add(iochan_man, con->iochan, 20))
+    {
+        session_log(se, YLOG_WARN, "%s: out of connections", client_get_id(cl));
+        iochan_destroy(con->iochan);
+        con->iochan = 0;
+        ZOOM_connection_destroy(con->link);
+        con->link = 0;
+        r = -1;
+    }
+    else
+    {
+        client_set_state(cl, Client_Connecting);
+    }
     ZOOM_options_destroy(zoptions);
     wrbuf_destroy(w);
-    return 0;
+    return r;
 }
 
 // Ensure that client has a connection associated
@@ -454,6 +466,8 @@ int client_prep_connection(struct client *cl,
             client_get_id(cl), url);
 
     co = client_get_connection(cl);
+    if (co)
+        return 2;
     if (!co)
     {
         co = connection_create(cl, url, zproxy,