From: Adam Dickmeiss Date: Thu, 10 Nov 2011 10:05:14 +0000 (+0100) Subject: Merge branch 'master' into bug_4688 X-Git-Tag: v1.6.6~41 X-Git-Url: http://lists.indexdata.com/cgi-bin?a=commitdiff_plain;h=5957bba20fb93c8c6829296d6ccf32e52b2114e2;hp=-c;p=pazpar2-moved-to-github.git Merge branch 'master' into bug_4688 --- 5957bba20fb93c8c6829296d6ccf32e52b2114e2 diff --combined src/client.c index ac2e01b,510cf68..4fe301f --- a/src/client.c +++ b/src/client.c @@@ -121,7 -121,6 +121,7 @@@ struct client YAZ_MUTEX mutex; int ref_count; char *id; + facet_limits_t facet_limits; }; struct suggestions { @@@ -555,61 -554,12 +555,61 @@@ void client_got_records(struct client * 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); } } @@@ -628,9 -578,11 +628,9 @@@ void client_record_response(struct clie } 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))) { @@@ -645,21 -597,49 +645,21 @@@ } 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); @@@ -703,12 -683,37 +703,37 @@@ int client_has_facet(struct client *cl 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); @@@ -724,7 -729,6 +749,7 @@@ assert(link); + cl->hits = 0; cl->record_offset = 0; cl->diagnostic = 0; @@@ -788,23 -792,39 +813,39 @@@ 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; + } } } rs = ZOOM_connection_search(link, q); @@@ -835,7 -855,6 +876,7 @@@ struct client *client_create(const cha 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); @@@ -874,7 -893,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) { @@@ -998,38 -1016,10 +1039,38 @@@ static char *make_solrquery(struct clie 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; @@@ -1081,14 -1071,6 +1122,14 @@@ 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; } } @@@ -1100,13 -1082,11 +1141,13 @@@ } } 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); @@@ -1118,24 -1098,10 +1159,24 @@@ 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); @@@ -1146,11 -1112,7 +1187,11 @@@ 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); @@@ -1187,12 -1149,8 +1228,12 @@@ 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); @@@ -1225,7 -1183,7 +1266,7 @@@ } ccl_rpn_delete(cn); - return 0; + return ret_value; } void client_set_session(struct client *cl, struct session *se) @@@ -1314,11 -1272,21 +1355,11 @@@ const char *client_get_id(struct clien 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 --combined src/client.h index 0b1d413,29eeb7e..275b294 --- a/src/client.h +++ b/src/client.h @@@ -77,23 -77,23 +77,22 @@@ int client_prep_connection(struct clien 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); @@@ -102,11 -102,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 --combined src/session.c index d811290,f2d7e2d..cdd588c --- a/src/session.c +++ b/src/session.c @@@ -95,12 -95,6 +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,14 -159,13 +159,14 @@@ static void session_leave(struct sessio 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; @@@ -209,14 -202,6 +203,14 @@@ } } 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)) { @@@ -414,8 -399,12 +408,8 @@@ static int prepare_map(struct session * { 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]; @@@ -450,6 -439,25 +444,6 @@@ 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) @@@ -516,60 -524,26 +510,60 @@@ void session_alert_watch(struct sessio 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) @@@ -598,7 -572,7 +592,7 @@@ int session_active_clients(struct sessi 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++; @@@ -610,38 -584,13 +604,13 @@@ int session_is_preferred_clients_ready( 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; @@@ -670,19 -619,15 +639,15 @@@ 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); } @@@ -698,9 -643,8 +663,9 @@@ enum pazpar2_error_code session_search( { 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; @@@ -708,15 -652,11 +673,15 @@@ *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; @@@ -747,68 -687,40 +712,67 @@@ 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++; - else + 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, strategy_plus_sort, increasing); + 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_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; } @@@ -892,8 -804,6 +856,8 @@@ void session_apply_setting(struct sessi 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) @@@ -907,12 -817,11 +871,12 @@@ } } -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); @@@ -954,9 -863,7 +918,9 @@@ struct session *new_session(NMEM nmem, 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; @@@ -981,12 -888,12 +945,12 @@@ static struct hitsbytarget *hitsbytarge 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(); @@@ -1228,7 -1135,7 +1192,7 @@@ struct record_cluster **show_range_star *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++) @@@ -1273,7 -1180,7 +1237,7 @@@ void statistics(struct session *se, str 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)) @@@ -1573,85 -1480,13 +1537,85 @@@ int ingest_record(struct client *cl, co } 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, @@@ -1725,16 -1560,6 +1689,16 @@@ } } + 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 --combined src/session.h index 4368026,98057d6..a819922 --- a/src/session.h +++ b/src/session.h @@@ -102,8 -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; @@@ -118,7 -117,6 +118,7 @@@ normalize_cache_t normalize_cache; YAZ_MUTEX session_mutex; unsigned session_id; + int settings_modified; struct session_sorted_results *sorted_results; }; @@@ -183,6 -181,7 +183,7 @@@ int ingest_record(struct client *cl, co 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, ...) @@@ -192,6 -191,12 +193,12 @@@ ; #endif + struct session_sorted_results { + const char *field; + int increasing; + struct session_sorted_results *next; + }; + /* * Local variables: * c-basic-offset: 4