#if HAVE_UNISTD_H
#include <unistd.h>
#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_NETDB_H
-#include <netdb.h>
-#endif
#include <signal.h>
-#include <ctype.h>
#include <assert.h>
#include <yaz/marcdisp.h>
#include <yaz/oid_db.h>
#include <yaz/diagbib1.h>
#include <yaz/snprintf.h>
+#include <yaz/rpn2cql.h>
#define USE_TIMING 0
#if USE_TIMING
#include <yaz/timing.h>
#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
#include "pazpar2.h"
#include "client.h"
struct connection *connection;
struct session *session;
char *pquery; // Current search
+ char *cqlquery; // used for SRU targets only
int hits;
- int records;
- int setno;
- int requestid; // ID of current outstanding request
+ int record_offset;
int diagnostic;
enum client_state state;
struct show_raw *show_raw;
static const char *client_states[] = {
"Client_Connecting",
- "Client_Connected",
"Client_Idle",
- "Client_Initializing",
- "Client_Searching",
- "Client_Presenting",
+ "Client_Working",
"Client_Error",
"Client_Failed",
- "Client_Disconnected",
- "Client_Stopped",
- "Client_Continue"
+ "Client_Disconnected"
};
static struct client *client_freelist = 0;
// Close connection and set state to error
void client_fatal(struct client *cl)
{
- //client_show_raw_error(cl, "client connection failure");
yaz_log(YLOG_WARN, "Fatal error from %s", client_get_url(cl));
connection_destroy(cl->connection);
client_set_state(cl, Client_Error);
return cl->pquery;
}
-void client_set_requestid(struct client *cl, int id)
-{
- cl->requestid = id;
-}
-
-
static void client_send_raw_present(struct client *cl);
int client_show_raw_begin(struct client *cl, int position,
if (ZOOM_connection_error(link, &error, &addinfo))
{
cl->hits = 0;
- cl->state = Client_Error;
+ client_set_state(cl, Client_Error);
yaz_log(YLOG_WARN, "Search error %s (%s): %s",
error, addinfo, client_get_url(cl));
}
else
{
+ cl->record_offset = 0;
cl->hits = ZOOM_resultset_size(resultset);
se->total_hits += cl->hits;
}
ZOOM_resultset resultset = connection_get_resultset(co);
const char *error, *addinfo;
- yaz_log(YLOG_LOG, "client_record_response");
if (ZOOM_connection_error(link, &error, &addinfo))
{
- cl->state = Client_Error;
+ client_set_state(cl, Client_Error);
yaz_log(YLOG_WARN, "Search error %s (%s): %s",
error, addinfo, client_get_url(cl));
}
cl->show_raw->active = 0;
ingest_raw_record(cl, rec);
}
+ else
+ {
+ yaz_log(YLOG_WARN, "Expected record, but got NULL, offset=%d",
+ cl->show_raw->position-1);
+ }
}
else
{
- int offset = cl->records;
+ int offset = cl->record_offset;
if ((rec = ZOOM_resultset_record(resultset, offset)))
{
- yaz_log(YLOG_LOG, "Record with offset %d", offset);
-
- cl->records++;
+ cl->record_offset++;
if (ZOOM_record_error(rec, &msg, &addinfo, 0))
yaz_log(YLOG_WARN, "Record error %s (%s): %s (rec #%d)",
- error, addinfo, client_get_url(cl), cl->records);
+ error, addinfo, client_get_url(cl),
+ cl->record_offset);
else
{
struct session_database *sdb = client_get_database(cl);
nativesyntax_to_type(sdb, type);
if ((xmlrec = ZOOM_record_get(rec, type, NULL)))
{
- if (ingest_record(cl, xmlrec, cl->records))
+ if (ingest_record(cl, xmlrec, cl->record_offset))
{
session_alert_watch(cl->session, SESSION_WATCH_SHOW);
session_alert_watch(cl->session, SESSION_WATCH_RECORD);
}
}
+ else
+ {
+ yaz_log(YLOG_WARN, "Expected record, but got NULL, offset=%d",
+ offset);
+ }
}
- if (!rec)
- yaz_log(YLOG_WARN, "Expected record, but got NULL");
}
}
const char *opt_elements = session_setting_oneval(sdb, PZ_ELEMENTS);
const char *opt_requestsyn = session_setting_oneval(sdb, PZ_REQUESTSYNTAX);
const char *opt_maxrecs = session_setting_oneval(sdb, PZ_MAXRECS);
+ const char *opt_sru = session_setting_oneval(sdb, PZ_SRU);
assert(link);
cl->hits = -1;
- cl->records = 0;
+ cl->record_offset = 0;
cl->diagnostic = 0;
+ client_set_state(cl, Client_Working);
if (*opt_piggyback)
ZOOM_connection_option_set(link, "piggyback", opt_piggyback);
ZOOM_connection_option_set(link, "piggyback", "1");
if (*opt_queryenc)
ZOOM_connection_option_set(link, "rpnCharset", opt_queryenc);
- if (*opt_elements)
+ if (*opt_sru && *opt_elements)
+ ZOOM_connection_option_set(link, "schema", opt_elements);
+ else if (*opt_elements)
ZOOM_connection_option_set(link, "elementSetName", opt_elements);
if (*opt_requestsyn)
ZOOM_connection_option_set(link, "preferredRecordSyntax", opt_requestsyn);
sprintf(n, "%d", global_parameters.toget);
ZOOM_connection_option_set(link, "count", n);
}
- if (!databaseName || !*databaseName)
- databaseName = "Default";
- ZOOM_connection_option_set(link, "databaseName", databaseName);
+ if (databaseName)
+ ZOOM_connection_option_set(link, "databaseName", databaseName);
ZOOM_connection_option_set(link, "presentChunk", "20");
- rs = ZOOM_connection_search_pqf(link, cl->pquery);
+ if (cl->cqlquery)
+ {
+ ZOOM_query q = ZOOM_query_create();
+ ZOOM_query_cql(q, cl->cqlquery);
+ rs = ZOOM_connection_search(link, q);
+ ZOOM_query_destroy(q);
+ }
+ else
+ rs = ZOOM_connection_search_pqf(link, cl->pquery);
connection_set_resultset(co, rs);
connection_continue(co);
}
else
r = xmalloc(sizeof(struct client));
r->pquery = 0;
+ r->cqlquery = 0;
r->database = 0;
r->connection = 0;
r->session = 0;
r->hits = 0;
- r->records = 0;
- r->setno = 0;
- r->requestid = -1;
+ r->record_offset = 0;
r->diagnostic = 0;
r->state = Client_Disconnected;
r->show_raw = 0;
cc->next = c->next;
}
xfree(c->pquery);
+ xfree(c->cqlquery);
if (c->connection)
connection_release(c->connection);
return res;
}
+// returns a xmalloced CQL query corresponding to the pquery in client
+static char *make_cqlquery(struct client *cl)
+{
+ cql_transform_t cqlt = cql_transform_create();
+ Z_RPNQuery *zquery;
+ char *r;
+ WRBUF wrb = wrbuf_alloc();
+ int status;
+
+ zquery = p_query_rpn(global_parameters.odr_out, cl->pquery);
+ if ((status = cql_transform_rpn2cql_wrbuf(cqlt, wrb, zquery)))
+ {
+ yaz_log(YLOG_WARN, "failed to generate CQL query, code=%d", status);
+ return 0;
+ }
+ r = xstrdup(wrbuf_cstr(wrb));
+
+ wrbuf_destroy(wrb);
+ odr_reset(global_parameters.odr_out); // releases the zquery
+ cql_transform_close(cqlt);
+ return r;
+}
+
// Parse the query given the settings specific to this client
int client_parse_query(struct client *cl, const char *query)
{
struct session *se = client_get_session(cl);
+ struct session_database *sdb = client_get_database(cl);
struct ccl_rpn_node *cn;
int cerror, cpos;
CCL_bibset ccl_map = prepare_cclmap(cl);
+ const char *sru = session_setting_oneval(sdb, PZ_SRU);
if (!ccl_map)
return -1;
ccl_qual_rm(&ccl_map);
if (!cn)
{
- cl->state = Client_Error;
+ client_set_state(cl, Client_Error);
yaz_log(YLOG_WARN, "Failed to parse query for %s",
client_get_database(cl)->database->url);
return -1;
xfree(cl->pquery);
cl->pquery = xstrdup(wrbuf_cstr(se->wrbuf));
+ xfree(cl->cqlquery);
+ if (*sru)
+ {
+ if (!(cl->cqlquery = make_cqlquery(cl)))
+ return -1;
+ }
+ else
+ cl->cqlquery = 0;
+
if (!se->relevance)
{
// Initialize relevance structure with query terms
int client_is_active(struct client *cl)
{
- if (cl->connection && (cl->state == Client_Continue ||
- cl->state == Client_Connecting ||
+ if (cl->connection && (cl->state == Client_Connecting ||
cl->state == Client_Working))
return 1;
return 0;
int client_get_num_records(struct client *cl)
{
- return cl->records;
+ return cl->record_offset;
}
int client_get_diagnostic(struct client *cl)