X-Git-Url: http://lists.indexdata.com/cgi-bin?a=blobdiff_plain;f=src%2Ffilter_multi.cpp;h=9a19cc356ce858aefb232f0e742cb0e1ed367533;hb=637a685d61a9ff0e3f398a59da426979815c4d68;hp=53bf19c1c8f541de9e3b28ecd6da814253bf3937;hpb=1e8a9fd11828523752f061d8446d6bbac014906b;p=metaproxy-moved-to-github.git diff --git a/src/filter_multi.cpp b/src/filter_multi.cpp index 53bf19c..9a19cc3 100644 --- a/src/filter_multi.cpp +++ b/src/filter_multi.cpp @@ -1,7 +1,22 @@ -/* $Id: filter_multi.cpp,v 1.13 2006-02-02 10:25:13 adam Exp $ - Copyright (c) 2005, Index Data. +/* $Id: filter_multi.cpp,v 1.27 2007-05-09 21:23:09 adam Exp $ + Copyright (c) 2005-2007, Index Data. -%LICENSE% +This file is part of Metaproxy. + +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 +Software Foundation; either version 2, or (at your option) any later +version. + +Metaproxy 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 Metaproxy; see the file LICENSE. If not, write to the +Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ #include "config.hpp" @@ -26,9 +41,10 @@ #include #include -namespace yf = yp2::filter; +namespace mp = metaproxy_1; +namespace yf = mp::filter; -namespace yp2 { +namespace metaproxy_1 { namespace filter { struct Multi::BackendSet { @@ -92,22 +108,25 @@ namespace yp2 { }; class Multi::Rep { friend class Multi; - friend class Frontend; + friend struct Frontend; + Rep(); FrontendPtr get_frontend(Package &package); void release_frontend(Package &package); private: - boost::mutex m_sessions_mutex; - std::mapm_maps; std::map m_target_route; boost::mutex m_mutex; boost::condition m_cond_session_ready; - std::map m_clients; + std::map m_clients; + bool m_hide_unavailable; }; } } -using namespace yp2; +yf::Multi::Rep::Rep() +{ + m_hide_unavailable = false; +} bool yf::Multi::BackendSet::operator < (const BackendSet &k) const { @@ -124,11 +143,11 @@ yf::Multi::Frontend::~Frontend() { } -yf::Multi::FrontendPtr yf::Multi::Rep::get_frontend(Package &package) +yf::Multi::FrontendPtr yf::Multi::Rep::get_frontend(mp::Package &package) { boost::mutex::scoped_lock lock(m_mutex); - std::map::iterator it; + std::map::iterator it; while(true) { @@ -149,10 +168,10 @@ yf::Multi::FrontendPtr yf::Multi::Rep::get_frontend(Package &package) return f; } -void yf::Multi::Rep::release_frontend(Package &package) +void yf::Multi::Rep::release_frontend(mp::Package &package) { boost::mutex::scoped_lock lock(m_mutex); - std::map::iterator it; + std::map::iterator it; it = m_clients.find(package.session()); if (it != m_clients.end()) @@ -202,20 +221,13 @@ yf::Multi::~Multi() { } -void yf::Multi::add_map_host2hosts(std::string host, - std::list hosts, - std::string route) -{ - m_p->m_maps[host] = Multi::Map(hosts, route); -} - void yf::Multi::Backend::operator() (void) { m_package->move(m_route); } -void yf::Multi::Frontend::close(Package &package) +void yf::Multi::Frontend::close(mp::Package &package) { std::list::const_iterator bit; for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) @@ -333,13 +345,13 @@ void yf::Multi::FrontendSet::round_robin(int start, int number, } } -void yf::Multi::Frontend::init(Package &package, Z_GDU *gdu) +void yf::Multi::Frontend::init(mp::Package &package, Z_GDU *gdu) { Z_InitRequest *req = gdu->u.z3950->u.initRequest; std::list targets; - yp2::util::get_vhost_otherinfo(&req->otherInfo, false, targets); + mp::util::get_vhost_otherinfo(req->otherInfo, targets); if (targets.size() < 1) { @@ -363,16 +375,16 @@ void yf::Multi::Frontend::init(Package &package, Z_GDU *gdu) m_is_multi = true; // create init request - std::list::const_iterator bit; + std::list::iterator bit; for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) { - yp2::odr odr; + mp::odr odr; BackendPtr b = *bit; Z_APDU *init_apdu = zget_APDU(odr, Z_APDU_initRequest); std::listvhost_one; vhost_one.push_back(b->m_vhost); - yp2::util::set_vhost_otherinfo(&init_apdu->u.initRequest->otherInfo, + mp::util::set_vhost_otherinfo(&init_apdu->u.initRequest->otherInfo, odr, vhost_one); Z_InitRequest *req = init_apdu->u.initRequest; @@ -393,7 +405,7 @@ void yf::Multi::Frontend::init(Package &package, Z_GDU *gdu) multi_move(m_backend_list); // create the frontend init response based on each backend init response - yp2::odr odr; + mp::odr odr; Z_APDU *f_apdu = odr.create_initResponse(gdu->u.z3950, 0, 0); Z_InitResponse *f_resp = f_apdu->u.initResponse; @@ -406,12 +418,21 @@ void yf::Multi::Frontend::init(Package &package, Z_GDU *gdu) ODR_MASK_SET(f_resp->protocolVersion, Z_ProtocolVersion_2); ODR_MASK_SET(f_resp->protocolVersion, Z_ProtocolVersion_3); - for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) + int no_failed = 0; + int no_succeeded = 0; + for (bit = m_backend_list.begin(); bit != m_backend_list.end(); ) { PackagePtr p = (*bit)->m_package; - if (p->session().is_closed()) // if any backend closes, close frontend - package.session().close(); + if (p->session().is_closed()) + { + // failed. Remove from list and increment number of failed + no_failed++; + bit = m_backend_list.erase(bit); + continue; + } + no_succeeded++; + Z_GDU *gdu = p->response().get(); if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which == Z_APDU_initResponse) @@ -441,11 +462,22 @@ void yf::Multi::Frontend::init(Package &package, Z_GDU *gdu) package.response() = p->response(); return; } + bit++; + } + if (m_p->m_hide_unavailable) + { + if (no_succeeded == 0) + package.session().close(); + } + else + { + if (no_failed) + package.session().close(); } package.response() = f_apdu; } -void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) +void yf::Multi::Frontend::search(mp::Package &package, Z_APDU *apdu_req) { // create search request Z_SearchRequest *req = apdu_req->u.searchRequest; @@ -467,9 +499,9 @@ void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) { PackagePtr p = (*bit)->m_package; - yp2::odr odr; + mp::odr odr; - if (!yp2::util::set_databases_from_zurl(odr, (*bit)->m_vhost, + if (!mp::util::set_databases_from_zurl(odr, (*bit)->m_vhost, &req->num_databaseNames, &req->databaseNames)) { @@ -522,7 +554,7 @@ void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) } } - yp2::odr odr; + mp::odr odr; Z_APDU *f_apdu = odr.create_searchResponse(apdu_req, 0, 0); Z_SearchResponse *f_resp = f_apdu->u.searchResponse; @@ -538,7 +570,7 @@ void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) m_sets[resultSet.m_setname] = resultSet; int number; - yp2::util::piggyback(smallSetUpperBound, + mp::util::piggyback(smallSetUpperBound, largeSetLowerBound, mediumSetPresentNumber, result_set_size, @@ -579,7 +611,7 @@ void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) package.response() = f_apdu; // in this scope because of p } -void yf::Multi::Frontend::present(Package &package, Z_APDU *apdu_req) +void yf::Multi::Frontend::present(mp::Package &package, Z_APDU *apdu_req) { // create present request Z_PresentRequest *req = apdu_req->u.presentRequest; @@ -588,7 +620,7 @@ void yf::Multi::Frontend::present(Package &package, Z_APDU *apdu_req) it = m_sets.find(std::string(req->resultSetId)); if (it == m_sets.end()) { - yp2::odr odr; + mp::odr odr; Z_APDU *apdu = odr.create_presentResponse( apdu_req, @@ -671,7 +703,7 @@ void yf::Multi::Frontend::present(Package &package, Z_APDU *apdu_req) } } - yp2::odr odr; + mp::odr odr; Z_APDU *f_apdu = odr.create_presentResponse(apdu_req, 0, 0); Z_PresentResponse *f_resp = f_apdu->u.presentResponse; @@ -694,7 +726,7 @@ void yf::Multi::Frontend::present(Package &package, Z_APDU *apdu_req) odr_malloc(odr, sizeof(Z_NamePlusRecord *) * nprl->num_records); int i = 0; std::list::const_iterator jit; - for (jit = jobs.begin(); jit != jobs.end(); jit++) + for (jit = jobs.begin(); jit != jobs.end(); jit++, i++) { PackagePtr p = jit->m_backend->m_package; @@ -702,21 +734,29 @@ void yf::Multi::Frontend::present(Package &package, Z_APDU *apdu_req) Z_APDU *b_apdu = gdu->u.z3950; Z_PresentResponse *b_resp = b_apdu->u.presentResponse; - nprl->records[i++] = - b_resp->records->u.databaseOrSurDiagnostics-> - records[jit->m_inside_pos]; + nprl->records[i] = (Z_NamePlusRecord*) + odr_malloc(odr, sizeof(Z_NamePlusRecord)); + int inside_pos = jit->m_inside_pos; + if (inside_pos >= b_resp->records-> + u.databaseOrSurDiagnostics->num_records) + break; + *nprl->records[i] = *b_resp->records-> + u.databaseOrSurDiagnostics->records[inside_pos]; + nprl->records[i]->databaseName = + odr_strdup(odr, jit->m_backend->m_vhost.c_str()); } + nprl->num_records = i; // usually same as jobs.size(); *f_resp->nextResultSetPosition = start + i; *f_resp->numberOfRecordsReturned = i; } package.response() = f_apdu; } -void yf::Multi::Frontend::scan1(Package &package, Z_APDU *apdu_req) +void yf::Multi::Frontend::scan1(mp::Package &package, Z_APDU *apdu_req) { if (m_backend_list.size() > 1) { - yp2::odr odr; + mp::odr odr; Z_APDU *f_apdu = odr.create_scanResponse( apdu_req, YAZ_BIB1_COMBI_OF_SPECIFIED_DATABASES_UNSUPP, 0); @@ -732,9 +772,9 @@ void yf::Multi::Frontend::scan1(Package &package, Z_APDU *apdu_req) for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) { PackagePtr p = (*bit)->m_package; - yp2::odr odr; + mp::odr odr; - if (!yp2::util::set_databases_from_zurl(odr, (*bit)->m_vhost, + if (!mp::util::set_databases_from_zurl(odr, (*bit)->m_vhost, &req->num_databaseNames, &req->databaseNames)) { @@ -803,7 +843,7 @@ Z_Entry *yf::Multi::ScanTermInfo::get_entry(ODR odr) return e; } -void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req) +void yf::Multi::Frontend::scan2(mp::Package &package, Z_APDU *apdu_req) { Z_ScanRequest *req = apdu_req->u.scanRequest; @@ -814,9 +854,9 @@ void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req) for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) { PackagePtr p = (*bit)->m_package; - yp2::odr odr; + mp::odr odr; - if (!yp2::util::set_databases_from_zurl(odr, (*bit)->m_vhost, + if (!mp::util::set_databases_from_zurl(odr, (*bit)->m_vhost, &req->num_databaseNames, &req->databaseNames)) { @@ -849,7 +889,7 @@ void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req) if (res->entries && res->entries->nonsurrogateDiagnostics) { // failure - yp2::odr odr; + mp::odr odr; Z_APDU *f_apdu = odr.create_scanResponse(apdu_req, 1, 0); Z_ScanResponse *f_res = f_apdu->u.scanResponse; @@ -981,13 +1021,13 @@ void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req) if (false) { - yp2::odr odr; + mp::odr odr; Z_APDU *f_apdu = odr.create_scanResponse(apdu_req, 1, "not implemented"); package.response() = f_apdu; } else { - yp2::odr odr; + mp::odr odr; Z_APDU *f_apdu = odr.create_scanResponse(apdu_req, 0, 0); Z_ScanResponse *resp = f_apdu->u.scanResponse; @@ -1031,7 +1071,7 @@ void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req) } -void yf::Multi::process(Package &package) const +void yf::Multi::process(mp::Package &package) const { FrontendPtr f = m_p->get_frontend(package); @@ -1049,7 +1089,7 @@ void yf::Multi::process(Package &package) const Z_APDU *apdu = gdu->u.z3950; if (apdu->which == Z_APDU_initRequest) { - yp2::odr odr; + mp::odr odr; package.response() = odr.create_close( apdu, @@ -1072,7 +1112,7 @@ void yf::Multi::process(Package &package) const } else { - yp2::odr odr; + mp::odr odr; package.response() = odr.create_close( apdu, Z_Close_protocolError, @@ -1084,7 +1124,7 @@ void yf::Multi::process(Package &package) const m_p->release_frontend(package); } -void yp2::filter::Multi::configure(const xmlNode * ptr) +void mp::filter::Multi::configure(const xmlNode * ptr) { for (ptr = ptr->children; ptr; ptr = ptr->next) { @@ -1092,44 +1132,18 @@ void yp2::filter::Multi::configure(const xmlNode * ptr) continue; if (!strcmp((const char *) ptr->name, "target")) { - std::string route = yp2::xml::get_route(ptr); - std::string target = yp2::xml::get_text(ptr); + std::string route = mp::xml::get_route(ptr); + std::string target = mp::xml::get_text(ptr); std::cout << "route=" << route << " target=" << target << "\n"; m_p->m_target_route[target] = route; } - else if (!strcmp((const char *) ptr->name, "virtual")) + else if (!strcmp((const char *) ptr->name, "hideunavailable")) { - std::list targets; - std::string vhost; - xmlNode *v_node = ptr->children; - for (; v_node; v_node = v_node->next) - { - if (v_node->type != XML_ELEMENT_NODE) - continue; - - if (yp2::xml::is_element_yp2(v_node, "vhost")) - vhost = yp2::xml::get_text(v_node); - else if (yp2::xml::is_element_yp2(v_node, "target")) - targets.push_back(yp2::xml::get_text(v_node)); - else - throw yp2::filter::FilterException - ("Bad element " - + std::string((const char *) v_node->name) - + " in virtual section" - ); - } - std::string route = yp2::xml::get_route(ptr); - add_map_host2hosts(vhost, targets, route); - std::list::const_iterator it; - for (it = targets.begin(); it != targets.end(); it++) - { - std::cout << "Add " << vhost << "->" << *it - << "," << route << "\n"; - } + m_p->m_hide_unavailable = true; } else { - throw yp2::filter::FilterException + throw mp::filter::FilterException ("Bad element " + std::string((const char *) ptr->name) + " in virt_db filter"); @@ -1137,13 +1151,13 @@ void yp2::filter::Multi::configure(const xmlNode * ptr) } } -static yp2::filter::Base* filter_creator() +static mp::filter::Base* filter_creator() { - return new yp2::filter::Multi; + return new mp::filter::Multi; } extern "C" { - struct yp2_filter_struct yp2_filter_multi = { + struct metaproxy_1_filter_struct metaproxy_1_filter_multi = { 0, "multi", filter_creator