- struct target *t = iochan_getdata(i);
- struct session *s = t->session;
- struct target **p;
- assert(iochan_getfun(i) == handler);
-
- yaz_log(YLOG_DEBUG, "Destroying target");
-
- if (t->ibuf)
- xfree(t->ibuf);
- cs_close(t->link);
- if (t->odr_in)
- odr_destroy(t->odr_in);
- if (t->odr_out)
- odr_destroy(t->odr_out);
- for (p = &s->targets; *p; p = &(*p)->next)
- if (*p == t)
+ struct connection *new;
+ COMSTACK link;
+ int res;
+ void *addr;
+
+ yaz_log(YLOG_DEBUG, "Connection create %s", cl->database->url);
+ if (!(link = cs_create(tcpip_type, 0, PROTO_Z3950)))
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create comstack");
+ exit(1);
+ }
+
+ if (!(addr = cs_straddr(link, cl->database->host->ipport)))
+ {
+ yaz_log(YLOG_WARN|YLOG_ERRNO, "Lookup of IP address failed?");
+ return 0;
+ }
+
+ res = cs_connect(link, addr);
+ if (res < 0)
+ {
+ yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_connect %s", cl->database->url);
+ return 0;
+ }
+
+ if ((new = connection_freelist))
+ connection_freelist = new->next;
+ else
+ {
+ new = xmalloc(sizeof (struct connection));
+ new->ibuf = 0;
+ new->ibufsize = 0;
+ }
+ new->state = Conn_Connecting;
+ new->host = cl->database->host;
+ new->next = new->host->connections;
+ new->host->connections = new;
+ new->client = cl;
+ cl->connection = new;
+ new->link = link;
+
+ new->iochan = iochan_create(cs_fileno(link), handler, 0);
+ iochan_setdata(new->iochan, new);
+ new->iochan->next = channel_list;
+ channel_list = new->iochan;
+ return new;
+}
+
+// Close connection and set state to error
+static void client_fatal(struct client *cl)
+{
+ yaz_log(YLOG_WARN, "Fatal error from %s", cl->database->url);
+ connection_destroy(cl->connection);
+ cl->state = Client_Error;
+}
+
+// Ensure that client has a connection associated
+static int client_prep_connection(struct client *cl)
+{
+ struct connection *co;
+ struct session *se = cl->session;
+ struct host *host = cl->database->host;
+
+ co = cl->connection;
+
+ yaz_log(YLOG_DEBUG, "Client prep %s", cl->database->url);
+
+ if (!co)
+ {
+ // See if someone else has an idle connection
+ // We should look at timestamps here to select the longest-idle connection
+ for (co = host->connections; co; co = co->next)
+ if (co->state == Conn_Open && (!co->client || co->client->session != se))
+ break;
+ if (co)