-
-// FIXME needs to be generalized. Should flexibly generate X lists per search
-static void extract_subject(struct session *s, const char *rec)
-{
- const char *field, *subfield;
-
- while ((field = find_field(rec, "650")))
- {
- rec = field;
- if ((subfield = find_subfield(field, 'a')))
- {
- char *e, *ef;
- char buf[1024];
- int len;
-
- ef = index(subfield, '\n');
- if (!ef)
- return;
- if ((e = index(subfield, '\t')) && e < ef)
- ef = e;
- while (ef > subfield && !isalpha(*(ef - 1)) && *(ef - 1) != ')')
- ef--;
- len = ef - subfield;
- assert(len < 1023);
- memcpy(buf, subfield, len);
- buf[len] = '\0';
- if (*buf)
- termlist_insert(s->termlist, buf);
- }
- }
-}
-
-static void pull_relevance_field(struct session *s, struct record *head, const char *rec,
- char *field, int mult)
-{
- const char *fb;
- while ((fb = find_field(rec, field)))
- {
- char *ffield = strchr(fb, '\t');
- if (!ffield)
- return;
- char *eol = strchr(ffield, '\n');
- if (!eol)
- return;
- relevance_countwords(s->relevance, head, ffield, eol - ffield, mult);
- rec = field + 1; // Crude way to cause a loop through repeating fields
- }
-}
-
-static void pull_relevance_keys(struct session *s, struct record *head, struct record *rec)
-{
- relevance_newrec(s->relevance, head);
- pull_relevance_field(s, head, rec->buf, "100", 2);
- pull_relevance_field(s, head, rec->buf, "245", 4);
- //pull_relevance_field(s, head, rec->buf, "530", 1);
- pull_relevance_field(s, head, rec->buf, "630", 1);
- pull_relevance_field(s, head, rec->buf, "650", 1);
- pull_relevance_field(s, head, rec->buf, "700", 1);
- relevance_donerecord(s->relevance, head);
-}
-
-static struct record *ingest_record(struct client *cl, char *buf, int len)
-{
- struct session *se = cl->session;
- struct record *res;
- struct record *head;
- const char *recbuf;
-
- wrbuf_rewind(se->wrbuf);
- yaz_marc_xml(global_parameters.yaz_marc, YAZ_MARC_LINE);
- if (yaz_marc_decode_wrbuf(global_parameters.yaz_marc, buf, len, se->wrbuf) < 0)
- {
- yaz_log(YLOG_WARN, "Failed to decode MARC record");
- return 0;
- }
- wrbuf_putc(se->wrbuf, '\0');
- recbuf = wrbuf_buf(se->wrbuf);
-
- res = nmem_malloc(se->nmem, sizeof(struct record));
- res->buf = nmem_strdup(se->nmem, recbuf);
-
- extract_subject(se, res->buf);
-
- res->title = extract_title(se, res->buf);
- res->merge_key = extract_mergekey(se, res->buf);
- if (!res->merge_key)
- return 0;
- res->client = cl;
- res->next_cluster = 0;
- res->target_offset = -1;
- res->term_frequency_vec = 0;
-
- head = reclist_insert(se->reclist, res);
-
- pull_relevance_keys(se, head, res);
-
- se->total_records++;
-
- return res;
-}
-
-static void ingest_records(struct client *cl, Z_Records *r)
-{
- struct record *rec;
- struct session *s = cl->session;
- Z_NamePlusRecordList *rlist;
- int i;
-
- if (r->which != Z_Records_DBOSD)
- return;
- rlist = r->u.databaseOrSurDiagnostics;
- for (i = 0; i < rlist->num_records; i++)
- {
- Z_NamePlusRecord *npr = rlist->records[i];
- Z_External *e;
- char *buf;
- int len;
-
- if (npr->which != Z_NamePlusRecord_databaseRecord)
- {
- yaz_log(YLOG_WARN, "Unexpected record type, probably diagnostic");
- continue;
- }
- e = npr->u.databaseRecord;
- if (e->which != Z_External_octet)
- {
- yaz_log(YLOG_WARN, "Unexpected external branch, probably BER");
- continue;
- }
- buf = (char*) e->u.octet_aligned->buf;
- len = e->u.octet_aligned->len;
-
- rec = ingest_record(cl, buf, len);
- if (!rec)
- continue;
- }
- if (s->watchlist[SESSION_WATCH_RECORDS].fun && rlist->num_records)
- session_alert_watch(s, SESSION_WATCH_RECORDS);
-}
-
-static void do_presentResponse(IOCHAN i, Z_APDU *a)
-{
- struct connection *co = iochan_getdata(i);
- struct client *cl = co->client;
- Z_PresentResponse *r = a->u.presentResponse;
-
- if (r->records) {
- Z_Records *recs = r->records;
- if (recs->which == Z_Records_NSD)
- {
- yaz_log(YLOG_WARN, "Non-surrogate diagnostic");
- cl->diagnostic = *recs->u.nonSurrogateDiagnostic->condition;
- cl->state = Client_Error;
- }
- }
-
- if (!*r->presentStatus && cl->state != Client_Error)
- {
- yaz_log(YLOG_DEBUG, "Good Present response");
- cl->records += *r->numberOfRecordsReturned;
- ingest_records(cl, r->records);
- cl->state = Client_Idle;
- }
- else if (*r->presentStatus)
- {
- yaz_log(YLOG_WARN, "Bad Present response");
- cl->state = Client_Error;
- }
-}
-
-static void handler(IOCHAN i, int event)
-{
- struct connection *co = iochan_getdata(i);
- struct client *cl = co->client;
- struct session *se = 0;
-
- if (cl)
- se = cl->session;
- else
- {
- yaz_log(YLOG_WARN, "Destroying orphan connection (fix me?)");
- connection_destroy(co);
- return;
- }
-
- if (co->state == Conn_Connecting && event & EVENT_OUTPUT)
- {
- int errcode;
- socklen_t errlen = sizeof(errcode);
-
- if (getsockopt(cs_fileno(co->link), SOL_SOCKET, SO_ERROR, &errcode,
- &errlen) < 0 || errcode != 0)
- {
- client_fatal(cl);
- return;
- }
- else
- {
- yaz_log(YLOG_DEBUG, "Connect OK");
- co->state = Conn_Open;
- if (cl)
- cl->state = Client_Connected;