46 #include <yaz/marcdisp.h>
47 #include <yaz/comstack.h>
48 #include <yaz/tcpip.h>
49 #include <yaz/proto.h>
50 #include <yaz/readconf.h>
51 #include <yaz/pquery.h>
52 #include <yaz/otherinfo.h>
53 #include <yaz/yaz-util.h>
55 #include <yaz/query-charset.h>
56 #include <yaz/querytowrbuf.h>
57 #include <yaz/oid_db.h>
58 #include <yaz/snprintf.h>
62 #include <yaz/timing.h>
78 #include <libxml/tree.h>
82 #define MAX(a,b) ((a)>(b)?(a):(b))
113 yaz_log(YLOG_DEBUG,
"%s sessions=%d", delta == 0 ?
"" : (delta > 0 ?
"INC" :
"DEC"),
no_sessions);
135 FILE *lf = yaz_log_file();
138 #if LIBXML_VERSION >= 20600
139 xmlDocDumpFormatMemory(doc, &result, &len, 1);
141 xmlDocDumpMemory(doc, &result, &len);
145 (void) fwrite(result, 1, len, lf);
154 session_log(s, YLOG_DEBUG,
"Session lock by %s", caller);
162 session_log(s, YLOG_DEBUG,
"Session unlock by %s", caller);
172 const char *facet_component;
174 const char *icu_chain_id = 0;
177 if (!strcmp((service->
metadata + i)->name, type))
178 icu_chain_id = (service->
metadata + i)->facetrule;
180 icu_chain_id =
"facet";
185 "Unknown ICU chain '%s' for facet of type '%s'",
187 wrbuf_destroy(facet_wrbuf);
188 wrbuf_destroy(display_wrbuf);
194 const char *display_component;
195 if (*facet_component)
197 if (wrbuf_len(facet_wrbuf))
198 wrbuf_puts(facet_wrbuf,
" ");
199 wrbuf_puts(facet_wrbuf, facet_component);
202 if (display_component)
204 if (wrbuf_len(display_wrbuf))
205 wrbuf_puts(display_wrbuf,
" ");
206 wrbuf_puts(display_wrbuf, display_component);
214 WRBUF facet_wrbuf = wrbuf_alloc();
215 WRBUF display_wrbuf = wrbuf_alloc();
219 if (wrbuf_len(facet_wrbuf))
230 wrbuf_destroy(facet_wrbuf);
231 wrbuf_destroy(display_wrbuf);
241 session_log(s, YLOG_LOG,
"Facets for %s: %s norm:%s (%d)", type, value, wrbuf_cstr(facet_wrbuf), count);
244 wrbuf_cstr(facet_wrbuf), count);
246 wrbuf_destroy(facet_wrbuf);
247 wrbuf_destroy(display_wrbuf);
256 rdoc = xmlParseMemory(rec, strlen(rec));
266 session_log(se, YLOG_LOG,
"Un-normalized record from %s", db->
id);
273 #define MAX_XSLT_ARGS 16
297 int len = strlen(val);
298 buf = nmem_malloc(nmem, len + 3);
300 strcpy(buf + 1, val);
303 parms[offset++] = md->
name;
304 parms[offset++] = buf;
329 xmlNode *r = xmlDocGetRootElement(doc);
330 xmlNode *n = xmlNewTextChild(r, 0, (xmlChar *)
"metadata",
332 xmlSetProp(n, (xmlChar *)
"type", (xmlChar *) md->
name);
341 const char *rec, NMEM nmem)
361 session_log(se, YLOG_LOG,
"Normalized record from %s",
377 for (i = 0; i < num; i++)
380 for (;s ; s = s->
next)
382 wrbuf_puts(w,
"<set name=\"");
383 wrbuf_xmlputs(w, s->
name);
384 wrbuf_puts(w,
"\" value=\"");
385 wrbuf_xmlputs(w, s->
value);
386 wrbuf_puts(w,
"\"/>");
417 char auto_stylesheet[256];
419 if (!strcmp(s,
"auto"))
426 yaz_snprintf(auto_stylesheet,
sizeof(auto_stylesheet),
427 "%s.xsl", request_syntax);
428 for (cp = auto_stylesheet; *cp; cp++)
431 if (*cp > 32 && *cp < 127)
439 "No pz:requestsyntax for auto stylesheet");
506 "Alert Watch: %d calling function: %p", what, fun);
531 l = xmalloc(
sizeof(*l));
539 l = xmalloc(
sizeof(*l));
620 session_log(s, YLOG_DEBUG,
"Has %d active preferred clients.", res);
627 if (nmem_total(se->
nmem))
628 session_log(se, YLOG_DEBUG,
"NMEN operation usage %zd",
629 nmem_total(se->
nmem));
630 nmem_reset(se->
nmem);
641 session_log(se, YLOG_DEBUG,
"clear_set session_sort: field=%s increasing=%d type=%d configured",
651 const char *field = sp->
name;
654 int clients_research = 0;
656 session_log(se, YLOG_DEBUG,
"session_sort field=%s increasing=%d type=%d",
657 field, increasing, type);
666 session_log(se, YLOG_DEBUG,
"search_sort: field=%s increasing=%d type=%d already fetched",
667 field, increasing, type);
670 session_log(se, YLOG_DEBUG,
"search_sort: field=%s increasing=%d type=%d must fetch",
671 field, increasing, type);
684 if (clients_research) {
686 "Reset results due to %d clients researching",
692 sr = nmem_malloc(se->
nmem,
sizeof(*sr));
693 sr->
name = nmem_strdup(se->
nmem, field);
698 session_log(se, YLOG_DEBUG,
"No research/ingesting done");
701 session_log(se, YLOG_DEBUG,
"Re- search/ingesting for clients due to change in sort order");
713 "Client %s: No re-start/ingest in show. Wrong client state: %d",
736 int live_channels = 0;
738 int no_failed_query = 0;
739 int no_failed_limit = 0;
778 for (l = l0; l; l = l->
next)
789 else if (parse_ret == -2)
791 else if (parse_ret < 0)
805 if (no_failed_query > 0)
810 else if (no_failed_limit > 0)
818 session_log(se, YLOG_LOG,
"session_start_search done");
839 new->settings[i] = setting;
889 struct setting *
new = nmem_malloc(se->
session_nmem,
sizeof(*
new));
895 new->target = dbname;
928 if (nmem_total(se->
nmem))
929 session_log(se, YLOG_DEBUG,
"NMEN operation usage %zd", nmem_total(se->
nmem));
933 nmem_destroy(se->
nmem);
943 session_nmem = nmem_total(session->
nmem);
957 sprintf(tmp_str,
"session#%u", session_id);
972 session->
nmem = nmem_create();
992 int *count, NMEM nmem)
1001 res = nmem_malloc(nmem,
sizeof(*res) * sz);
1006 WRBUF w = wrbuf_alloc();
1011 res[*count].
name = *name ? name :
"Unknown";
1022 res[*count].
settings_xml = nmem_strdup(nmem, wrbuf_cstr(w));
1042 static int cmp_ht(
const void *p1,
const void *p2)
1058 NMEM nmem,
int version)
1068 for (i = 0; i < count && i < num && ht[i].
hits > 0; i++)
1073 wrbuf_puts(wrbuf,
"<term>\n");
1075 wrbuf_puts(wrbuf,
"<id>");
1076 wrbuf_xmlputs(wrbuf, ht[i].
id);
1077 wrbuf_puts(wrbuf,
"</id>\n");
1079 wrbuf_puts(wrbuf,
"<name>");
1081 wrbuf_xmlputs(wrbuf,
"NO TARGET NAME");
1083 wrbuf_xmlputs(wrbuf, ht[i].name);
1084 wrbuf_puts(wrbuf,
"</name>\n");
1086 wrbuf_printf(wrbuf,
"<frequency>" ODR_INT_PRINTF
"</frequency>\n",
1091 wrbuf_printf(wrbuf,
"<approximation>" ODR_INT_PRINTF
"</approximation>\n", ht[i].
approximation);
1092 wrbuf_printf(wrbuf,
"<records>%d</records>\n", ht[i].
records - ht[i].
filtered);
1093 wrbuf_printf(wrbuf,
"<filtered>%d</filtered>\n", ht[i].filtered);
1096 wrbuf_puts(wrbuf,
"<state>");
1097 wrbuf_xmlputs(wrbuf, ht[i].
state);
1098 wrbuf_puts(wrbuf,
"</state>\n");
1100 wrbuf_printf(wrbuf,
"<diagnostic>%d</diagnostic>\n",
1102 wrbuf_puts(wrbuf,
"</term>\n");
1108 const char *
name,
int num,
int version)
1111 NMEM nmem_tmp = nmem_create();
1118 nmem_strsplit(nmem_tmp,
",", name, &names, &num_names);
1122 for (j = 0; j < num_names; j++)
1125 int must_generate_empty = 1;
1130 if (!strcmp(names[j], tname) || !strcmp(names[j],
"*"))
1135 wrbuf_puts(c->
wrbuf,
"<list name=\"");
1136 wrbuf_xmlputs(c->
wrbuf, tname);
1137 wrbuf_puts(c->
wrbuf,
"\">\n");
1138 must_generate_empty = 0;
1145 for (i = 0; i < len && i < num; i++)
1151 wrbuf_puts(c->
wrbuf,
"<term>");
1152 wrbuf_puts(c->
wrbuf,
"<name>");
1154 wrbuf_puts(c->
wrbuf,
"</name>");
1156 wrbuf_printf(c->
wrbuf,
1157 "<frequency>%d</frequency>",
1159 wrbuf_puts(c->
wrbuf,
"</term>\n");
1162 wrbuf_puts(c->
wrbuf,
"</list>\n");
1166 if (!strcmp(names[j], tname) || !strcmp(names[j],
"*"))
1168 wrbuf_puts(c->
wrbuf,
"<list name=\"");
1169 wrbuf_xmlputs(c->
wrbuf, tname);
1170 wrbuf_puts(c->
wrbuf,
"\">\n");
1173 wrbuf_puts(c->
wrbuf,
"</list>\n");
1174 must_generate_empty = 0;
1176 if (must_generate_empty)
1178 wrbuf_puts(c->
wrbuf,
"<list name=\"");
1179 wrbuf_xmlputs(c->
wrbuf, names[j]);
1180 wrbuf_puts(c->
wrbuf,
"\"/>\n");
1184 nmem_destroy(nmem_tmp);
1187 #ifdef MISSING_HEADERS
1188 void report_nmem_stats(
void)
1190 size_t in_use, is_free;
1192 nmem_get_memory_in_use(&in_use);
1193 nmem_get_memory_free(&is_free);
1195 yaz_log(YLOG_LOG,
"nmem stat: use=%ld free=%ld",
1196 (
long) in_use, (
long) is_free);
1214 if (!strcmp(r->
recid,
id))
1257 session_log(se, YLOG_LOG,
"%s: no fetch due to state=%s",
1267 int start,
int *num,
int *total,
1268 Odr_int *sumhits, Odr_int *approx_hits,
1277 yaz_timing_t t = yaz_timing_create();
1286 for (spp = sp; spp; spp = spp->
next)
1305 for (i = 0; i < start; i++)
1316 for (;rec; rec = rec->
next)
1320 recs = nmem_malloc(se->
nmem, (*num > 0 ? *num : 1) *
sizeof(*recs));
1321 for (i = 0; i < *num; i++)
1332 for (;rec; rec = rec->
next)
1340 session_log(se, YLOG_LOG,
"show %6.5f %3.2f %3.2f",
1341 yaz_timing_get_real(t), yaz_timing_get_user(t),
1342 yaz_timing_get_sys(t));
1343 yaz_timing_destroy(&t);
1351 session_log(se, YLOG_LOG,
"fetching more in progress");
1355 session_log(se, YLOG_WARN,
"Ignoring show block");
1377 memset(stat, 0,
sizeof(*stat));
1403 struct _xmlAttr *attr)
1408 for (; attr; attr = attr->next)
1410 if (attr->children && attr->children->content)
1412 if (strcmp((
const char *) attr->name,
"type")
1413 && strcmp((
const char *) attr->name,
"empty"))
1417 *attrp = nmem_malloc(nmem,
sizeof(**attrp));
1419 nmem_strdup(nmem, (
const char *) attr->name);
1421 nmem_strdup(nmem, (
const char *) attr->children->content);
1422 attrp = &(*attrp)->
next;
1430 char *p = nmem_strdup(nmem, value);
1460 for (n = root->children; n; n = n->next)
1462 if (n->type != XML_ELEMENT_NODE)
1464 if (!strcmp((
const char *) n->name,
"metadata"))
1466 xmlChar *type = xmlGetProp(n, (xmlChar *)
"type");
1468 yaz_log(YLOG_FATAL,
"Missing type attribute on metadata element. Skipping!");
1470 else if (!strcmp(name, (
const char *) type))
1472 xmlChar *
value = xmlNodeListGetString(doc, n->children, 1);
1475 const char *norm_str;
1480 if (wrbuf_len(norm_wr) > 0)
1481 wrbuf_puts(norm_wr,
" ");
1482 wrbuf_puts(norm_wr, name);
1488 wrbuf_puts(norm_wr,
" ");
1489 wrbuf_puts(norm_wr, norm_str);
1506 char *mergekey_norm = 0;
1507 xmlNode *root = xmlDocGetRootElement(doc);
1508 WRBUF norm_wr = wrbuf_alloc();
1511 xmlChar *mergekey = xmlGetProp(root, (xmlChar *)
"mergekey");
1514 const char *norm_str;
1523 if (wrbuf_len(norm_wr))
1524 wrbuf_puts(norm_wr,
" ");
1525 wrbuf_puts(norm_wr, norm_str);
1535 for (field_id = 0; field_id < service->
num_metadata; field_id++)
1546 wrbuf_rewind(norm_wr);
1554 if (wrbuf_len(norm_wr) == 0)
1556 wrbuf_printf(norm_wr,
"position: %s-%d",
1561 const char *lead =
"content: ";
1562 wrbuf_insert(norm_wr, 0, lead, strlen(lead));
1564 if (wrbuf_len(norm_wr) > 0)
1565 mergekey_norm = nmem_strdup(nmem, wrbuf_cstr(norm_wr));
1566 wrbuf_destroy(norm_wr);
1567 return mergekey_norm;
1590 for (n = root->children; n; n = n->next)
1592 if (n->type != XML_ELEMENT_NODE)
1594 if (!strcmp((
const char *) n->name,
"metadata"))
1596 xmlChar *
type = xmlGetProp(n, (xmlChar *)
"type");
1603 if ((eq = strchr(s,
'=')))
1605 else if ((eq = strchr(s,
'~')))
1611 if (len == strlen((
const char *)type) &&
1612 !memcmp((
const char *) type, s, len))
1614 xmlChar *value = xmlNodeGetContent(n);
1615 if (value && *value)
1618 (substring && strstr((
const char *) value, eq+1)) ||
1619 (!substring && !strcmp((
const char *) value, eq + 1)))
1636 const char *mergekey_norm);
1648 int record_no, NMEM nmem)
1656 const char *mergekey_norm;
1661 root = xmlDocGetRootElement(xdoc);
1670 mergekey_norm =
get_mergekey(xdoc, cl, record_no, service, nmem);
1690 char **values,
int num_v)
1694 for (i = 0; i < num_v; )
1701 int y = atoi(values[i]);
1708 yaz_log(YLOG_DEBUG,
"cmp: '%s' '%s'", rec_md->
data.
text.
disp, values[i]);
1715 rec_md = rec_md->
next;
1723 return i < num_v ? 1 : 0;
1733 NMEM nmem_tmp = nmem_create();
1749 if (md_field_id < 0)
1755 nmem_strsplit_escape2(nmem_tmp,
"|", value, &values,
1768 nmem_destroy(nmem_tmp);
1777 int skip_record = 0;
1780 NMEM nmem_tmp = nmem_create();
1783 while (!skip_record)
1794 if (!strcmp(name,
"*"))
1796 for (md_field_id = 0; md_field_id < service->
num_metadata;
1811 if (md_field_id < 0)
1825 nmem_destroy(nmem_tmp);
1833 const char *mergekey_norm)
1840 int term_factor = 1;
1849 for (n = root->children; n; n = n->next)
1857 if (n->type != XML_ELEMENT_NODE)
1859 if (!strcmp((
const char *) n->name,
"metadata"))
1864 int md_field_id = -1;
1866 type = xmlGetProp(n, (xmlChar *)
"type");
1867 value = xmlNodeListGetString(xdoc, n->children, 1);
1870 if (!value || !*value)
1872 xmlChar *empty = xmlGetProp(n, (xmlChar *)
"empty");
1881 if (md_field_id < 0)
1886 "Ignoring unknown metadata element: %s", type);
1892 ser_md = &service->
metadata[md_field_id];
1896 ser_md->
type, n->properties);
1899 session_log(se, YLOG_WARN,
"bad metadata data '%s' "
1900 "for element '%s'", value, type);
1903 wheretoput = &record->
metadata[md_field_id];
1905 wheretoput = &(*wheretoput)->
next;
1906 *wheretoput = rec_md;
1912 session_log(se, YLOG_LOG,
"Facet filtered out record no %d from %s",
1926 const char *use_term_factor_str =
1928 if (use_term_factor_str && use_term_factor_str[0] ==
'1')
1932 term_factor =
MAX(hits, maxrecs) /
MAX(1, maxrecs);
1933 assert(term_factor >= 1);
1934 session_log(se, YLOG_DEBUG,
"Using term factor: %d (%d / %d)",
1935 term_factor,
MAX(hits, maxrecs),
MAX(1, maxrecs));
1947 metadata0 = xmalloc(
sizeof(*metadata0) * service->
num_metadata);
1948 memcpy(metadata0, cluster->
metadata,
1952 for (n = root->children; n; n = n->next)
1961 if (n->type != XML_ELEMENT_NODE)
1963 if (!strcmp((
const char *) n->name,
"metadata"))
1969 int md_field_id = -1;
1970 int sk_field_id = -1;
1974 type = xmlGetProp(n, (xmlChar *)
"type");
1975 value = xmlNodeListGetString(xdoc, n->children, 1);
1977 if (!type || !value || !*value)
1982 if (md_field_id < 0)
1985 ser_md = &service->
metadata[md_field_id];
1990 ser_sk = &service->
sortkeys[sk_field_id];
2002 xml_rank = xmlGetProp(n, (xmlChar *)
"rank");
2003 rank = xml_rank ? (
const char *) xml_rank : ser_md->
rank;
2005 wheretoput = &cluster->
metadata[md_field_id];
2009 if (!metadata0[md_field_id])
2012 wheretoput = &(*wheretoput)->
next;
2013 *wheretoput = rec_md;
2020 if (!strcmp((
const char *) (*wheretoput)->data.text.disp,
2023 wheretoput = &(*wheretoput)->
next;
2026 *wheretoput = rec_md;
2032 > strlen((*wheretoput)->data.text.disp))
2034 *wheretoput = rec_md;
2037 const char *sort_str = 0;
2041 if (!cluster->
sortkeys[sk_field_id])
2043 nmem_malloc(se->
nmem,
2062 "Could not make sortkey. Bug #1858");
2065 nmem_strdup(se->
nmem, sort_str);
2073 wheretoput = &(*wheretoput)->
next;
2074 *wheretoput = rec_md;
2080 *wheretoput = rec_md;
2089 if (this_min < (*wheretoput)->data.number.min)
2090 (*wheretoput)->data.number.min = this_min;
2091 if (this_max > (*wheretoput)->data.number.max)
2092 (*wheretoput)->data.number.max = this_max;
2100 (
char *) value, rank, ser_md->
name);
2111 add_facet(se, (
char *) type, year, term_factor);
2115 add_facet(se, (
char *) type, year, term_factor);
2119 add_facet(se, (
char *) type, (
char *) value, term_factor);
2133 "Unexpected element in internal record: %s", n->name);
2155 yaz_vsnprintf(buf,
sizeof(buf)-30, fmt, ap);
2156 yaz_log(level,
"Session %u: %s", s ? s->
session_id : 0, buf);