/* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2010 Index Data
+ * Copyright (C) 1995-2011 Index Data
* See the file LICENSE for details.
*/
/**
* \file zoom-c.c
* \brief Implements ZOOM C interface.
*/
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <assert.h>
#include <string.h>
static void resultset_destroy(ZOOM_resultset r);
static zoom_ret do_write_ex(ZOOM_connection c, char *buf_out, int len_out);
-ZOOM_API(const char *) ZOOM_get_event_str(int event)
-{
- static const char *ar[] = {
- "NONE",
- "CONNECT",
- "SEND_DATA",
- "RECV_DATA",
- "TIMEOUT",
- "UNKNOWN",
- "SEND_APDU",
- "RECV_APDU",
- "RECV_RECORD",
- "RECV_SEARCH",
- "END"
- };
- return ar[event];
-}
-
static void initlog(void)
{
static int log_level_initialized = 0;
+
if (!log_level_initialized)
{
log_api0 = yaz_log_module_level("zoom");
}
}
-ZOOM_Event ZOOM_Event_create(int kind)
-{
- ZOOM_Event event = (ZOOM_Event) xmalloc(sizeof(*event));
- event->kind = kind;
- event->next = 0;
- event->prev = 0;
- return event;
-}
-
-static void ZOOM_Event_destroy(ZOOM_Event event)
-{
- xfree(event);
-}
-
-void ZOOM_connection_put_event(ZOOM_connection c, ZOOM_Event event)
-{
- if (c->m_queue_back)
- {
- c->m_queue_back->prev = event;
- assert(c->m_queue_front);
- }
- else
- {
- assert(!c->m_queue_front);
- c->m_queue_front = event;
- }
- event->next = c->m_queue_back;
- event->prev = 0;
- c->m_queue_back = event;
-}
-
-static ZOOM_Event ZOOM_connection_get_event(ZOOM_connection c)
-{
- ZOOM_Event event = c->m_queue_front;
- if (!event)
- {
- c->last_event = ZOOM_EVENT_NONE;
- return 0;
- }
- assert(c->m_queue_back);
- c->m_queue_front = event->prev;
- if (c->m_queue_front)
- {
- assert(c->m_queue_back);
- c->m_queue_front->next = 0;
- }
- else
- c->m_queue_back = 0;
- c->last_event = event->kind;
- return event;
-}
-
-static void ZOOM_connection_remove_events(ZOOM_connection c)
-{
- ZOOM_Event event;
- while ((event = ZOOM_connection_get_event(c)))
- ZOOM_Event_destroy(event);
-}
-
-ZOOM_API(int) ZOOM_connection_peek_event(ZOOM_connection c)
-{
- ZOOM_Event event = c->m_queue_front;
-
- return event ? event->kind : ZOOM_EVENT_NONE;
-}
-
void ZOOM_connection_remove_tasks(ZOOM_connection c);
void ZOOM_set_dset_error(ZOOM_connection c, int error,
}
if (addinfo && addinfo2)
{
- c->addinfo = (char*) xmalloc(strlen(addinfo) + strlen(addinfo2) + 2);
+ c->addinfo = (char*) xmalloc(strlen(addinfo) + strlen(addinfo2) + 3);
strcpy(c->addinfo, addinfo);
+ strcat(c->addinfo, ": ");
strcat(c->addinfo, addinfo2);
}
else if (addinfo)
task->running = 0;
task->which = which;
- clear_error(c);
return task;
}
c->options = ZOOM_options_create_with_parent(options);
c->host_port = 0;
- c->path = 0;
c->proxy = 0;
+ c->tproxy = 0;
c->charset = c->lang = 0;
return zoom_sru_get;
else if (!yaz_matchstr(s, "post"))
return zoom_sru_post;
+ else if (!yaz_matchstr(s, "solr"))
+ return zoom_sru_solr;
return zoom_sru_error;
}
const char *host, int portnum)
{
const char *val;
- ZOOM_task task;
initlog();
c->proxy = xstrdup(val);
}
+ xfree(c->tproxy);
+ c->tproxy = 0;
+ val = ZOOM_options_get(c->options, "tproxy");
+ if (val && *val)
+ {
+ yaz_log(c->log_details, "%p ZOOM_connection_connect tproxy=%s", c, val);
+ c->tproxy = xstrdup(val);
+ }
+
+
xfree(c->charset);
c->charset = 0;
val = ZOOM_options_get(c->options, "charset");
ZOOM_options_get_int(c->options, "preferredMessageSize", 1024*1024);
c->async = ZOOM_options_get_bool(c->options, "async", 0);
+
+ if (c->sru_mode == zoom_sru_error)
+ {
+ ZOOM_set_error(c, ZOOM_ERROR_UNSUPPORTED_PROTOCOL, val);
+ ZOOM_connection_remove_tasks(c);
+ return;
+ }
+
yaz_log(c->log_details, "%p ZOOM_connection_connect async=%d", c, c->async);
-
- task = ZOOM_connection_add_task(c, ZOOM_TASK_CONNECT);
+ ZOOM_connection_add_task(c, ZOOM_TASK_CONNECT);
if (!c->async)
{
cs_close(c->cs);
#if ZOOM_RESULT_LISTS
- // Remove the connection's usage of resultsets
+ /* Remove the connection's usage of resultsets */
list = c->resultsets;
while (list) {
ZOOM_resultsets removed = list;
ZOOM_connection_remove_tasks(c);
ZOOM_connection_remove_events(c);
xfree(c->host_port);
- xfree(c->path);
xfree(c->proxy);
+ xfree(c->tproxy);
xfree(c->charset);
xfree(c->lang);
xfree(c->cookie_out);
}
}
+static int g_resultsets = 0;
+static YAZ_MUTEX g_resultset_mutex = 0;
+
+/* TODO We need to initialize this before running threaded:
+ * call resultset_use(0) */
+
+static int resultset_use(int delta) {
+ int resultset_count;
+ if (g_resultset_mutex == 0)
+ yaz_mutex_create(&g_resultset_mutex);
+ yaz_mutex_enter(g_resultset_mutex);
+ g_resultsets += delta;
+ resultset_count = g_resultsets;
+ yaz_mutex_leave(g_resultset_mutex);
+ return resultset_count;
+}
+
+int resultsets_count(void) {
+ return resultset_use(0);
+}
+
ZOOM_resultset ZOOM_resultset_create(void)
{
int i;
YAZ_SHPTR_INIT(r->record_wrbuf, w);
}
#endif
+ resultset_use(1);
return r;
}
#if SHPTR
YAZ_SHPTR_DEC(r->record_wrbuf, wrbuf_destroy);
#endif
+ resultset_use(-1);
xfree(r);
}
else
}
static zoom_ret do_connect_host(ZOOM_connection c,
- const char *effective_host,
const char *logical_url);
static zoom_ret do_connect(ZOOM_connection c)
{
- const char *effective_host;
-
- if (c->proxy)
- effective_host = c->proxy;
- else
- effective_host = c->host_port;
- return do_connect_host(c, effective_host, c->host_port);
+ return do_connect_host(c, c->host_port);
}
-static zoom_ret do_connect_host(ZOOM_connection c, const char *effective_host,
- const char *logical_url)
+static zoom_ret do_connect_host(ZOOM_connection c, const char *logical_url)
{
void *add;
- yaz_log(c->log_details, "%p do_connect effective_host=%s", c, effective_host);
-
if (c->cs)
cs_close(c->cs);
- c->cs = cs_create_host(effective_host, 0, &add);
-
+ c->cs = cs_create_host_proxy(logical_url, 0, &add,
+ c->tproxy ? c->tproxy : c->proxy);
+
if (c->cs && c->cs->protocol == PROTO_HTTP)
{
#if YAZ_HAVE_XML2
- if (logical_url)
- {
- const char *db = 0;
-
- c->proto = PROTO_HTTP;
- cs_get_host_args(logical_url, &db);
- xfree(c->path);
-
- c->path = xmalloc(strlen(db) * 3 + 2);
- yaz_encode_sru_dbpath_buf(c->path, db);
- }
+ c->proto = PROTO_HTTP;
#else
ZOOM_set_error(c, ZOOM_ERROR_UNSUPPORTED_PROTOCOL, "SRW");
ZOOM_connection_close(c);
}
#if YAZ_HAVE_XML2
-static Z_GDU *get_HTTP_Request_url(ODR odr, const char *url)
-{
- Z_GDU *p = z_get_HTTP_Request(odr);
- const char *host = url;
- const char *cp0 = strstr(host, "://");
- const char *cp1 = 0;
- if (cp0)
- cp0 = cp0+3;
- else
- cp0 = host;
-
- cp1 = strchr(cp0, '/');
- if (!cp1)
- cp1 = cp0 + strlen(cp0);
-
- if (cp0 && cp1)
- {
- char *h = (char*) odr_malloc(odr, cp1 - cp0 + 1);
- memcpy (h, cp0, cp1 - cp0);
- h[cp1-cp0] = '\0';
- z_HTTP_header_add(odr, &p->u.HTTP_Request->headers, "Host", h);
- }
- p->u.HTTP_Request->path = odr_strdup(odr, *cp1 ? cp1 : "/");
- return p;
-}
static zoom_ret send_HTTP_redirect(ZOOM_connection c, const char *uri,
Z_HTTP_Response *cookie_hres)
{
struct Z_HTTP_Header *h;
- Z_GDU *gdu = get_HTTP_Request_url(c->odr_out, uri);
- char *combined_cookies;
+ char *combined_cookies = 0;
int combined_cookies_len = 0;
+ Z_GDU *gdu = z_get_HTTP_Request_uri(c->odr_out, uri, 0, c->proxy ? 1 : 0);
gdu->u.HTTP_Request->method = odr_strdup(c->odr_out, "GET");
z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers, "Accept",
{
zoom_ret cret = zoom_complete;
int ret = -1;
- const char *addinfo = 0;
+ char *addinfo = 0;
const char *connection_head = z_HTTP_header_lookup(hres->headers,
"Connection");
const char *location;
ZOOM_connection_set_mask(c, 0);
yaz_log(c->log_details, "%p handle_http", c);
-
+
if ((hres->code == 301 || hres->code == 302) && c->sru_mode == zoom_sru_get
&& (location = z_HTTP_header_lookup(hres->headers, "Location")))
{
{
/* since redirect may change host we just reconnect. A smarter
implementation might check whether it's the same server */
- do_connect_host(c, location, 0);
+ do_connect_host(c, location);
send_HTTP_redirect(c, location, hres);
/* we're OK for now. Operation is not really complete */
- ret = 0;
- cret = zoom_pending;
+ return;
}
}
else
{
- ret = ZOOM_handle_sru(c, hres, &cret);
+ ret = ZOOM_handle_sru(c, hres, &cret, &addinfo);
if (ret == 0)
{
if (c->no_redirects) /* end of redirect. change hosts again */
if (hres->code != 200)
ZOOM_set_HTTP_error(c, hres->code, 0, 0);
else
+ {
+ yaz_log(YLOG_LOG, "set error... addinfo=%s", addinfo ?
+ addinfo : "NULL");
ZOOM_set_error(c, ZOOM_ERROR_DECODE, addinfo);
+ }
ZOOM_connection_close(c);
}
if (cret == zoom_complete)
{
- yaz_log(YLOG_LOG, "removing tasks in handle_http");
+ yaz_log(c->log_details, "removing tasks in handle_http");
ZOOM_connection_remove_task(c);
}
{
c->reconnect_ok = 0;
}
}
+ else
+ c->reconnect_ok = 1; /* if the server closes anyway */
}
}
#endif
#endif
}
}
- c->reconnect_ok = 0;
}
return 1;
}
return "CCL configuration error";
case ZOOM_ERROR_CCL_PARSE:
return "CCL parsing error";
+ case ZOOM_ERROR_ES_INVALID_ACTION:
+ return "Extended Service. invalid action";
+ case ZOOM_ERROR_ES_INVALID_VERSION:
+ return "Extended Service. invalid version";
+ case ZOOM_ERROR_ES_INVALID_SYNTAX:
+ return "Extended Service. invalid syntax";
default:
return diagbib1_str(error);
}