1 /* This file is part of Pazpar2.
2 Copyright (C) 2006-2008 Index Data
4 Pazpar2 is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
9 Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
38 #include <sys/socket.h>
47 #include <yaz/marcdisp.h>
48 #include <yaz/comstack.h>
49 #include <yaz/tcpip.h>
50 #include <yaz/proto.h>
51 #include <yaz/readconf.h>
52 #include <yaz/pquery.h>
53 #include <yaz/otherinfo.h>
54 #include <yaz/yaz-util.h>
56 #include <yaz/query-charset.h>
57 #include <yaz/querytowrbuf.h>
58 #include <yaz/oid_db.h>
59 #include <yaz/diagbib1.h>
63 #include <yaz/timing.h>
67 #include <netinet/in.h>
73 #include "connection.h"
76 /** \brief Represents client state for a connection to one search target */
78 struct session_database *database;
79 struct connection *connection;
80 struct session *session;
81 char *pquery; // Current search
85 int requestid; // ID of current outstanding request
87 enum client_state state;
88 struct show_raw *show_raw;
89 struct client *next; // next client in session or next in free list
93 int active; // whether this request has been sent to the server
98 void (*error_handler)(void *data, const char *addinfo);
99 void (*record_handler)(void *data, const char *buf, size_t sz);
101 struct show_raw *next;
104 static const char *client_states[] = {
108 "Client_Initializing",
113 "Client_Disconnected",
118 static struct client *client_freelist = 0;
120 static int send_apdu(struct client *c, Z_APDU *a)
122 struct session_database *sdb = client_get_database(c);
123 const char *apdulog = session_setting_oneval(sdb, PZ_APDULOG);
124 if (apdulog && *apdulog && *apdulog != '0')
126 ODR p = odr_createmem(ODR_PRINT);
127 yaz_log(YLOG_LOG, "send APDU %s", client_get_url(c));
129 odr_setprint(p, yaz_log_file());
131 odr_setprint(p, stderr);
134 return connection_send_apdu(client_get_connection(c), a);
138 const char *client_get_state_str(struct client *cl)
140 return client_states[cl->state];
143 enum client_state client_get_state(struct client *cl)
148 void client_set_state(struct client *cl, enum client_state st)
153 int no_active = session_active_clients(cl->session);
155 session_alert_watch(cl->session, SESSION_WATCH_SHOW);
159 static void client_show_raw_error(struct client *cl, const char *addinfo);
161 // Close connection and set state to error
162 void client_fatal(struct client *cl)
164 client_show_raw_error(cl, "client connection failure");
165 yaz_log(YLOG_WARN, "Fatal error from %s", client_get_url(cl));
166 connection_destroy(cl->connection);
167 client_set_state(cl, Client_Error);
171 static int diag_to_wrbuf(Z_DiagRec **pp, int num, WRBUF w)
175 for (i = 0; i<num; i++)
177 Z_DiagRec *p = pp[i];
180 if (p->which != Z_DiagRec_defaultFormat)
182 wrbuf_puts(w, "? Not in default format");
186 Z_DefaultDiagFormat *r = p->u.defaultFormat;
188 if (!r->diagnosticSetId)
189 wrbuf_puts(w, "? Missing diagset");
193 char diag_name_buf[OID_STR_MAX];
194 const char *diag_name = 0;
195 diag_name = yaz_oid_to_string_buf
196 (r->diagnosticSetId, &oclass, diag_name_buf);
197 wrbuf_puts(w, diag_name);
200 code = *r->condition;
201 wrbuf_printf(w, " %d %s", *r->condition,
202 diagbib1_str(*r->condition));
205 case Z_DefaultDiagFormat_v2Addinfo:
206 wrbuf_printf(w, " -- v2 addinfo '%s'", r->u.v2Addinfo);
208 case Z_DefaultDiagFormat_v3Addinfo:
209 wrbuf_printf(w, " -- v3 addinfo '%s'", r->u.v3Addinfo);
219 struct connection *client_get_connection(struct client *cl)
221 return cl->connection;
224 struct session_database *client_get_database(struct client *cl)
229 struct session *client_get_session(struct client *cl)
234 const char *client_get_pquery(struct client *cl)
239 void client_set_requestid(struct client *cl, int id)
244 int client_show_raw_begin(struct client *cl, int position,
245 const char *syntax, const char *esn,
247 void (*error_handler)(void *data, const char *addinfo),
248 void (*record_handler)(void *data, const char *buf,
253 struct show_raw *rr, **rrp;
255 { /* the client has no connection */
258 rr = xmalloc(sizeof(*rr));
260 rr->position = position;
263 rr->error_handler = error_handler;
264 rr->record_handler = record_handler;
267 rr->syntax = xstrdup(syntax);
271 rr->esn = xstrdup(esn);
276 for (rrp = &cl->show_raw; *rrp; rrp = &(*rrp)->next)
280 if (cl->state == Client_Failed)
282 client_show_raw_error(cl, "client failed");
284 else if (cl->state == Client_Disconnected)
286 client_show_raw_error(cl, "client disconnected");
295 void client_show_raw_remove(struct client *cl, void *data)
297 struct show_raw *rr = data;
298 struct show_raw **rrp = &cl->show_raw;
308 void client_show_raw_dequeue(struct client *cl)
310 struct show_raw *rr = cl->show_raw;
312 cl->show_raw = rr->next;
316 static void client_show_raw_error(struct client *cl, const char *addinfo)
320 cl->show_raw->error_handler(cl->show_raw->data, addinfo);
321 client_show_raw_dequeue(cl);
325 static void client_show_raw_cancel(struct client *cl)
329 cl->show_raw->error_handler(cl->show_raw->data, "cancel");
330 client_show_raw_dequeue(cl);
334 static void client_present_syntax(Z_APDU *a, const char *syntax)
336 // empty string for syntax OMITS preferredRecordSyntax (OPTIONAL)
337 if (syntax && *syntax)
338 a->u.presentRequest->preferredRecordSyntax =
339 yaz_string_to_oid_odr(yaz_oid_std(),
340 CLASS_RECSYN, syntax,
341 global_parameters.odr_out);
344 static void client_present_elements(Z_APDU *a, const char *elements)
346 if (elements && *elements) // element set is optional
348 Z_ElementSetNames *elementSetNames =
349 odr_malloc(global_parameters.odr_out, sizeof(*elementSetNames));
350 Z_RecordComposition *compo =
351 odr_malloc(global_parameters.odr_out, sizeof(*compo));
352 a->u.presentRequest->recordComposition = compo;
354 compo->which = Z_RecordComp_simple;
355 compo->u.simple = elementSetNames;
357 elementSetNames->which = Z_ElementSetNames_generic;
358 elementSetNames->u.generic =
359 odr_strdup(global_parameters.odr_out, elements);
363 void client_send_raw_present(struct client *cl)
365 struct session_database *sdb = client_get_database(cl);
366 Z_APDU *a = zget_APDU(global_parameters.odr_out, Z_APDU_presentRequest);
368 int start = cl->show_raw->position;
369 const char *syntax = 0;
370 const char *elements = 0;
372 assert(cl->show_raw);
374 yaz_log(YLOG_DEBUG, "%s: trying to present %d record(s) from %d",
375 client_get_url(cl), toget, start);
377 a->u.presentRequest->resultSetStartPoint = &start;
378 a->u.presentRequest->numberOfRecordsRequested = &toget;
380 if (cl->show_raw->syntax)
381 syntax = cl->show_raw->syntax;
383 syntax = session_setting_oneval(sdb, PZ_REQUESTSYNTAX);
385 client_present_syntax(a, syntax);
386 if (cl->show_raw->esn)
387 elements = cl->show_raw->esn;
389 elements = session_setting_oneval(sdb, PZ_ELEMENTS);
390 client_present_elements(a, elements);
392 if (send_apdu(cl, a) >= 0)
394 cl->show_raw->active = 1;
395 cl->state = Client_Presenting;
399 client_show_raw_error(cl, "send_apdu failed");
400 cl->state = Client_Error;
402 odr_reset(global_parameters.odr_out);
405 void client_send_present(struct client *cl)
407 struct session_database *sdb = client_get_database(cl);
408 Z_APDU *a = zget_APDU(global_parameters.odr_out, Z_APDU_presentRequest);
410 int start = cl->records + 1;
411 const char *syntax = 0;
412 const char *elements = 0;
414 toget = global_parameters.chunk;
415 if (toget > global_parameters.toget - cl->records)
416 toget = global_parameters.toget - cl->records;
417 if (toget > cl->hits - cl->records)
418 toget = cl->hits - cl->records;
420 yaz_log(YLOG_DEBUG, "Trying to present %d record(s) from %d",
423 a->u.presentRequest->resultSetStartPoint = &start;
424 a->u.presentRequest->numberOfRecordsRequested = &toget;
426 syntax = session_setting_oneval(sdb, PZ_REQUESTSYNTAX);
427 client_present_syntax(a, syntax);
429 elements = session_setting_oneval(sdb, PZ_ELEMENTS);
430 client_present_elements(a, elements);
432 if (send_apdu(cl, a) >= 0)
433 cl->state = Client_Presenting;
435 cl->state = Client_Error;
436 odr_reset(global_parameters.odr_out);
440 void client_send_search(struct client *cl)
442 struct session *se = client_get_session(cl);
443 struct session_database *sdb = client_get_database(cl);
444 Z_APDU *a = zget_APDU(global_parameters.odr_out, Z_APDU_searchRequest);
448 int ssub = 0, lslb = 100000, mspn = 10;
449 const char *piggyback = session_setting_oneval(sdb, PZ_PIGGYBACK);
450 const char *queryenc = session_setting_oneval(sdb, PZ_QUERYENCODING);
452 yaz_log(YLOG_DEBUG, "Sending search to %s", sdb->database->url);
455 // constructing RPN query
456 a->u.searchRequest->query = zquery = odr_malloc(global_parameters.odr_out,
458 zquery->which = Z_Query_type_1;
459 zquery->u.type_1 = p_query_rpn(global_parameters.odr_out,
460 client_get_pquery(cl));
462 // converting to target encoding
463 if (queryenc && *queryenc)
465 yaz_iconv_t iconv = yaz_iconv_open(queryenc, "UTF-8");
467 yaz_query_charset_convert_rpnquery(zquery->u.type_1,
468 global_parameters.odr_out,
470 yaz_iconv_close(iconv);
472 yaz_log(YLOG_WARN, "Query encoding failed %s %s",
473 client_get_database(cl)->database->url, queryenc);
476 for (ndb = 0; sdb->database->databases[ndb]; ndb++)
478 databaselist = odr_malloc(global_parameters.odr_out, sizeof(char*) * ndb);
479 for (ndb = 0; sdb->database->databases[ndb]; ndb++)
480 databaselist[ndb] = sdb->database->databases[ndb];
482 if (!piggyback || *piggyback == '1')
484 const char *elements = session_setting_oneval(sdb, PZ_ELEMENTS);
485 const char *recsyn = session_setting_oneval(sdb, PZ_REQUESTSYNTAX);
486 if (recsyn && *recsyn)
488 a->u.searchRequest->preferredRecordSyntax =
489 yaz_string_to_oid_odr(yaz_oid_std(),
490 CLASS_RECSYN, recsyn,
491 global_parameters.odr_out);
493 if (elements && *elements)
495 Z_ElementSetNames *esn =
496 odr_malloc(global_parameters.odr_out, sizeof(*esn));
497 esn->which = Z_ElementSetNames_generic;
498 esn->u.generic = odr_strdup(global_parameters.odr_out, elements);
500 a->u.searchRequest->smallSetElementSetNames = esn;
501 a->u.searchRequest->mediumSetElementSetNames = esn;
503 a->u.searchRequest->smallSetUpperBound = &ssub;
504 a->u.searchRequest->largeSetLowerBound = &lslb;
505 a->u.searchRequest->mediumSetPresentNumber = &mspn;
507 a->u.searchRequest->databaseNames = databaselist;
508 a->u.searchRequest->num_databaseNames = ndb;
511 { //scope for sending and logging queries
512 WRBUF wbquery = wrbuf_alloc();
513 yaz_query_to_wrbuf(wbquery, a->u.searchRequest->query);
516 if (send_apdu(cl, a) >= 0)
518 client_set_state(cl, Client_Searching);
519 client_set_requestid(cl, se->requestid);
520 yaz_log(YLOG_LOG, "SearchRequest %s %s %s",
521 client_get_database(cl)->database->url,
522 queryenc ? queryenc : "UTF-8",
523 wrbuf_cstr(wbquery));
526 client_set_state(cl, Client_Error);
527 yaz_log(YLOG_WARN, "Failed SearchRequest %s %s %s",
528 client_get_database(cl)->database->url,
529 queryenc ? queryenc : "UTF-8",
530 wrbuf_cstr(wbquery));
533 wrbuf_destroy(wbquery);
536 odr_reset(global_parameters.odr_out);
539 void client_init_response(struct client *cl, Z_APDU *a)
541 Z_InitResponse *r = a->u.initResponse;
543 yaz_log(YLOG_DEBUG, "Init response %s", cl->database->database->url);
546 cl->state = Client_Continue;
548 cl->state = Client_Failed; // FIXME need to do something to the connection
552 static void ingest_raw_records(struct client *cl, Z_Records *r)
554 Z_NamePlusRecordList *rlist;
555 Z_NamePlusRecord *npr;
559 if (r->which != Z_Records_DBOSD)
561 client_show_raw_error(cl, "non-surrogate diagnostics");
565 rlist = r->u.databaseOrSurDiagnostics;
566 if (rlist->num_records != 1 || !rlist->records || !rlist->records[0])
568 client_show_raw_error(cl, "no records");
571 npr = rlist->records[0];
572 if (npr->which != Z_NamePlusRecord_databaseRecord)
574 client_show_raw_error(cl, "surrogate diagnostic");
578 if (cl->show_raw && cl->show_raw->binary)
580 Z_External *rec = npr->u.databaseRecord;
581 if (rec->which == Z_External_octet)
583 cl->show_raw->record_handler(cl->show_raw->data,
585 rec->u.octet_aligned->buf,
586 rec->u.octet_aligned->len);
587 client_show_raw_dequeue(cl);
590 client_show_raw_error(cl, "no records");
593 doc = record_to_xml(client_get_database(cl), npr->u.databaseRecord);
596 client_show_raw_error(cl, "unable to convert record to xml");
600 xmlDocDumpMemory(doc, &buf_out, &len_out);
605 cl->show_raw->record_handler(cl->show_raw->data,
606 (const char *) buf_out, len_out);
607 client_show_raw_dequeue(cl);
612 static void ingest_records(struct client *cl, Z_Records *r)
615 yaz_timing_t t = yaz_timing_create();
618 struct session *s = client_get_session(cl);
619 Z_NamePlusRecordList *rlist;
622 if (r->which != Z_Records_DBOSD)
624 rlist = r->u.databaseOrSurDiagnostics;
625 for (i = 0; i < rlist->num_records; i++)
627 Z_NamePlusRecord *npr = rlist->records[i];
630 if (npr->which != Z_NamePlusRecord_databaseRecord)
633 "Unexpected record type, probably diagnostic %s",
634 cl->database->database->url);
638 rec = ingest_record(cl, npr->u.databaseRecord, cl->records);
642 if (rlist->num_records)
643 session_alert_watch(s, SESSION_WATCH_SHOW);
644 if (rlist->num_records)
645 session_alert_watch(s, SESSION_WATCH_RECORD);
649 yaz_log(YLOG_LOG, "ingest_records %6.5f %3.2f %3.2f",
650 yaz_timing_get_real(t), yaz_timing_get_user(t),
651 yaz_timing_get_sys(t));
652 yaz_timing_destroy(&t);
657 void client_search_response(struct client *cl, Z_APDU *a)
659 struct session *se = cl->session;
660 Z_SearchResponse *r = a->u.searchResponse;
662 yaz_log(YLOG_DEBUG, "Search response %s (status=%d)",
663 cl->database->database->url, *r->searchStatus);
665 if (*r->searchStatus)
667 cl->hits = *r->resultCount;
670 yaz_log(YLOG_WARN, "Target %s returns hit count %d",
671 cl->database->database->url, cl->hits);
674 se->total_hits += cl->hits;
675 if (r->presentStatus && !*r->presentStatus && r->records)
677 yaz_log(YLOG_DEBUG, "Records in search response %s",
678 cl->database->database->url);
679 ingest_records(cl, r->records);
681 cl->state = Client_Continue;
685 Z_Records *recs = r->records;
687 cl->state = Client_Error;
688 if (recs && recs->which == Z_Records_NSD)
690 WRBUF w = wrbuf_alloc();
692 Z_DiagRec dr, *dr_p = &dr;
693 dr.which = Z_DiagRec_defaultFormat;
694 dr.u.defaultFormat = recs->u.nonSurrogateDiagnostic;
696 wrbuf_printf(w, "Search response NSD %s: ",
697 cl->database->database->url);
699 cl->diagnostic = diag_to_wrbuf(&dr_p, 1, w);
701 yaz_log(YLOG_WARN, "%s", wrbuf_cstr(w));
703 cl->state = Client_Error;
706 else if (recs && recs->which == Z_Records_multipleNSD)
708 WRBUF w = wrbuf_alloc();
710 wrbuf_printf(w, "Search response multipleNSD %s: ",
711 cl->database->database->url);
713 diag_to_wrbuf(recs->u.multipleNonSurDiagnostics->diagRecs,
714 recs->u.multipleNonSurDiagnostics->num_diagRecs,
716 yaz_log(YLOG_WARN, "%s", wrbuf_cstr(w));
717 cl->state = Client_Error;
723 void client_present_response(struct client *cl, Z_APDU *a)
725 Z_PresentResponse *r = a->u.presentResponse;
726 Z_Records *recs = r->records;
728 if (recs && recs->which == Z_Records_NSD)
730 WRBUF w = wrbuf_alloc();
732 Z_DiagRec dr, *dr_p = &dr;
733 dr.which = Z_DiagRec_defaultFormat;
734 dr.u.defaultFormat = recs->u.nonSurrogateDiagnostic;
736 wrbuf_printf(w, "Present response NSD %s: ",
737 cl->database->database->url);
739 cl->diagnostic = diag_to_wrbuf(&dr_p, 1, w);
741 yaz_log(YLOG_WARN, "%s", wrbuf_cstr(w));
743 cl->state = Client_Error;
746 client_show_raw_error(cl, "non surrogate diagnostics");
748 else if (recs && recs->which == Z_Records_multipleNSD)
750 WRBUF w = wrbuf_alloc();
752 wrbuf_printf(w, "Present response multipleNSD %s: ",
753 cl->database->database->url);
755 diag_to_wrbuf(recs->u.multipleNonSurDiagnostics->diagRecs,
756 recs->u.multipleNonSurDiagnostics->num_diagRecs,
758 yaz_log(YLOG_WARN, "%s", wrbuf_cstr(w));
759 cl->state = Client_Error;
762 else if (recs && !*r->presentStatus && cl->state != Client_Error)
764 yaz_log(YLOG_DEBUG, "Good Present response %s",
765 cl->database->database->url);
767 // we can mix show raw and normal show ..
768 if (cl->show_raw && cl->show_raw->active)
770 cl->show_raw->active = 0; // no longer active
771 ingest_raw_records(cl, recs);
774 ingest_records(cl, recs);
775 cl->state = Client_Continue;
777 else if (*r->presentStatus)
779 yaz_log(YLOG_WARN, "Bad Present response %s",
780 cl->database->database->url);
781 cl->state = Client_Error;
782 client_show_raw_error(cl, "bad present response");
786 void client_close_response(struct client *cl, Z_APDU *a)
788 struct connection *co = cl->connection;
789 /* Z_Close *r = a->u.close; */
791 yaz_log(YLOG_WARN, "Close response %s", cl->database->database->url);
793 cl->state = Client_Failed;
794 connection_destroy(co);
797 int client_is_our_response(struct client *cl)
799 struct session *se = client_get_session(cl);
801 if (cl && (cl->requestid == se->requestid ||
802 cl->state == Client_Initializing))
807 // Set authentication token in init if one is set for the client
808 // TODO: Extend this to handle other schemes than open (should be simple)
809 static void init_authentication(struct client *cl, Z_InitRequest *req)
811 struct session_database *sdb = client_get_database(cl);
812 const char *auth = session_setting_oneval(sdb, PZ_AUTHENTICATION);
816 struct connection *co = client_get_connection(cl);
817 struct session *se = client_get_session(cl);
818 Z_IdAuthentication *idAuth = odr_malloc(global_parameters.odr_out,
820 idAuth->which = Z_IdAuthentication_open;
821 idAuth->u.open = odr_strdup(global_parameters.odr_out, auth);
822 req->idAuthentication = idAuth;
823 connection_set_authentication(co, nmem_strdup(se->session_nmem, auth));
827 static void init_zproxy(struct client *cl, Z_InitRequest *req)
829 struct session_database *sdb = client_get_database(cl);
830 char *ztarget = sdb->database->url;
831 //char *ztarget = sdb->url;
832 const char *zproxy = session_setting_oneval(sdb, PZ_ZPROXY);
835 yaz_oi_set_string_oid(&req->otherInfo,
836 global_parameters.odr_out,
837 yaz_oid_userinfo_proxy,
842 static void client_init_request(struct client *cl)
844 Z_APDU *a = zget_APDU(global_parameters.odr_out, Z_APDU_initRequest);
846 a->u.initRequest->implementationId = global_parameters.implementationId;
847 a->u.initRequest->implementationName = global_parameters.implementationName;
848 a->u.initRequest->implementationVersion =
849 global_parameters.implementationVersion;
850 ODR_MASK_SET(a->u.initRequest->options, Z_Options_search);
851 ODR_MASK_SET(a->u.initRequest->options, Z_Options_present);
852 ODR_MASK_SET(a->u.initRequest->options, Z_Options_namedResultSets);
854 ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_1);
855 ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_2);
856 ODR_MASK_SET(a->u.initRequest->protocolVersion, Z_ProtocolVersion_3);
858 init_authentication(cl, a->u.initRequest);
859 init_zproxy(cl, a->u.initRequest);
861 if (send_apdu(cl, a) >= 0)
862 client_set_state(cl, Client_Initializing);
864 client_set_state(cl, Client_Error);
865 odr_reset(global_parameters.odr_out);
868 void client_continue(struct client *cl)
870 if (cl->state == Client_Connected) {
871 client_init_request(cl);
873 if (cl->state == Client_Continue || cl->state == Client_Idle)
875 struct session *se = client_get_session(cl);
876 if (cl->requestid != se->requestid && cl->pquery) {
877 // we'll have to abort this because result set is to be deleted
878 client_show_raw_cancel(cl);
879 client_send_search(cl);
881 else if (cl->show_raw)
883 client_send_raw_present(cl);
885 else if (cl->hits > 0 && cl->records < global_parameters.toget &&
886 cl->records < cl->hits) {
887 client_send_present(cl);
890 client_set_state(cl, Client_Idle);
894 struct client *client_create(void)
900 client_freelist = client_freelist->next;
903 r = xmalloc(sizeof(struct client));
913 r->state = Client_Disconnected;
919 void client_destroy(struct client *c)
921 struct session *se = c->session;
922 if (c == se->clients)
923 se->clients = c->next;
927 for (cc = se->clients; cc && cc->next != c; cc = cc->next)
935 connection_release(c->connection);
936 c->next = client_freelist;
940 void client_set_connection(struct client *cl, struct connection *con)
942 cl->connection = con;
945 void client_disconnect(struct client *cl)
947 if (cl->state != Client_Idle)
948 client_set_state(cl, Client_Disconnected);
949 client_set_connection(cl, 0);
952 // Extract terms from query into null-terminated termlist
953 static void extract_terms(NMEM nmem, struct ccl_rpn_node *query, char **termlist)
957 pull_terms(nmem, query, termlist, &num);
961 // Initialize CCL map for a target
962 static CCL_bibset prepare_cclmap(struct client *cl)
964 struct session_database *sdb = client_get_database(cl);
971 for (s = sdb->settings[PZ_CCLMAP]; s; s = s->next)
973 char *p = strchr(s->name + 3, ':');
976 yaz_log(YLOG_WARN, "Malformed cclmap name: %s", s->name);
981 ccl_qual_fitem(res, s->value, p);
986 // Parse the query given the settings specific to this client
987 int client_parse_query(struct client *cl, const char *query)
989 struct session *se = client_get_session(cl);
990 struct ccl_rpn_node *cn;
992 CCL_bibset ccl_map = prepare_cclmap(cl);
997 cn = ccl_find_str(ccl_map, query, &cerror, &cpos);
998 ccl_qual_rm(&ccl_map);
1001 cl->state = Client_Error;
1002 yaz_log(YLOG_WARN, "Failed to parse query for %s",
1003 client_get_database(cl)->database->url);
1006 wrbuf_rewind(se->wrbuf);
1007 ccl_pquery(se->wrbuf, cn);
1009 cl->pquery = xstrdup(wrbuf_cstr(se->wrbuf));
1013 // Initialize relevance structure with query terms
1015 extract_terms(se->nmem, cn, p);
1016 se->relevance = relevance_create(
1017 global_parameters.server->relevance_pct,
1018 se->nmem, (const char **) p,
1019 se->expected_maxrecs);
1026 void client_set_session(struct client *cl, struct session *se)
1029 cl->next = se->clients;
1033 int client_is_active(struct client *cl)
1035 if (cl->connection && (cl->state == Client_Continue ||
1036 cl->state == Client_Connecting ||
1037 cl->state == Client_Connected ||
1038 cl->state == Client_Initializing ||
1039 cl->state == Client_Searching ||
1040 cl->state == Client_Presenting))
1045 struct client *client_next_in_session(struct client *cl)
1053 int client_get_hits(struct client *cl)
1058 int client_get_num_records(struct client *cl)
1063 int client_get_diagnostic(struct client *cl)
1065 return cl->diagnostic;
1068 void client_set_database(struct client *cl, struct session_database *db)
1073 struct host *client_get_host(struct client *cl)
1075 return client_get_database(cl)->database->host;
1078 const char *client_get_url(struct client *cl)
1080 return client_get_database(cl)->database->url;
1086 * indent-tabs-mode: nil
1088 * vim: shiftwidth=4 tabstop=8 expandtab