X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fsession.c;h=3567ab62086ab874d2adc38675b984bc3ef24575;hb=856d06997c1494ed13ddad8eed3531d0852290c9;hp=f1f742a57ab5026c7019a034d4882f2efc60ee65;hpb=3606fd6346ccfe3508aa7cd366b849e389f1b861;p=pazpar2-moved-to-github.git diff --git a/src/session.c b/src/session.c index f1f742a..3567ab6 100644 --- a/src/session.c +++ b/src/session.c @@ -86,7 +86,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA struct parameters global_parameters = { 0, // dump_records - 0 // debug_mode + 0, // debug_mode + 0, // predictable sessions }; struct client_list { @@ -97,6 +98,7 @@ struct client_list { /* session counting (1) , disable client counting (0) */ static YAZ_MUTEX g_session_mutex = 0; static int no_sessions = 0; +static int no_session_total = 0; static int session_use(int delta) { @@ -105,16 +107,30 @@ static int session_use(int delta) yaz_mutex_create(&g_session_mutex); yaz_mutex_enter(g_session_mutex); no_sessions += delta; + if (delta > 0) + no_session_total += delta; sessions = no_sessions; yaz_mutex_leave(g_session_mutex); - yaz_log(YLOG_DEBUG, "%s sesions=%d", delta == 0 ? "" : (delta > 0 ? "INC" : "DEC"), no_sessions); + yaz_log(YLOG_DEBUG, "%s sessions=%d", delta == 0 ? "" : (delta > 0 ? "INC" : "DEC"), no_sessions); return sessions; } -int sessions_count(void) { +int sessions_count(void) +{ return session_use(0); } +int session_count_total(void) +{ + int total = 0; + if (!g_session_mutex) + return 0; + yaz_mutex_enter(g_session_mutex); + total = no_session_total; + yaz_mutex_leave(g_session_mutex); + return total; +} + static void log_xml_doc(xmlDoc *doc) { FILE *lf = yaz_log_file(); @@ -143,53 +159,50 @@ static void session_leave(struct session *s) yaz_mutex_leave(s->session_mutex); } -// Recursively traverse query structure to extract terms. -void pull_terms(NMEM nmem, struct ccl_rpn_node *n, char **termlist, int *num) -{ - char **words; - int numwords; - int i; - - switch (n->kind) - { - case CCL_RPN_AND: - case CCL_RPN_OR: - case CCL_RPN_NOT: - case CCL_RPN_PROX: - pull_terms(nmem, n->u.p[0], termlist, num); - pull_terms(nmem, n->u.p[1], termlist, num); - break; - case CCL_RPN_TERM: - nmem_strsplit(nmem, " ", n->u.t.term, &words, &numwords); - for (i = 0; i < numwords; i++) - termlist[(*num)++] = words[i]; - break; - default: // NOOP - break; - } -} - - void add_facet(struct session *s, const char *type, const char *value, int count) { struct conf_service *service = s->service; - pp2_relevance_token_t prt; + pp2_charset_token_t prt; const char *facet_component; WRBUF facet_wrbuf = wrbuf_alloc(); - prt = pp2_relevance_tokenize(service->facet_pct); - - pp2_relevance_first(prt, value, 0); - while ((facet_component = pp2_relevance_token_next(prt))) + WRBUF display_wrbuf = wrbuf_alloc(); + int i; + const char *icu_chain_id = 0; + + for (i = 0; i < service->num_metadata; i++) + if (!strcmp((service->metadata + i)->name, type)) + icu_chain_id = (service->metadata + i)->facetrule; + if (!icu_chain_id) + icu_chain_id = "facet"; + prt = pp2_charset_token_create(service->charsets, icu_chain_id); + if (!prt) + { + yaz_log(YLOG_FATAL, "Unknown ICU chain '%s' for facet of type '%s'", + icu_chain_id, type); + wrbuf_destroy(facet_wrbuf); + wrbuf_destroy(display_wrbuf); + return; + } + pp2_charset_token_first(prt, value, 0); + while ((facet_component = pp2_charset_token_next(prt))) { + const char *display_component; if (*facet_component) { if (wrbuf_len(facet_wrbuf)) wrbuf_puts(facet_wrbuf, " "); wrbuf_puts(facet_wrbuf, facet_component); } + display_component = pp2_get_display(prt); + if (display_component) + { + if (wrbuf_len(display_wrbuf)) + wrbuf_puts(display_wrbuf, " "); + wrbuf_puts(display_wrbuf, display_component); + } } - pp2_relevance_token_destroy(prt); - + pp2_charset_token_destroy(prt); + if (wrbuf_len(facet_wrbuf)) { int i; @@ -202,6 +215,7 @@ void add_facet(struct session *s, const char *type, const char *value, int count { session_log(s, YLOG_FATAL, "Too many termlists"); wrbuf_destroy(facet_wrbuf); + wrbuf_destroy(display_wrbuf); return; } @@ -211,13 +225,14 @@ void add_facet(struct session *s, const char *type, const char *value, int count s->num_termlists = i + 1; } -#if +#if 0 session_log(s, YLOG_DEBUG, "Facets for %s: %s norm:%s (%d)", type, value, wrbuf_cstr(facet_wrbuf), count); #endif - termlist_insert(s->termlists[i].termlist, wrbuf_cstr(facet_wrbuf), - count); + termlist_insert(s->termlists[i].termlist, wrbuf_cstr(display_wrbuf), + wrbuf_cstr(facet_wrbuf), count); } wrbuf_destroy(facet_wrbuf); + wrbuf_destroy(display_wrbuf); } static xmlDoc *record_to_xml(struct session *se, @@ -473,7 +488,7 @@ int session_set_watch(struct session *s, int what, ret = 0; } session_leave(s); - return 0; + return ret; } void session_alert_watch(struct session *s, int what) @@ -506,11 +521,18 @@ void session_alert_watch(struct session *s, int what) } //callback for grep_databases -static void select_targets_callback(void *context, struct session_database *db) +static void select_targets_callback(struct session *se, + struct session_database *db) { - struct session *se = (struct session*) context; struct client *cl = client_create(); struct client_list *l; + const char *url = session_setting_oneval(db, PZ_URL); + + if (!url || !*url) + url = db->database->url; + + resolve_database(se->service, db->database, url); + client_set_database(cl, db); client_set_session(cl, se); @@ -575,12 +597,11 @@ int session_is_preferred_clients_ready(struct session *s) return res == 0; } - - enum pazpar2_error_code search(struct session *se, const char *query, const char *startrecs, const char *maxrecs, const char *filter, + const char *limit, const char **addinfo) { int live_channels = 0; @@ -588,6 +609,7 @@ enum pazpar2_error_code search(struct session *se, int no_failed = 0; struct client_list *l; struct timeval tval; + facet_limits_t facet_limits; session_log(se, YLOG_DEBUG, "Search"); @@ -614,6 +636,13 @@ enum pazpar2_error_code search(struct session *se, tval.tv_sec += 5; + facet_limits = facet_limits_create(limit); + if (!facet_limits) + { + *addinfo = "limit"; + session_leave(se); + return PAZPAR2_MALFORMED_PARAMETER_VALUE; + } for (l = se->clients; l; l = l->next) { struct client *cl = l->client; @@ -624,7 +653,7 @@ enum pazpar2_error_code search(struct session *se, client_set_startrecs(cl, atoi(startrecs)); if (prepare_session_database(se, client_get_database(cl)) < 0) ; - else if (client_parse_query(cl, query) < 0) + else if (client_parse_query(cl, query, facet_limits) < 0) no_failed++; else { @@ -636,6 +665,7 @@ enum pazpar2_error_code search(struct session *se, client_start_search(cl); } } + facet_limits_destroy(facet_limits); session_leave(se); if (no_working == 0) { @@ -694,8 +724,6 @@ static struct session_database *load_session_database(struct session *se, { struct database *db = new_database(id, se->session_nmem); - resolve_database(se->service, db); - session_init_databases_fun((void*) se, db); // New sdb is head of se->databases list @@ -745,8 +773,7 @@ void session_apply_setting(struct session *se, char *dbname, char *setting, } } -void destroy_session(struct session *se) -{ +void session_destroy(struct session *se) { struct session_database *sdb; session_log(se, YLOG_DEBUG, "Destroying"); session_use(-1); @@ -760,7 +787,12 @@ void destroy_session(struct session *se) nmem_destroy(se->nmem); service_destroy(se->service); yaz_mutex_destroy(&se->session_mutex); - wrbuf_destroy(se->wrbuf); +} + +/* Depreciated: use session_destroy */ +void destroy_session(struct session *se) +{ + session_destroy(se); } size_t session_get_memory_status(struct session *session) { @@ -797,7 +829,6 @@ struct session *new_session(NMEM nmem, struct conf_service *service, session->clients = 0; session->session_nmem = nmem; session->nmem = nmem_create(); - session->wrbuf = wrbuf_alloc(); session->databases = 0; for (i = 0; i <= SESSION_WATCH_MAX; i++) { @@ -811,13 +842,13 @@ struct session *new_session(NMEM nmem, struct conf_service *service, return session; } -struct hitsbytarget *hitsbytarget(struct session *se, int *count, NMEM nmem) +static struct hitsbytarget *hitsbytarget_nb(struct session *se, + int *count, NMEM nmem) { struct hitsbytarget *res = 0; struct client_list *l; size_t sz = 0; - session_enter(se); for (l = se->clients; l; l = l->next) sz++; @@ -838,14 +869,24 @@ struct hitsbytarget *hitsbytarget(struct session *se, int *count, NMEM nmem) res[*count].state = client_get_state_str(cl); res[*count].connected = client_get_connection(cl) ? 1 : 0; session_settings_dump(se, client_get_database(cl), w); - res[*count].settings_xml = w; + res[*count].settings_xml = nmem_strdup(nmem, wrbuf_cstr(w)); + wrbuf_destroy(w); (*count)++; } - session_leave(se); return res; } -struct termlist_score **termlist(struct session *se, const char *name, int *num) +struct hitsbytarget *get_hitsbytarget(struct session *se, int *count, NMEM nmem) +{ + struct hitsbytarget *p; + session_enter(se); + p = hitsbytarget_nb(se, count, nmem); + session_leave(se); + return p; +} + +struct termlist_score **get_termlist_score(struct session *se, + const char *name, int *num) { int i; struct termlist_score **tl = 0; @@ -861,6 +902,118 @@ struct termlist_score **termlist(struct session *se, const char *name, int *num) return tl; } +// Compares two hitsbytarget nodes by hitcount +static int cmp_ht(const void *p1, const void *p2) +{ + const struct hitsbytarget *h1 = p1; + const struct hitsbytarget *h2 = p2; + return h2->hits - h1->hits; +} + +static int targets_termlist_nb(WRBUF wrbuf, struct session *se, int num, + NMEM nmem) +{ + struct hitsbytarget *ht; + int count, i; + + ht = hitsbytarget_nb(se, &count, nmem); + qsort(ht, count, sizeof(struct hitsbytarget), cmp_ht); + for (i = 0; i < count && i < num && ht[i].hits > 0; i++) + { + + // do only print terms which have display names + + wrbuf_puts(wrbuf, "\n"); + + wrbuf_puts(wrbuf, ""); + wrbuf_xmlputs(wrbuf, ht[i].id); + wrbuf_puts(wrbuf, "\n"); + + wrbuf_puts(wrbuf, ""); + if (!ht[i].name || !ht[i].name[0]) + wrbuf_xmlputs(wrbuf, "NO TARGET NAME"); + else + wrbuf_xmlputs(wrbuf, ht[i].name); + wrbuf_puts(wrbuf, "\n"); + + wrbuf_printf(wrbuf, "" ODR_INT_PRINTF "\n", + ht[i].hits); + + wrbuf_puts(wrbuf, ""); + wrbuf_xmlputs(wrbuf, ht[i].state); + wrbuf_puts(wrbuf, "\n"); + + wrbuf_printf(wrbuf, "%d\n", + ht[i].diagnostic); + wrbuf_puts(wrbuf, "\n"); + } + return count; +} + +void perform_termlist(struct http_channel *c, struct session *se, + const char *name, int num) +{ + int i, j; + NMEM nmem_tmp = nmem_create(); + char **names; + int num_names = 0; + + if (name) + nmem_strsplit(nmem_tmp, ",", name, &names, &num_names); + + session_enter(se); + + for (j = 0; j < num_names; j++) + { + const char *tname; + for (i = 0; i < se->num_termlists; i++) + { + tname = se->termlists[i].name; + if (num_names > 0 && !strcmp(names[j], tname)) + { + struct termlist_score **p = 0; + int len; + p = termlist_highscore(se->termlists[i].termlist, &len); + if (p) + { + int i; + wrbuf_puts(c->wrbuf, "wrbuf, tname); + wrbuf_puts(c->wrbuf, "\">\n"); + for (i = 0; i < len && i < num; i++) + { + // prevent sending empty term elements + if (!p[i]->display_term || !p[i]->display_term[0]) + continue; + + wrbuf_puts(c->wrbuf, ""); + wrbuf_puts(c->wrbuf, ""); + wrbuf_xmlputs(c->wrbuf, p[i]->display_term); + wrbuf_puts(c->wrbuf, ""); + + wrbuf_printf(c->wrbuf, + "%d", + p[i]->frequency); + wrbuf_puts(c->wrbuf, "\n"); + } + wrbuf_puts(c->wrbuf, "\n"); + } + } + } + tname = "xtargets"; + if (num_names > 0 && !strcmp(names[j], tname)) + { + wrbuf_puts(c->wrbuf, "wrbuf, tname); + wrbuf_puts(c->wrbuf, "\">\n"); + targets_termlist_nb(c->wrbuf, se, num, c->nmem); + wrbuf_puts(c->wrbuf, "\n"); + } + } + session_leave(se); + nmem_destroy(nmem_tmp); +} + #ifdef MISSING_HEADERS void report_nmem_stats(void) { @@ -1077,15 +1230,15 @@ static int get_mergekey_from_doc(xmlDoc *doc, xmlNode *root, const char *name, if (value) { const char *norm_str; - pp2_relevance_token_t prt = - pp2_relevance_tokenize(service->mergekey_pct); + pp2_charset_token_t prt = + pp2_charset_token_create(service->charsets, "mergekey"); - pp2_relevance_first(prt, (const char *) value, 0); + pp2_charset_token_first(prt, (const char *) value, 0); if (wrbuf_len(norm_wr) > 0) wrbuf_puts(norm_wr, " "); wrbuf_puts(norm_wr, name); while ((norm_str = - pp2_relevance_token_next(prt))) + pp2_charset_token_next(prt))) { if (*norm_str) { @@ -1094,7 +1247,7 @@ static int get_mergekey_from_doc(xmlDoc *doc, xmlNode *root, const char *name, } } xmlFree(value); - pp2_relevance_token_destroy(prt); + pp2_charset_token_destroy(prt); no_found++; } } @@ -1116,11 +1269,11 @@ static const char *get_mergekey(xmlDoc *doc, struct client *cl, int record_no, if (mergekey) { const char *norm_str; - pp2_relevance_token_t prt = - pp2_relevance_tokenize(service->mergekey_pct); + pp2_charset_token_t prt = + pp2_charset_token_create(service->charsets, "mergekey"); - pp2_relevance_first(prt, (const char *) mergekey, 0); - while ((norm_str = pp2_relevance_token_next(prt))) + pp2_charset_token_first(prt, (const char *) mergekey, 0); + while ((norm_str = pp2_charset_token_next(prt))) { if (*norm_str) { @@ -1129,7 +1282,7 @@ static const char *get_mergekey(xmlDoc *doc, struct client *cl, int record_no, wrbuf_puts(norm_wr, norm_str); } } - pp2_relevance_token_destroy(prt); + pp2_charset_token_destroy(prt); xmlFree(mergekey); } else @@ -1241,6 +1394,7 @@ static int ingest_to_cluster(struct client *cl, \param nmem working NMEM \retval 0 OK \retval -1 failure + \retval -2 Filtered */ int ingest_record(struct client *cl, const char *rec, int record_no, NMEM nmem) @@ -1260,10 +1414,10 @@ int ingest_record(struct client *cl, const char *rec, if (!check_record_filter(root, sdb)) { - session_log(se, YLOG_WARN, "Filtered out record no %d from %s", + session_log(se, YLOG_LOG, "Filtered out record no %d from %s", record_no, sdb->database->url); xmlFreeDoc(xdoc); - return -1; + return -2; } mergekey_norm = get_mergekey(xdoc, cl, record_no, service, nmem); @@ -1327,7 +1481,7 @@ static int ingest_to_cluster(struct client *cl, // now parsing XML record and adding data to cluster or record metadata for (n = root->children; n; n = n->next) { - pp2_relevance_token_t prt; + pp2_charset_token_t prt; if (type) xmlFree(type); if (value) @@ -1394,16 +1548,15 @@ static int ingest_to_cluster(struct client *cl, // assign cluster or record based on merge action if (ser_md->merge == Metadata_merge_unique) { - struct record_metadata *mnode; - for (mnode = *wheretoput; mnode; mnode = mnode->next) - if (!strcmp((const char *) mnode->data.text.disp, + while (*wheretoput) + { + if (!strcmp((const char *) (*wheretoput)->data.text.disp, rec_md->data.text.disp)) break; - if (!mnode) - { - rec_md->next = *wheretoput; - *wheretoput = rec_md; + wheretoput = &(*wheretoput)->next; } + if (!*wheretoput) + *wheretoput = rec_md; } else if (ser_md->merge == Metadata_merge_longest) { @@ -1423,12 +1576,13 @@ static int ingest_to_cluster(struct client *cl, nmem_malloc(se->nmem, sizeof(union data_types)); - prt = pp2_relevance_tokenize(service->sort_pct); + prt = + pp2_charset_token_create(service->charsets, "sort"); - pp2_relevance_first(prt, rec_md->data.text.disp, - skip_article); + pp2_charset_token_first(prt, rec_md->data.text.disp, + skip_article); - pp2_relevance_token_next(prt); + pp2_charset_token_next(prt); sort_str = pp2_get_sort(prt); @@ -1442,13 +1596,14 @@ static int ingest_to_cluster(struct client *cl, } cluster->sortkeys[sk_field_id]->text.sort = nmem_strdup(se->nmem, sort_str); - pp2_relevance_token_destroy(prt); + pp2_charset_token_destroy(prt); } } } else if (ser_md->merge == Metadata_merge_all) { - rec_md->next = *wheretoput; + while (*wheretoput) + wheretoput = &(*wheretoput)->next; *wheretoput = rec_md; } else if (ser_md->merge == Metadata_merge_range) @@ -1481,7 +1636,6 @@ static int ingest_to_cluster(struct client *cl, // construct facets ... unless the client already has reported them if (ser_md->termlist && !client_has_facet(cl, (char *) type)) { - if (ser_md->type == Metadata_type_year) { char year[64];