X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Fseshigh.c;h=1a2af630a7091922c3071486a1e5fb90bbc05ae4;hb=cc8dd1424e89a4ad96ce0b30a1bd0a6ecf4f8715;hp=76755815dc5d765e0f3e90c052ffbfbf33f3e02f;hpb=d21c0a79df949a31f337094b8e169d04a939a9dc;p=yaz-moved-to-github.git
diff --git a/src/seshigh.c b/src/seshigh.c
index 7675581..1a2af63 100644
--- a/src/seshigh.c
+++ b/src/seshigh.c
@@ -1,11 +1,13 @@
/*
- * Copyright (c) 1995-2003, Index Data
+ * Copyright (c) 1995-2004, Index Data
* See the file LICENSE for details.
*
- * $Id: seshigh.c,v 1.6 2003-12-21 11:33:29 adam Exp $
+ * $Id: seshigh.c,v 1.39 2004-12-20 23:38:03 adam Exp $
*/
-
-/*
+/**
+ * \file seshigh.c
+ * \brief Implements GFS session logic.
+ *
* Frontend server logic.
*
* This code receives incoming APDUs, and handles client requests by means
@@ -66,7 +68,8 @@ void backend_response(IOCHAN i, int event);
static int process_gdu_response(association *assoc, request *req, Z_GDU *res);
static int process_z_response(association *assoc, request *req, Z_APDU *res);
static Z_APDU *process_initRequest(association *assoc, request *reqb);
-static Z_External *init_diagnostics(ODR odr, int errcode, char *errstring);
+static Z_External *init_diagnostics(ODR odr, int errcode,
+ const char *errstring);
static Z_APDU *process_searchRequest(association *assoc, request *reqb,
int *fd);
static Z_APDU *response_searchRequest(association *assoc, request *reqb,
@@ -86,6 +89,32 @@ static statserv_options_block *control_block = 0;
static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd);
+/* dynamic logging levels */
+static int logbits_set=0;
+static int log_session=0;
+static int log_request=0; /* one-line logs for requests */
+static int log_requestdetail=0; /* more detailed stuff */
+
+/** get_logbits sets global loglevel bits */
+static void get_logbits()
+{ /* needs to be called after parsing cmd-line args that can set loglevels!*/
+ if (!logbits_set)
+ {
+ logbits_set=1;
+ log_session=yaz_log_module_level("session");
+ log_request=yaz_log_module_level("request");
+ log_requestdetail=yaz_log_module_level("requestdetail");
+ }
+}
+
+static void wr_diag(WRBUF w, int error, const char *addinfo)
+{
+ wrbuf_printf(w, "ERROR [%d] %s%s%s",
+ error, diagbib1_str(error),
+ addinfo ? "--" : "", addinfo ? addinfo : "");
+}
+
+
/*
* Create and initialize a new association-handle.
* channel : iochannel for the current line.
@@ -96,10 +125,12 @@ association *create_association(IOCHAN channel, COMSTACK link)
{
association *anew;
+ if (!logbits_set)
+ get_logbits();
if (!control_block)
- control_block = statserv_getcontrol();
+ control_block = statserv_getcontrol();
if (!(anew = (association *)xmalloc(sizeof(*anew))))
- return 0;
+ return 0;
anew->init = 0;
anew->version = 0;
anew->client_chan = channel;
@@ -108,51 +139,51 @@ association *create_association(IOCHAN channel, COMSTACK link)
anew->cs_put_mask = 0;
anew->cs_accept_mask = 0;
if (!(anew->decode = odr_createmem(ODR_DECODE)) ||
- !(anew->encode = odr_createmem(ODR_ENCODE)))
- return 0;
+ !(anew->encode = odr_createmem(ODR_ENCODE)))
+ return 0;
if (*control_block->apdufile)
{
- char filename[256];
- FILE *f;
+ char filename[256];
+ FILE *f;
- strcpy(filename, control_block->apdufile);
- if (!(anew->print = odr_createmem(ODR_PRINT)))
- return 0;
- if (*control_block->apdufile == '@')
+ strcpy(filename, control_block->apdufile);
+ if (!(anew->print = odr_createmem(ODR_PRINT)))
+ return 0;
+ if (*control_block->apdufile == '@')
+ {
+ odr_setprint(anew->print, yaz_log_file());
+ }
+ else if (*control_block->apdufile != '-')
{
- odr_setprint(anew->print, yaz_log_file());
- }
- else if (*control_block->apdufile != '-')
- {
- strcpy(filename, control_block->apdufile);
- if (!control_block->dynamic)
- {
- if (!apduf)
- {
- if (!(apduf = fopen(filename, "w")))
- {
- yaz_log(LOG_WARN|LOG_ERRNO, "%s", filename);
- return 0;
- }
- setvbuf(apduf, 0, _IONBF, 0);
- }
- f = apduf;
- }
- else
- {
- sprintf(filename + strlen(filename), ".%d", getpid());
- if (!(f = fopen(filename, "w")))
- {
- yaz_log(LOG_WARN|LOG_ERRNO, "%s", filename);
- return 0;
- }
- setvbuf(f, 0, _IONBF, 0);
- }
- odr_setprint(anew->print, f);
- }
+ strcpy(filename, control_block->apdufile);
+ if (!control_block->dynamic)
+ {
+ if (!apduf)
+ {
+ if (!(apduf = fopen(filename, "w")))
+ {
+ yaz_log(YLOG_WARN|YLOG_ERRNO, "can't open apdu dump %s", filename);
+ return 0;
+ }
+ setvbuf(apduf, 0, _IONBF, 0);
+ }
+ f = apduf;
+ }
+ else
+ {
+ sprintf(filename + strlen(filename), ".%d", getpid());
+ if (!(f = fopen(filename, "w")))
+ {
+ yaz_log(YLOG_WARN|YLOG_ERRNO, "%s", filename);
+ return 0;
+ }
+ setvbuf(f, 0, _IONBF, 0);
+ }
+ odr_setprint(anew->print, f);
+ }
}
else
- anew->print = 0;
+ anew->print = 0;
anew->input_buffer = 0;
anew->input_buffer_len = 0;
anew->backend = 0;
@@ -175,27 +206,27 @@ void destroy_association(association *h)
odr_destroy(h->decode);
odr_destroy(h->encode);
if (h->print)
- odr_destroy(h->print);
+ odr_destroy(h->print);
if (h->input_buffer)
xfree(h->input_buffer);
if (h->backend)
- (*cb->bend_close)(h->backend);
+ (*cb->bend_close)(h->backend);
while ((req = request_deq(&h->incoming)))
- request_release(req);
+ request_release(req);
while ((req = request_deq(&h->outgoing)))
- request_release(req);
+ request_release(req);
request_delq(&h->incoming);
request_delq(&h->outgoing);
xfree(h);
xmalloc_trav("session closed");
if (control_block && control_block->one_shot)
{
- exit (0);
+ exit (0);
}
}
static void do_close_req(association *a, int reason, char *message,
- request *req)
+ request *req)
{
Z_APDU apdu;
Z_Close *cls = zget_Close(a->encode);
@@ -205,20 +236,20 @@ static void do_close_req(association *a, int reason, char *message,
while (request_deq(&a->outgoing));
if (a->version >= 3)
{
- yaz_log(LOG_LOG, "Sending Close PDU, reason=%d, message=%s",
- reason, message ? message : "none");
- apdu.which = Z_APDU_close;
- apdu.u.close = cls;
- *cls->closeReason = reason;
- cls->diagnosticInformation = message;
- process_z_response(a, req, &apdu);
- iochan_settimeout(a->client_chan, 20);
+ yaz_log(log_requestdetail, "Sending Close PDU, reason=%d, message=%s",
+ reason, message ? message : "none");
+ apdu.which = Z_APDU_close;
+ apdu.u.close = cls;
+ *cls->closeReason = reason;
+ cls->diagnosticInformation = message;
+ process_z_response(a, req, &apdu);
+ iochan_settimeout(a->client_chan, 20);
}
else
{
- request_release(req);
- yaz_log(LOG_DEBUG, "v2 client. No Close PDU");
- iochan_setevent(a->client_chan, EVENT_TIMEOUT); /* force imm close */
+ request_release(req);
+ yaz_log(log_requestdetail, "v2 client. No Close PDU");
+ iochan_setevent(a->client_chan, EVENT_TIMEOUT); /* force imm close */
}
a->state = ASSOC_DEAD;
}
@@ -248,100 +279,100 @@ void ir_session(IOCHAN h, int event)
assert(h && conn && assoc);
if (event == EVENT_TIMEOUT)
{
- if (assoc->state != ASSOC_UP)
- {
- yaz_log(LOG_LOG, "Final timeout - closing connection.");
- cs_close(conn);
- destroy_association(assoc);
- iochan_destroy(h);
- }
- else
- {
- yaz_log(LOG_LOG, "Session idle too long. Sending close.");
- do_close(assoc, Z_Close_lackOfActivity, 0);
- }
- return;
+ if (assoc->state != ASSOC_UP)
+ {
+ yaz_log(YLOG_DEBUG, "Final timeout - closing connection.");
+ /* do we need to lod this at all */
+ cs_close(conn);
+ destroy_association(assoc);
+ iochan_destroy(h);
+ }
+ else
+ {
+ yaz_log(log_session, "Session idle too long. Sending close.");
+ do_close(assoc, Z_Close_lackOfActivity, 0);
+ }
+ return;
}
if (event & assoc->cs_accept_mask)
{
- yaz_log (LOG_DEBUG, "ir_session (accept)");
- if (!cs_accept (conn))
- {
- yaz_log (LOG_LOG, "accept failed");
- destroy_association(assoc);
- iochan_destroy(h);
- }
- iochan_clearflag (h, EVENT_OUTPUT|EVENT_OUTPUT);
- if (conn->io_pending)
- { /* cs_accept didn't complete */
- assoc->cs_accept_mask =
- ((conn->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) |
- ((conn->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0);
-
- iochan_setflag (h, assoc->cs_accept_mask);
- }
- else
- { /* cs_accept completed. Prepare for reading (cs_get) */
- assoc->cs_accept_mask = 0;
- assoc->cs_get_mask = EVENT_INPUT;
- iochan_setflag (h, assoc->cs_get_mask);
- }
- return;
+ if (!cs_accept (conn))
+ {
+ yaz_log (YLOG_WARN, "accept failed");
+ destroy_association(assoc);
+ iochan_destroy(h);
+ }
+ iochan_clearflag (h, EVENT_OUTPUT);
+ if (conn->io_pending)
+ { /* cs_accept didn't complete */
+ assoc->cs_accept_mask =
+ ((conn->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) |
+ ((conn->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0);
+
+ iochan_setflag (h, assoc->cs_accept_mask);
+ }
+ else
+ { /* cs_accept completed. Prepare for reading (cs_get) */
+ assoc->cs_accept_mask = 0;
+ assoc->cs_get_mask = EVENT_INPUT;
+ iochan_setflag (h, assoc->cs_get_mask);
+ }
+ return;
}
if ((event & assoc->cs_get_mask) || (event & EVENT_WORK)) /* input */
{
- if ((assoc->cs_put_mask & EVENT_INPUT) == 0 && (event & assoc->cs_get_mask))
- {
- yaz_log(LOG_DEBUG, "ir_session (input)");
- /* We aren't speaking to this fellow */
- if (assoc->state == ASSOC_DEAD)
- {
- yaz_log(LOG_LOG, "Connection closed - end of session");
- cs_close(conn);
- destroy_association(assoc);
- iochan_destroy(h);
- return;
- }
- assoc->cs_get_mask = EVENT_INPUT;
- if ((res = cs_get(conn, &assoc->input_buffer,
- &assoc->input_buffer_len)) <= 0)
- {
- yaz_log(LOG_LOG, "Connection closed by client");
- cs_close(conn);
- destroy_association(assoc);
- iochan_destroy(h);
- return;
- }
- else if (res == 1) /* incomplete read - wait for more */
- {
- if (conn->io_pending & CS_WANT_WRITE)
- assoc->cs_get_mask |= EVENT_OUTPUT;
- iochan_setflag(h, assoc->cs_get_mask);
- return;
- }
- if (cs_more(conn)) /* more stuff - call us again later, please */
- iochan_setevent(h, EVENT_INPUT);
-
- /* we got a complete PDU. Let's decode it */
- yaz_log(LOG_DEBUG, "Got PDU, %d bytes: lead=%02X %02X %02X", res,
- assoc->input_buffer[0] & 0xff,
- assoc->input_buffer[1] & 0xff,
- assoc->input_buffer[2] & 0xff);
- req = request_get(&assoc->incoming); /* get a new request */
- odr_reset(assoc->decode);
- odr_setbuf(assoc->decode, assoc->input_buffer, res, 0);
- if (!z_GDU(assoc->decode, &req->gdu_request, 0, 0))
- {
- yaz_log(LOG_LOG, "ODR error on incoming PDU: %s [element %s] "
+ if ((assoc->cs_put_mask & EVENT_INPUT) == 0 && (event & assoc->cs_get_mask))
+ {
+ yaz_log(YLOG_DEBUG, "ir_session (input)");
+ /* We aren't speaking to this fellow */
+ if (assoc->state == ASSOC_DEAD)
+ {
+ yaz_log(log_session, "Connection closed - end of session");
+ cs_close(conn);
+ destroy_association(assoc);
+ iochan_destroy(h);
+ return;
+ }
+ assoc->cs_get_mask = EVENT_INPUT;
+ if ((res = cs_get(conn, &assoc->input_buffer,
+ &assoc->input_buffer_len)) <= 0)
+ {
+ yaz_log(log_session, "Connection closed by client");
+ cs_close(conn);
+ destroy_association(assoc);
+ iochan_destroy(h);
+ return;
+ }
+ else if (res == 1) /* incomplete read - wait for more */
+ {
+ if (conn->io_pending & CS_WANT_WRITE)
+ assoc->cs_get_mask |= EVENT_OUTPUT;
+ iochan_setflag(h, assoc->cs_get_mask);
+ return;
+ }
+ if (cs_more(conn)) /* more stuff - call us again later, please */
+ iochan_setevent(h, EVENT_INPUT);
+
+ /* we got a complete PDU. Let's decode it */
+ yaz_log(YLOG_DEBUG, "Got PDU, %d bytes: lead=%02X %02X %02X", res,
+ assoc->input_buffer[0] & 0xff,
+ assoc->input_buffer[1] & 0xff,
+ assoc->input_buffer[2] & 0xff);
+ req = request_get(&assoc->incoming); /* get a new request */
+ odr_reset(assoc->decode);
+ odr_setbuf(assoc->decode, assoc->input_buffer, res, 0);
+ if (!z_GDU(assoc->decode, &req->gdu_request, 0, 0))
+ {
+ yaz_log(YLOG_WARN, "ODR error on incoming PDU: %s [element %s] "
"[near byte %d] ",
- odr_errmsg(odr_geterror(assoc->decode)),
+ odr_errmsg(odr_geterror(assoc->decode)),
odr_getelement(assoc->decode),
- odr_offset(assoc->decode));
+ odr_offset(assoc->decode));
if (assoc->decode->error != OHTTP)
{
- yaz_log(LOG_LOG, "PDU dump:");
+ yaz_log(YLOG_WARN, "PDU dump:");
odr_dumpBER(yaz_log_file(), assoc->input_buffer, res);
- request_release(req);
+ request_release(req);
do_close(assoc, Z_Close_protocolError,"Malformed package");
}
else
@@ -350,76 +381,77 @@ void ir_session(IOCHAN h, int event)
assoc->state = ASSOC_DEAD;
process_gdu_response(assoc, req, p);
}
- return;
- }
- req->request_mem = odr_extract_mem(assoc->decode);
- if (assoc->print && !z_GDU(assoc->print, &req->gdu_request, 0, 0))
- {
- yaz_log(LOG_WARN, "ODR print error: %s",
- odr_errmsg(odr_geterror(assoc->print)));
- odr_reset(assoc->print);
- }
- request_enq(&assoc->incoming, req);
- }
-
- /* can we do something yet? */
- req = request_head(&assoc->incoming);
- if (req->state == REQUEST_IDLE)
- {
- request_deq(&assoc->incoming);
- process_gdu_request(assoc, req);
- }
+ return;
+ }
+ req->request_mem = odr_extract_mem(assoc->decode);
+ if (assoc->print)
+ {
+ if (!z_GDU(assoc->print, &req->gdu_request, 0, 0))
+ yaz_log(YLOG_WARN, "ODR print error: %s",
+ odr_errmsg(odr_geterror(assoc->print)));
+ odr_reset(assoc->print);
+ }
+ request_enq(&assoc->incoming, req);
+ }
+
+ /* can we do something yet? */
+ req = request_head(&assoc->incoming);
+ if (req->state == REQUEST_IDLE)
+ {
+ request_deq(&assoc->incoming);
+ process_gdu_request(assoc, req);
+ }
}
if (event & assoc->cs_put_mask)
{
- request *req = request_head(&assoc->outgoing);
+ request *req = request_head(&assoc->outgoing);
- assoc->cs_put_mask = 0;
- yaz_log(LOG_DEBUG, "ir_session (output)");
+ assoc->cs_put_mask = 0;
+ yaz_log(YLOG_DEBUG, "ir_session (output)");
req->state = REQUEST_PENDING;
- switch (res = cs_put(conn, req->response, req->len_response))
- {
- case -1:
- yaz_log(LOG_LOG, "Connection closed by client");
- cs_close(conn);
- destroy_association(assoc);
- iochan_destroy(h);
- break;
- case 0: /* all sent - release the request structure */
- yaz_log(LOG_DEBUG, "Wrote PDU, %d bytes", req->len_response);
+ switch (res = cs_put(conn, req->response, req->len_response))
+ {
+ case -1:
+ yaz_log(log_session, "Connection closed by client");
+ cs_close(conn);
+ destroy_association(assoc);
+ iochan_destroy(h);
+ break;
+ case 0: /* all sent - release the request structure */
+ yaz_log(YLOG_DEBUG, "Wrote PDU, %d bytes", req->len_response);
#if 0
- yaz_log(LOG_DEBUG, "HTTP out:\n%.*s", req->len_response,
+ yaz_log(YLOG_DEBUG, "HTTP out:\n%.*s", req->len_response,
req->response);
#endif
- nmem_destroy(req->request_mem);
- request_deq(&assoc->outgoing);
- request_release(req);
- if (!request_head(&assoc->outgoing))
- { /* restore mask for cs_get operation ... */
- iochan_clearflag(h, EVENT_OUTPUT|EVENT_INPUT);
- iochan_setflag(h, assoc->cs_get_mask);
+ nmem_destroy(req->request_mem);
+ request_deq(&assoc->outgoing);
+ request_release(req);
+ if (!request_head(&assoc->outgoing))
+ { /* restore mask for cs_get operation ... */
+ iochan_clearflag(h, EVENT_OUTPUT|EVENT_INPUT);
+ iochan_setflag(h, assoc->cs_get_mask);
if (assoc->state == ASSOC_DEAD)
iochan_setevent(assoc->client_chan, EVENT_TIMEOUT);
- }
+ }
else
{
assoc->cs_put_mask = EVENT_OUTPUT;
}
- break;
- default:
- if (conn->io_pending & CS_WANT_WRITE)
- assoc->cs_put_mask |= EVENT_OUTPUT;
- if (conn->io_pending & CS_WANT_READ)
- assoc->cs_put_mask |= EVENT_INPUT;
- iochan_setflag(h, assoc->cs_put_mask);
- }
+ break;
+ default:
+ if (conn->io_pending & CS_WANT_WRITE)
+ assoc->cs_put_mask |= EVENT_OUTPUT;
+ if (conn->io_pending & CS_WANT_READ)
+ assoc->cs_put_mask |= EVENT_INPUT;
+ iochan_setflag(h, assoc->cs_put_mask);
+ }
}
if (event & EVENT_EXCEPT)
{
- yaz_log(LOG_LOG, "ir_session (exception)");
- cs_close(conn);
- destroy_association(assoc);
- iochan_destroy(h);
+ yaz_log(YLOG_WARN, "ir_session (exception)");
+ cs_close(conn);
+ destroy_association(assoc);
+ iochan_destroy(h);
}
}
@@ -470,10 +502,11 @@ static int srw_bend_init(association *assoc)
ce = yaz_set_proposal_charneg(assoc->decode, &encoding, 1, 0, 0, 1);
assoc->init->charneg_request = ce->u.charNeg3;
#endif
+ assoc->backend = 0;
if (!(binitres = (*cb->bend_init)(assoc->init)))
{
- yaz_log(LOG_WARN, "Bad response from backend.");
- return 0;
+ yaz_log(YLOG_WARN, "Bad response from backend.");
+ return 0;
}
assoc->backend = binitres->handle;
return 1;
@@ -494,10 +527,10 @@ static int srw_bend_fetch(association *assoc, int pos,
CLASS_TRANSYN,
VAL_TEXT_XML);
rr.comp = (Z_RecordComposition *)
- odr_malloc(assoc->decode, sizeof(*rr.comp));
+ odr_malloc(assoc->decode, sizeof(*rr.comp));
rr.comp->which = Z_RecordComp_complex;
rr.comp->u.complex = (Z_CompSpec *)
- odr_malloc(assoc->decode, sizeof(Z_CompSpec));
+ odr_malloc(assoc->decode, sizeof(Z_CompSpec));
rr.comp->u.complex->selectAlternativeSyntax = (bool_t *)
odr_malloc(assoc->encode, sizeof(bool_t));
*rr.comp->u.complex->selectAlternativeSyntax = 0;
@@ -507,10 +540,23 @@ static int srw_bend_fetch(association *assoc, int pos,
rr.comp->u.complex->recordSyntax = 0;
rr.comp->u.complex->generic = (Z_Specification *)
- odr_malloc(assoc->decode, sizeof(Z_Specification));
+ odr_malloc(assoc->decode, sizeof(Z_Specification));
+
+ /* schema uri = recordSchema (or NULL if recordSchema is not given) */
rr.comp->u.complex->generic->which = Z_Schema_uri;
rr.comp->u.complex->generic->schema.uri = srw_req->recordSchema;
+
+ /* ESN = recordSchema if recordSchema is present */
rr.comp->u.complex->generic->elementSpec = 0;
+ if (srw_req->recordSchema)
+ {
+ rr.comp->u.complex->generic->elementSpec =
+ (Z_ElementSpec *) odr_malloc(assoc->encode, sizeof(Z_ElementSpec));
+ rr.comp->u.complex->generic->elementSpec->which =
+ Z_ElementSpec_elementSetName;
+ rr.comp->u.complex->generic->elementSpec->u.elementSetName =
+ srw_req->recordSchema;
+ }
rr.stream = assoc->encode;
rr.print = assoc->print;
@@ -531,7 +577,35 @@ static int srw_bend_fetch(association *assoc, int pos,
(*assoc->init->bend_fetch)(assoc->backend, &rr);
- if (rr.len >= 0)
+ if (rr.errcode && rr.surrogate_flag)
+ {
+ int code = yaz_diag_bib1_to_srw(rr.errcode);
+ const char *message = yaz_diag_srw_str(code);
+ int len = 200;
+ if (message)
+ len += strlen(message);
+ if (rr.errstring)
+ len += strlen(rr.errstring);
+
+ record->recordData_buf = odr_malloc(o, len);
+
+ sprintf(record->recordData_buf, "
YAZ " - YAZ_VERSION "
\n" - "%s" - " \n" - "\n", doclink); - hres->content_len = strlen(hres->content_buf); - z_HTTP_header_add(o, &hres->headers, "Content-Type", "text/html"); + yaz_add_srw_diagnostic(o, + &res->u.scan_response->diagnostics, + &res->u.scan_response->num_diagnostics, + 4, "scan"); + if (http_code == 200) + soap_package->u.generic->p = res; } -#endif - - if (!p) + else { - p = z_get_HTTP_Response(o, 404); + yaz_log(log_request, "generate soap error"); + /* FIXME - what error, what query */ + http_code = 500; + z_soap_error(assoc->encode, soap_package, + "SOAP-ENV:Client", "Bad method", 0); } - } - else if (!strcmp(hreq->method, "POST")) - { - const char *content_type = z_HTTP_header_lookup(hreq->headers, - "Content-Type"); - if (content_type && !yaz_strcmp_del("text/xml", content_type, "; ")) + if (http_code == 200 || http_code == 500) { - Z_SOAP *soap_package = 0; - int ret = -1; - int http_code = 500; - const char *charset_p = 0; - char *charset = 0; - - static Z_SOAP_Handler soap_handlers[2] = { + static Z_SOAP_Handler soap_handlers[3] = { #if HAVE_XML2 {"http://www.loc.gov/zing/srw/", 0, (Z_SOAP_fun) yaz_srw_codec}, + {"http://www.loc.gov/zing/srw/v1.0/", 0, + (Z_SOAP_fun) yaz_srw_codec}, #endif {0, 0, 0} }; - if ((charset_p = strstr(content_type, "; charset="))) - { - int i = 0; - charset_p += 10; - while (i < 20 && charset_p[i] && - !strchr("; \n\r", charset_p[i])) - i++; - charset = odr_malloc(assoc->encode, i+1); - memcpy(charset, charset_p, i); - charset[i] = '\0'; - yaz_log(LOG_LOG, "SOAP encoding %s", charset); - } - ret = z_soap_codec(assoc->decode, &soap_package, - &hreq->content_buf, &hreq->content_len, - soap_handlers); -#if HAVE_XML2 - if (!ret && soap_package->which == Z_SOAP_generic && - soap_package->u.generic->no == 0) - { - /* SRW package */ - char *db = "Default"; - const char *p0 = hreq->path, *p1; - Z_SRW_PDU *sr = soap_package->u.generic->p; - - if (*p0 == '/') - p0++; - p1 = strchr(p0, '?'); - if (!p1) - p1 = p0 + strlen(p0); - if (p1 != p0) - { - db = (char*) odr_malloc(assoc->decode, p1 - p0 + 1); - memcpy (db, p0, p1 - p0); - db[p1 - p0] = '\0'; - } - - if (sr->which == Z_SRW_searchRetrieve_request) - { - Z_SRW_PDU *res = - yaz_srw_get(assoc->encode, - Z_SRW_searchRetrieve_response); - - if (!sr->u.request->database) - sr->u.request->database = db; - - srw_bend_search(assoc, req, sr->u.request, - res->u.response); - - soap_package->u.generic->p = res; - http_code = 200; - } - else if (sr->which == Z_SRW_explain_request) - { - Z_SRW_PDU *res = - yaz_srw_get(assoc->encode, Z_SRW_explain_response); - - if (!sr->u.explain_request->database) - sr->u.explain_request->database = db; - - srw_bend_explain(assoc, req, sr->u.explain_request, - res->u.explain_response); - if (!res->u.explain_response->record.recordData_buf) - { - z_soap_error(assoc->encode, soap_package, - "SOAP-ENV:Client", "Explain Not Supported", 0); - } - else - { - soap_package->u.generic->p = res; - http_code = 200; - } - } - else - { - z_soap_error(assoc->encode, soap_package, - "SOAP-ENV:Client", "Bad method", 0); - } - } -#endif + char ctype[60]; + int ret; p = z_get_HTTP_Response(o, 200); hres = p->u.HTTP_Response; - ret = z_soap_codec_enc(assoc->encode, &soap_package, - &hres->content_buf, &hres->content_len, - soap_handlers, charset); + ret = z_soap_codec_enc_xsl(assoc->encode, &soap_package, + &hres->content_buf, &hres->content_len, + soap_handlers, charset, stylesheet); hres->code = http_code; - if (!charset) - z_HTTP_header_add(o, &hres->headers, "Content-Type", "text/xml"); - else + + strcpy(ctype, "text/xml"); + if (charset) { - char ctype[60]; - strcpy(ctype, "text/xml; charset="); + strcat(ctype, "; charset="); strcat(ctype, charset); - z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype); } + z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype); } - if (!p) /* still no response ? */ - p = z_get_HTTP_Response(o, 500); + else + p = z_get_HTTP_Response(o, http_code); } - else - { - p = z_get_HTTP_Response(o, 405); - hres = p->u.HTTP_Response; - z_HTTP_header_add(o, &hres->headers, "Allow", "GET, POST"); - } + if (p == 0) + p = z_get_HTTP_Response(o, 500); hres = p->u.HTTP_Response; if (!strcmp(hreq->version, "1.0")) { @@ -1143,6 +1027,7 @@ static void process_http_request(association *assoc, request *req) { z_HTTP_header_add(o, &hres->headers, "Connection", "close"); assoc->state = ASSOC_DEAD; + assoc->cs_get_mask = 0; } else { @@ -1191,95 +1076,97 @@ static int process_z_request(association *assoc, request *req, char **msg) assert(req && req->state == REQUEST_IDLE); if (req->apdu_request->which != Z_APDU_initRequest && !assoc->init) { - *msg = "Missing InitRequest"; - return -1; + *msg = "Missing InitRequest"; + return -1; } switch (req->apdu_request->which) { case Z_APDU_initRequest: iochan_settimeout(assoc->client_chan, statserv_getcontrol()->idle_timeout * 60); - res = process_initRequest(assoc, req); break; + res = process_initRequest(assoc, req); break; case Z_APDU_searchRequest: - res = process_searchRequest(assoc, req, &fd); break; + res = process_searchRequest(assoc, req, &fd); break; case Z_APDU_presentRequest: - res = process_presentRequest(assoc, req, &fd); break; + res = process_presentRequest(assoc, req, &fd); break; case Z_APDU_scanRequest: - if (assoc->init->bend_scan) - res = process_scanRequest(assoc, req, &fd); - else - { - *msg = "Cannot handle Scan APDU"; - return -1; - } - break; + if (assoc->init->bend_scan) + res = process_scanRequest(assoc, req, &fd); + else + { + *msg = "Cannot handle Scan APDU"; + return -1; + } + break; case Z_APDU_extendedServicesRequest: - if (assoc->init->bend_esrequest) - res = process_ESRequest(assoc, req, &fd); - else - { - *msg = "Cannot handle Extended Services APDU"; - return -1; - } - break; + if (assoc->init->bend_esrequest) + res = process_ESRequest(assoc, req, &fd); + else + { + *msg = "Cannot handle Extended Services APDU"; + return -1; + } + break; case Z_APDU_sortRequest: - if (assoc->init->bend_sort) - res = process_sortRequest(assoc, req, &fd); - else - { - *msg = "Cannot handle Sort APDU"; - return -1; - } - break; + if (assoc->init->bend_sort) + res = process_sortRequest(assoc, req, &fd); + else + { + *msg = "Cannot handle Sort APDU"; + return -1; + } + break; case Z_APDU_close: - process_close(assoc, req); - return 0; + process_close(assoc, req); + return 0; case Z_APDU_deleteResultSetRequest: - if (assoc->init->bend_delete) - res = process_deleteRequest(assoc, req, &fd); - else - { - *msg = "Cannot handle Delete APDU"; - return -1; - } - break; + if (assoc->init->bend_delete) + res = process_deleteRequest(assoc, req, &fd); + else + { + *msg = "Cannot handle Delete APDU"; + return -1; + } + break; case Z_APDU_segmentRequest: - if (assoc->init->bend_segment) - { - res = process_segmentRequest (assoc, req); - } - else - { - *msg = "Cannot handle Segment APDU"; - return -1; - } - break; + if (assoc->init->bend_segment) + { + res = process_segmentRequest (assoc, req); + } + else + { + *msg = "Cannot handle Segment APDU"; + return -1; + } + break; + case Z_APDU_triggerResourceControlRequest: + return 0; default: - *msg = "Bad APDU received"; - return -1; + *msg = "Bad APDU received"; + return -1; } if (res) { - yaz_log(LOG_DEBUG, " result immediately available"); - retval = process_z_response(assoc, req, res); + yaz_log(YLOG_DEBUG, " result immediately available"); + retval = process_z_response(assoc, req, res); } else if (fd < 0) { - yaz_log(LOG_DEBUG, " result unavailble"); - retval = 0; + yaz_log(YLOG_DEBUG, " result unavailble"); + retval = 0; } else /* no result yet - one will be provided later */ { - IOCHAN chan; + IOCHAN chan; - /* Set up an I/O handler for the fd supplied by the backend */ + /* Set up an I/O handler for the fd supplied by the backend */ - yaz_log(LOG_DEBUG, " establishing handler for result"); - req->state = REQUEST_PENDING; - if (!(chan = iochan_create(fd, backend_response, EVENT_INPUT))) - abort(); - iochan_setdata(chan, assoc); - retval = 0; + yaz_log(YLOG_DEBUG, " establishing handler for result"); + req->state = REQUEST_PENDING; + if (!(chan = iochan_create(fd, backend_response, EVENT_INPUT))) + abort(); + iochan_setdata(chan, assoc); + retval = 0; } return retval; } @@ -1294,34 +1181,34 @@ void backend_response(IOCHAN i, int event) Z_APDU *res; int fd; - yaz_log(LOG_DEBUG, "backend_response"); + yaz_log(YLOG_DEBUG, "backend_response"); assert(assoc && req && req->state != REQUEST_IDLE); /* determine what it is we're waiting for */ switch (req->apdu_request->which) { - case Z_APDU_searchRequest: - res = response_searchRequest(assoc, req, 0, &fd); break; + case Z_APDU_searchRequest: + res = response_searchRequest(assoc, req, 0, &fd); break; #if 0 - case Z_APDU_presentRequest: - res = response_presentRequest(assoc, req, 0, &fd); break; - case Z_APDU_scanRequest: - res = response_scanRequest(assoc, req, 0, &fd); break; + case Z_APDU_presentRequest: + res = response_presentRequest(assoc, req, 0, &fd); break; + case Z_APDU_scanRequest: + res = response_scanRequest(assoc, req, 0, &fd); break; #endif - default: - yaz_log(LOG_WARN, "Serious programmer's lapse or bug"); - abort(); + default: + yaz_log(YLOG_FATAL, "Serious programmer's lapse or bug"); + abort(); } if ((res && process_z_response(assoc, req, res) < 0) || fd < 0) { - yaz_log(LOG_LOG, "Fatal error when talking to backend"); - do_close(assoc, Z_Close_systemProblem, 0); - iochan_destroy(i); - return; + yaz_log(YLOG_WARN, "Fatal error when talking to backend"); + do_close(assoc, Z_Close_systemProblem, 0); + iochan_destroy(i); + return; } else if (!res) /* no result yet - try again later */ { - yaz_log(LOG_DEBUG, " no result yet"); - iochan_setfd(i, fd); /* in case fd has changed */ + yaz_log(YLOG_DEBUG, " no result yet"); + iochan_setfd(i, fd); /* in case fd has changed */ } } @@ -1332,22 +1219,22 @@ static int process_gdu_response(association *assoc, request *req, Z_GDU *res) { odr_setbuf(assoc->encode, req->response, req->size_response, 1); - if (assoc->print && !z_GDU(assoc->print, &res, 0, 0)) + if (assoc->print) { - yaz_log(LOG_WARN, "ODR print error: %s", - odr_errmsg(odr_geterror(assoc->print))); - odr_reset(assoc->print); + if (!z_GDU(assoc->print, &res, 0, 0)) + yaz_log(YLOG_WARN, "ODR print error: %s", + odr_errmsg(odr_geterror(assoc->print))); + odr_reset(assoc->print); } if (!z_GDU(assoc->encode, &res, 0, 0)) { - yaz_log(LOG_WARN, "ODR error when encoding PDU: %s [element %s]", + yaz_log(YLOG_WARN, "ODR error when encoding PDU: %s [element %s]", odr_errmsg(odr_geterror(assoc->decode)), odr_getelement(assoc->decode)); - request_release(req); - return -1; + return -1; } req->response = odr_getbuf(assoc->encode, &req->len_response, - &req->size_response); + &req->size_response); odr_setbuf(assoc->encode, 0, 0, 0); /* don'txfree if we abort later */ odr_reset(assoc->encode); req->state = REQUEST_IDLE; @@ -1359,8 +1246,8 @@ static int process_gdu_response(association *assoc, request *req, Z_GDU *res) #if 1 if (request_head(&assoc->incoming)) { - yaz_log (LOG_DEBUG, "more work to be done"); - iochan_setevent(assoc->client_chan, EVENT_WORK); + yaz_log (YLOG_DEBUG, "more work to be done"); + iochan_setevent(assoc->client_chan, EVENT_WORK); } #endif return 0; @@ -1396,13 +1283,13 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) char *version; char options[140]; - yaz_log(LOG_LOG, "Got initRequest"); + yaz_log(log_requestdetail, "Got initRequest"); if (req->implementationId) - yaz_log(LOG_LOG, "Id: %s", req->implementationId); + yaz_log(log_requestdetail, "Id: %s", req->implementationId); if (req->implementationName) - yaz_log(LOG_LOG, "Name: %s", req->implementationName); + yaz_log(log_requestdetail, "Name: %s", req->implementationName); if (req->implementationVersion) - yaz_log(LOG_LOG, "Version: %s", req->implementationVersion); + yaz_log(log_requestdetail, "Version: %s", req->implementationVersion); assoc_init_reset(assoc); @@ -1413,228 +1300,183 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) { Z_CharSetandLanguageNegotiation *negotiation = yaz_get_charneg_record (req->otherInfo); - if (negotiation->which == Z_CharSetandLanguageNegotiation_proposal) + if (negotiation && + negotiation->which == Z_CharSetandLanguageNegotiation_proposal) assoc->init->charneg_request = negotiation; } + assoc->backend = 0; if (!(binitres = (*cb->bend_init)(assoc->init))) { - yaz_log(LOG_WARN, "Bad response from backend."); - return 0; + yaz_log(YLOG_WARN, "Bad response from backend."); + return 0; } assoc->backend = binitres->handle; if ((assoc->init->bend_sort)) - yaz_log (LOG_DEBUG, "Sort handler installed"); + yaz_log (YLOG_DEBUG, "Sort handler installed"); if ((assoc->init->bend_search)) - yaz_log (LOG_DEBUG, "Search handler installed"); + yaz_log (YLOG_DEBUG, "Search handler installed"); if ((assoc->init->bend_present)) - yaz_log (LOG_DEBUG, "Present handler installed"); + yaz_log (YLOG_DEBUG, "Present handler installed"); if ((assoc->init->bend_esrequest)) - yaz_log (LOG_DEBUG, "ESRequest handler installed"); + yaz_log (YLOG_DEBUG, "ESRequest handler installed"); if ((assoc->init->bend_delete)) - yaz_log (LOG_DEBUG, "Delete handler installed"); + yaz_log (YLOG_DEBUG, "Delete handler installed"); if ((assoc->init->bend_scan)) - yaz_log (LOG_DEBUG, "Scan handler installed"); + yaz_log (YLOG_DEBUG, "Scan handler installed"); if ((assoc->init->bend_segment)) - yaz_log (LOG_DEBUG, "Segment handler installed"); + yaz_log (YLOG_DEBUG, "Segment handler installed"); resp->referenceId = req->referenceId; *options = '\0'; /* let's tell the client what we can do */ if (ODR_MASK_GET(req->options, Z_Options_search)) { - ODR_MASK_SET(resp->options, Z_Options_search); - strcat(options, "srch"); + ODR_MASK_SET(resp->options, Z_Options_search); + strcat(options, "srch"); } if (ODR_MASK_GET(req->options, Z_Options_present)) { - ODR_MASK_SET(resp->options, Z_Options_present); - strcat(options, " prst"); + ODR_MASK_SET(resp->options, Z_Options_present); + strcat(options, " prst"); } if (ODR_MASK_GET(req->options, Z_Options_delSet) && - assoc->init->bend_delete) + assoc->init->bend_delete) { - ODR_MASK_SET(resp->options, Z_Options_delSet); - strcat(options, " del"); + ODR_MASK_SET(resp->options, Z_Options_delSet); + strcat(options, " del"); } if (ODR_MASK_GET(req->options, Z_Options_extendedServices) && - assoc->init->bend_esrequest) + assoc->init->bend_esrequest) { - ODR_MASK_SET(resp->options, Z_Options_extendedServices); - strcat (options, " extendedServices"); + ODR_MASK_SET(resp->options, Z_Options_extendedServices); + strcat (options, " extendedServices"); } if (ODR_MASK_GET(req->options, Z_Options_namedResultSets)) { - ODR_MASK_SET(resp->options, Z_Options_namedResultSets); - strcat(options, " namedresults"); + ODR_MASK_SET(resp->options, Z_Options_namedResultSets); + strcat(options, " namedresults"); } if (ODR_MASK_GET(req->options, Z_Options_scan) && assoc->init->bend_scan) { - ODR_MASK_SET(resp->options, Z_Options_scan); - strcat(options, " scan"); + ODR_MASK_SET(resp->options, Z_Options_scan); + strcat(options, " scan"); } if (ODR_MASK_GET(req->options, Z_Options_concurrentOperations)) { - ODR_MASK_SET(resp->options, Z_Options_concurrentOperations); - strcat(options, " concurrop"); + ODR_MASK_SET(resp->options, Z_Options_concurrentOperations); + strcat(options, " concurrop"); } if (ODR_MASK_GET(req->options, Z_Options_sort) && assoc->init->bend_sort) { - ODR_MASK_SET(resp->options, Z_Options_sort); - strcat(options, " sort"); + ODR_MASK_SET(resp->options, Z_Options_sort); + strcat(options, " sort"); } if (ODR_MASK_GET(req->options, Z_Options_negotiationModel) && assoc->init->charneg_response) { - Z_OtherInformation **p; - Z_OtherInformationUnit *p0; - - yaz_oi_APDU(apdu, &p); - - if ((p0=yaz_oi_update(p, assoc->encode, NULL, 0, 0))) { + Z_OtherInformation **p; + Z_OtherInformationUnit *p0; + + yaz_oi_APDU(apdu, &p); + + if ((p0=yaz_oi_update(p, assoc->encode, NULL, 0, 0))) { ODR_MASK_SET(resp->options, Z_Options_negotiationModel); p0->which = Z_OtherInfo_externallyDefinedInfo; p0->information.externallyDefinedInfo = assoc->init->charneg_response; } - ODR_MASK_SET(resp->options, Z_Options_negotiationModel); - strcat(options, " negotiation"); + ODR_MASK_SET(resp->options, Z_Options_negotiationModel); + strcat(options, " negotiation"); } + + ODR_MASK_SET(resp->options, Z_Options_triggerResourceCtrl); if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_1)) { - ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1); - assoc->version = 2; /* 1 & 2 are equivalent */ + ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1); + assoc->version = 1; /* 1 & 2 are equivalent */ } if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_2)) { - ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_2); - assoc->version = 2; + ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_2); + assoc->version = 2; } if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_3)) { - ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3); - assoc->version = 3; + ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3); + assoc->version = 3; } - yaz_log(LOG_LOG, "Negotiated to v%d: %s", assoc->version, options); + yaz_log(log_requestdetail, "Negotiated to v%d: %s", assoc->version, options); assoc->maximumRecordSize = *req->maximumRecordSize; if (assoc->maximumRecordSize > control_block->maxrecordsize) - assoc->maximumRecordSize = control_block->maxrecordsize; + assoc->maximumRecordSize = control_block->maxrecordsize; assoc->preferredMessageSize = *req->preferredMessageSize; if (assoc->preferredMessageSize > assoc->maximumRecordSize) - assoc->preferredMessageSize = assoc->maximumRecordSize; + assoc->preferredMessageSize = assoc->maximumRecordSize; resp->preferredMessageSize = &assoc->preferredMessageSize; resp->maximumRecordSize = &assoc->maximumRecordSize; resp->implementationId = odr_prepend(assoc->encode, - assoc->init->implementation_id, - resp->implementationId); + assoc->init->implementation_id, + resp->implementationId); resp->implementationName = odr_prepend(assoc->encode, - assoc->init->implementation_name, - odr_prepend(assoc->encode, "GFS", resp->implementationName)); + assoc->init->implementation_name, + odr_prepend(assoc->encode, "GFS", resp->implementationName)); - version = odr_strdup(assoc->encode, "$Revision: 1.6 $"); - if (strlen(version) > 10) /* check for unexpanded CVS strings */ - version[strlen(version)-2] = '\0'; + version = odr_strdup(assoc->encode, "$Revision: 1.39 $"); + if (strlen(version) > 10) /* check for unexpanded CVS strings */ + version[strlen(version)-2] = '\0'; resp->implementationVersion = odr_prepend(assoc->encode, - assoc->init->implementation_version, - odr_prepend(assoc->encode, &version[11], - resp->implementationVersion)); + assoc->init->implementation_version, + odr_prepend(assoc->encode, &version[11], + resp->implementationVersion)); if (binitres->errcode) { - yaz_log(LOG_LOG, "Connection rejected by backend."); - *resp->result = 0; - assoc->state = ASSOC_DEAD; - resp->userInformationField = init_diagnostics(assoc->encode, - binitres->errcode, - binitres->errstring); + WRBUF wr = wrbuf_alloc(); + *resp->result = 0; + assoc->state = ASSOC_DEAD; + resp->userInformationField = + init_diagnostics(assoc->encode, binitres->errcode, + binitres->errstring); + wr_diag(wr, binitres->errcode, binitres->errstring); + yaz_log(log_request, "Init from '%s' (%s) (ver %s) %s", + req->implementationName ? req->implementationName :"??", + req->implementationId ? req->implementationId :"?", + req->implementationVersion ? req->implementationVersion: "?", + wrbuf_buf(wr)); + wrbuf_free(wr, 1); } else - assoc->state = ASSOC_UP; - return apdu; -} - -/* - * Diagnostic in default format, to be returned as either a surrogate - * or non-surrogate diagnostic in the context of an open session, or - * as User-information when an Init is refused. - */ -static Z_DefaultDiagFormat *justdiag(ODR odr, int error, char *addinfo) -{ - int *err = odr_intdup(odr, error); - Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *) - odr_malloc (odr, sizeof(*dr)); - - yaz_log(LOG_LOG, "[%d] %s%s%s", error, diagbib1_str(error), - addinfo ? " -- " : "", addinfo ? addinfo : ""); + { + assoc->state = ASSOC_UP; + yaz_log(log_request, "Init from '%s' (%s) (ver %s) OK", + req->implementationName ? req->implementationName :"??", + req->implementationId ? req->implementationId :"?", + req->implementationVersion ? req->implementationVersion: "?"); + } - dr->diagnosticSetId = - yaz_oidval_to_z3950oid (odr, CLASS_DIAGSET, VAL_BIB1); - dr->condition = err; - dr->which = Z_DefaultDiagFormat_v2Addinfo; - dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : ""); - return dr; + return apdu; } /* * Set the specified `errcode' and `errstring' into a UserInfo-1 * external to be returned to the client in accordance with Z35.90 * Implementor Agreement 5 (Returning diagnostics in an InitResponse): - * http://lcweb.loc.gov/z3950/agency/agree/initdiag.html + * http://lcweb.loc.gov/z3950/agency/agree/initdiag.html */ -static Z_External *init_diagnostics(ODR odr, int error, char *addinfo) +static Z_External *init_diagnostics(ODR odr, int error, const char *addinfo) { - Z_External *x, *x2; - oident oid; - Z_OtherInformation *u; - Z_OtherInformationUnit *l; - Z_DiagnosticFormat *d; - Z_DiagnosticFormat_s *e; - - x = (Z_External*) odr_malloc(odr, sizeof *x); - x->descriptor = 0; - x->indirect_reference = 0; - oid.proto = PROTO_Z3950; - oid.oclass = CLASS_USERINFO; - oid.value = VAL_USERINFO1; - x->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid)); - x->which = Z_External_userInfo1; - - u = odr_malloc(odr, sizeof *u); - x->u.userInfo1 = u; - u->num_elements = 1; - u->list = (Z_OtherInformationUnit**) odr_malloc(odr, sizeof *u->list); - u->list[0] = (Z_OtherInformationUnit*) odr_malloc(odr, sizeof *u->list[0]); - l = u->list[0]; - l->category = 0; - l->which = Z_OtherInfo_externallyDefinedInfo; - - x2 = (Z_External*) odr_malloc(odr, sizeof *x); - l->information.externallyDefinedInfo = x2; - x2->descriptor = 0; - x2->indirect_reference = 0; - oid.oclass = CLASS_DIAGSET; - oid.value = VAL_DIAG1; - x2->direct_reference = odr_oiddup(odr, oid_getoidbyent(&oid)); - x2->which = Z_External_diag1; - - d = (Z_DiagnosticFormat*) odr_malloc(odr, sizeof *d); - x2->u.diag1 = d; - d->num = 1; - d->elements = (Z_DiagnosticFormat_s**) odr_malloc (odr, sizeof *d->elements); - d->elements[0] = (Z_DiagnosticFormat_s*) odr_malloc (odr, sizeof *d->elements[0]); - e = d->elements[0]; - - e->which = Z_DiagnosticFormat_s_defaultDiagRec; - e->u.defaultDiagRec = justdiag(odr, error, addinfo); - return x; + yaz_log(log_requestdetail, "[%d] %s%s%s", error, diagbib1_str(error), + addinfo ? " -- " : "", addinfo ? addinfo : ""); + return zget_init_diagnostics(odr, error, addinfo); } /* @@ -1642,204 +1484,175 @@ static Z_External *init_diagnostics(ODR odr, int error, char *addinfo) */ static Z_Records *diagrec(association *assoc, int error, char *addinfo) { - Z_Records *rec = (Z_Records *) - odr_malloc (assoc->encode, sizeof(*rec)); - rec->which = Z_Records_NSD; - rec->u.nonSurrogateDiagnostic = justdiag(assoc->encode, error, addinfo); - return rec; -} + Z_Records *rec = (Z_Records *) odr_malloc (assoc->encode, sizeof(*rec)); -/* - * surrogate diagnostic. - */ -static Z_NamePlusRecord *surrogatediagrec(association *assoc, char *dbname, - int error, char *addinfo) -{ - Z_NamePlusRecord *rec = (Z_NamePlusRecord *) - odr_malloc (assoc->encode, sizeof(*rec)); - Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec)); - - yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo); - rec->databaseName = dbname; - rec->which = Z_NamePlusRecord_surrogateDiagnostic; - rec->u.surrogateDiagnostic = drec; - drec->which = Z_DiagRec_defaultFormat; - drec->u.defaultFormat = justdiag(assoc->encode, error, addinfo); + yaz_log(log_requestdetail, "[%d] %s%s%s", error, diagbib1_str(error), + addinfo ? " -- " : "", addinfo ? addinfo : ""); + rec->which = Z_Records_NSD; + rec->u.nonSurrogateDiagnostic = zget_DefaultDiagFormat(assoc->encode, + error, addinfo); return rec; } /* - * multiple nonsurrogate diagnostics. + * surrogate diagnostic. */ -static Z_DiagRecs *diagrecs(association *assoc, int error, char *addinfo) +static Z_NamePlusRecord *surrogatediagrec(association *assoc, + const char *dbname, + int error, const char *addinfo) { - Z_DiagRecs *recs = (Z_DiagRecs *)odr_malloc (assoc->encode, sizeof(*recs)); - int *err = odr_intdup(assoc->encode, error); - Z_DiagRec **recp = (Z_DiagRec **)odr_malloc (assoc->encode, sizeof(*recp)); - Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec)); - Z_DefaultDiagFormat *rec = (Z_DefaultDiagFormat *) - odr_malloc (assoc->encode, sizeof(*rec)); - - yaz_log(LOG_DEBUG, "DiagRecs: %d -- %s", error, addinfo ? addinfo : ""); - - recs->num_diagRecs = 1; - recs->diagRecs = recp; - recp[0] = drec; - drec->which = Z_DiagRec_defaultFormat; - drec->u.defaultFormat = rec; - - rec->diagnosticSetId = - yaz_oidval_to_z3950oid (assoc->encode, CLASS_DIAGSET, VAL_BIB1); - rec->condition = err; - - rec->which = Z_DefaultDiagFormat_v2Addinfo; - rec->u.v2Addinfo = odr_strdup (assoc->encode, addinfo ? addinfo : ""); - return recs; + yaz_log(log_requestdetail, "[%d] %s%s%s", error, diagbib1_str(error), + addinfo ? " -- " : "", addinfo ? addinfo : ""); + return zget_surrogateDiagRec(assoc->encode, dbname, error, addinfo); } static Z_Records *pack_records(association *a, char *setname, int start, - int *num, Z_RecordComposition *comp, - int *next, int *pres, oid_value format, - Z_ReferenceId *referenceId, - int *oid) + int *num, Z_RecordComposition *comp, + int *next, int *pres, oid_value format, + Z_ReferenceId *referenceId, + int *oid, int *errcode) { int recno, total_length = 0, toget = *num, dumped_records = 0; Z_Records *records = - (Z_Records *) odr_malloc (a->encode, sizeof(*records)); + (Z_Records *) odr_malloc (a->encode, sizeof(*records)); Z_NamePlusRecordList *reclist = - (Z_NamePlusRecordList *) odr_malloc (a->encode, sizeof(*reclist)); + (Z_NamePlusRecordList *) odr_malloc (a->encode, sizeof(*reclist)); Z_NamePlusRecord **list = - (Z_NamePlusRecord **) odr_malloc (a->encode, sizeof(*list) * toget); + (Z_NamePlusRecord **) odr_malloc (a->encode, sizeof(*list) * toget); records->which = Z_Records_DBOSD; records->u.databaseOrSurDiagnostics = reclist; reclist->num_records = 0; reclist->records = list; - *pres = Z_PRES_SUCCESS; + *pres = Z_PresentStatus_success; *num = 0; *next = 0; - yaz_log(LOG_LOG, "Request to pack %d+%d+%s", start, toget, setname); - yaz_log(LOG_DEBUG, "pms=%d, mrs=%d", a->preferredMessageSize, - a->maximumRecordSize); + yaz_log(log_requestdetail, "Request to pack %d+%d %s", start, toget, setname); + yaz_log(log_requestdetail, "pms=%d, mrs=%d", a->preferredMessageSize, + a->maximumRecordSize); for (recno = start; reclist->num_records < toget; recno++) { - bend_fetch_rr freq; - Z_NamePlusRecord *thisrec; - int this_length = 0; - /* - * we get the number of bytes allocated on the stream before any - * allocation done by the backend - this should give us a reasonable - * idea of the total size of the data so far. - */ - total_length = odr_total(a->encode) - dumped_records; - freq.errcode = 0; - freq.errstring = 0; - freq.basename = 0; - freq.len = 0; - freq.record = 0; - freq.last_in_set = 0; - freq.setname = setname; - freq.surrogate_flag = 0; - freq.number = recno; - freq.comp = comp; - freq.request_format = format; - freq.request_format_raw = oid; - freq.output_format = format; - freq.output_format_raw = 0; - freq.stream = a->encode; - freq.print = a->print; - freq.referenceId = referenceId; + bend_fetch_rr freq; + Z_NamePlusRecord *thisrec; + int this_length = 0; + /* + * we get the number of bytes allocated on the stream before any + * allocation done by the backend - this should give us a reasonable + * idea of the total size of the data so far. + */ + total_length = odr_total(a->encode) - dumped_records; + freq.errcode = 0; + freq.errstring = 0; + freq.basename = 0; + freq.len = 0; + freq.record = 0; + freq.last_in_set = 0; + freq.setname = setname; + freq.surrogate_flag = 0; + freq.number = recno; + freq.comp = comp; + freq.request_format = format; + freq.request_format_raw = oid; + freq.output_format = format; + freq.output_format_raw = 0; + freq.stream = a->encode; + freq.print = a->print; + freq.referenceId = referenceId; freq.schema = 0; - (*a->init->bend_fetch)(a->backend, &freq); - /* backend should be able to signal whether error is system-wide - or only pertaining to current record */ - if (freq.errcode) - { - if (!freq.surrogate_flag) - { - char s[20]; - *pres = Z_PRES_FAILURE; - /* for 'present request out of range', + (*a->init->bend_fetch)(a->backend, &freq); + /* backend should be able to signal whether error is system-wide + or only pertaining to current record */ + if (freq.errcode) + { + if (!freq.surrogate_flag) + { + char s[20]; + *pres = Z_PresentStatus_failure; + /* for 'present request out of range', set addinfo to record position if not set */ - if (freq.errcode == 13 && freq.errstring == 0) - { - sprintf (s, "%d", recno); - freq.errstring = s; - } - return diagrec(a, freq.errcode, freq.errstring); - } - reclist->records[reclist->num_records] = - surrogatediagrec(a, freq.basename, freq.errcode, - freq.errstring); - reclist->num_records++; - *next = freq.last_in_set ? 0 : recno + 1; - continue; - } - if (freq.len >= 0) - this_length = freq.len; - else - this_length = odr_total(a->encode) - total_length; - yaz_log(LOG_DEBUG, " fetched record, len=%d, total=%d", - this_length, total_length); - if (this_length + total_length > a->preferredMessageSize) - { - /* record is small enough, really */ - if (this_length <= a->preferredMessageSize) - { - yaz_log(LOG_DEBUG, " Dropped last normal-sized record"); - *pres = Z_PRES_PARTIAL_2; - break; - } - /* record can only be fetched by itself */ - if (this_length < a->maximumRecordSize) - { - yaz_log(LOG_DEBUG, " Record > prefmsgsz"); - if (toget > 1) - { - yaz_log(LOG_DEBUG, " Dropped it"); - reclist->records[reclist->num_records] = - surrogatediagrec(a, freq.basename, 16, 0); - reclist->num_records++; - *next = freq.last_in_set ? 0 : recno + 1; - dumped_records += this_length; - continue; - } - } - else /* too big entirely */ - { - yaz_log(LOG_LOG, "Record > maxrcdsz this=%d max=%d", this_length, a->maximumRecordSize); - reclist->records[reclist->num_records] = - surrogatediagrec(a, freq.basename, 17, 0); - reclist->num_records++; - *next = freq.last_in_set ? 0 : recno + 1; - dumped_records += this_length; - continue; - } - } - - if (!(thisrec = (Z_NamePlusRecord *) - odr_malloc(a->encode, sizeof(*thisrec)))) - return 0; - if (!(thisrec->databaseName = (char *)odr_malloc(a->encode, - strlen(freq.basename) + 1))) - return 0; - strcpy(thisrec->databaseName, freq.basename); - thisrec->which = Z_NamePlusRecord_databaseRecord; - - if (freq.output_format_raw) - { - struct oident *ident = oid_getentbyoid(freq.output_format_raw); - freq.output_format = ident->value; - } - thisrec->u.databaseRecord = z_ext_record(a->encode, freq.output_format, - freq.record, freq.len); - if (!thisrec->u.databaseRecord) - return 0; - reclist->records[reclist->num_records] = thisrec; - reclist->num_records++; - *next = freq.last_in_set ? 0 : recno + 1; + if (freq.errcode == 13 && freq.errstring == 0) + { + sprintf (s, "%d", recno); + freq.errstring = s; + } + if (errcode) + *errcode = freq.errcode; + return diagrec(a, freq.errcode, freq.errstring); + } + reclist->records[reclist->num_records] = + surrogatediagrec(a, freq.basename, freq.errcode, + freq.errstring); + reclist->num_records++; + *next = freq.last_in_set ? 0 : recno + 1; + continue; + } + if (freq.len >= 0) + this_length = freq.len; + else + this_length = odr_total(a->encode) - total_length - dumped_records; + yaz_log(YLOG_DEBUG, " fetched record, len=%d, total=%d dumped=%d", + this_length, total_length, dumped_records); + if (a->preferredMessageSize > 0 && + this_length + total_length > a->preferredMessageSize) + { + /* record is small enough, really */ + if (this_length <= a->preferredMessageSize && recno > start) + { + yaz_log(log_requestdetail, " Dropped last normal-sized record"); + *pres = Z_PresentStatus_partial_2; + break; + } + /* record can only be fetched by itself */ + if (this_length < a->maximumRecordSize) + { + yaz_log(log_requestdetail, " Record > prefmsgsz"); + if (toget > 1) + { + yaz_log(YLOG_DEBUG, " Dropped it"); + reclist->records[reclist->num_records] = + surrogatediagrec(a, freq.basename, 16, 0); + reclist->num_records++; + *next = freq.last_in_set ? 0 : recno + 1; + dumped_records += this_length; + continue; + } + } + else /* too big entirely */ + { + yaz_log(log_requestdetail, "Record > maxrcdsz this=%d max=%d", + this_length, a->maximumRecordSize); + reclist->records[reclist->num_records] = + surrogatediagrec(a, freq.basename, 17, 0); + reclist->num_records++; + *next = freq.last_in_set ? 0 : recno + 1; + dumped_records += this_length; + continue; + } + } + + if (!(thisrec = (Z_NamePlusRecord *) + odr_malloc(a->encode, sizeof(*thisrec)))) + return 0; + if (!(thisrec->databaseName = (char *)odr_malloc(a->encode, + strlen(freq.basename) + 1))) + return 0; + strcpy(thisrec->databaseName, freq.basename); + thisrec->which = Z_NamePlusRecord_databaseRecord; + + if (freq.output_format_raw) + { + struct oident *ident = oid_getentbyoid(freq.output_format_raw); + freq.output_format = ident->value; + } + thisrec->u.databaseRecord = z_ext_record(a->encode, freq.output_format, + freq.record, freq.len); + if (!thisrec->u.databaseRecord) + return 0; + reclist->records[reclist->num_records] = thisrec; + reclist->num_records++; + *next = freq.last_in_set ? 0 : recno + 1; } *num = reclist->num_records; return records; @@ -1850,42 +1663,48 @@ static Z_APDU *process_searchRequest(association *assoc, request *reqb, { Z_SearchRequest *req = reqb->apdu_request->u.searchRequest; bend_search_rr *bsrr = - (bend_search_rr *)nmem_malloc (reqb->request_mem, sizeof(*bsrr)); + (bend_search_rr *)nmem_malloc (reqb->request_mem, sizeof(*bsrr)); - yaz_log(LOG_LOG, "Got SearchRequest."); + yaz_log(log_requestdetail, "Got SearchRequest."); bsrr->fd = fd; bsrr->request = reqb; bsrr->association = assoc; bsrr->referenceId = req->referenceId; save_referenceId (reqb, bsrr->referenceId); - yaz_log (LOG_LOG, "ResultSet '%s'", req->resultSetName); + yaz_log (log_requestdetail, "ResultSet '%s'", req->resultSetName); if (req->databaseNames) { - int i; - for (i = 0; i < req->num_databaseNames; i++) - yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]); + int i; + for (i = 0; i < req->num_databaseNames; i++) + yaz_log (log_requestdetail, "Database '%s'", req->databaseNames[i]); } - yaz_log_zquery(req->query); + + yaz_log_zquery_level(log_requestdetail,req->query); if (assoc->init->bend_search) { - bsrr->setname = req->resultSetName; - bsrr->replace_set = *req->replaceIndicator; - bsrr->num_bases = req->num_databaseNames; - bsrr->basenames = req->databaseNames; - bsrr->query = req->query; - bsrr->stream = assoc->encode; - nmem_transfer(bsrr->stream->mem, reqb->request_mem); - bsrr->decode = assoc->decode; - bsrr->print = assoc->print; - bsrr->errcode = 0; - bsrr->hits = 0; - bsrr->errstring = NULL; + bsrr->setname = req->resultSetName; + bsrr->replace_set = *req->replaceIndicator; + bsrr->num_bases = req->num_databaseNames; + bsrr->basenames = req->databaseNames; + bsrr->query = req->query; + bsrr->stream = assoc->encode; + nmem_transfer(bsrr->stream->mem, reqb->request_mem); + bsrr->decode = assoc->decode; + bsrr->print = assoc->print; + bsrr->errcode = 0; + bsrr->hits = 0; + bsrr->errstring = NULL; bsrr->search_info = NULL; - (assoc->init->bend_search)(assoc->backend, bsrr); - if (!bsrr->request) - return 0; + (assoc->init->bend_search)(assoc->backend, bsrr); + if (!bsrr->request) /* backend not ready with the search response */ + return 0; /* should not be used any more */ + } + else + { + /* FIXME - make a diagnostic for it */ + yaz_log(YLOG_WARN,"Search not supported ?!?!"); } return response_searchRequest(assoc, reqb, bsrr, fd); } @@ -1905,11 +1724,12 @@ static Z_APDU *response_searchRequest(association *assoc, request *reqb, Z_SearchRequest *req = reqb->apdu_request->u.searchRequest; Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu)); Z_SearchResponse *resp = (Z_SearchResponse *) - odr_malloc (assoc->encode, sizeof(*resp)); + odr_malloc (assoc->encode, sizeof(*resp)); int *nulint = odr_intdup (assoc->encode, 0); bool_t *sr = odr_intdup(assoc->encode, 1); int *next = odr_intdup(assoc->encode, 0); - int *none = odr_intdup(assoc->encode, Z_RES_NONE); + int *none = odr_intdup(assoc->encode, Z_SearchResponse_none); + int returnedrecs=0; apdu->which = Z_APDU_searchResponse; apdu->u.searchResponse = resp; @@ -1919,81 +1739,99 @@ static Z_APDU *response_searchRequest(association *assoc, request *reqb, *fd = -1; if (!bsrt && !bend_searchresponse(assoc->backend, bsrt)) { - yaz_log(LOG_FATAL, "Bad result from backend"); - return 0; + yaz_log(YLOG_FATAL, "Bad result from backend"); + return 0; } else if (bsrt->errcode) { - resp->records = diagrec(assoc, bsrt->errcode, bsrt->errstring); - resp->resultCount = nulint; - resp->numberOfRecordsReturned = nulint; - resp->nextResultSetPosition = nulint; - resp->searchStatus = nulint; - resp->resultSetStatus = none; - resp->presentStatus = 0; + resp->records = diagrec(assoc, bsrt->errcode, bsrt->errstring); + resp->resultCount = nulint; + resp->numberOfRecordsReturned = nulint; + resp->nextResultSetPosition = nulint; + resp->searchStatus = nulint; + resp->resultSetStatus = none; + resp->presentStatus = 0; } else { - int *toget = odr_intdup(assoc->encode, 0); + int *toget = odr_intdup(assoc->encode, 0); int *presst = odr_intdup(assoc->encode, 0); - Z_RecordComposition comp, *compp = 0; - - yaz_log (LOG_LOG, "resultCount: %d", bsrt->hits); - - resp->records = 0; - resp->resultCount = &bsrt->hits; - - comp.which = Z_RecordComp_simple; - /* how many records does the user agent want, then? */ - if (bsrt->hits <= *req->smallSetUpperBound) - { - *toget = bsrt->hits; - if ((comp.u.simple = req->smallSetElementSetNames)) - compp = ∁ - } - else if (bsrt->hits < *req->largeSetLowerBound) - { - *toget = *req->mediumSetPresentNumber; - if (*toget > bsrt->hits) - *toget = bsrt->hits; - if ((comp.u.simple = req->mediumSetElementSetNames)) - compp = ∁ - } - else - *toget = 0; - - if (*toget && !resp->records) - { - oident *prefformat; - oid_value form; - - if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax))) - form = VAL_NONE; - else - form = prefformat->value; - resp->records = pack_records(assoc, req->resultSetName, 1, - toget, compp, next, presst, form, req->referenceId, - req->preferredRecordSyntax); - if (!resp->records) - return 0; - resp->numberOfRecordsReturned = toget; - resp->nextResultSetPosition = next; - resp->searchStatus = sr; - resp->resultSetStatus = 0; - resp->presentStatus = presst; - } - else - { - if (*resp->resultCount) - *next = 1; - resp->numberOfRecordsReturned = nulint; - resp->nextResultSetPosition = next; - resp->searchStatus = sr; - resp->resultSetStatus = 0; - resp->presentStatus = 0; - } + Z_RecordComposition comp, *compp = 0; + + yaz_log (log_requestdetail, "resultCount: %d", bsrt->hits); + + resp->records = 0; + resp->resultCount = &bsrt->hits; + + comp.which = Z_RecordComp_simple; + /* how many records does the user agent want, then? */ + if (bsrt->hits <= *req->smallSetUpperBound) + { + *toget = bsrt->hits; + if ((comp.u.simple = req->smallSetElementSetNames)) + compp = ∁ + } + else if (bsrt->hits < *req->largeSetLowerBound) + { + *toget = *req->mediumSetPresentNumber; + if (*toget > bsrt->hits) + *toget = bsrt->hits; + if ((comp.u.simple = req->mediumSetElementSetNames)) + compp = ∁ + } + else + *toget = 0; + + if (*toget && !resp->records) + { + oident *prefformat; + oid_value form; + + if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax))) + form = VAL_NONE; + else + form = prefformat->value; + resp->records = pack_records(assoc, req->resultSetName, 1, + toget, compp, next, presst, form, req->referenceId, + req->preferredRecordSyntax, NULL); + if (!resp->records) + return 0; + resp->numberOfRecordsReturned = toget; + returnedrecs = *toget; + resp->nextResultSetPosition = next; + resp->searchStatus = sr; + resp->resultSetStatus = 0; + resp->presentStatus = presst; + } + else + { + if (*resp->resultCount) + *next = 1; + resp->numberOfRecordsReturned = nulint; + resp->nextResultSetPosition = next; + resp->searchStatus = sr; + resp->resultSetStatus = 0; + resp->presentStatus = 0; + } } resp->additionalSearchInfo = bsrt->search_info; + + if (log_request) + { + WRBUF wr=wrbuf_alloc(); + wrbuf_put_zquery(wr, req->query); + if (bsrt->errcode) + wr_diag(wr, bsrt->errcode, bsrt->errstring); + else + { + wrbuf_printf(wr," OK:%d hits ", bsrt->hits); + if (returnedrecs) + wrbuf_printf(wr," %d records returned", returnedrecs); + } + yaz_log(log_request, "Search %s %s", req->resultSetName, + wrbuf_buf(wr)); + wrbuf_free(wr,1); + } return apdu; } @@ -2013,7 +1851,7 @@ static Z_APDU *response_searchRequest(association *assoc, request *reqb, * speed - which is normally more true for search than for present. */ static Z_APDU *process_presentRequest(association *assoc, request *reqb, - int *fd) + int *fd) { Z_PresentRequest *req = reqb->apdu_request->u.presentRequest; oident *prefformat; @@ -2022,41 +1860,45 @@ static Z_APDU *process_presentRequest(association *assoc, request *reqb, Z_PresentResponse *resp; int *next; int *num; + int errcode = 0; + const char *errstring = 0; - yaz_log(LOG_LOG, "Got PresentRequest."); + yaz_log(log_requestdetail, "Got PresentRequest."); if (!(prefformat = oid_getentbyoid(req->preferredRecordSyntax))) - form = VAL_NONE; + form = VAL_NONE; else - form = prefformat->value; + form = prefformat->value; resp = (Z_PresentResponse *)odr_malloc (assoc->encode, sizeof(*resp)); resp->records = 0; resp->presentStatus = odr_intdup(assoc->encode, 0); if (assoc->init->bend_present) { - bend_present_rr *bprr = (bend_present_rr *) - nmem_malloc (reqb->request_mem, sizeof(*bprr)); - bprr->setname = req->resultSetId; - bprr->start = *req->resultSetStartPoint; - bprr->number = *req->numberOfRecordsRequested; - bprr->format = form; - bprr->comp = req->recordComposition; - bprr->referenceId = req->referenceId; - bprr->stream = assoc->encode; - bprr->print = assoc->print; - bprr->request = reqb; - bprr->association = assoc; - bprr->errcode = 0; - bprr->errstring = NULL; - (*assoc->init->bend_present)(assoc->backend, bprr); - - if (!bprr->request) - return 0; - if (bprr->errcode) - { - resp->records = diagrec(assoc, bprr->errcode, bprr->errstring); - *resp->presentStatus = Z_PRES_FAILURE; - } + bend_present_rr *bprr = (bend_present_rr *) + nmem_malloc (reqb->request_mem, sizeof(*bprr)); + bprr->setname = req->resultSetId; + bprr->start = *req->resultSetStartPoint; + bprr->number = *req->numberOfRecordsRequested; + bprr->format = form; + bprr->comp = req->recordComposition; + bprr->referenceId = req->referenceId; + bprr->stream = assoc->encode; + bprr->print = assoc->print; + bprr->request = reqb; + bprr->association = assoc; + bprr->errcode = 0; + bprr->errstring = NULL; + (*assoc->init->bend_present)(assoc->backend, bprr); + + if (!bprr->request) + return 0; /* should not happen */ + if (bprr->errcode) + { + resp->records = diagrec(assoc, bprr->errcode, bprr->errstring); + *resp->presentStatus = Z_PresentStatus_failure; + errcode = bprr->errcode; + errstring = bprr->errstring; + } } apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu)); next = odr_intdup(assoc->encode, 0); @@ -2069,14 +1911,32 @@ static Z_APDU *process_presentRequest(association *assoc, request *reqb, if (!resp->records) { - *num = *req->numberOfRecordsRequested; - resp->records = - pack_records(assoc, req->resultSetId, *req->resultSetStartPoint, - num, req->recordComposition, next, resp->presentStatus, - form, req->referenceId, req->preferredRecordSyntax); + *num = *req->numberOfRecordsRequested; + resp->records = + pack_records(assoc, req->resultSetId, *req->resultSetStartPoint, + num, req->recordComposition, next, + resp->presentStatus, + form, req->referenceId, req->preferredRecordSyntax, + &errcode); + } + if (log_request) + { + WRBUF wr = wrbuf_alloc(); + wrbuf_printf(wr, "Present %s %d+%d ", + req->resultSetId, *req->resultSetStartPoint, + *req->numberOfRecordsRequested); + if (*resp->presentStatus == Z_PresentStatus_failure) + wr_diag(wr, errcode, errstring); + else if (*resp->presentStatus == Z_PresentStatus_success) + wrbuf_printf(wr," OK %d records returned ", *num); + else + wrbuf_printf(wr," Partial (%d) OK %d records returned ", + *resp->presentStatus, *num); + yaz_log(log_request, "%s", wrbuf_buf(wr) ); + wrbuf_free(wr, 1); } if (!resp->records) - return 0; + return 0; resp->numberOfRecordsReturned = num; resp->nextResultSetPosition = next; @@ -2092,18 +1952,18 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) Z_ScanRequest *req = reqb->apdu_request->u.scanRequest; Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu)); Z_ScanResponse *res = (Z_ScanResponse *) - odr_malloc (assoc->encode, sizeof(*res)); + odr_malloc (assoc->encode, sizeof(*res)); int *scanStatus = odr_intdup(assoc->encode, Z_Scan_failure); int *numberOfEntriesReturned = odr_intdup(assoc->encode, 0); Z_ListEntries *ents = (Z_ListEntries *) - odr_malloc (assoc->encode, sizeof(*ents)); + odr_malloc (assoc->encode, sizeof(*ents)); Z_DiagRecs *diagrecs_p = NULL; oident *attset; bend_scan_rr *bsrr = (bend_scan_rr *) odr_malloc (assoc->encode, sizeof(*bsrr)); struct scan_entry *save_entries; - yaz_log(LOG_LOG, "Got ScanRequest"); + yaz_log(log_requestdetail, "Got ScanRequest"); apdu->which = Z_APDU_scanResponse; apdu->u.scanResponse = res; @@ -2112,7 +1972,7 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) /* if step is absent, set it to 0 */ res->stepSize = odr_intdup(assoc->encode, 0); if (req->stepSize) - *res->stepSize = *req->stepSize; + *res->stepSize = *req->stepSize; res->scanStatus = scanStatus; res->numberOfEntriesReturned = numberOfEntriesReturned; @@ -2129,8 +1989,11 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) { int i; for (i = 0; i < req->num_databaseNames; i++) - yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]); + yaz_log (log_requestdetail, "Database '%s'", req->databaseNames[i]); } + yaz_log(log_requestdetail, "pos %d step %d entries %d", + *req->preferredPositionInResponse, *res->stepSize, + *req->numberOfTermsRequested); bsrr->num_bases = req->num_databaseNames; bsrr->basenames = req->databaseNames; bsrr->num_entries = *req->numberOfTermsRequested; @@ -2167,13 +2030,17 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) bsrr->attributeset = attset->value; else bsrr->attributeset = VAL_NONE; - log_scan_term (req->termListAndStartPoint, bsrr->attributeset); + log_scan_term_level (log_requestdetail, req->termListAndStartPoint, + bsrr->attributeset); bsrr->term_position = req->preferredPositionInResponse ? *req->preferredPositionInResponse : 1; + ((int (*)(void *, bend_scan_rr *)) (*assoc->init->bend_scan))(assoc->backend, bsrr); + if (bsrr->errcode) - diagrecs_p = diagrecs(assoc, bsrr->errcode, bsrr->errstring); + diagrecs_p = zget_DiagRecs(assoc->encode, + bsrr->errcode, bsrr->errstring); else { int i; @@ -2186,7 +2053,7 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) *scanStatus = Z_Scan_success; ents->entries = tab; ents->num_entries = bsrr->num_entries; - res->numberOfEntriesReturned = &ents->num_entries; + res->numberOfEntriesReturned = &ents->num_entries; res->positionOfTerm = &bsrr->term_position; for (i = 0; i < bsrr->num_entries; i++) { @@ -2225,14 +2092,14 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) odr_malloc(assoc->encode, o->len = o->size = strlen(bsrr->entries[i].term)); memcpy(o->buf, bsrr->entries[i].term, o->len); - yaz_log(LOG_DEBUG, " term #%d: '%s' (%d)", i, - bsrr->entries[i].term, bsrr->entries[i].occurrences); + yaz_log(YLOG_DEBUG, " term #%d: '%s' (%d)", i, + bsrr->entries[i].term, bsrr->entries[i].occurrences); } else { - Z_DiagRecs *drecs = diagrecs (assoc, - bsrr->entries[i].errcode, - bsrr->entries[i].errstring); + Z_DiagRecs *drecs = zget_DiagRecs(assoc->encode, + bsrr->entries[i].errcode, + bsrr->entries[i].errstring); assert (drecs->num_diagRecs == 1); e->which = Z_Entry_surrogateDiagnostic; assert (drecs->diagRecs[0]); @@ -2242,8 +2109,28 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) } if (diagrecs_p) { - ents->num_nonsurrogateDiagnostics = diagrecs_p->num_diagRecs; - ents->nonsurrogateDiagnostics = diagrecs_p->diagRecs; + ents->num_nonsurrogateDiagnostics = diagrecs_p->num_diagRecs; + ents->nonsurrogateDiagnostics = diagrecs_p->diagRecs; + } + if (log_request) + { + WRBUF wr=wrbuf_alloc(); + wrbuf_printf(wr, "Scan %d@%d ", + *req->preferredPositionInResponse, + *req->numberOfTermsRequested); + if (*res->stepSize) + wrbuf_printf(wr, "(step %d) ",*res->stepSize); + wrbuf_scan_term(wr, req->termListAndStartPoint, + bsrr->attributeset); + + if (*res->scanStatus == Z_Scan_success) + { + wrbuf_printf(wr," OK"); + } + else + wrbuf_printf(wr," Error"); + yaz_log(log_request, "%s", wrbuf_buf(wr) ); + wrbuf_free(wr,1); } return apdu; } @@ -2251,25 +2138,32 @@ static Z_APDU *process_scanRequest(association *assoc, request *reqb, int *fd) static Z_APDU *process_sortRequest(association *assoc, request *reqb, int *fd) { + int i; Z_SortRequest *req = reqb->apdu_request->u.sortRequest; Z_SortResponse *res = (Z_SortResponse *) - odr_malloc (assoc->encode, sizeof(*res)); + odr_malloc (assoc->encode, sizeof(*res)); bend_sort_rr *bsrr = (bend_sort_rr *) - odr_malloc (assoc->encode, sizeof(*bsrr)); + odr_malloc (assoc->encode, sizeof(*bsrr)); Z_APDU *apdu = (Z_APDU *)odr_malloc (assoc->encode, sizeof(*apdu)); - yaz_log(LOG_LOG, "Got SortRequest."); + yaz_log(log_requestdetail, "Got SortRequest."); bsrr->num_input_setnames = req->num_inputResultSetNames; + for (i=0;i