30 #include <sys/locking.h>
39 #include <yaz/yaz-util.h>
40 #include <yaz/yaz-version.h>
41 #include <yaz/diagbib1.h>
42 #include <yaz/querytowrbuf.h>
43 #include <yaz/snprintf.h>
44 #include <yaz/pquery.h>
45 #include <sys/types.h>
47 #include <yaz/backend.h>
48 #include <yaz/charneg.h>
51 static int bend_sort(
void *handle, bend_sort_rr *rr);
52 static int bend_delete(
void *handle, bend_delete_rr *rr);
54 static int bend_segment(
void *handle, bend_segment_rr *rr);
55 static int bend_search(
void *handle, bend_search_rr *r);
56 static int bend_fetch(
void *handle, bend_fetch_rr *r);
57 static int bend_scan(
void *handle, bend_scan_rr *r);
61 bend_initresult *r = (bend_initresult *)
62 odr_malloc(q->stream,
sizeof(*r));
64 struct statserv_options_block *sob;
81 q->implementation_name =
"Zebra Information Server";
82 q->implementation_version = odr_strdup(q->stream, version_str);
84 yaz_log(YLOG_DEBUG,
"bend_init");
86 sob = statserv_getcontrol();
89 yaz_log(YLOG_WARN,
"Failed to read config `%s'", sob->configname);
90 r->errcode = YAZ_BIB1_PERMANENT_SYSTEM_ERROR;
98 if (q->auth->which == Z_IdAuthentication_open)
100 char *openpass = xstrdup(q->auth->u.open);
101 char *cp = strchr(openpass,
'/');
105 user = nmem_strdup(odr_getmem(q->stream), openpass);
106 passwd = nmem_strdup(odr_getmem(q->stream), cp+1);
110 else if (q->auth->which == Z_IdAuthentication_idPass)
112 Z_IdPass *idPass = q->auth->u.idPass;
114 user = idPass->userId;
115 passwd = idPass->password;
120 r->errcode = YAZ_BIB1_INIT_AC_BAD_USERID_AND_OR_PASSWORD;
124 if (q->charneg_request)
132 NMEM nmem = nmem_create();
134 yaz_get_proposal_charneg(nmem, q->charneg_request,
135 &charsets, &num_charsets,
136 &langs, &num_langs, &selected);
138 for (i = 0; i < num_charsets; i++)
140 const char *right_name =
"";
148 if (!yaz_matchstr(charsets[i],
"win")) {
149 right_name =
"WINDOWS-1251";
150 }
else if (!yaz_matchstr(charsets[i],
"koi")) {
151 right_name =
"KOI8-R";
152 }
else if (!yaz_matchstr(charsets[i],
"iso")) {
153 right_name =
"ISO-8859-5";
154 }
else if (!yaz_matchstr(charsets[i],
"dos")) {
155 right_name =
"CP866";
156 }
else if (!yaz_matchstr(charsets[i],
"uni")) {
157 right_name =
"UTF-8";
159 right_name = charsets[i];
161 if (odr_set_charset(q->decode,
"UTF-8", right_name) == 0)
163 yaz_log(YLOG_LOG,
"charset %d %s (proper name %s): OK", i,
164 charsets[i], right_name);
165 odr_set_charset(q->stream, right_name,
"UTF-8");
169 q->charneg_response =
170 yaz_set_response_charneg(q->stream, charsets[i],
174 yaz_log(YLOG_LOG,
"charset %d %s (proper name %s): unsupported", i,
175 charsets[i], right_name);
187 int type = Z_Term_general;
188 struct Z_External *ext;
189 Z_SearchInfoReport *sr;
195 r->search_info = odr_malloc(r->stream,
sizeof(*r->search_info));
197 r->search_info->num_elements = 1;
198 r->search_info->list =
199 odr_malloc(r->stream,
sizeof(*r->search_info->list));
200 r->search_info->list[0] =
201 odr_malloc(r->stream,
sizeof(**r->search_info->list));
202 r->search_info->list[0]->category = 0;
203 r->search_info->list[0]->which = Z_OtherInfo_externallyDefinedInfo;
204 ext = odr_malloc(r->stream,
sizeof(*ext));
205 r->search_info->list[0]->information.externallyDefinedInfo = ext;
206 ext->direct_reference = odr_oiddup(r->stream,
207 yaz_oid_userinfo_searchresult_1);
208 ext->indirect_reference = 0;
210 ext->which = Z_External_searchResult1;
211 sr = odr_malloc(r->stream,
sizeof(Z_SearchInfoReport));
212 ext->u.searchResult1 = sr;
214 sr->elements = odr_malloc(r->stream, sr->num *
215 sizeof(*sr->elements));
216 for (i = 0; i < no_terms; i++)
218 Z_SearchInfoReport_s *se;
223 size_t len =
sizeof(outbuf);
224 const char *term_ref_id = 0;
227 &count, &approx, outbuf, &len,
229 se = sr->elements[i] = odr_malloc(r->stream,
sizeof(**sr->elements));
230 se->subqueryId = term_ref_id ?
231 odr_strdup(r->stream, term_ref_id) : 0;
233 se->fullQuery = odr_booldup(r->stream, 0);
234 se->subqueryExpression =
235 odr_malloc(r->stream,
sizeof(Z_QueryExpression));
236 se->subqueryExpression->which =
237 Z_QueryExpression_term;
238 se->subqueryExpression->u.term =
239 odr_malloc(r->stream,
sizeof(Z_QueryExpressionTerm));
240 term = odr_malloc(r->stream,
sizeof(Z_Term));
241 se->subqueryExpression->u.term->queryTerm = term;
244 case Z_Term_characterString:
245 term->which = Z_Term_characterString;
246 term->u.characterString = odr_strdup(r->stream, outbuf);
249 term->which = Z_Term_general;
250 term->u.general = odr_create_Odr_oct(r->stream,
251 #
if YAZ_VERSIONL < 0x50000
257 term->which = Z_Term_general;
258 term->u.null = odr_nullval();
260 se->subqueryExpression->u.term->termComment = 0;
261 se->subqueryInterpretation = 0;
262 se->subqueryRecommendation = 0;
263 se->subqueryCount = odr_intdup(r->stream, count);
264 se->subqueryWeight = 0;
271 bend_association assoc =(bend_association) client_data;
272 if (!bend_assoc_is_alive(assoc))
278 const char *sortKeys)
280 #if YAZ_VERSIONL >= 0x40200
284 int num_sortspec = 0;
288 nmem_strsplit_blank(odr_getmem(o), sortKeys, &sortspec, &num_sortspec);
289 if (num_sortspec > 0)
292 WRBUF w = wrbuf_alloc();
295 wrbuf_puts(w,
"@or d");
296 for (i = 0; i < num_sortspec; i++)
301 nmem_strsplitx(odr_getmem(o),
",", sortspec[i], &arg, &num_arg, 0);
303 if (num_arg > 5 || num_arg < 1)
305 yaz_log(YLOG_WARN,
"Invalid sort spec '%s' num_arg=%d",
306 sortspec[i], num_arg);
309 if (num_arg > 2 && arg[2][0])
310 ascending = atoi(arg[2]);
312 if (i < num_sortspec-1)
313 wrbuf_puts(w,
" @or");
314 wrbuf_puts(w,
" @attr 1=");
315 yaz_encode_pqf_term(w, arg[0], strlen(arg[0]));
316 wrbuf_printf(w,
"@attr 7=%d %d", ascending ? 1 : 2, i);
318 nquery = p_query_rpn(o, wrbuf_cstr(w));
321 yaz_log(YLOG_WARN,
"query_add_sortkeys: bad RPN: '%s'",
326 Z_RPNStructure *s = nquery->RPNStructure;
328 if (s->which != Z_RPNStructure_complex)
330 yaz_log(YLOG_WARN,
"query_add_sortkeys: not complex operand");
335 s->u.complex->s1 = query->RPNStructure;
337 query->RPNStructure = s;
345 yaz_log(YLOG_WARN,
"sortkeys ignored because YAZ version < 4.2.0");
366 yaz_log(YLOG_DEBUG,
"ResultSet '%s'", r->setname);
367 switch (r->query->which)
369 case Z_Query_type_1:
case Z_Query_type_101:
373 &r->estimated_hit_count,
374 &r->partial_resultset);
384 r->errcode = YAZ_BIB1_QUERY_TYPE_UNSUPP;
385 r->errstring =
"type-2";
388 r->errcode = YAZ_BIB1_QUERY_TYPE_UNSUPP;
401 retrievalRecord.
position = r->number;
405 r->request_format, 1, &retrievalRecord);
411 else if (retrievalRecord.
errCode)
414 r->surrogate_flag = 1;
415 r->errcode = retrievalRecord.
errCode;
416 r->errstring = retrievalRecord.
errString;
417 r->basename = retrievalRecord.
base;
421 r->basename = retrievalRecord.
base;
422 r->record = retrievalRecord.
buf;
423 r->len = retrievalRecord.
len;
424 r->output_format = odr_oiddup(r->stream, retrievalRecord.
format);
443 if (r->step_size != 0 && *r->step_size != 0) {
444 r->errcode = YAZ_BIB1_ONLY_ZERO_STEP_SIZE_SUPPORTED_FOR_SCAN;
451 &r->num_entries, &entries, &is_partial,
456 r->status = BEND_SCAN_PARTIAL;
458 r->status = BEND_SCAN_SUCCESS;
459 for (i = 0; i < r->num_entries; i++)
461 r->entries[i].term = entries[i].
term;
463 r->entries[i].occurrences = entries[i].
occurrences;
468 r->status = BEND_SCAN_PARTIAL;
477 xmalloc_trav(
"bend_close");
485 rr->num_input_setnames, (
const char **) rr->input_setnames,
486 rr->output_setname, rr->sort_sequence, &rr->sort_status)
497 rr->num_setnames, rr->setnames,
505 if (r->toKeep->databaseName)
507 yaz_log(YLOG_LOG,
"adm request database %s", r->toKeep->databaseName);
509 switch (r->toKeep->which)
511 case Z_ESAdminOriginPartToKeep_reIndex:
512 yaz_log(YLOG_LOG,
"adm-reindex");
513 rr->errcode = YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED;
514 rr->errstring =
"adm-reindex not implemented yet";
516 case Z_ESAdminOriginPartToKeep_truncate:
517 rr->errcode = YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED;
518 rr->errstring =
"adm-reindex not implemented yet";
519 yaz_log(YLOG_LOG,
"adm-truncate");
521 case Z_ESAdminOriginPartToKeep_drop:
522 yaz_log(YLOG_LOG,
"adm-drop");
525 case Z_ESAdminOriginPartToKeep_create:
526 yaz_log(YLOG_LOG,
"adm-create %s", r->toKeep->databaseName);
529 case Z_ESAdminOriginPartToKeep_import:
530 yaz_log(YLOG_LOG,
"adm-import");
532 r->toKeep->u.import->recordType);
534 case Z_ESAdminOriginPartToKeep_refresh:
535 yaz_log(YLOG_LOG,
"adm-refresh");
537 case Z_ESAdminOriginPartToKeep_commit:
538 yaz_log(YLOG_LOG,
"adm-commit");
539 if (r->toKeep->databaseName)
543 yaz_log(YLOG_WARN,
"zebra_select_database failed in "
548 case Z_ESAdminOriginPartToKeep_shutdown:
549 yaz_log(YLOG_LOG,
"shutdown");
552 case Z_ESAdminOriginPartToKeep_start:
553 yaz_log(YLOG_LOG,
"start");
557 yaz_log(YLOG_LOG,
"unknown admin");
558 rr->errcode = YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED;
559 rr->errstring =
"adm-reindex not implemented yet";
569 case Z_Admin_esRequest:
575 yaz_log(YLOG_WARN,
"adm taskpackage (unhandled)");
576 rr->errcode = YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED;
577 rr->errstring =
"adm-task package (unhandled)";
583 Z_Segment *segment = rr->segment;
585 if (segment->num_segmentRecords)
596 yaz_log(YLOG_LOG,
"function: " ODR_INT_PRINTF, *rr->esr->function);
597 if (rr->esr->packageName)
598 yaz_log(YLOG_LOG,
"packagename: %s", rr->esr->packageName);
599 yaz_log(YLOG_LOG,
"Waitaction: " ODR_INT_PRINTF, *rr->esr->waitAction);
601 if (!rr->esr->taskSpecificParameters)
603 yaz_log(YLOG_WARN,
"No task specific parameters");
605 else if (rr->esr->taskSpecificParameters->which == Z_External_ESAdmin)
607 es_admin(rr, zh, rr->esr->taskSpecificParameters->u.adminService);
609 else if (rr->esr->taskSpecificParameters->which == Z_External_update)
611 Z_IUUpdate *up = rr->esr->taskSpecificParameters->u.update;
612 yaz_log(YLOG_LOG,
"Received DB Update");
613 if (up->which == Z_IUUpdate_esRequest)
615 Z_IUUpdateEsRequest *esRequest = up->u.esRequest;
616 Z_IUOriginPartToKeep *toKeep = esRequest->toKeep;
617 Z_IUSuppliedRecords *notToKeep = esRequest->notToKeep;
619 yaz_log(YLOG_LOG,
"action");
622 switch (*toKeep->action)
624 case Z_IUOriginPartToKeep_recordInsert:
625 yaz_log(YLOG_LOG,
"recordInsert");
627 case Z_IUOriginPartToKeep_recordReplace:
628 yaz_log(YLOG_LOG,
"recordUpdate");
630 case Z_IUOriginPartToKeep_recordDelete:
631 yaz_log(YLOG_LOG,
"recordDelete");
633 case Z_IUOriginPartToKeep_elementUpdate:
634 yaz_log(YLOG_LOG,
"elementUpdate");
636 case Z_IUOriginPartToKeep_specialUpdate:
637 yaz_log(YLOG_LOG,
"specialUpdate");
639 case Z_ESAdminOriginPartToKeep_shutdown:
640 yaz_log(YLOG_LOG,
"shutDown");
642 case Z_ESAdminOriginPartToKeep_start:
643 yaz_log(YLOG_LOG,
"start");
646 yaz_log(YLOG_LOG,
" unknown (" ODR_INT_PRINTF
")",
650 if (toKeep->databaseName)
652 yaz_log(YLOG_LOG,
"database: %s", toKeep->databaseName);
659 yaz_log(YLOG_WARN,
"no database supplied for ES Update");
661 YAZ_BIB1_ES_MISSING_MANDATORY_PARAMETER_FOR_SPECIFIED_FUNCTION_;
662 rr->errstring =
"database";
672 for (i = 0; notToKeep && i < notToKeep->num; i++)
674 Z_External *rec = notToKeep->elements[i]->record;
675 Odr_oct *opaque_recid = 0;
679 if (notToKeep->elements[i]->u.opaque)
681 switch(notToKeep->elements[i]->which)
683 case Z_IUSuppliedRecords_elem_opaque:
684 opaque_recid = notToKeep->elements[i]->u.opaque;
686 case Z_IUSuppliedRecords_elem_number:
687 sysno_tmp = *notToKeep->elements[i]->u.number;
692 if (rec->direct_reference)
694 char oid_name_str[OID_STR_MAX];
695 const char *oid_name =
696 yaz_oid_to_string_buf(
697 rec->direct_reference,
700 yaz_log(YLOG_LOG,
"record %d type %s", i,
705 case Z_External_sutrs:
706 if (rec->u.octet_aligned->len > 170)
707 yaz_log(YLOG_LOG,
"%d bytes:\n%.168s ...",
711 yaz_log(YLOG_LOG,
"%d bytes:\n%s",
715 case Z_External_octet:
716 if (rec->u.octet_aligned->len > 170)
717 yaz_log(YLOG_LOG,
"%d bytes:\n%.168s ...",
718 rec->u.octet_aligned->len,
719 rec->u.octet_aligned->buf);
721 yaz_log(YLOG_LOG,
"%d bytes\n%s",
722 rec->u.octet_aligned->len,
723 rec->u.octet_aligned->buf);
725 if (rec->which == Z_External_octet)
729 const char *match_criteria = 0;
732 if (*toKeep->action ==
733 Z_IUOriginPartToKeep_recordInsert)
735 else if (*toKeep->action ==
736 Z_IUOriginPartToKeep_recordReplace)
738 else if (*toKeep->action ==
739 Z_IUOriginPartToKeep_recordDelete)
741 else if (*toKeep->action ==
742 Z_IUOriginPartToKeep_specialUpdate)
747 YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED;
748 rr->errstring =
"unsupported ES Update action";
754 size_t l = opaque_recid->len;
755 if (l >=
sizeof(recid_str))
757 rr->errcode = YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED;
758 rr->errstring =
"opaque record ID too large";
761 memcpy(recid_str, opaque_recid->buf, l);
763 match_criteria = recid_str;
768 sysno, match_criteria, 0,
769 (
const char *) rec->u.octet_aligned->buf,
770 rec->u.octet_aligned->len);
774 YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED;
775 rr->errstring =
"update_record failed";
781 yaz_log(YLOG_WARN,
"zebra_end_trans failed for"
782 " extended service operation");
789 yaz_log(YLOG_WARN,
"Unknown Extended Service(%d)",
790 rr->esr->taskSpecificParameters->which);
791 rr->errcode = YAZ_BIB1_ES_EXTENDED_SERVICE_TYPE_UNSUPP;
803 res_set(default_res,
"profilePath", DEFAULT_PROFILE_PATH);
804 res_set(default_res,
"modulePath", DEFAULT_MODULE_PATH);
809 yaz_log(YLOG_FATAL,
"Failed to read config `%s'", sob->configname);
815 if (!sob->inetd && !sob->background)
823 fd = open(pidfname, O_EXCL|O_WRONLY|O_CREAT, 0666);
828 yaz_log(YLOG_FATAL|YLOG_ERRNO,
"lock file %s", pidfname);
831 fd = open(pidfname, O_RDWR, 0666);
834 yaz_log(YLOG_FATAL|YLOG_ERRNO,
"lock file %s", pidfname);
838 area.l_type = F_WRLCK;
839 area.l_whence = SEEK_SET;
840 area.l_len = area.l_start = 0L;
841 if (fcntl(
fd, F_SETLK, &area) == -1)
843 yaz_log(YLOG_ERRNO|YLOG_FATAL,
"Zebra server already running");
850 yaz_snprintf(pidstr,
sizeof(pidstr),
"%ld", (
long) getpid());
851 if (write(
fd, pidstr, strlen(pidstr)) != strlen(pidstr))
853 yaz_log(YLOG_ERRNO|YLOG_FATAL,
"write fail %s", pidfname);
861 static void bend_stop(
struct statserv_options_block *sob)
866 if (!sob->inetd && !sob->background && sob->handle)
880 int main(
int argc,
char **argv)
883 struct statserv_options_block *sob;
885 sob = statserv_getcontrol();
886 strcpy(sob->configname,
"zebra.cfg");
890 strcpy(sob->service_name,
"zebrasrv");
891 strcpy(sob->service_display_name,
"Zebra Server");
893 statserv_setcontrol(sob);
ZEBRA_RES zebra_end_trans(ZebraHandle zh) ZEBRA_GCC_ATTR((warn_unused_result))
ZEBRA_RES zebra_admin_shutdown(ZebraHandle zh)
ZEBRA_RES zebra_close(ZebraHandle zh)
Destroys Zebra session handle.
struct zebra_session * ZebraHandle
a Zebra Handle - (session)
ZEBRA_RES zebra_admin_start(ZebraHandle zh)
ZebraService zebra_start_res(const char *configName, Res def_res, Res over_res) ZEBRA_GCC_ATTR((warn_unused_result))
Creates a Zebra service with resources.
ZEBRA_RES zebra_admin_import_segment(ZebraHandle zh, Z_Segment *segment)
ZEBRA_RES zebra_drop_database(ZebraHandle zh, const char *db)
Deletes a database (drop)
ZEBRA_RES zebra_record_encoding(ZebraHandle zh, const char *encoding)
ZEBRA_RES zebra_records_retrieve(ZebraHandle zh, ODR stream, const char *setname, Z_RecordComposition *comp, const Odr_oid *input_format, int num_recs, ZebraRetrievalRecord *recs)
Retrieve records from result set (after search)
ZEBRA_RES zebra_update_record(ZebraHandle zh, enum zebra_recctrl_action_t action, const char *recordType, zint *sysno, const char *match, const char *fname, const char *buf, int buf_size)
Updates record.
ZEBRA_RES zebra_select_databases(ZebraHandle zh, int num_bases, const char **basenames) ZEBRA_GCC_ATTR((warn_unused_result))
ZEBRA_RES zebra_commit(ZebraHandle zh)
ZEBRA_RES zebra_create_database(ZebraHandle zh, const char *db)
Creates a database.
ZEBRA_RES zebra_octet_term_encoding(ZebraHandle zh, const char *encoding)
ZEBRA_RES zebra_begin_trans(ZebraHandle zh, int rw) ZEBRA_GCC_ATTR((warn_unused_result))
ZEBRA_RES zebra_sort(ZebraHandle zh, ODR stream, int num_input_setnames, const char **input_setnames, const char *output_setname, Z_SortKeySpecList *sort_sequence, int *sort_status) ZEBRA_GCC_ATTR((warn_unused_result))
void zebra_result(ZebraHandle zh, int *code, char **addinfo)
Returns error code and additional info for last error.
int zebra_deleteResultSet(ZebraHandle zh, int function, int num_setnames, char **setnames, int *statuses)
Deletes one or more resultsets.
ZEBRA_RES zebra_select_database(ZebraHandle zh, const char *basename) ZEBRA_GCC_ATTR((warn_unused_result))
ZEBRA_RES zebra_auth(ZebraHandle zh, const char *user, const char *pass)
authenticate user. Returns 0 if OK, != 0 on failure
ZEBRA_RES zebra_set_break_handler(ZebraHandle zh, int(*f)(void *client_data), void *client_data)
ZEBRA_RES zebra_stop(ZebraService zs)
stops a Zebra service.
ZEBRA_RES zebra_admin_import_end(ZebraHandle zh)
ZEBRA_RES zebra_admin_import_begin(ZebraHandle zh, const char *database, const char *record_type)
ZEBRA_RES zebra_result_set_term_info(ZebraHandle zh, const char *setname, int no, zint *count, int *approx, char *termbuf, size_t *termlen, const char **term_ref_id)
returns information about a term assocated with a result set
const char * zebra_get_encoding(ZebraHandle zh)
Returns character set encoding for session.
ZEBRA_RES zebra_scan(ZebraHandle zh, ODR stream, Z_AttributesPlusTerm *zapt, const Odr_oid *attributeset, int *position, int *num_entries, ZebraScanEntry **entries, int *is_partial, const char *setname)
performs Scan (Z39.50 style)
ZEBRA_RES zebra_result_set_term_no(ZebraHandle zh, const char *setname, int *num_terms)
returns number of term info terms assocaited with result set
ZEBRA_RES zebra_search_RPN_x(ZebraHandle zh, ODR o, Z_RPNQuery *query, const char *setname, zint *hits, int *estimated_hit_count, int *partial_resultset)
Search using RPN Query structure (from ASN.1)
ZebraHandle zebra_open(ZebraService zs, Res res) ZEBRA_GCC_ATTR((warn_unused_result))
Creates a Zebra session handle within service.
void zebra_pidfname(ZebraService zs, char *path)
void res_set(Res r, const char *name, const char *value)
Res res_open(Res res_def, Res over_res)
short ZEBRA_RES
Common return type for Zebra API.
void zebra_get_version(char *version_str, char *sha1_str)
Returns Zebra version and SHA1 ID as generated by Git.
static void bend_start(struct statserv_options_block *sob)
static int bend_sort(void *handle, bend_sort_rr *rr)
void bend_close(void *handle)
int main(int argc, char **argv)
bend_initresult * bend_init(bend_initrequest *q)
static int break_handler(void *client_data)
static int bend_scan(void *handle, bend_scan_rr *r)
static void es_admin_request(bend_esrequest_rr *rr, ZebraHandle zh, Z_AdminEsRequest *r)
static void es_admin(bend_esrequest_rr *rr, ZebraHandle zh, Z_Admin *r)
static int bend_fetch(void *handle, bend_fetch_rr *r)
static int bend_segment(void *handle, bend_segment_rr *rr)
static void search_terms(ZebraHandle zh, bend_search_rr *r)
static void bend_stop(struct statserv_options_block *sob)
static int bend_esrequest(void *handle, bend_esrequest_rr *rr)
static int bend_search(void *handle, bend_search_rr *r)
static Z_RPNQuery * query_add_sortkeys(ODR o, Z_RPNQuery *query, const char *sortKeys)
static int bend_delete(void *handle, bend_delete_rr *rr)