struct host *host;
struct client *client;
char *zproxy;
+ char *url;
enum {
Conn_Closed,
Conn_Connecting,
ZOOM_connection_destroy(co->link);
iochan_destroy(co->iochan);
}
- yaz_log(YLOG_DEBUG, "%p Connection destroy %s", co, co->host->url);
+ yaz_log(YLOG_DEBUG, "%p Connection destroy %s", co, co->url);
if (co->client)
{
}
xfree(co->zproxy);
+ xfree(co->url);
xfree(co);
connection_use(-1);
}
// Creates a new connection for client, associated with the host of
// client's database
static struct connection *connection_create(struct client *cl,
+ const char *url,
struct host *host,
int operation_timeout,
int session_timeout,
co->host = host;
co->client = cl;
+ co->url = xstrdup(url);
co->zproxy = 0;
client_set_connection(cl, co);
co->link = 0;
{
struct connection *con;
-start:
yaz_mutex_enter(host->mutex);
con = host->connections;
while (con)
{
if (con->state == Conn_Closed)
{
- if (!host->ipport) /* unresolved */
+ if (!host->ipport || !con->client) /* unresolved or no client */
{
remove_connection_from_host(con);
yaz_mutex_leave(host->mutex);
connection_destroy(con);
- goto start;
- /* start all over .. at some point it will be NULL */
- }
- else if (!con->client)
- {
- remove_connection_from_host(con);
- yaz_mutex_leave(host->mutex);
- connection_destroy(con);
- /* start all over .. at some point it will be NULL */
- goto start;
}
else
{
- yaz_mutex_leave(host->mutex);
- connection_connect(con, iochan_man);
- client_start_search(con->client);
- goto start;
+ struct session_database *sdb = client_get_database(con->client);
+ if (sdb)
+ {
+ yaz_mutex_leave(host->mutex);
+ connection_connect(con, iochan_man);
+ client_start_search(con->client);
+ }
+ else
+ {
+ remove_connection_from_host(con);
+ yaz_mutex_leave(host->mutex);
+ connection_destroy(con);
+ }
}
+ /* start all over .. at some point it will be NULL */
+ yaz_mutex_enter(host->mutex);
+ con = host->connections;
}
else
{
return -1;
}
- if (sru && *sru && !strstr(host->url, "://"))
+ if (sru && *sru && !strstr(con->url, "://"))
{
WRBUF w = wrbuf_alloc();
wrbuf_puts(w, "http://");
- wrbuf_puts(w, host->url);
+ wrbuf_puts(w, con->url);
+ ZOOM_connection_connect(con->link, wrbuf_cstr(w), 0);
+ wrbuf_destroy(w);
+ }
+ else if (strchr(con->url, '#'))
+ {
+ const char *cp = strchr(con->url, '#');
+ WRBUF w = wrbuf_alloc();
+ wrbuf_write(w, con->url, cp - con->url);
ZOOM_connection_connect(con->link, wrbuf_cstr(w), 0);
wrbuf_destroy(w);
}
else
{
- ZOOM_connection_connect(con->link, host->url, 0);
+ ZOOM_connection_connect(con->link, con->url, 0);
}
con->iochan = iochan_create(-1, connection_handler, 0, "connection_socket");
con->state = Conn_Connecting;
return 0;
co = client_get_connection(cl);
-
if (co)
{
assert(co->host);
for (co = host->connections; co; co = co->next)
{
if (connection_is_idle(co) &&
+ !strcmp(url, co->url) &&
(!co->client || client_get_state(co->client) == Client_Idle) &&
!strcmp(ZOOM_connection_option_get(co->link, "user"),
session_setting_oneval(client_get_database(cl),
else
{
yaz_mutex_leave(host->mutex);
- co = connection_create(cl, host, operation_timeout, session_timeout,
+ co = connection_create(cl, url, host,
+ operation_timeout, session_timeout,
iochan_man);
}
assert(co->host);
}
static void run_fun(iochan_man_t man, IOCHAN p) {
- if (p->this_event) {
- if (man->sel_thread) {
- yaz_log(man->log_level,
- "eventl: work add chan=%p name=%s event=%d", p,
- p->name ? p->name : "", p->this_event);
- p->thread_users++;
- sel_thread_add(man->sel_thread, p);
- } else
- work_handler(p);
- }
+ if (man->sel_thread) {
+ yaz_log(man->log_level,
+ "eventl: work add chan=%p name=%s event=%d", p,
+ p->name ? p->name : "", p->this_event);
+ p->thread_users++;
+ sel_thread_add(man->sel_thread, p);
+ } else
+ work_handler(p);
}
static int event_loop(iochan_man_t man, IOCHAN *iochans) {
struct timeval *timeout;
// struct yaz_poll_fd *fds;
- int no_fds = 0;
+ int i, no_fds = 0;
FD_ZERO(&in);
FD_ZERO(&out);
FD_ZERO(&except);
}
yaz_log(man->log_level, "%d channels", no);
}
+ i = 0;
for (p = start; p; p = p->next) {
time_t now = time(0);
p->this_event |= EVENT_EXCEPT;
}
}
- run_fun(man, p);
+ /* only fire one Z39.50/SRU socket event.. except for timeout */
+ if (p->this_event) {
+ if (!(p->this_event & EVENT_TIMEOUT) &&
+ !strcmp(p->name, "connection_socket")) {
+ /* not a timeout and we have a Z39.50/SRU socket */
+ if (i == 0)
+ run_fun(man, p);
+ i++;
+ } else
+ run_fun(man, p);
+ }
}
assert(inv_start == start);
yaz_mutex_enter(man->iochan_mutex);
static int log_level = YLOG_LOG;
-void perform_getaddrinfo(struct work *w)
+static void perform_getaddrinfo(struct work *w)
{
struct addrinfo hints, *res;
char host[512], *cp;
int host_getaddrinfo(struct host *host, iochan_man_t iochan_man)
{
struct work *w = xmalloc(sizeof(*w));
- int use_thread = 0; /* =0 to disable threading entirely */
+ int use_thread = 1; /* =0 to disable threading entirely */
w->hostport = host->tproxy ? host->tproxy : host->proxy;
w->ipport = 0;
#include <sys/stat.h>
#include <yaz/log.h>
#include <yaz/nmem.h>
+#include <yaz/matchstr.h>
#include "ppmutex.h"
#include "session.h"
YAZ_MUTEX mutex;
};
+#if YAZ_VERSIONL > 0x4023e
+#define strcmp_null(x, y) yaz_strcmp_null(x, y)
+#else
+#define strcmp_null(x, y) local_strcmp_null(x, y)
+
+static int local_strcmp_null(const char *v1, const char *v2)
+{
+ if (v1)
+ {
+ if (v2)
+ return strcmp(v1, v2);
+ else
+ return 1;
+ }
+ else if (v2)
+ return -1;
+ return 0;
+}
+#endif
+
// Create a new host structure for hostport
-static struct host *create_host(const char *url, const char *proxy,
- int default_port,
+static struct host *create_host(const char *proxy,
+ const char *tproxy,
iochan_man_t iochan_man)
{
struct host *host;
- char *db_comment;
host = xmalloc(sizeof(struct host));
- host->url = xstrdup(url);
host->proxy = 0;
host->tproxy = 0;
if (proxy && *proxy)
host->proxy = xstrdup(proxy);
else
{
- char *cp;
-
- host->tproxy = xmalloc (strlen(url) + 10); /* so we can add :port */
- strcpy(host->tproxy, url);
- for (cp = host->tproxy; *cp; cp++)
- if (strchr("/?#~", *cp))
- {
- *cp = '\0';
- break;
- }
- if (!strchr(host->tproxy, ':'))
- sprintf(cp, ":%d", default_port); /* no port given, add it */
+ assert(tproxy);
+ host->tproxy = xstrdup(tproxy);
}
-
- db_comment = strchr(host->url, '#');
- if (db_comment)
- *db_comment = '\0';
host->connections = 0;
host->ipport = 0;
host->mutex = 0;
xfree(host->ipport);
xfree(host->tproxy);
xfree(host->proxy);
- xfree(host->url);
xfree(host);
return 0;
}
iochan_man_t iochan_man)
{
struct host *p;
+ char *tproxy = 0;
+
+ if (!proxy || !*proxy)
+ {
+ char *cp;
+
+ tproxy = xmalloc (strlen(url) + 10); /* so we can add :port */
+ strcpy(tproxy, url);
+ for (cp = tproxy; *cp; cp++)
+ if (strchr("/?#~", *cp))
+ {
+ *cp = '\0';
+ break;
+ }
+ if (!strchr(tproxy, ':'))
+ sprintf(cp, ":%d", port); /* no port given, add it */
+ }
yaz_mutex_enter(hosts->mutex);
for (p = hosts->hosts; p; p = p->next)
- if (!strcmp(p->url, url))
+ {
+ if (!strcmp_null(p->tproxy, tproxy) &&
+ !strcmp_null(p->proxy, proxy))
{
- if (p->proxy && proxy && !strcmp(p->proxy, proxy))
- break;
- if (!p->proxy && !proxy)
- break;
+ break;
}
+ }
if (!p)
{
- p = create_host(url, proxy, port, iochan_man);
+ p = create_host(proxy, tproxy, iochan_man);
if (p)
{
p->next = hosts->hosts;
}
}
yaz_mutex_leave(hosts->mutex);
+ xfree(tproxy);
return p;
}
struct host *p_next = p->next;
yaz_mutex_destroy(&p->mutex);
yaz_cond_destroy(&p->cond_ready);
- xfree(p->url);
xfree(p->ipport);
xfree(p);
p = p_next;
/** \brief Represents a host (irrespective of databases) */
struct host {
- char *url; // logical host/database?args ..
char *tproxy; // tproxy address (no Z39.50 UI)
char *proxy; // logical proxy address
char *ipport; // tproxy or proxy resolved