From: Dennis Schafroth Date: Tue, 15 Nov 2011 10:27:02 +0000 (+0100) Subject: Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/pazpar2 X-Git-Tag: v1.6.6~13^2~7 X-Git-Url: http://git.indexdata.com/?a=commitdiff_plain;h=ee0c5796c67648c25249bf34c035d512f98e87b4;hp=fbdba021c917c36b27a594bfa555de45d4f2383c;p=pazpar2-moved-to-github.git Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/pazpar2 Conflicts: www/iphone/example_client.js Fix: added md-author in branch. Added recIDs on head. --- diff --git a/.cproject b/.cproject index 370e803..6fed192 100644 --- a/.cproject +++ b/.cproject @@ -43,6 +43,7 @@ diff --git a/IDMETA b/IDMETA index 86664dc..fb98791 100644 --- a/IDMETA +++ b/IDMETA @@ -1,2 +1,3 @@ DEBIAN_DIST="wheezy squeeze lenny" UBUNTU_DIST="natty maverick lucid karmic" +VERSION=1.6.5 diff --git a/Makefile.am b/Makefile.am index 85fbc8b..c69169e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,7 +4,7 @@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src test js doc -EXTRA_DIST = $(PACKAGE).spec README NEWS LICENSE \ +EXTRA_DIST = $(PACKAGE).spec IDMETA README NEWS LICENSE \ buildconf.sh Doxyfile.in m4/yaz.m4 \ win/makefile win/version.nsi win/version.nsi.in win/license.txt diff --git a/NEWS b/NEWS index d818d3f..d5376e7 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,12 @@ +For search, when limit and or filtering is in place and search +is identical to previous search, the result set is re-used and the +target is not searched. + +Limits may work perform local filtering as well, by using "local:" +for a limitmap. + --- 1.6.5 2011/11/01 + Updated bytarget command to contain a suggestions element with misspelled words and suggestions to these. pz2.js has been updated to deliver this onwards as well. Only target that currently delivers this is the solr diff --git a/configure.ac b/configure.ac index 2580281..ef4469c 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,9 @@ # Autoconf and automake setup AC_PREREQ(2.60) -AC_INIT([pazpar2],[1.6.5],[pazpar2-help@indexdata.dk]) +AC_INIT([pazpar2], +m4_esyscmd([. ./IDMETA; echo $VERSION|tr -d '\n']), +[pazpar2-help@indexdata.dk]) AC_CONFIG_HEADERS(src/config.h) @@ -22,7 +24,7 @@ AC_LANG(C) AC_C_INLINE -YAZ_INIT([static icu],[4.2.18]) +YAZ_INIT([static icu],[4.2.20]) if test -z "$YAZLIB"; then AC_MSG_ERROR([YAZ development libraries missing]) fi diff --git a/debian/control b/debian/control index 21e3fd7..9f04b67 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: extra Maintainer: Adam Dickmeiss Build-Depends: debhelper (>= 5), autotools-dev, - libyaz4-dev (>= 4.2.18), + libyaz4-dev (>= 4.2.20), docbook-xsl, libgnutls-dev Standards-Version: 3.7.2 diff --git a/doc/pazpar2_conf.xml b/doc/pazpar2_conf.xml index dcc1fdf..f41070c 100644 --- a/doc/pazpar2_conf.xml +++ b/doc/pazpar2_conf.xml @@ -1242,20 +1242,23 @@ Specifies attributes for limiting a search to a field - using - the limit parameter for search. In some cases the mapping of + the limit parameter for search. It can be used to filter locally + or remotely (search in a target). In some cases the mapping of a field to a value is identical to an existing cclmap field; in other cases the field must be specified in a different way - for example to match a complete field (rather than parts of a subfield). - The value of limitmap may have one of two forms: referral to - an exisiting CCL field or a raw PQF string. Leading string - determines type; either ccl: for CCL field or - rpn: for PQF/RPN. + The value of limitmap may have one of three forms: referral to + an existing CCL field, a raw PQF string or a local limit. Leading string + determines type; either ccl: for CCL field, + rpn: for PQF/RPN, or local: + for filtering in Pazpar2. The limitmap facility is supported for Pazpar2 version 1.6.0. + Local filtering is supported in Pazpar2 1.6.6. diff --git a/etc/.gitignore b/etc/.gitignore index 017796c..23669ea 100644 --- a/etc/.gitignore +++ b/etc/.gitignore @@ -1 +1,2 @@ pazpar2.cfg +pz22usi.xsl diff --git a/etc/cf.xsl b/etc/cf.xsl index ec4615f..4742628 100644 --- a/etc/cf.xsl +++ b/etc/cf.xsl @@ -16,6 +16,13 @@ + + @@ -121,6 +128,13 @@ + + @@ -192,6 +206,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etc/settings/opencontent-solr.xml b/etc/settings/opencontent-solr.xml index 0e3d3af..1263eee 100644 --- a/etc/settings/opencontent-solr.xml +++ b/etc/settings/opencontent-solr.xml @@ -1,4 +1,4 @@ - + diff --git a/pazpar2.spec b/pazpar2.spec index e65dc44..2f015ab 100644 --- a/pazpar2.spec +++ b/pazpar2.spec @@ -1,6 +1,7 @@ +%define idmetaversion %(. ./IDMETA; echo $VERSION|tr -d '\n') Summary: Metasearcher Name: pazpar2 -Version: 1.6.5 +Version: %{idmetaversion} Release: 1indexdata License: GPL Group: Applications/Internet diff --git a/src/Makefile.am b/src/Makefile.am index 55d3ed5..156d677 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,8 @@ libpazpar2_a_SOURCES = \ database.c database.h \ eventl.c eventl.h \ facet_limit.c facet_limit.h \ - host.h \ + getaddrinfo.c \ + host.c host.h \ http.c http.h http_command.c \ incref.c incref.h \ jenkins_hash.c jenkins_hash.h \ diff --git a/src/client.c b/src/client.c index 8751137..5100f80 100644 --- a/src/client.c +++ b/src/client.c @@ -121,6 +121,7 @@ struct client { YAZ_MUTEX mutex; int ref_count; char *id; + facet_limits_t facet_limits; }; struct suggestions { @@ -554,12 +555,61 @@ void client_got_records(struct client *cl) struct session *se = cl->session; if (se) { - client_unlock(cl); - session_alert_watch(se, SESSION_WATCH_SHOW); - session_alert_watch(se, SESSION_WATCH_BYTARGET); - session_alert_watch(se, SESSION_WATCH_TERMLIST); - session_alert_watch(se, SESSION_WATCH_RECORD); - client_lock(cl); + if (reclist_get_num_records(se->reclist) > 0) + { + client_unlock(cl); + session_alert_watch(se, SESSION_WATCH_SHOW); + session_alert_watch(se, SESSION_WATCH_BYTARGET); + session_alert_watch(se, SESSION_WATCH_TERMLIST); + session_alert_watch(se, SESSION_WATCH_RECORD); + client_lock(cl); + } + } +} + +static void client_record_ingest(struct client *cl) +{ + const char *msg, *addinfo; + ZOOM_record rec = 0; + ZOOM_resultset resultset = cl->resultset; + int offset = cl->record_offset; + if ((rec = ZOOM_resultset_record(resultset, offset))) + { + cl->record_offset++; + if (cl->session == 0) + ; + else if (ZOOM_record_error(rec, &msg, &addinfo, 0)) + { + yaz_log(YLOG_WARN, "Record error %s (%s): %s (rec #%d)", + msg, addinfo, client_get_id(cl), + cl->record_offset); + } + else + { + struct session_database *sdb = client_get_database(cl); + NMEM nmem = nmem_create(); + const char *xmlrec; + char type[80]; + + if (nativesyntax_to_type(sdb, type, rec)) + yaz_log(YLOG_WARN, "Failed to determine record type"); + xmlrec = ZOOM_record_get(rec, type, NULL); + if (!xmlrec) + yaz_log(YLOG_WARN, "ZOOM_record_get failed from %s", + client_get_id(cl)); + else + { + /* OK = 0, -1 = failure, -2 = Filtered */ + if (ingest_record(cl, xmlrec, cl->record_offset, nmem) == -1) + yaz_log(YLOG_WARN, "Failed to ingest from %s", client_get_id(cl)); + } + nmem_destroy(nmem); + } + } + else + { + yaz_log(YLOG_WARN, "Expected record, but got NULL, offset=%d", + offset); } } @@ -578,11 +628,9 @@ void client_record_response(struct client *cl) } else { - ZOOM_record rec = 0; - const char *msg, *addinfo; - if (cl->show_raw && cl->show_raw->active) { + ZOOM_record rec = 0; if ((rec = ZOOM_resultset_record(resultset, cl->show_raw->position-1))) { @@ -597,49 +645,21 @@ void client_record_response(struct client *cl) } else { - int offset = cl->record_offset; - if ((rec = ZOOM_resultset_record(resultset, offset))) - { - cl->record_offset++; - if (cl->session == 0) - ; - else if (ZOOM_record_error(rec, &msg, &addinfo, 0)) - { - yaz_log(YLOG_WARN, "Record error %s (%s): %s (rec #%d)", - msg, addinfo, client_get_id(cl), - cl->record_offset); - } - else - { - struct session_database *sdb = client_get_database(cl); - NMEM nmem = nmem_create(); - const char *xmlrec; - char type[80]; - - if (nativesyntax_to_type(sdb, type, rec)) - yaz_log(YLOG_WARN, "Failed to determine record type"); - xmlrec = ZOOM_record_get(rec, type, NULL); - if (!xmlrec) - yaz_log(YLOG_WARN, "ZOOM_record_get failed from %s", - client_get_id(cl)); - else - { - /* OK = 0, -1 = failure, -2 = Filtered */ - if (ingest_record(cl, xmlrec, cl->record_offset, nmem) == -1) - yaz_log(YLOG_WARN, "Failed to ingest from %s", client_get_id(cl)); - } - nmem_destroy(nmem); - } - } - else - { - yaz_log(YLOG_WARN, "Expected record, but got NULL, offset=%d", - offset); - } + client_record_ingest(cl); } } } +void client_reingest(struct client *cl) +{ + int i = cl->startrecs; + int to = cl->record_offset; + + cl->record_offset = i; + for (; i < to; i++) + client_record_ingest(cl); +} + static void client_set_facets_request(struct client *cl, ZOOM_connection link) { struct session_database *sdb = client_get_database(cl); @@ -683,12 +703,37 @@ int client_has_facet(struct client *cl, const char *name) return 0; } -void client_start_search(struct client *cl, const char *sort_strategy_and_spec, - int increasing) +static const char *get_strategy_plus_sort(struct client *l, const char *field) +{ + struct session_database *sdb = client_get_database(l); + struct setting *s; + + const char *strategy_plus_sort = 0; + + for (s = sdb->settings[PZ_SORTMAP]; s; s = s->next) + { + char *p = strchr(s->name + 3, ':'); + if (!p) + { + yaz_log(YLOG_WARN, "Malformed sortmap name: %s", s->name); + continue; + } + p++; + if (!strcmp(p, field)) + { + strategy_plus_sort = s->value; + break; + } + } + return strategy_plus_sort; +} + +void client_start_search(struct client *cl) { struct session_database *sdb = client_get_database(cl); struct connection *co = client_get_connection(cl); ZOOM_connection link = connection_get_link(co); + struct session *se = client_get_session(cl); ZOOM_resultset rs; const char *opt_piggyback = session_setting_oneval(sdb, PZ_PIGGYBACK); const char *opt_queryenc = session_setting_oneval(sdb, PZ_QUERYENCODING); @@ -704,7 +749,6 @@ void client_start_search(struct client *cl, const char *sort_strategy_and_spec, assert(link); - cl->record_offset = 0; cl->diagnostic = 0; if (extra_args && *extra_args) @@ -767,25 +811,43 @@ void client_start_search(struct client *cl, const char *sort_strategy_and_spec, ZOOM_query_prefix(q, cl->pquery); } - if (sort_strategy_and_spec && - strlen(sort_strategy_and_spec) < 40 /* spec below */) - { - char spec[50], *p; - strcpy(spec, sort_strategy_and_spec); - p = strchr(spec, ':'); - if (p) + if (se->sorted_results) + { /* first entry is current sorting ! */ + const char *sort_strategy_and_spec = + get_strategy_plus_sort(cl, se->sorted_results->field); + int increasing = se->sorted_results->increasing; + if (sort_strategy_and_spec && strlen(sort_strategy_and_spec) < 40) { - *p++ = '\0'; /* cut the string in two */ - while (*p == ' ') - p++; - if (increasing) - strcat(p, " <"); - else - strcat(p, " >"); - yaz_log(YLOG_LOG, "applying %s %s", spec, p); - ZOOM_query_sortby2(q, spec, p); + char spec[50], *p; + strcpy(spec, sort_strategy_and_spec); + p = strchr(spec, ':'); + if (p) + { + *p++ = '\0'; /* cut the string in two */ + while (*p == ' ') + p++; + if (increasing) + strcat(p, " <"); + else + strcat(p, " >"); + yaz_log(YLOG_LOG, "applying %s %s", spec, p); + ZOOM_query_sortby2(q, spec, p); + } + } + else + { + /* no native sorting.. If this is not the first search, then + skip it entirely */ + if (se->sorted_results->next) + { + ZOOM_query_destroy(q); + client_set_state_nb(cl, Client_Idle); + return; + } } } + cl->hits = 0; + cl->record_offset = 0; rs = ZOOM_connection_search(link, q); ZOOM_query_destroy(q); ZOOM_resultset_destroy(cl->resultset); @@ -814,6 +876,7 @@ struct client *client_create(const char *id) pazpar2_mutex_create(&cl->mutex, "client"); cl->preferred = 0; cl->ref_count = 1; + cl->facet_limits = 0; assert(id); cl->id = xstrdup(id); client_use(1); @@ -852,6 +915,7 @@ int client_destroy(struct client *c) c->cqlquery = 0; xfree(c->id); assert(!c->connection); + facet_limits_destroy(c->facet_limits); if (c->resultset) { @@ -975,10 +1039,38 @@ static char *make_solrquery(struct client *cl) return r; } -static void apply_limit(struct session_database *sdb, - facet_limits_t facet_limits, - WRBUF w_pqf, WRBUF w_ccl) +const char *client_get_facet_limit_local(struct client *cl, + struct session_database *sdb, + int *l, + NMEM nmem, int *num, char ***values) { + const char *name = 0; + const char *value = 0; + for (; (name = facet_limits_get(cl->facet_limits, *l, &value)); (*l)++) + { + struct setting *s = 0; + + for (s = sdb->settings[PZ_LIMITMAP]; s; s = s->next) + { + const char *p = strchr(s->name + 3, ':'); + if (p && !strcmp(p + 1, name) && s->value && + !strncmp(s->value, "local:", 6)) + { + nmem_strsplit_escape2(nmem, "|", value, values, + num, 1, '\\', 1); + (*l)++; + return name; + } + } + } + return 0; +} + +static int apply_limit(struct session_database *sdb, + facet_limits_t facet_limits, + WRBUF w_pqf, WRBUF w_ccl) +{ + int ret = 0; int i = 0; const char *name; const char *value; @@ -1030,6 +1122,14 @@ static void apply_limit(struct session_database *sdb, wrbuf_puts(w_ccl, ")"); } + else if (!strncmp(s->value, "local:", 6)) + ; + else + { + yaz_log(YLOG_WARN, "Target %s: Bad limitmap '%s'", + sdb->database->id, s->value); + ret = -1; /* bad limitmap */ + } break; } } @@ -1041,11 +1141,13 @@ static void apply_limit(struct session_database *sdb, } } nmem_destroy(nmem_tmp); + return ret; } // Parse the query given the settings specific to this client int client_parse_query(struct client *cl, const char *query, - facet_limits_t facet_limits) + facet_limits_t facet_limits, + const char *startrecs, const char *maxrecs) { struct session *se = client_get_session(cl); struct session_database *sdb = client_get_database(cl); @@ -1057,10 +1159,24 @@ int client_parse_query(struct client *cl, const char *query, const char *pqf_strftime = session_setting_oneval(sdb, PZ_PQF_STRFTIME); const char *query_syntax = session_setting_oneval(sdb, PZ_QUERY_SYNTAX); WRBUF w_ccl, w_pqf; + int ret_value = 1; + if (!ccl_map) return -1; - cl->hits = -1; + + if (maxrecs && atoi(maxrecs) != cl->maxrecs) + { + ret_value = 0; + cl->maxrecs = atoi(maxrecs); + } + + if (startrecs && atoi(startrecs) != cl->startrecs) + { + ret_value = 0; + cl->startrecs = atoi(startrecs); + } + w_ccl = wrbuf_alloc(); wrbuf_puts(w_ccl, query); @@ -1071,7 +1187,11 @@ int client_parse_query(struct client *cl, const char *query, wrbuf_puts(w_pqf, " "); } - apply_limit(sdb, facet_limits, w_pqf, w_ccl); + if (apply_limit(sdb, facet_limits, w_pqf, w_ccl)) + return -2; + + facet_limits_destroy(cl->facet_limits); + cl->facet_limits = facet_limits_dup(facet_limits); yaz_log(YLOG_LOG, "CCL query: %s", wrbuf_cstr(w_ccl)); cn = ccl_find_str(ccl_map, wrbuf_cstr(w_ccl), &cerror, &cpos); @@ -1108,8 +1228,12 @@ int client_parse_query(struct client *cl, const char *query, wrbuf_putc(w_pqf, cp[0]); } } - xfree(cl->pquery); - cl->pquery = xstrdup(wrbuf_cstr(w_pqf)); + if (!cl->pquery || strcmp(cl->pquery, wrbuf_cstr(w_pqf))) + { + xfree(cl->pquery); + cl->pquery = xstrdup(wrbuf_cstr(w_pqf)); + ret_value = 0; + } wrbuf_destroy(w_pqf); yaz_log(YLOG_LOG, "PQF query: %s", cl->pquery); @@ -1142,7 +1266,7 @@ int client_parse_query(struct client *cl, const char *query, } ccl_rpn_delete(cn); - return 0; + return ret_value; } void client_set_session(struct client *cl, struct session *se) @@ -1231,21 +1355,11 @@ const char *client_get_id(struct client *cl) return cl->id; } -void client_set_maxrecs(struct client *cl, int v) -{ - cl->maxrecs = v; -} - int client_get_maxrecs(struct client *cl) { return cl->maxrecs; } -void client_set_startrecs(struct client *cl, int v) -{ - cl->startrecs = v; -} - void client_set_preferred(struct client *cl, int v) { cl->preferred = v; diff --git a/src/client.h b/src/client.h index 9cc9666..275b294 100644 --- a/src/client.h +++ b/src/client.h @@ -77,24 +77,22 @@ int client_prep_connection(struct client *cl, int operation_timeout, int session_timeout, iochan_man_t iochan, const struct timeval *abstime); -void client_start_search(struct client *cl, const char *sort_strategy_and_spec, - int increasing); +void client_start_search(struct client *cl); void client_set_session(struct client *cl, struct session *se); int client_is_active(struct client *cl); int client_is_active_preferred(struct client *cl); struct client *client_next_in_session(struct client *cl); int client_parse_query(struct client *cl, const char *query, - facet_limits_t facet_limits); + facet_limits_t facet_limits, const char *startrecs, + const char *maxrecs); Odr_int client_get_hits(struct client *cl); int client_get_num_records(struct client *cl); int client_get_diagnostic(struct client *cl); void client_set_diagnostic(struct client *cl, int diagnostic); void client_set_database(struct client *cl, struct session_database *db); const char *client_get_id(struct client *cl); -void client_set_maxrecs(struct client *cl, int v); int client_get_maxrecs(struct client *cl); -void client_set_startrecs(struct client *cl, int v); void client_remove_from_session(struct client *c); void client_incref(struct client *c); void client_got_records(struct client *c); @@ -103,7 +101,11 @@ void client_unlock(struct client *c); int client_has_facet(struct client *cl, const char *name); void client_check_preferred_watch(struct client *cl); - +void client_reingest(struct client *cl); +const char *client_get_facet_limit_local(struct client *cl, + struct session_database *sdb, + int *l, + NMEM nmem, int *num, char ***values); #endif /* diff --git a/src/connection.c b/src/connection.c index 4db12ff..4be296f 100644 --- a/src/connection.c +++ b/src/connection.c @@ -150,7 +150,7 @@ static void connection_destroy(struct connection *co) ZOOM_connection_destroy(co->link); iochan_destroy(co->iochan); } - yaz_log(YLOG_DEBUG, "%p Connection destroy %s", co, co->host->hostport); + yaz_log(YLOG_DEBUG, "%p Connection destroy %s", co, co->host->url); if (co->client) { @@ -183,7 +183,8 @@ static struct connection *connection_create(struct client *cl, co->operation_timeout = operation_timeout; co->session_timeout = session_timeout; - connection_connect(co, iochan_man); + if (host->ipport) + connection_connect(co, iochan_man); yaz_mutex_enter(host->mutex); co->next = co->host->connections; @@ -368,6 +369,50 @@ static void connection_release(struct connection *co) co->client = 0; } +void connect_resolver_host(struct host *host, iochan_man_t iochan_man) +{ + struct connection *con; + +start: + yaz_mutex_enter(host->mutex); + con = host->connections; + while (con) + { + if (con->state == Conn_Closed) + { + if (!host->ipport) /* unresolved */ + { + remove_connection_from_host(con); + yaz_mutex_leave(host->mutex); + connection_destroy(con); + goto start; + /* start all over .. at some point it will be NULL */ + } + else if (!con->client) + { + remove_connection_from_host(con); + yaz_mutex_leave(host->mutex); + connection_destroy(con); + /* start all over .. at some point it will be NULL */ + goto start; + } + else + { + yaz_mutex_leave(host->mutex); + connection_connect(con, iochan_man); + client_start_search(con->client); + goto start; + } + } + else + { + yaz_log(YLOG_LOG, "connect_resolver_host: state=%d", con->state); + con = con->next; + } + } + yaz_mutex_leave(host->mutex); +} + static struct host *connection_get_host(struct connection *con) { return con->host; @@ -383,7 +428,6 @@ static int connection_connect(struct connection *con, iochan_man_t iochan_man) const char *sru_version = 0; struct session_database *sdb = client_get_database(con->client); - const char *zproxy = session_setting_oneval(sdb, PZ_ZPROXY); const char *apdulog = session_setting_oneval(sdb, PZ_APDULOG); assert(con); @@ -395,11 +439,19 @@ static int connection_connect(struct connection *con, iochan_man_t iochan_man) if ((charset = session_setting_oneval(sdb, PZ_NEGOTIATION_CHARSET))) ZOOM_options_set(zoptions, "charset", charset); - if (zproxy && *zproxy) + assert(host->ipport); + if (host->proxy) { - con->zproxy = xstrdup(zproxy); - ZOOM_options_set(zoptions, "proxy", zproxy); + yaz_log(YLOG_LOG, "proxy=%s", host->ipport); + ZOOM_options_set(zoptions, "proxy", host->ipport); } + else + { + assert(host->tproxy); + yaz_log(YLOG_LOG, "tproxy=%s", host->ipport); + ZOOM_options_set(zoptions, "tproxy", host->ipport); + } + if (apdulog && *apdulog) ZOOM_options_set(zoptions, "apdulog", apdulog); @@ -421,14 +473,14 @@ static int connection_connect(struct connection *con, iochan_man_t iochan_man) { char http_hostport[512]; strcpy(http_hostport, "http://"); - strcat(http_hostport, host->hostport); + strcat(http_hostport, host->url); + yaz_log(YLOG_LOG, "SRU connect to : %s", http_hostport); ZOOM_connection_connect(con->link, http_hostport, 0); } else { - ZOOM_connection_connect(con->link, host->hostport, 0); + ZOOM_connection_connect(con->link, host->url, 0); } - con->iochan = iochan_create(-1, connection_handler, 0, "connection_socket"); con->state = Conn_Connecting; iochan_settimeout(con->iochan, con->operation_timeout); @@ -450,7 +502,9 @@ int client_prep_connection(struct client *cl, struct session_database *sdb = client_get_database(cl); const char *zproxy = session_setting_oneval(sdb, PZ_ZPROXY); const char *url = session_setting_oneval(sdb, PZ_URL); + const char *sru = session_setting_oneval(sdb, PZ_SRU); struct host *host = 0; + int default_port = *sru ? 80 : 210; if (zproxy && zproxy[0] == '\0') zproxy = 0; @@ -459,10 +513,12 @@ int client_prep_connection(struct client *cl, url = sdb->database->id; host = find_host(client_get_session(cl)->service->server->database_hosts, - url); + url, zproxy, default_port, iochan_man); yaz_log(YLOG_DEBUG, "client_prep_connection: target=%s url=%s", client_get_id(cl), url); + if (!host) + return 0; co = client_get_connection(cl); diff --git a/src/connection.h b/src/connection.h index 6b61047..0aa0f4c 100644 --- a/src/connection.h +++ b/src/connection.h @@ -33,6 +33,7 @@ struct host; void connect_resolver_host(struct host *host, iochan_man_t iochan); ZOOM_connection connection_get_link(struct connection *co); void connection_continue(struct connection *co); +void connect_resolver_host(struct host *host, iochan_man_t iochan_man); #endif diff --git a/src/database.c b/src/database.c index 41e0f06..c933181 100644 --- a/src/database.c +++ b/src/database.c @@ -54,52 +54,6 @@ struct database_criterion { struct database_criterion *next; }; -struct database_hosts { - struct host *hosts; - YAZ_MUTEX mutex; -}; - -// Create a new host structure for hostport -static struct host *create_host(const char *hostport) -{ - struct host *host; - char *db_comment; - - host = xmalloc(sizeof(struct host)); - host->hostport = xstrdup(hostport); - db_comment = strchr(host->hostport, '#'); - if (db_comment) - *db_comment = '\0'; - host->connections = 0; - host->mutex = 0; - - pazpar2_mutex_create(&host->mutex, "host"); - - yaz_cond_create(&host->cond_ready); - - return host; -} - -struct host *find_host(database_hosts_t hosts, const char *hostport) -{ - struct host *p; - yaz_mutex_enter(hosts->mutex); - for (p = hosts->hosts; p; p = p->next) - if (!strcmp(p->hostport, hostport)) - break; - if (!p) - { - p = create_host(hostport); - if (p) - { - p->next = hosts->hosts; - hosts->hosts = p; - } - } - yaz_mutex_leave(hosts->mutex); - return p; -} - struct database *new_database(const char *id, NMEM nmem) { struct database *db; @@ -313,34 +267,6 @@ int predef_grep_databases(void *context, struct conf_service *service, return i; } -database_hosts_t database_hosts_create(void) -{ - database_hosts_t p = xmalloc(sizeof(*p)); - p->hosts = 0; - p->mutex = 0; - pazpar2_mutex_create(&p->mutex, "database"); - return p; -} - -void database_hosts_destroy(database_hosts_t *pp) -{ - if (*pp) - { - struct host *p = (*pp)->hosts; - while (p) - { - struct host *p_next = p->next; - yaz_mutex_destroy(&p->mutex); - yaz_cond_destroy(&p->cond_ready); - xfree(p->hostport); - xfree(p); - p = p_next; - } - yaz_mutex_destroy(&(*pp)->mutex); - xfree(*pp); - } -} - /* * Local variables: * c-basic-offset: 4 diff --git a/src/database.h b/src/database.h index 1394732..2b0a3fc 100644 --- a/src/database.h +++ b/src/database.h @@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef DATABASE_H #define DATABASE_H -typedef struct database_hosts *database_hosts_t; struct session_database; struct session; struct conf_service; @@ -33,9 +32,5 @@ int predef_grep_databases(void *context, struct conf_service *service, int match_zurl(const char *zurl, const char *pattern); struct database *new_database(const char *id, NMEM nmem); -database_hosts_t database_hosts_create(void); -void database_hosts_destroy(database_hosts_t *); - -struct host *find_host(database_hosts_t hosts, const char *hostport); #endif diff --git a/src/facet_limit.c b/src/facet_limit.c index 44bcff0..92d7eaf 100644 --- a/src/facet_limit.c +++ b/src/facet_limit.c @@ -39,6 +39,28 @@ struct facet_limits { char **darray; }; +facet_limits_t facet_limits_dup(facet_limits_t fl) +{ + int i; + NMEM nmem = nmem_create(); + facet_limits_t fn = nmem_malloc(nmem, sizeof(*fn)); + fn->nmem = nmem; + fn->num = fl->num; + fn->darray = 0; + if (fl->num) + { + fn->darray = nmem_malloc(nmem, fn->num * sizeof(*fn->darray)); + for (i = 0; i < fn->num; i++) + { + const char *src = fl->darray[i]; + size_t sz = strlen(src) + 2 + strlen(src + strlen(src) + 1); + fn->darray[i] = nmem_malloc(nmem, sz); + memcpy(fn->darray[i], src, sz); + } + } + return fn; +} + facet_limits_t facet_limits_create(const char *param) { int i; diff --git a/src/facet_limit.h b/src/facet_limit.h index 60b8e9a..60ce8ce 100644 --- a/src/facet_limit.h +++ b/src/facet_limit.h @@ -32,6 +32,8 @@ const char *facet_limits_get(facet_limits_t fl, int idx, const char **value); void facet_limits_destroy(facet_limits_t fl); +facet_limits_t facet_limits_dup(facet_limits_t fl); + #endif /* diff --git a/src/getaddrinfo.c b/src/getaddrinfo.c new file mode 100644 index 0000000..3ca2f4e --- /dev/null +++ b/src/getaddrinfo.c @@ -0,0 +1,228 @@ +/* This file is part of Pazpar2. + Copyright (C) 2006-2011 Index Data + +Pazpar2 is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#if HAVE_CONFIG_H +#include +#endif + +#include "sel_thread.h" + +#if HAVE_UNISTD_H +#include +#endif +#include + +#include +#include +#if HAVE_SYS_SOCKET_H +#include +#endif +#ifdef WIN32 +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif + +#include +#include +#include + +#include "session.h" +#include "connection.h" +#include "host.h" + +/* Only use a threaded resolver on Unix that offers getaddrinfo. + gethostbyname is NOT reentrant. + */ +#if HAVE_GETADDRINFO +#ifndef WIN32 +#define USE_THREADED_RESOLVER 1 +#endif +#endif + +struct work { + char *hostport; /* hostport to be resolved in separate thread */ + char *ipport; /* result or NULL if it could not be resolved */ + struct host *host; /* host that we're dealing with - mother thread */ + iochan_man_t iochan_man; /* iochan manager */ +}; + +static int log_level = YLOG_LOG; + +void perform_getaddrinfo(struct work *w) +{ + int res = 0; + char *port; +#if HAVE_GETADDRINFO + struct addrinfo *addrinfo, hints; +#else + struct hostent *hp; +#endif + char *hostport = xstrdup(w->hostport); + if ((port = strchr(hostport, ':'))) + *(port++) = '\0'; + else + { + port = "210"; + } + +#if HAVE_GETADDRINFO + hints.ai_flags = 0; + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_addrlen = 0; + hints.ai_addr = 0; + hints.ai_canonname = 0; + hints.ai_next = 0; + // This is not robust code. It assumes that getaddrinfo always + // returns AF_INET address. + if ((res = getaddrinfo(hostport, port, &hints, &addrinfo))) + { + yaz_log(YLOG_WARN, "Failed to resolve %s %s", + w->hostport, gai_strerror(res)); + } + else + { + char ipport[128]; + unsigned char addrbuf[4]; + assert(addrinfo->ai_family == PF_INET); + memcpy(addrbuf, + &((struct sockaddr_in*)addrinfo->ai_addr)->sin_addr.s_addr, 4); + sprintf(ipport, "%u.%u.%u.%u:%s", + addrbuf[0], addrbuf[1], addrbuf[2], addrbuf[3], port); + freeaddrinfo(addrinfo); + w->ipport = xstrdup(ipport); + yaz_log(log_level, "Resolved %s -> %s", hostport, ipport); + } +#else + hp = gethostbyname(hostport); + if (!hp) + { + yaz_log(YLOG_WARN|YLOG_ERRNO, "Failed to resolve %s", hostport); + } + else + { + char ipport[128]; + unsigned char addrbuf[4]; + + memcpy(addrbuf, *hp->h_addr_list, 4 * sizeof(unsigned char)); + sprintf(ipport, "%u.%u.%u.%u:%s", + addrbuf[0], addrbuf[1], addrbuf[2], addrbuf[3], port); + w->ipport = xstrdup(ipport); + yaz_log(log_level, "Resolved %s -> %s", hostport, ipport); + } +#endif + xfree(hostport); +} + +static void work_handler(void *vp) +{ + struct work *w = vp; + + int sec = 0; /* >0 for debugging/testing purposes */ + if (sec) + { + yaz_log(log_level, "waiting %d seconds", sec); +#if HAVE_UNISTD_H + sleep(sec); +#endif + } + perform_getaddrinfo(w); +} + +#if USE_THREADED_RESOLVER +void iochan_handler(struct iochan *i, int event) +{ + sel_thread_t p = iochan_getdata(i); + + if (event & EVENT_INPUT) + { + struct work *w = sel_thread_result(p); + w->host->ipport = w->ipport; + connect_resolver_host(w->host, w->iochan_man); + xfree(w); + } +} + +static sel_thread_t resolver_thread = 0; + +static void getaddrinfo_start(iochan_man_t iochan_man) +{ + int fd; + sel_thread_t p = resolver_thread = + sel_thread_create(work_handler, 0 /* work_destroy */, &fd, + 3 /* no of resolver threads */); + if (!p) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "sel_create_create failed"); + exit(1); + } + else + { + IOCHAN chan = iochan_create(fd, iochan_handler, EVENT_INPUT, + "getaddrinfo_socket"); + iochan_setdata(chan, p); + iochan_add(iochan_man, chan); + } + yaz_log(log_level, "resolver start"); + resolver_thread = p; +} +#endif + +int host_getaddrinfo(struct host *host, iochan_man_t iochan_man) +{ + struct work *w = xmalloc(sizeof(*w)); + int use_thread = 0; /* =0 to disable threading entirely */ + + w->hostport = host->tproxy ? host->tproxy : host->proxy; + w->ipport = 0; + w->host = host; + w->iochan_man = iochan_man; +#if USE_THREADED_RESOLVER + if (use_thread) + { + if (resolver_thread == 0) + getaddrinfo_start(iochan_man); + assert(resolver_thread); + sel_thread_add(resolver_thread, w); + return 0; + } +#endif + perform_getaddrinfo(w); + host->ipport = w->ipport; + xfree(w); + if (!host->ipport) + return -1; + return 0; +} + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/host.c b/src/host.c new file mode 100644 index 0000000..57c6eb6 --- /dev/null +++ b/src/host.c @@ -0,0 +1,153 @@ +/* This file is part of Pazpar2. + Copyright (C) 2006-2011 Index Data + +Pazpar2 is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "ppmutex.h" +#include "session.h" +#include "host.h" + +#include + +struct database_hosts { + struct host *hosts; + YAZ_MUTEX mutex; +}; + +// Create a new host structure for hostport +static struct host *create_host(const char *url, const char *proxy, + int default_port, + iochan_man_t iochan_man) +{ + struct host *host; + char *db_comment; + + host = xmalloc(sizeof(struct host)); + host->url = xstrdup(url); + host->proxy = 0; + host->tproxy = 0; + if (proxy && *proxy) + host->proxy = xstrdup(proxy); + else + { + char *cp; + + host->tproxy = xmalloc (strlen(url) + 10); /* so we can add :port */ + strcpy(host->tproxy, url); + for (cp = host->tproxy; *cp; cp++) + if (strchr("/?#~", *cp)) + { + *cp = '\0'; + break; + } + if (!strchr(host->tproxy, ':')) + sprintf(cp, ":%d", default_port); /* no port given, add it */ + } + + db_comment = strchr(host->url, '#'); + if (db_comment) + *db_comment = '\0'; + host->connections = 0; + host->ipport = 0; + host->mutex = 0; + + if (host_getaddrinfo(host, iochan_man)) + { + xfree(host->ipport); + xfree(host->tproxy); + xfree(host->proxy); + xfree(host->url); + xfree(host); + return 0; + } + pazpar2_mutex_create(&host->mutex, "host"); + + yaz_cond_create(&host->cond_ready); + + return host; +} + +struct host *find_host(database_hosts_t hosts, const char *url, + const char *proxy, int port, + iochan_man_t iochan_man) +{ + struct host *p; + yaz_mutex_enter(hosts->mutex); + for (p = hosts->hosts; p; p = p->next) + if (!strcmp(p->url, url)) + break; + if (!p) + { + p = create_host(url, proxy, port, iochan_man); + if (p) + { + p->next = hosts->hosts; + hosts->hosts = p; + } + } + yaz_mutex_leave(hosts->mutex); + return p; +} + +database_hosts_t database_hosts_create(void) +{ + database_hosts_t p = xmalloc(sizeof(*p)); + p->hosts = 0; + p->mutex = 0; + pazpar2_mutex_create(&p->mutex, "database"); + return p; +} + +void database_hosts_destroy(database_hosts_t *pp) +{ + if (*pp) + { + struct host *p = (*pp)->hosts; + while (p) + { + struct host *p_next = p->next; + yaz_mutex_destroy(&p->mutex); + yaz_cond_destroy(&p->cond_ready); + xfree(p->url); + xfree(p->ipport); + xfree(p); + p = p_next; + } + yaz_mutex_destroy(&(*pp)->mutex); + xfree(*pp); + } +} + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/host.h b/src/host.h index 752ca09..d30632f 100644 --- a/src/host.h +++ b/src/host.h @@ -22,15 +22,27 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include +typedef struct database_hosts *database_hosts_t; + /** \brief Represents a host (irrespective of databases) */ struct host { - char *hostport; + char *url; // logical host/database?args .. + char *tproxy; // tproxy address (no Z39.50 UI) + char *proxy; // logical proxy address + char *ipport; // tproxy or proxy resolved struct connection *connections; // All connections to this struct host *next; YAZ_MUTEX mutex; YAZ_COND cond_ready; }; +database_hosts_t database_hosts_create(void); +void database_hosts_destroy(database_hosts_t *); + +struct host *find_host(database_hosts_t hosts, const char *hostport, + const char *proxy, int port, iochan_man_t iochan_man); + +int host_getaddrinfo(struct host *host, iochan_man_t iochan_man); #endif diff --git a/src/pazpar2.c b/src/pazpar2.c index 585c0f8..cb0d162 100644 --- a/src/pazpar2.c +++ b/src/pazpar2.c @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #endif #ifdef WIN32 #include +#include #endif #if HAVE_UNISTD_H #include @@ -157,7 +158,13 @@ static int sc_main( show_version(); break; case 'w': - if (chdir(arg)) + if ( +#ifdef WIN32 + _chdir +#else + chdir +#endif + (arg)) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "chdir %s", arg); return 1; diff --git a/src/pazpar2_config.h b/src/pazpar2_config.h index 403ec16..f5fb27d 100644 --- a/src/pazpar2_config.h +++ b/src/pazpar2_config.h @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "charsets.h" #include "http.h" #include "database.h" +#include "host.h" enum conf_metadata_type { Metadata_type_generic, // Generic text field diff --git a/src/session.c b/src/session.c index 21a4729..cdd588c 100644 --- a/src/session.c +++ b/src/session.c @@ -95,12 +95,6 @@ struct client_list { struct client_list *next; }; -struct session_sorted_results { - const char *field; - int increasing; - struct session_sorted_results *next; -}; - /* session counting (1) , disable client counting (0) */ static YAZ_MUTEX g_session_mutex = 0; static int no_sessions = 0; @@ -165,13 +159,14 @@ static void session_leave(struct session *s) yaz_mutex_leave(s->session_mutex); } -void add_facet(struct session *s, const char *type, const char *value, int count) +static void session_normalize_facet(struct session *s, const char *type, + const char *value, + WRBUF display_wrbuf, + WRBUF facet_wrbuf) { struct conf_service *service = s->service; pp2_charset_token_t prt; const char *facet_component; - WRBUF facet_wrbuf = wrbuf_alloc(); - WRBUF display_wrbuf = wrbuf_alloc(); int i; const char *icu_chain_id = 0; @@ -208,6 +203,14 @@ void add_facet(struct session *s, const char *type, const char *value, int count } } pp2_charset_token_destroy(prt); +} + +void add_facet(struct session *s, const char *type, const char *value, int count) +{ + WRBUF facet_wrbuf = wrbuf_alloc(); + WRBUF display_wrbuf = wrbuf_alloc(); + + session_normalize_facet(s, type, value, display_wrbuf, facet_wrbuf); if (wrbuf_len(facet_wrbuf)) { @@ -405,12 +408,8 @@ static int prepare_map(struct session *se, struct session_database *sdb) { const char *s; - if (!sdb->settings) - { - session_log(se, YLOG_WARN, "No settings on %s", sdb->database->id); - return -1; - } - if ((s = session_setting_oneval(sdb, PZ_XSLT))) + if (sdb->settings && sdb->settings[PZ_XSLT] && !sdb->map && + (s = session_setting_oneval(sdb, PZ_XSLT))) { char auto_stylesheet[256]; @@ -445,25 +444,6 @@ static int prepare_map(struct session *se, struct session_database *sdb) return 0; } -// This analyzes settings and recomputes any supporting data structures -// if necessary. -static int prepare_session_database(struct session *se, - struct session_database *sdb) -{ - if (!sdb->settings) - { - session_log(se, YLOG_WARN, - "No settings associated with %s", sdb->database->id); - return -1; - } - if (sdb->settings[PZ_XSLT] && !sdb->map) - { - if (prepare_map(se, sdb) < 0) - return -1; - } - return 0; -} - // called if watch should be removed because http_channel is to be destroyed static void session_watch_cancel(void *data, struct http_channel *c, void *data2) @@ -530,26 +510,60 @@ void session_alert_watch(struct session *s, int what) static void select_targets_callback(struct session *se, struct session_database *db) { - struct client *cl = client_create(db->database->id); + struct client *cl; struct client_list *l; - client_set_database(cl, db); + for (l = se->clients_cached; l; l = l->next) + if (client_get_database(l->client) == db) + break; - client_set_session(cl, se); + if (l) + cl = l->client; + else + { + cl = client_create(db->database->id); + client_set_database(cl, db); + client_set_session(cl, se); + + l = xmalloc(sizeof(*l)); + l->client = cl; + l->next = se->clients_cached; + se->clients_cached = l; + } l = xmalloc(sizeof(*l)); l->client = cl; - l->next = se->clients; - se->clients = l; + l->next = se->clients_active; + se->clients_active = l; } -static void session_remove_clients(struct session *se) +static void session_reset_active_clients(struct session *se, + struct client_list *new_list) { struct client_list *l; session_enter(se); - l = se->clients; - se->clients = 0; + l = se->clients_active; + se->clients_active = new_list; + session_leave(se); + + while (l) + { + struct client_list *l_next = l->next; + xfree(l); + l = l_next; + } +} + +static void session_remove_cached_clients(struct session *se) +{ + struct client_list *l; + + session_reset_active_clients(se, 0); + + session_enter(se); + l = se->clients_cached; + se->clients_cached = 0; session_leave(se); while (l) @@ -578,7 +592,7 @@ int session_active_clients(struct session *s) struct client_list *l; int res = 0; - for (l = s->clients; l; l = l->next) + for (l = s->clients_active; l; l = l->next) if (client_is_active(l->client)) res++; @@ -590,38 +604,13 @@ int session_is_preferred_clients_ready(struct session *s) struct client_list *l; int res = 0; - for (l = s->clients; l; l = l->next) + for (l = s->clients_active; l; l = l->next) if (client_is_active_preferred(l->client)) res++; session_log(s, YLOG_DEBUG, "Has %d active preferred clients.", res); return res == 0; } -static const char *get_strategy_plus_sort(struct client *l, const char *field) -{ - struct session_database *sdb = client_get_database(l); - struct setting *s; - - const char *strategy_plus_sort = 0; - - for (s = sdb->settings[PZ_SORTMAP]; s; s = s->next) - { - char *p = strchr(s->name + 3, ':'); - if (!p) - { - yaz_log(YLOG_WARN, "Malformed sortmap name: %s", s->name); - continue; - } - p++; - if (!strcmp(p, field)) - { - strategy_plus_sort = s->value; - break; - } - } - return strategy_plus_sort; -} - void session_sort(struct session *se, const char *field, int increasing) { struct session_sorted_results *sr; @@ -650,19 +639,15 @@ void session_sort(struct session *se, const char *field, int increasing) sr->next = se->sorted_results; se->sorted_results = sr; - for (l = se->clients; l; l = l->next) + for (l = se->clients_active; l; l = l->next) { struct client *cl = l->client; - const char *strategy_plus_sort = get_strategy_plus_sort(cl, field); - if (strategy_plus_sort) - { - struct timeval tval; - if (client_prep_connection(cl, se->service->z3950_operation_timeout, - se->service->z3950_session_timeout, - se->service->server->iochan_man, - &tval)) - client_start_search(cl, strategy_plus_sort, increasing); - } + struct timeval tval; + if (client_prep_connection(cl, se->service->z3950_operation_timeout, + se->service->z3950_session_timeout, + se->service->server->iochan_man, + &tval)) + client_start_search(cl); } session_leave(se); } @@ -678,8 +663,9 @@ enum pazpar2_error_code session_search(struct session *se, { int live_channels = 0; int no_working = 0; - int no_failed = 0; - struct client_list *l; + int no_failed_query = 0; + int no_failed_limit = 0; + struct client_list *l, *l0; struct timeval tval; facet_limits_t facet_limits; @@ -687,11 +673,15 @@ enum pazpar2_error_code session_search(struct session *se, *addinfo = 0; - session_remove_clients(se); + if (se->settings_modified) + session_remove_cached_clients(se); + else + session_reset_active_clients(se, 0); session_enter(se); reclist_destroy(se->reclist); se->reclist = 0; + se->settings_modified = 0; relevance_destroy(&se->relevance); nmem_reset(se->nmem); se->total_records = se->total_merged = 0; @@ -722,41 +712,67 @@ enum pazpar2_error_code session_search(struct session *se, session_leave(se); return PAZPAR2_MALFORMED_PARAMETER_VALUE; } - for (l = se->clients; l; l = l->next) + + l0 = se->clients_active; + se->clients_active = 0; + session_leave(se); + + for (l = l0; l; l = l->next) { + int parse_ret; struct client *cl = l->client; - const char *strategy_plus_sort = get_strategy_plus_sort(cl, sort_field); - - if (maxrecs) - client_set_maxrecs(cl, atoi(maxrecs)); - if (startrecs) - client_set_startrecs(cl, atoi(startrecs)); - if (prepare_session_database(se, client_get_database(cl)) < 0) - ; - else if (client_parse_query(cl, query, facet_limits) < 0) - no_failed++; + + if (prepare_map(se, client_get_database(cl)) < 0) + continue; + + parse_ret = client_parse_query(cl, query, facet_limits, startrecs, + maxrecs); + if (parse_ret == -1) + no_failed_query++; + else if (parse_ret == -2) + no_failed_limit++; + else if (parse_ret == 0) + { + session_log(se, YLOG_LOG, "client NEW %s", client_get_id(cl)); + no_working++; + if (client_prep_connection(cl, se->service->z3950_operation_timeout, + se->service->z3950_session_timeout, + se->service->server->iochan_man, + &tval)) + client_start_search(cl); + } else { + session_log(se, YLOG_LOG, "client REUSE %s", client_get_id(cl)); no_working++; if (client_prep_connection(cl, se->service->z3950_operation_timeout, se->service->z3950_session_timeout, se->service->server->iochan_man, &tval)) - client_start_search(cl, strategy_plus_sort, increasing); + { + client_reingest(cl); + } } } facet_limits_destroy(facet_limits); - session_leave(se); + session_reset_active_clients(se, l0); + if (no_working == 0) { - if (no_failed > 0) + if (no_failed_query > 0) { *addinfo = "query"; return PAZPAR2_MALFORMED_PARAMETER_VALUE; } + else if (no_failed_limit > 0) + { + *addinfo = "limit"; + return PAZPAR2_MALFORMED_PARAMETER_VALUE; + } else return PAZPAR2_NO_TARGETS; } + yaz_log(YLOG_LOG, "session_start_search done"); return PAZPAR2_NO_ERROR; } @@ -840,6 +856,8 @@ void session_apply_setting(struct session *se, char *dbname, char *setting, new->next = sdb->settings[offset]; sdb->settings[offset] = new; + se->settings_modified = 1; + // Force later recompute of settings-driven data structures // (happens when a search starts and client connections are prepared) switch (offset) @@ -853,11 +871,12 @@ void session_apply_setting(struct session *se, char *dbname, char *setting, } } -void session_destroy(struct session *se) { +void session_destroy(struct session *se) +{ struct session_database *sdb; session_log(se, YLOG_DEBUG, "Destroying"); session_use(-1); - session_remove_clients(se); + session_remove_cached_clients(se); for (sdb = se->databases; sdb; sdb = sdb->next) session_database_destroy(sdb); @@ -899,7 +918,9 @@ struct session *new_session(NMEM nmem, struct conf_service *service, session->number_of_warnings_unknown_metadata = 0; session->num_termlists = 0; session->reclist = 0; - session->clients = 0; + session->clients_active = 0; + session->clients_cached = 0; + session->settings_modified = 0; session->session_nmem = nmem; session->nmem = nmem_create(); session->databases = 0; @@ -924,12 +945,12 @@ static struct hitsbytarget *hitsbytarget_nb(struct session *se, struct client_list *l; size_t sz = 0; - for (l = se->clients; l; l = l->next) + for (l = se->clients_active; l; l = l->next) sz++; res = nmem_malloc(nmem, sizeof(*res) * sz); *count = 0; - for (l = se->clients; l; l = l->next) + for (l = se->clients_active; l; l = l->next) { struct client *cl = l->client; WRBUF w = wrbuf_alloc(); @@ -1171,7 +1192,7 @@ struct record_cluster **show_range_start(struct session *se, *total = reclist_get_num_records(se->reclist); *sumhits = 0; - for (l = se->clients; l; l = l->next) + for (l = se->clients_active; l; l = l->next) *sumhits += client_get_hits(l->client); for (i = 0; i < start; i++) @@ -1216,7 +1237,7 @@ void statistics(struct session *se, struct statistics *stat) memset(stat, 0, sizeof(*stat)); stat->num_hits = 0; - for (l = se->clients; l; l = l->next) + for (l = se->clients_active; l; l = l->next) { struct client *cl = l->client; if (!client_get_connection(cl)) @@ -1516,13 +1537,85 @@ int ingest_record(struct client *cl, const char *rec, } session_enter(se); if (client_get_session(cl) == se) - ingest_to_cluster(cl, xdoc, root, record_no, mergekey_norm); + ret = ingest_to_cluster(cl, xdoc, root, record_no, mergekey_norm); session_leave(se); xmlFreeDoc(xdoc); return ret; } +static int check_limit_local(struct client *cl, + struct record *record, + int record_no) +{ + int skip_record = 0; + struct session *se = client_get_session(cl); + struct conf_service *service = se->service; + NMEM nmem_tmp = nmem_create(); + struct session_database *sdb = client_get_database(cl); + int l = 0; + while (!skip_record) + { + struct conf_metadata *ser_md = 0; + struct record_metadata *rec_md = 0; + int md_field_id; + char **values = 0; + int i, num_v = 0; + + const char *name = + client_get_facet_limit_local(cl, sdb, &l, nmem_tmp, &num_v, + &values); + if (!name) + break; + + md_field_id = conf_service_metadata_field_id(service, name); + if (md_field_id < 0) + { + skip_record = 1; + break; + } + ser_md = &service->metadata[md_field_id]; + rec_md = record->metadata[md_field_id]; + yaz_log(YLOG_LOG, "check limit local %s", name); + for (i = 0; i < num_v; ) + { + if (rec_md) + { + if (ser_md->type == Metadata_type_year + || ser_md->type == Metadata_type_date) + { + int y = atoi(values[i]); + if (y >= rec_md->data.number.min + && y <= rec_md->data.number.max) + break; + } + else + { + yaz_log(YLOG_LOG, "cmp: '%s' '%s'", + rec_md->data.text.disp, values[i]); + if (!strcmp(rec_md->data.text.disp, values[i])) + { + break; + } + } + rec_md = rec_md->next; + } + else + { + rec_md = record->metadata[md_field_id]; + i++; + } + } + if (i == num_v) + { + skip_record = 1; + break; + } + } + nmem_destroy(nmem_tmp); + return skip_record; +} + static int ingest_to_cluster(struct client *cl, xmlDoc *xdoc, xmlNode *root, @@ -1596,6 +1689,16 @@ static int ingest_to_cluster(struct client *cl, } } + if (check_limit_local(cl, record, record_no)) + { + session_log(se, YLOG_LOG, "Facet filtered out record no %d from %s", + record_no, sdb->database->id); + if (type) + xmlFree(type); + if (value) + xmlFree(value); + return -2; + } cluster = reclist_insert(se->reclist, service, record, mergekey_norm, &se->total_merged); if (!cluster) diff --git a/src/session.h b/src/session.h index 44bd94c..a819922 100644 --- a/src/session.h +++ b/src/session.h @@ -102,7 +102,8 @@ struct client_list; struct session { struct conf_service *service; /* service in use for this session */ struct session_database *databases; // All databases, settings overriden - struct client_list *clients; // Clients connected for current search + struct client_list *clients_active; // Clients connected for current search + struct client_list *clients_cached; // Clients in cache NMEM session_nmem; // Nmem for session-permanent storage NMEM nmem; // Nmem for each operation (i.e. search, result set, etc) int num_termlists; @@ -117,6 +118,7 @@ struct session { normalize_cache_t normalize_cache; YAZ_MUTEX session_mutex; unsigned session_id; + int settings_modified; struct session_sorted_results *sorted_results; }; @@ -181,6 +183,7 @@ int ingest_record(struct client *cl, const char *rec, int record_no, NMEM nmem); void session_alert_watch(struct session *s, int what); void add_facet(struct session *s, const char *type, const char *value, int count); + void perform_termlist(struct http_channel *c, struct session *se, const char *name, int num); void session_log(struct session *s, int level, const char *fmt, ...) @@ -190,6 +193,12 @@ void session_log(struct session *s, int level, const char *fmt, ...) ; #endif +struct session_sorted_results { + const char *field; + int increasing; + struct session_sorted_results *next; +}; + /* * Local variables: * c-basic-offset: 4 diff --git a/test/marc21_test.xsl b/test/marc21_test.xsl index 38c1d38..a33a2d0 100644 --- a/test/marc21_test.xsl +++ b/test/marc21_test.xsl @@ -205,7 +205,7 @@ - + diff --git a/test/test_http.cfg b/test/test_http.cfg index 77c902f..d084f9e 100644 --- a/test/test_http.cfg +++ b/test/test_http.cfg @@ -14,7 +14,7 @@ - + diff --git a/test/test_http.urls b/test/test_http.urls index c6feb28..de45220 100644 --- a/test/test_http.urls +++ b/test/test_http.urls @@ -55,9 +55,22 @@ http://localhost:9763/search.pz2?session=8&command=search&query=xyzzyz 2 http://localhost:9763/search.pz2?session=8&command=show&block=1 http://localhost:9763/search.pz2?session=8&command=search&query=a+and 1 http://localhost:9763/search.pz2?session=8&command=show&block=1 -http://localhost:9763/search.pz2?command=init&pz:limitmap:author%5Bz3950.indexdata.com%2Fmarc%5D=ccl:author_phrase -1 http://localhost:9763/search.pz2?session=9&command=search&query=greece&limit=author%3dadam\,+james%7Cother_author +http://localhost:9763/search.pz2?command=init&pz:limitmap:author%5Bz3950.indexdata.com%2Fmarc%5D=ccl:author_phrase&pz:limitmap:subject%5Bz3950.indexdata.com%2fmarc%5D=local:&pz:limitmap:date%5Bz3950.indexdata.com%2fmarc%5D=local: +1 http://localhost:9763/search.pz2?session=9&command=search&query=greece&limit=author%3Dadam\,+james%7Cother_author 1 http://localhost:9763/search.pz2?session=9&command=show&block=1 -http://localhost:9763/search.pz2?session=9&command=settings&pz:limitmap:author%5Bz3950.indexdata.com%2Fmarc%5D=rpn:%40attr+1%3d1003+%40attr+6%3d3 -1 http://localhost:9763/search.pz2?session=9&command=search&query=greece&limit=author%3dadam\,+james%7Cother_author +http://localhost:9763/search.pz2?session=9&command=settings&pz:limitmap:author%5Bz3950.indexdata.com%2Fmarc%5D=rpn:%40attr+1%3D1003+%40attr+6%3D3 +1 http://localhost:9763/search.pz2?session=9&command=search&query=greece&limit=author%3Dadam\,+james%7Cother_author 1 http://localhost:9763/search.pz2?session=9&command=show&block=1 +http://localhost:9763/search.pz2?session=9&command=search&query=greece&limit=author%3Dadam\,+james%7Cother_author&filter=pz%3Aid%3Dz3950.indexdata.com%2Fmarc +http://localhost:9763/search.pz2?session=9&command=bytarget +http://localhost:9763/search.pz2?session=9&command=show +http://localhost:9763/search.pz2?session=9&command=search&query=greece&limit=author%3Dadam\,+james%7Cother_author&filter=pz%3Aid%3Dnone +http://localhost:9763/search.pz2?session=9&command=bytarget +http://localhost:9763/search.pz2?session=9&command=show +http://localhost:9763/search.pz2?session=9&command=search&query=greece&limit=author%3Dadam\,+james%7Cother_author +http://localhost:9763/search.pz2?session=9&command=bytarget +http://localhost:9763/search.pz2?session=9&command=show +http://localhost:9763/search.pz2?session=9&command=search&query=computer&limit=subject%3DRailroads +http://localhost:9763/search.pz2?session=9&command=show&block=1 +http://localhost:9763/search.pz2?session=9&command=search&query=computer&limit=date%3D1977 +http://localhost:9763/search.pz2?session=9&command=show&block=1 diff --git a/test/test_http_10.res b/test/test_http_10.res index 7d0e680..2678940 100644 --- a/test/test_http_10.res +++ b/test/test_http_10.res @@ -9,9 +9,13 @@ The Computer Bible 1973-1980 +Bible. O.T +Bible Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates The Computer Bible 1973-1980 +Bible. O.T +Bible Hebrew and Greek; introductions in English Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates XXXXXXXXXX @@ -23,10 +27,12 @@ Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 -1977 +1977 +Optical pattern recognition Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 1977 +Optical pattern recognition XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -37,10 +43,12 @@ Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -51,10 +59,12 @@ The use of passwords for controlled access to computer resources 1977 -Wood, Helen M +Wood, Helen M +Computers The use of passwords for controlled access to computer resources 1977 Wood, Helen M +Computers XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -65,10 +75,16 @@ Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -81,11 +97,15 @@ a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 The Puget Sound Region a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 Bibliography: p. 4 XXXXXXXXXX @@ -97,9 +117,13 @@ A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title XXXXXXXXXX test-usersetting-2 data: @@ -112,11 +136,13 @@ final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." Washington metropolitan area rail computer feasibility study; final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." XXXXXXXXXX test-usersetting-2 data: diff --git a/test/test_http_11.res b/test/test_http_11.res index 50799ac..8cfa59f 100644 --- a/test/test_http_11.res +++ b/test/test_http_11.res @@ -9,9 +9,13 @@ A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title XXXXXXXXXX test-usersetting-2 data: @@ -24,11 +28,13 @@ final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." Washington metropolitan area rail computer feasibility study; final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." XXXXXXXXXX test-usersetting-2 data: @@ -39,9 +45,13 @@ The Computer Bible 1973-1980 +Bible. O.T +Bible Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates The Computer Bible 1973-1980 +Bible. O.T +Bible Hebrew and Greek; introductions in English Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates XXXXXXXXXX @@ -54,10 +64,16 @@ Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -70,11 +86,15 @@ a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 The Puget Sound Region a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 Bibliography: p. 4 XXXXXXXXXX @@ -86,10 +106,12 @@ Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 -1977 +1977 +Optical pattern recognition Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 1977 +Optical pattern recognition XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -100,10 +122,12 @@ Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -114,10 +138,12 @@ The use of passwords for controlled access to computer resources 1977 -Wood, Helen M +Wood, Helen M +Computers The use of passwords for controlled access to computer resources 1977 Wood, Helen M +Computers XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY diff --git a/test/test_http_36.res b/test/test_http_36.res index e8ead75..77a1857 100644 --- a/test/test_http_36.res +++ b/test/test_http_36.res @@ -9,10 +9,12 @@ Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 -1977 +1977 +Optical pattern recognition Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 1977 +Optical pattern recognition XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -23,9 +25,13 @@ The Computer Bible 1973-1980 +Bible. O.T +Bible Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates The Computer Bible 1973-1980 +Bible. O.T +Bible Hebrew and Greek; introductions in English Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates XXXXXXXXXX @@ -38,9 +44,13 @@ A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title XXXXXXXXXX test-usersetting-2 data: @@ -54,11 +64,13 @@ final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." Washington metropolitan area rail computer feasibility study; final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." XXXXXXXXXX test-usersetting-2 data: @@ -72,11 +84,15 @@ a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 The Puget Sound Region a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 Bibliography: p. 4 XXXXXXXXXX @@ -90,10 +106,16 @@ Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -105,10 +127,12 @@ The use of passwords for controlled access to computer resources 1977 -Wood, Helen M +Wood, Helen M +Computers The use of passwords for controlled access to computer resources 1977 Wood, Helen M +Computers XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -120,10 +144,12 @@ Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: diff --git a/test/test_http_42.res b/test/test_http_42.res index 67eb248..49f526b 100644 --- a/test/test_http_42.res +++ b/test/test_http_42.res @@ -10,10 +10,16 @@ The religious teachers of Greece 1972 Adam, James +Greek literature +Philosophy, Ancient +Greece Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures The religious teachers of Greece 1972 Adam, James +Greek literature +Philosophy, Ancient +Greece Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures Includes bibliographical references XXXXXXXXXX @@ -28,11 +34,15 @@ a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 The Puget Sound Region a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 Bibliography: p. 4 XXXXXXXXXX @@ -46,10 +56,12 @@ Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -61,10 +73,12 @@ The use of passwords for controlled access to computer resources 1977 -Wood, Helen M +Wood, Helen M +Computers The use of passwords for controlled access to computer resources 1977 Wood, Helen M +Computers XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -75,10 +89,12 @@ Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 -1977 +1977 +Optical pattern recognition Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 1977 +Optical pattern recognition XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY diff --git a/test/test_http_45.res b/test/test_http_45.res index f4f9579..ce9623a 100644 --- a/test/test_http_45.res +++ b/test/test_http_45.res @@ -10,10 +10,16 @@ Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: diff --git a/test/test_http_49.res b/test/test_http_49.res index ecb7374..70b1451 100644 --- a/test/test_http_49.res +++ b/test/test_http_49.res @@ -10,16 +10,22 @@ The religious teachers of Greece 1972 Adam, James +Greek literature +Philosophy, Ancient +Greece Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures The religious teachers of Greece 1972 Adam, James +Greek literature +Philosophy, Ancient +Greece Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures Includes bibliographical references XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY -120000 +420000 content: title the religious teachers of greece author adam james medium book \ No newline at end of file diff --git a/test/test_http_5.res b/test/test_http_5.res index 1c1d8d3..c045cc2 100644 --- a/test/test_http_5.res +++ b/test/test_http_5.res @@ -28,10 +28,12 @@ Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 -1977 +1977 +Optical pattern recognition Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 1977 +Optical pattern recognition XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -42,9 +44,13 @@ The Computer Bible 1973-1980 +Bible. O.T +Bible Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates The Computer Bible 1973-1980 +Bible. O.T +Bible Hebrew and Greek; introductions in English Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates XXXXXXXXXX @@ -57,9 +63,13 @@ A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title XXXXXXXXXX test-usersetting-2 data: @@ -73,11 +83,13 @@ final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." Washington metropolitan area rail computer feasibility study; final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." XXXXXXXXXX test-usersetting-2 data: @@ -91,11 +103,15 @@ a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 The Puget Sound Region a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 Bibliography: p. 4 XXXXXXXXXX @@ -109,10 +125,16 @@ Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -124,10 +146,12 @@ The use of passwords for controlled access to computer resources 1977 -Wood, Helen M +Wood, Helen M +Computers The use of passwords for controlled access to computer resources 1977 Wood, Helen M +Computers XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -139,10 +163,12 @@ Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: diff --git a/test/test_http_50.res b/test/test_http_50.res index f4f9579..ce9623a 100644 --- a/test/test_http_50.res +++ b/test/test_http_50.res @@ -10,10 +10,16 @@ Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: diff --git a/test/test_http_60.res b/test/test_http_60.res index 28b128f..f9283fd 100644 --- a/test/test_http_60.res +++ b/test/test_http_60.res @@ -10,16 +10,22 @@ The religious teachers of Greece 1972 Adam, James +Greek literature +Philosophy, Ancient +Greece Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures The religious teachers of Greece 1972 Adam, James +Greek literature +Philosophy, Ancient +Greece Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures Includes bibliographical references XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY -320000 +620000 content: title the religious teachers of greece author adam james medium book \ No newline at end of file diff --git a/test/test_http_63.res b/test/test_http_63.res index ecb7374..70b1451 100644 --- a/test/test_http_63.res +++ b/test/test_http_63.res @@ -10,16 +10,22 @@ The religious teachers of Greece 1972 Adam, James +Greek literature +Philosophy, Ancient +Greece Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures The religious teachers of Greece 1972 Adam, James +Greek literature +Philosophy, Ancient +Greece Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures Includes bibliographical references XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY -120000 +420000 content: title the religious teachers of greece author adam james medium book \ No newline at end of file diff --git a/test/test_http_64.res b/test/test_http_64.res new file mode 100644 index 0000000..ab63fe6 --- /dev/null +++ b/test/test_http_64.res @@ -0,0 +1,2 @@ + +OK \ No newline at end of file diff --git a/test/test_http_65.res b/test/test_http_65.res new file mode 100644 index 0000000..b24d50f --- /dev/null +++ b/test/test_http_65.res @@ -0,0 +1,9 @@ + +OK +z3950.indexdata.com/marc +Index Data MARC test server +1 +0 +1 +Client_Idle + \ No newline at end of file diff --git a/test/test_http_66.res b/test/test_http_66.res new file mode 100644 index 0000000..70b1451 --- /dev/null +++ b/test/test_http_66.res @@ -0,0 +1,31 @@ + +OK +0 +1 +1 +0 +1 + + +The religious teachers of Greece +1972 +Adam, James +Greek literature +Philosophy, Ancient +Greece +Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures +The religious teachers of Greece +1972 +Adam, James +Greek literature +Philosophy, Ancient +Greece +Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures +Includes bibliographical references +XXXXXXXXXX +test-usersetting-2 data: + YYYYYYYYY +420000 +content: title the religious teachers of greece author adam james medium book + + \ No newline at end of file diff --git a/test/test_http_67.res b/test/test_http_67.res new file mode 100644 index 0000000..d486aeb --- /dev/null +++ b/test/test_http_67.res @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/test/test_http_68.res b/test/test_http_68.res new file mode 100644 index 0000000..e506085 --- /dev/null +++ b/test/test_http_68.res @@ -0,0 +1,2 @@ + +OK \ No newline at end of file diff --git a/test/test_http_69.res b/test/test_http_69.res new file mode 100644 index 0000000..5a1147b --- /dev/null +++ b/test/test_http_69.res @@ -0,0 +1,8 @@ + +OK +0 +0 +0 +0 +0 + \ No newline at end of file diff --git a/test/test_http_70.res b/test/test_http_70.res new file mode 100644 index 0000000..ab63fe6 --- /dev/null +++ b/test/test_http_70.res @@ -0,0 +1,2 @@ + +OK \ No newline at end of file diff --git a/test/test_http_71.res b/test/test_http_71.res new file mode 100644 index 0000000..b24d50f --- /dev/null +++ b/test/test_http_71.res @@ -0,0 +1,9 @@ + +OK +z3950.indexdata.com/marc +Index Data MARC test server +1 +0 +1 +Client_Idle + \ No newline at end of file diff --git a/test/test_http_72.res b/test/test_http_72.res new file mode 100644 index 0000000..70b1451 --- /dev/null +++ b/test/test_http_72.res @@ -0,0 +1,31 @@ + +OK +0 +1 +1 +0 +1 + + +The religious teachers of Greece +1972 +Adam, James +Greek literature +Philosophy, Ancient +Greece +Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures +The religious teachers of Greece +1972 +Adam, James +Greek literature +Philosophy, Ancient +Greece +Reprint of the 1909 ed., which was issued as the 1904-1906 Gifford lectures +Includes bibliographical references +XXXXXXXXXX +test-usersetting-2 data: + YYYYYYYYY +420000 +content: title the religious teachers of greece author adam james medium book + + \ No newline at end of file diff --git a/test/test_http_73.res b/test/test_http_73.res new file mode 100644 index 0000000..ab63fe6 --- /dev/null +++ b/test/test_http_73.res @@ -0,0 +1,2 @@ + +OK \ No newline at end of file diff --git a/test/test_http_74.res b/test/test_http_74.res new file mode 100644 index 0000000..64e8673 --- /dev/null +++ b/test/test_http_74.res @@ -0,0 +1,28 @@ + +OK +0 +1 +10 +0 +1 + + +Washington metropolitan area rail computer feasibility study; +final report +1971 +Englund, Carl R +Railroads +"Contract DOT-UT-10003." +Washington metropolitan area rail computer feasibility study; +final report +1971 +Englund, Carl R +Railroads +"Contract DOT-UT-10003." +XXXXXXXXXX +test-usersetting-2 data: + YYYYYYYYY +85714 +content: title washington metropolitan area rail computer feasibility study author englund carl r medium book + + \ No newline at end of file diff --git a/test/test_http_75.res b/test/test_http_75.res new file mode 100644 index 0000000..ab63fe6 --- /dev/null +++ b/test/test_http_75.res @@ -0,0 +1,2 @@ + +OK \ No newline at end of file diff --git a/test/test_http_76.res b/test/test_http_76.res new file mode 100644 index 0000000..ba0f848 --- /dev/null +++ b/test/test_http_76.res @@ -0,0 +1,77 @@ + +OK +0 +4 +10 +0 +4 + + +Computer science & technology +proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 +1977 +Optical pattern recognition +Computer science & technology +proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 +1977 +Optical pattern recognition +XXXXXXXXXX +test-usersetting-2 data: + YYYYYYYYY +57536 +content: title computer science technology author medium book + + + +The Computer Bible +1973-1980 +Bible. O.T +Bible +Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates +The Computer Bible +1973-1980 +Bible. O.T +Bible +Hebrew and Greek; introductions in English +Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates +XXXXXXXXXX +test-usersetting-2 data: + YYYYYYYYY +57536 +content: title the computer bible author medium book + + + +The use of passwords for controlled access to computer resources +1977 +Wood, Helen M +Computers +The use of passwords for controlled access to computer resources +1977 +Wood, Helen M +Computers +XXXXXXXXXX +test-usersetting-2 data: + YYYYYYYYY +17260 +content: title the use of passwords for controlled access to computer resources author wood helen m medium book + + + +Reconstruction tomography in diagnostic radiology and nuclear medicine +proceedings of the workshop +1977 +Tomography +Includes bibliographical references and index +Reconstruction tomography in diagnostic radiology and nuclear medicine +proceedings of the workshop +1977 +Tomography +Includes bibliographical references and index +XXXXXXXXXX +test-usersetting-2 data: + YYYYYYYYY +0 +content: title reconstruction tomography in diagnostic radiology and nuclear medicine author medium book + + \ No newline at end of file diff --git a/test/test_http_8.res b/test/test_http_8.res index 5375925..d39c96f 100644 --- a/test/test_http_8.res +++ b/test/test_http_8.res @@ -11,11 +11,13 @@ final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." Washington metropolitan area rail computer feasibility study; final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." XXXXXXXXXX test-usersetting-2 data: @@ -26,10 +28,12 @@ The use of passwords for controlled access to computer resources 1977 -Wood, Helen M +Wood, Helen M +Computers The use of passwords for controlled access to computer resources 1977 Wood, Helen M +Computers XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -40,10 +44,12 @@ Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -56,11 +62,15 @@ a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 The Puget Sound Region a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 Bibliography: p. 4 XXXXXXXXXX @@ -72,9 +82,13 @@ A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title XXXXXXXXXX test-usersetting-2 data: @@ -103,10 +117,12 @@ Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 -1977 +1977 +Optical pattern recognition Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 1977 +Optical pattern recognition XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -117,10 +133,16 @@ Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -131,9 +153,13 @@ The Computer Bible 1973-1980 +Bible. O.T +Bible Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates The Computer Bible 1973-1980 +Bible. O.T +Bible Hebrew and Greek; introductions in English Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates XXXXXXXXXX diff --git a/test/test_http_9.res b/test/test_http_9.res index fcefa9b..41a8c73 100644 --- a/test/test_http_9.res +++ b/test/test_http_9.res @@ -9,9 +9,13 @@ The Computer Bible 1973-1980 +Bible. O.T +Bible Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates The Computer Bible 1973-1980 +Bible. O.T +Bible Hebrew and Greek; introductions in English Vols. 2, 8: Missoula, Mont. : Published by Scholars Press for Biblical Research Associates XXXXXXXXXX @@ -24,10 +28,16 @@ Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index Computer processing of dynamic images from an Anger scintillation camera the proceedings of a workshop 1974 +Radioisotope scanning +Scintillation cameras +Imaging systems in medicine Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -38,10 +48,12 @@ Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 -1977 +1977 +Optical pattern recognition Computer science & technology proceedings of a workshop held at the National Bureau of Standards, Gaithersburg, MD, June 3-4, 1976 1977 +Optical pattern recognition XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -69,9 +81,13 @@ A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title A plan for community college computer development 1971 +Universities and colleges +Community colleges Cover title XXXXXXXXXX test-usersetting-2 data: @@ -84,11 +100,15 @@ a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 The Puget Sound Region a portfolio of thematic computer maps 1974 Mairs, John W +Cartography +Puget Sound region (Wash.) Scale of maps ca. 1:1,000,000 Bibliography: p. 4 XXXXXXXXXX @@ -101,10 +121,12 @@ Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index Reconstruction tomography in diagnostic radiology and nuclear medicine proceedings of the workshop 1977 +Tomography Includes bibliographical references and index XXXXXXXXXX test-usersetting-2 data: @@ -115,10 +137,12 @@ The use of passwords for controlled access to computer resources 1977 -Wood, Helen M +Wood, Helen M +Computers The use of passwords for controlled access to computer resources 1977 Wood, Helen M +Computers XXXXXXXXXX test-usersetting-2 data: YYYYYYYYY @@ -130,11 +154,13 @@ final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." Washington metropolitan area rail computer feasibility study; final report 1971 Englund, Carl R +Railroads "Contract DOT-UT-10003." XXXXXXXXXX test-usersetting-2 data: diff --git a/test/test_icu_8.res b/test/test_icu_8.res index 80dde63..05af6d5 100644 --- a/test/test_icu_8.res +++ b/test/test_icu_8.res @@ -7,11 +7,14 @@ Wood, Helen M.1 +Bible1 +Bible. O.t1 Cartography1 Community Colleges1 Computers1 Imaging Systems In Medicine1 Optical Pattern Recognition1 +Puget Sound Region (Wash.)1 Radioisotope Scanning1 Railroads1 Scintillation Cameras1 diff --git a/win/makefile b/win/makefile index 7e6b3ea..8caf4e3 100644 --- a/win/makefile +++ b/win/makefile @@ -178,6 +178,8 @@ LNKOPT= $(COMMON_LNK_OPTIONS) $(RELEASE_LNK_OPTIONS) $(LNK_LIBS) # Source and object modules PAZPAR2_OBJS = \ + "$(OBJDIR)\getaddrinfo.obj" \ + "$(OBJDIR)\host.obj" \ "$(OBJDIR)\pazpar2.obj" \ "$(OBJDIR)\pazpar2_config.obj" \ "$(OBJDIR)\http.obj" \ diff --git a/www/iphone/example_client.js b/www/iphone/example_client.js index ea74e67..3edabac 100644 --- a/www/iphone/example_client.js +++ b/www/iphone/example_client.js @@ -4,13 +4,18 @@ // create a parameters array and pass it to the pz2's constructor // then register the form submit event with the pz2.search function // autoInit is set to true on default -var usesessions = true; +var usesessions = false; var pazpar2path = '/service-proxy/'; var showResponseType = ''; +// Facet configuration var querys = {'su': '', 'au': '', 'xt': ''}; -var showResponseType = 'json'; +var query_client_server = {'su': 'subject', 'au': 'author', 'xt': 'xtargets'}; +var querys_server = {}; +var useLimit = 1; +// Fail to get JSON working stabil. +var showResponseType = 'xml'; if (document.location.hash == '#pazpar2' || document.location.search.match("useproxy=false")) { - usesessions = false; + usesessions = true; pazpar2path = '/pazpar2/search.pz2'; showResponseType = 'xml'; } @@ -29,7 +34,10 @@ my_paz = new pz2( { "onshow": my_onshow, "onrecord": my_onrecord } ); // some state vars var curPage = 1; -var recPerPage = 20; +var recPerPage = 100; +var recToShowPageSize = 20; +var recToShow = recToShowPageSize; +var recIDs = {}; var totalRec = 0; var curDetRecId = ''; var curDetRecData = null; @@ -52,7 +60,7 @@ function loginFormSubmit() { authCb, authCb); } -function handleKeyPress(e, formId, focusId) +function handleKeyPress(e) { var key; if(window.event) @@ -62,11 +70,11 @@ function handleKeyPress(e, formId, focusId) if(key == 13 || key == 10) { - document.getElementById(formId).submit(); - focusElement = document.getElementById(focusId); - if (focusElement) - focusElement.focus(); - return false; + button = document.getElementById('button'); + button.focus(); + button.click(); + + return false; } else return true; @@ -130,6 +138,21 @@ function my_oninit() { my_paz.bytarget(); } +function showMoreRecords() { + var i = recToShow; + recToShow += recToShowPageSize; + for ( ; i < recToShow && i < recPerPage; i++) { + var element = document.getElementById(recIDs[i]); + if (element) + element.style.display = ''; + } + if (i == recPerPage) { + var element = document.getElementById('recdiv_END'); + if (element) + element.style.display = 'none'; + } +} + function my_onshow(data) { totalRec = data.merged; // move it out @@ -142,31 +165,43 @@ function my_onshow(data) { drawPager(pager); var results = document.getElementById("results"); - + var html = []; if (data.hits == undefined) - return ; + return ; + var style = ''; for (var i = 0; i < data.hits.length; i++) { var hit = data.hits[i]; - html.push('
  • ' - /* +''+ (i + 1 + recPerPage * (curPage - 1)) +'. ' */ - +'' - + hit["md-title"] +' '); - if (hit["md-title-remainder"] !== undefined) { - html.push('' + hit["md-title-remainder"] + ' '); - if (hit["md-author"] != undefined) { - html.push(''+hit["md-author"]+' '); - } - else if (hit["md-title-responsibility"] !== undefined) { - html.push(''+hit["md-title-responsibility"]+' '); - } - } + var recID = "recdiv_" + hit.recid; + //var recID = "recdiv_" + i; + recIDs[i] = recID; + if (i == recToShow) + style = ' style="display:none" '; + html.push('
  • ' + +'' + + hit["md-title"] +' '); + if (hit["md-title-remainder"] !== undefined) { + html.push('' + hit["md-title-remainder"] + ' '); + } + if (hit["md-author"] != undefined) { + html.push(''+hit["md-author"]+' '); + } + else if (hit["md-title-responsibility"] !== undefined) { + html.push(''+hit["md-title-responsibility"]+' '); + } if (hit.recid == curDetRecId) { html.push(renderDetails_iphone(curDetRecData)); } - html.push(''); + html.push('
  • '); } + // set up "More..." if needed. + style = 'display:none'; + if (recToShow < recPerPage) { + style = 'display:block'; + } + html.push('
  • More...
  • '); + replaceHtml(results, html.join('')); } @@ -259,7 +294,7 @@ function my_onterm(data) { termlists.push('