- switch (n->kind)
- {
- case CCL_RPN_AND:
- case CCL_RPN_OR:
- case CCL_RPN_NOT:
- case CCL_RPN_PROX:
- pull_terms(nmem, n->u.p[0], termlist, num);
- pull_terms(nmem, n->u.p[1], termlist, num);
- break;
- case CCL_RPN_TERM:
- termlist[(*num)++] = nmem_strdup(nmem, n->u.t.term);
- break;
- default: // NOOP
- break;
- }
-}
-
-// Extract terms from query into null-terminated termlist
-static void extract_terms(NMEM nmem, struct ccl_rpn_node *query, char **termlist)
-{
- int num = 0;
-
- pull_terms(nmem, query, termlist, &num);
- termlist[num] = 0;
-}
-
-static void send_search(IOCHAN i)
-{
- struct connection *co = iochan_getdata(i);
- struct client *cl = co->client;
- struct session *se = cl->session;
- struct database *db = cl->database;
- Z_APDU *a = zget_APDU(global_parameters.odr_out, Z_APDU_searchRequest);
- int ndb, cerror, cpos;
- char **databaselist;
- Z_Query *zquery;
- struct ccl_rpn_node *cn;
- int ssub = 0, lslb = 100000, mspn = 10;
- char *recsyn;
- char *piggyback;
-
- yaz_log(YLOG_DEBUG, "Sending search");
-
- cn = ccl_find_str(db->ccl_map, se->query, &cerror, &cpos);
- if (!cn)
- return;
-
- if (!se->relevance)
- {
- // Initialize relevance structure with query terms
- char *p[512];
- extract_terms(se->nmem, cn, p);
- se->relevance = relevance_create(se->nmem, (const char **) p,
- se->expected_maxrecs);
- }
-
- a->u.searchRequest->query = zquery = odr_malloc(global_parameters.odr_out,
- sizeof(Z_Query));
- zquery->which = Z_Query_type_1;
- zquery->u.type_1 = ccl_rpn_query(global_parameters.odr_out, cn);
- ccl_rpn_delete(cn);
-
- for (ndb = 0; db->databases[ndb]; ndb++)
- ;
- databaselist = odr_malloc(global_parameters.odr_out, sizeof(char*) * ndb);
- for (ndb = 0; db->databases[ndb]; ndb++)
- databaselist[ndb] = db->databases[ndb];
-
- if (!(piggyback = session_setting_oneval(se, db, PZ_PIGGYBACK)) || *piggyback == '1')
- {
- if ((recsyn = session_setting_oneval(se, db, PZ_REQUESTSYNTAX)))
- a->u.searchRequest->preferredRecordSyntax =
- yaz_str_to_z3950oid(global_parameters.odr_out,
- CLASS_RECSYN, recsyn);
- a->u.searchRequest->smallSetUpperBound = &ssub;
- a->u.searchRequest->largeSetLowerBound = &lslb;
- a->u.searchRequest->mediumSetPresentNumber = &mspn;
- }
- a->u.searchRequest->resultSetName = "Default";
- a->u.searchRequest->databaseNames = databaselist;
- a->u.searchRequest->num_databaseNames = ndb;
-
- if (send_apdu(cl, a) >= 0)
- {
- iochan_setflags(i, EVENT_INPUT);
- cl->state = Client_Searching;
- cl->requestid = se->requestid;
- }
- else
- cl->state = Client_Error;
-
- odr_reset(global_parameters.odr_out);
-}
-
-static void send_present(IOCHAN i)
-{
- struct connection *co = iochan_getdata(i);
- struct client *cl = co->client;
- struct session *se = cl->session;
- struct database *db = cl->database;
- Z_APDU *a = zget_APDU(global_parameters.odr_out, Z_APDU_presentRequest);
- int toget;
- int start = cl->records + 1;
- char *recsyn;
-
- toget = global_parameters.chunk;
- if (toget > global_parameters.toget - cl->records)
- toget = global_parameters.toget - cl->records;
- if (toget > cl->hits - cl->records)
- toget = cl->hits - cl->records;
-
- yaz_log(YLOG_DEBUG, "Trying to present %d records\n", toget);
-
- a->u.presentRequest->resultSetStartPoint = &start;
- a->u.presentRequest->numberOfRecordsRequested = &toget;
-
- a->u.presentRequest->resultSetId = "Default";
-
- if ((recsyn = session_setting_oneval(se, db, PZ_REQUESTSYNTAX)))
- a->u.presentRequest->preferredRecordSyntax =
- yaz_str_to_z3950oid(global_parameters.odr_out,
- CLASS_RECSYN, recsyn);
-
- if (send_apdu(cl, a) >= 0)
- {
- iochan_setflags(i, EVENT_INPUT);
- cl->state = Client_Presenting;
- }
- else
- cl->state = Client_Error;
- odr_reset(global_parameters.odr_out);
-}
-
-static void do_initResponse(IOCHAN i, Z_APDU *a)
-{
- struct connection *co = iochan_getdata(i);
- struct client *cl = co->client;
- Z_InitResponse *r = a->u.initResponse;
-
- yaz_log(YLOG_DEBUG, "Init response %s", cl->database->url);
-
- if (*r->result)
- {
- cl->state = Client_Idle;
- }
- else
- cl->state = Client_Failed; // FIXME need to do something to the connection
-}
-
-static void do_searchResponse(IOCHAN i, Z_APDU *a)
-{
- struct connection *co = iochan_getdata(i);
- struct client *cl = co->client;
- struct session *se = cl->session;
- Z_SearchResponse *r = a->u.searchResponse;
-
- yaz_log(YLOG_DEBUG, "Search response %s (status=%d)",
- cl->database->url, *r->searchStatus);
-
- if (*r->searchStatus)
- {
- cl->hits = *r->resultCount;
- se->total_hits += cl->hits;
- if (r->presentStatus && !*r->presentStatus && r->records)
- {
- yaz_log(YLOG_DEBUG, "Records in search response %s",
- cl->database->url);
- ingest_records(cl, r->records);
- }
- cl->state = Client_Idle;
- }
- else
- { /*"FAILED"*/
- cl->hits = 0;
- cl->state = Client_Error;
- if (r->records) {
- Z_Records *recs = r->records;
- if (recs->which == Z_Records_NSD)
- {
- yaz_log(YLOG_WARN,
- "Search response: Non-surrogate diagnostic %s",
- cl->database->url);
- cl->diagnostic = *recs->u.nonSurrogateDiagnostic->condition;
- cl->state = Client_Error;
- }
- }
- }
-}
-
-static void do_closeResponse(IOCHAN i, Z_APDU *a)
-{
- struct connection *co = iochan_getdata(i);
- struct client *cl = co->client;
- /* Z_Close *r = a->u.close; */
-
- yaz_log(YLOG_WARN, "Close response %s", cl->database->url);
-
- cl->state = Client_Failed;
- connection_destroy(co);
-}
-
-
-char *normalize_mergekey(char *buf, int skiparticle)
-{
- char *p = buf, *pout = buf;
-
- if (skiparticle)
- {
- char firstword[64];
- char articles[] = "the den der die des an a "; // must end in space
-
- while (*p && !isalnum(*p))
- p++;
- pout = firstword;
- while (*p && *p != ' ' && pout - firstword < 62)
- *(pout++) = tolower(*(p++));
- *(pout++) = ' ';
- *(pout++) = '\0';
- if (!strstr(articles, firstword))
- p = buf;
- pout = buf;
- }