/* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2012 Index Data
+ * Copyright (C) Index Data
* See the file LICENSE for details.
*/
/**
#include <yaz/log.h>
#include <yaz/pquery.h>
-void handle_facet_list(ZOOM_resultset r, Z_FacetList *fl);
-
#if YAZ_HAVE_XML2
static void set_SRU_error(ZOOM_connection c, Z_SRW_diagnostic *d)
{
static zoom_ret send_srw(ZOOM_connection c, Z_SRW_PDU *sr)
{
Z_GDU *gdu;
- ZOOM_Event event;
const char *database = ZOOM_options_get(c->options, "databaseName");
gdu = z_get_HTTP_Request_uri(c->odr_out, c->host_port,
{
yaz_solr_encode_request(gdu->u.HTTP_Request, sr, c->odr_out, c->charset);
}
- if (!z_GDU(c->odr_out, &gdu, 0, 0))
- return zoom_complete;
- if (c->odr_print)
- z_GDU(c->odr_print, &gdu, 0, 0);
- if (c->odr_save)
- z_GDU(c->odr_save, &gdu, 0, 0);
- c->buf_out = odr_getbuf(c->odr_out, &c->len_out, 0);
-
- event = ZOOM_Event_create(ZOOM_EVENT_SEND_APDU);
- ZOOM_connection_put_event(c, event);
- odr_reset(c->odr_out);
- return ZOOM_send_buf(c);
+ return ZOOM_send_GDU(c, gdu);
}
#endif
static Z_SRW_PDU *ZOOM_srw_get_pdu(ZOOM_connection c, int type)
{
Z_SRW_PDU *sr = yaz_srw_get_pdu(c->odr_out, type, c->sru_version);
- sr->username = c->user;
- sr->password = c->password;
+ if (c->url_authentication && c->user)
+ {
+ Z_SRW_extra_arg **ea = &sr->extra_args;
+ while (*ea)
+ ea = &(*ea)->next;
+ *ea = (Z_SRW_extra_arg *) odr_malloc(c->odr_out, sizeof(**ea));
+ (*ea)->name = "x-username";
+ (*ea)->value = c->user;
+ ea = &(*ea)->next;
+ if (c->password)
+ {
+ *ea = (Z_SRW_extra_arg *) odr_malloc(c->odr_out, sizeof(**ea));
+ (*ea)->name = "x-password";
+ (*ea)->value = c->password;
+ ea = &(*ea)->next;
+ }
+ *ea = 0;
+ }
+ else
+ {
+ sr->username = c->user;
+ sr->password = c->password;
+ }
return sr;
}
#endif
/* SRU scan can only carry CQL and PQF */
if (z_query->which == Z_Query_type_104)
{
- sr->u.scan_request->query_type = Z_SRW_query_type_cql;
- sr->u.scan_request->scanClause.cql =
+ sr->u.scan_request->queryType = "cql";
+ sr->u.scan_request->scanClause =
odr_strdup(c->odr_out, ZOOM_query_get_query_string(scan->query));
}
else if (z_query->which == Z_Query_type_1
|| z_query->which == Z_Query_type_101)
{
- sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
- sr->u.scan_request->scanClause.pqf =
+ sr->u.scan_request->queryType = "pqf";
+ sr->u.scan_request->scanClause =
odr_strdup(c->odr_out, ZOOM_query_get_query_string(scan->query));
}
else
#if YAZ_HAVE_XML2
zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
{
- const char *facets = 0;
int i;
int *start, *count;
ZOOM_resultset resultset = 0;
Z_SRW_PDU *sr = 0;
const char *option_val = 0;
+ const char *schema = 0;
Z_Query *z_query;
Z_FacetList *facet_list = 0;
+
if (c->error) /* don't continue on error */
return zoom_complete;
assert(c->tasks);
- switch(c->tasks->which)
- {
- case ZOOM_TASK_SEARCH:
- resultset = c->tasks->u.search.resultset;
- if (!resultset->setname)
- resultset->setname = xstrdup("default");
- ZOOM_options_set(resultset->options, "setname", resultset->setname);
- start = &c->tasks->u.search.start;
- count = &c->tasks->u.search.count;
- facets = ZOOM_options_get(resultset->options, "facets");
- if (facets)
- facet_list = yaz_pqf_parse_facet_list(c->odr_out, facets);
- break;
- case ZOOM_TASK_RETRIEVE:
- resultset = c->tasks->u.retrieve.resultset;
-
- start = &c->tasks->u.retrieve.start;
- count = &c->tasks->u.retrieve.count;
+ if (c->tasks->which != ZOOM_TASK_SEARCH)
+ return zoom_complete;
+ resultset = c->tasks->u.search.resultset;
+
+ ZOOM_memcached_search(c, resultset);
+
+ if (!resultset->setname)
+ resultset->setname = odr_strdup(resultset->odr, "default");
+ ZOOM_options_set(resultset->options, "setname", resultset->setname);
+ start = &c->tasks->u.search.start;
+ count = &c->tasks->u.search.count;
+ if (resultset->req_facets)
+ facet_list = yaz_pqf_parse_facet_list(c->odr_out,
+ resultset->req_facets);
+ schema = c->tasks->u.search.schema;
+
+ if (resultset->live_set)
+ {
if (*start >= resultset->size)
return zoom_complete;
if (*start + *count > resultset->size)
*count = resultset->size - *start;
+ }
+ for (i = 0; i < *count; i++)
+ {
+ ZOOM_record rec =
+ ZOOM_record_cache_lookup(resultset, i + *start,
+ c->tasks->u.search.syntax,
+ c->tasks->u.search.elementSetName,
+ schema);
+ if (!rec)
+ break;
+ }
+ *start += i;
+ *count -= i;
- for (i = 0; i < *count; i++)
- {
- ZOOM_record rec =
- ZOOM_record_cache_lookup(resultset, i + *start,
- c->tasks->u.retrieve.syntax,
- c->tasks->u.retrieve.elementSetName);
- if (!rec)
- break;
- else
- {
- ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
- ZOOM_connection_put_event(c, event);
- }
- }
- *start += i;
- *count -= i;
-
- if (*count == 0)
- return zoom_complete;
- break;
- default:
+ if (*count == 0 && resultset->live_set)
return zoom_complete;
- }
+
assert(resultset->query);
sr = ZOOM_srw_get_pdu(c, Z_SRW_searchRetrieve_request);
if (z_query->which == Z_Query_type_104
&& z_query->u.type_104->which == Z_External_CQL)
{
- sr->u.request->query_type = Z_SRW_query_type_cql;
- sr->u.request->query.cql = z_query->u.type_104->u.cql;
+ sr->u.request->queryType = "cql";
+ sr->u.request->query = z_query->u.type_104->u.cql;
}
else if (z_query->which == Z_Query_type_1 && z_query->u.type_1)
{
- sr->u.request->query_type = Z_SRW_query_type_pqf;
- sr->u.request->query.pqf =
+ sr->u.request->queryType = "pqf";
+ sr->u.request->query =
odr_strdup(c->odr_out,
ZOOM_query_get_query_string(resultset->query));
}
sr->u.request->maximumRecords = odr_intdup(
c->odr_out, (resultset->step > 0 && resultset->step < *count) ?
resultset->step : *count);
- sr->u.request->recordSchema = resultset->schema;
+ sr->u.request->recordSchema = odr_strdup_null(c->odr_out, schema);
sr->u.request->facetList = facet_list;
option_val = ZOOM_resultset_option_get(resultset, "recordPacking");
Z_SRW_searchRetrieveResponse *res)
{
ZOOM_resultset resultset = 0;
+ int *start, *count;
int i;
NMEM nmem;
ZOOM_Event event;
- int *start, *count;
- const char *syntax, *elementSetName;
+ const char *syntax, *elementSetName, *schema;
if (!c->tasks)
return zoom_complete;
- switch(c->tasks->which)
- {
- case ZOOM_TASK_SEARCH:
- resultset = c->tasks->u.search.resultset;
- start = &c->tasks->u.search.start;
- count = &c->tasks->u.search.count;
- syntax = c->tasks->u.search.syntax;
- elementSetName = c->tasks->u.search.elementSetName;
-
- /* Required not for reporting client hit count multiple times into session */
- if (!c->tasks->u.search.recv_search_fired) {
- yaz_log(YLOG_DEBUG, "posting ZOOM_EVENT_RECV_SEARCH");
- event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
- ZOOM_connection_put_event(c, event);
- c->tasks->u.search.recv_search_fired = 1;
- }
- if (res->facetList)
- handle_facet_list(resultset, res->facetList);
- break;
- case ZOOM_TASK_RETRIEVE:
- resultset = c->tasks->u.retrieve.resultset;
- start = &c->tasks->u.retrieve.start;
- count = &c->tasks->u.retrieve.count;
- syntax = c->tasks->u.retrieve.syntax;
- elementSetName = c->tasks->u.retrieve.elementSetName;
- break;
- default:
+ if (c->tasks->which != ZOOM_TASK_SEARCH)
return zoom_complete;
+
+ resultset = c->tasks->u.search.resultset;
+ start = &c->tasks->u.search.start;
+ count = &c->tasks->u.search.count;
+ syntax = c->tasks->u.search.syntax;
+ elementSetName = c->tasks->u.search.elementSetName;
+ schema = c->tasks->u.search.schema;
+
+ if (resultset->live_set == 0)
+ {
+ event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
+ ZOOM_connection_put_event(c, event);
}
+ if (res->facetList)
+ ZOOM_handle_facet_list(resultset, res->facetList);
resultset->size = 0;
if (res->num_diagnostics > 0)
{
+ resultset->live_set = 2;
set_SRU_error(c, &res->diagnostics[0]);
}
else
{
- if (res->numberOfRecords) {
+ if (res->numberOfRecords)
+ {
+ Z_OtherInformation *oi = 0;
+ if (res->facetList)
+ {
+ ODR o = c->odr_in;
+ Z_External *ext = (Z_External *)
+ odr_malloc(o, sizeof(*ext));
+
+ ext->which = Z_External_userFacets;
+ ext->u.facetList = res->facetList;
+ ext->direct_reference =
+ odr_oiddup(o, yaz_oid_userinfo_facet_1);
+ ext->indirect_reference = 0;
+ ext->descriptor = 0;
+ oi = (Z_OtherInformation *) odr_malloc(o, sizeof(*oi));
+ oi->num_elements = 1;
+ oi->list = (Z_OtherInformationUnit **)
+ odr_malloc(o, sizeof(*oi->list));
+ oi->list[0] = (Z_OtherInformationUnit *)
+ odr_malloc(o, sizeof(**oi->list));
+ oi->list[0]->category = 0;
+ oi->list[0]->which = Z_OtherInfo_externallyDefinedInfo;
+ oi->list[0]->information.externallyDefinedInfo = ext;
+ }
resultset->size = *res->numberOfRecords;
+ ZOOM_memcached_hitcount(c, resultset, oi,
+ res->resultCountPrecision ?
+ res->resultCountPrecision : "exact");
}
- if (res->suggestions) {
- ZOOM_resultset_option_set(resultset, "suggestions", res->suggestions);
- }
- for (i = 0; i<res->num_records; i++)
+ resultset->live_set = 2;
+ if (res->suggestions)
+ ZOOM_resultset_option_set(resultset, "suggestions",
+ res->suggestions);
+ for (i = 0; i < res->num_records; i++)
{
- int pos;
+ int pos = c->tasks->u.search.start + i;
Z_SRW_record *sru_rec;
Z_SRW_diagnostic *diag = 0;
int num_diag;
- Z_NamePlusRecord *npr = (Z_NamePlusRecord *)
- odr_malloc(c->odr_in, sizeof(Z_NamePlusRecord));
-
- /* recordPosition is 1 based */
+ /* only trust recordPosition if >= calculated position */
if (res->records[i].recordPosition &&
- *res->records[i].recordPosition > 0)
+ *res->records[i].recordPosition >= pos + 1)
pos = *res->records[i].recordPosition - 1;
- else
- pos = *start + i;
-
- sru_rec = &res->records[i];
-
- npr->databaseName = 0;
- npr->which = Z_NamePlusRecord_databaseRecord;
- npr->u.databaseRecord = (Z_External *)
- odr_malloc(c->odr_in, sizeof(Z_External));
- npr->u.databaseRecord->descriptor = 0;
- npr->u.databaseRecord->direct_reference =
- odr_oiddup(c->odr_in, yaz_oid_recsyn_xml);
- npr->u.databaseRecord->indirect_reference = 0;
- npr->u.databaseRecord->which = Z_External_octet;
-
- npr->u.databaseRecord->u.octet_aligned = (Odr_oct *)
- odr_malloc(c->odr_in, sizeof(Odr_oct));
- npr->u.databaseRecord->u.octet_aligned->buf = (unsigned char*)
- sru_rec->recordData_buf;
- npr->u.databaseRecord->u.octet_aligned->len =
- npr->u.databaseRecord->u.octet_aligned->size =
- sru_rec->recordData_len;
-
- if (sru_rec->recordSchema
- && !strcmp(sru_rec->recordSchema,
- "info:srw/schema/1/diagnostics-v1.1"))
+
+ if (!ZOOM_record_cache_lookup(resultset,
+ pos,
+ syntax, elementSetName, schema))
{
- sru_decode_surrogate_diagnostics(sru_rec->recordData_buf,
- sru_rec->recordData_len,
- &diag, &num_diag,
- resultset->odr);
+ Z_NamePlusRecord *npr = (Z_NamePlusRecord *)
+ odr_malloc(c->odr_in, sizeof(Z_NamePlusRecord));
+ sru_rec = &res->records[i];
+
+ npr->databaseName = 0;
+ npr->which = Z_NamePlusRecord_databaseRecord;
+ npr->u.databaseRecord = (Z_External *)
+ odr_malloc(c->odr_in, sizeof(Z_External));
+ npr->u.databaseRecord->descriptor = 0;
+ npr->u.databaseRecord->direct_reference =
+ odr_oiddup(c->odr_in, yaz_oid_recsyn_xml);
+ npr->u.databaseRecord->indirect_reference = 0;
+ npr->u.databaseRecord->which = Z_External_octet;
+
+ npr->u.databaseRecord->u.octet_aligned =
+ odr_create_Odr_oct(c->odr_in,
+ sru_rec->recordData_buf,
+ sru_rec->recordData_len);
+ if (sru_rec->recordSchema
+ && !strcmp(sru_rec->recordSchema,
+ "info:srw/schema/1/diagnostics-v1.1"))
+ {
+ sru_decode_surrogate_diagnostics(sru_rec->recordData_buf,
+ sru_rec->recordData_len,
+ &diag, &num_diag,
+ resultset->odr);
+ }
+ ZOOM_record_cache_add(resultset, npr,
+ pos, syntax, elementSetName,
+ schema, diag);
}
- ZOOM_record_cache_add(resultset, npr, pos, syntax, elementSetName,
- sru_rec->recordSchema, diag);
}
*count -= i;
- *start += i;
- if (*count + *start > resultset->size)
- *count = resultset->size - *start;
- yaz_log(YLOG_DEBUG, "SRU result set size " ODR_INT_PRINTF " start %d count %d", resultset->size, *start, *count);
if (*count < 0)
*count = 0;
+ *start += i;
nmem = odr_extract_mem(c->odr_in);
nmem_transfer(odr_getmem(resultset->odr), nmem);
nmem_destroy(nmem);
- if (*count > 0)
- return ZOOM_connection_srw_send_search(c);
+ return ZOOM_connection_srw_send_search(c);
}
return zoom_complete;
}
Z_SRW_PDU *sr;
ret = yaz_solr_decode_response(c->odr_in, hres, &sr);
if (ret == 0)
+ {
if (sr->which == Z_SRW_searchRetrieve_response)
*cret = handle_srw_response(c, sr->u.response);
+ else if (sr->which == Z_SRW_scan_response)
+ handle_srw_scan_response(c, sr->u.scan_response);
+ }
}
else
{
Z_SOAP *soap_package = 0;
ODR o = c->odr_in;
- Z_SOAP_Handler soap_handlers[3] = {
- {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
- {YAZ_XMLNS_SRU_v2_response, 0, (Z_SOAP_fun) yaz_srw_codec},
+ Z_SOAP_Handler soap_handlers[4] = {
+ {YAZ_XMLNS_SRU_v1_response, 0, (Z_SOAP_fun) yaz_srw_codec},
+ {YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec},
+ {"searchRetrieveResponse", 0, (Z_SOAP_fun) yaz_srw_codec},
{0, 0, 0}
};
ret = z_soap_codec(o, &soap_package,