X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Ffilter_multi.cpp;h=c49825ba7f76d4bf0a28b8bd2d945143db375968;hb=1c7ebc4b50e702c562b9ae91eb2bb0612b9d3735;hp=33de6a4235563ea70456cf9e143d61ba533136d8;hpb=4bfec20c393570a81471c644fad6268eed3dba29;p=metaproxy-moved-to-github.git diff --git a/src/filter_multi.cpp b/src/filter_multi.cpp index 33de6a4..c49825b 100644 --- a/src/filter_multi.cpp +++ b/src/filter_multi.cpp @@ -1,5 +1,5 @@ /* This file is part of Metaproxy. - Copyright (C) 2005-2011 Index Data + Copyright (C) 2005-2012 Index Data Metaproxy 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 @@ -136,6 +136,7 @@ namespace metaproxy_1 { boost::condition m_cond_session_ready; std::map m_clients; bool m_hide_unavailable; + bool m_hide_errors; multi_merge_type m_merge_type; }; } @@ -144,6 +145,7 @@ namespace metaproxy_1 { yf::Multi::Rep::Rep() { m_hide_unavailable = false; + m_hide_errors = false; m_merge_type = round_robin; } @@ -566,56 +568,103 @@ void yf::Multi::Frontend::search(mp::Package &package, Z_APDU *apdu_req) // look at each response FrontendSet resultSet(std::string(req->resultSetName)); + mp::odr odr; Odr_int result_set_size = 0; - Z_Records *z_records_diag = 0; // no diagnostics (yet) + Z_DiagRecs *z_diag = 0; + int no_successful = 0; + PackagePtr close_p; + for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) { PackagePtr p = (*bit)->m_package; - if (p->session().is_closed()) // if any backend closes, close frontend - package.session().close(); - + // save closing package for at least one target + if (p->session().is_closed()) + close_p = p; + Z_GDU *gdu = p->response().get(); if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which == Z_APDU_searchResponse) { Z_APDU *b_apdu = gdu->u.z3950; Z_SearchResponse *b_resp = b_apdu->u.searchResponse; - + // see we get any errors (AKA diagnstics) if (b_resp->records) { - if (b_resp->records->which == Z_Records_NSD - || b_resp->records->which == Z_Records_multipleNSD) - z_records_diag = b_resp->records; - // we may set this multiple times (TOO BAD!) + if (b_resp->records->which == Z_Records_NSD) + { + if (!z_diag) + { + z_diag = (Z_DiagRecs *) + odr_malloc(odr, sizeof(*z_diag)); + z_diag->num_diagRecs = 0; + z_diag->diagRecs = (Z_DiagRec**) + odr_malloc(odr, sizeof(*z_diag->diagRecs)); + } + else + { + Z_DiagRec **n = (Z_DiagRec **) + odr_malloc(odr, + (1+z_diag->num_diagRecs) * sizeof(*n)); + memcpy(n, z_diag->diagRecs, z_diag->num_diagRecs + * sizeof(*n)); + z_diag->diagRecs = n; + } + Z_DiagRec *nr = (Z_DiagRec *) odr_malloc(odr, sizeof(*nr)); + nr->which = Z_DiagRec_defaultFormat; + nr->u.defaultFormat = + b_resp->records->u.nonSurrogateDiagnostic; + z_diag->diagRecs[z_diag->num_diagRecs++] = nr; + } + else if (b_resp->records->which == Z_Records_multipleNSD) + { + // we may set this multiple times (TOO BAD!) + z_diag = b_resp->records->u.multipleNonSurDiagnostics; + } + else + no_successful++; // probably piggyback } + else + no_successful++; // no records and no diagnostics BackendSet backendSet; backendSet.m_backend = *bit; backendSet.m_count = *b_resp->resultCount; result_set_size += *b_resp->resultCount; resultSet.m_backend_sets.push_back(backendSet); } - else - { - // if any target does not return search response - return that - package.response() = p->response(); - return; - } } - mp::odr odr; Z_APDU *f_apdu = odr.create_searchResponse(apdu_req, 0, 0); Z_SearchResponse *f_resp = f_apdu->u.searchResponse; + yaz_log(YLOG_LOG, "no_successful=%d is_closed=%s hide_errors=%s", + no_successful, + close_p ? "true" : "false", + m_p->m_hide_errors ? "true" : "false"); *f_resp->resultCount = result_set_size; - if (z_records_diag) + if (close_p && (no_successful == 0 || !m_p->m_hide_errors)) { - // search error - f_resp->records = z_records_diag; - package.response() = f_apdu; + package.session().close(); + package.response() = close_p->response(); return; } + if (z_diag && (no_successful == 0 || !m_p->m_hide_errors)) + { + f_resp->records = (Z_Records *) + odr_malloc(odr, sizeof(*f_resp->records)); + if (z_diag->num_diagRecs > 1) + { + f_resp->records->which = Z_Records_multipleNSD; + f_resp->records->u.multipleNonSurDiagnostics = z_diag; + } + else + { + f_resp->records->which = Z_Records_NSD; + f_resp->records->u.nonSurrogateDiagnostic = + z_diag->diagRecs[0]->u.defaultFormat; + } + } // assume OK m_sets[resultSet.m_setname] = resultSet; @@ -627,7 +676,7 @@ void yf::Multi::Frontend::search(mp::Package &package, Z_APDU *apdu_req) result_set_size, number, 0); Package pp(package.session(), package.origin()); - if (number > 0) + if (z_diag == 0 && number > 0) { pp.copy_filter(package); Z_APDU *p_apdu = zget_APDU(odr, Z_APDU_presentRequest); @@ -1252,6 +1301,10 @@ void mp::filter::Multi::configure(const xmlNode * ptr, bool test_only, { m_p->m_hide_unavailable = true; } + else if (!strcmp((const char *) ptr->name, "hideerrors")) + { + m_p->m_hide_errors = true; + } else if (!strcmp((const char *) ptr->name, "mergetype")) { std::string mergetype = mp::xml::get_text(ptr);