X-Git-Url: http://lists.indexdata.com/cgi-bin?a=blobdiff_plain;f=src%2Ffilter_multi.cpp;h=f02ecc76ce8f5021ebe4383c6457541fd2322f95;hb=9b8466644a970341459fd3fe3b270defd337ed48;hp=fcf3f5b6260d1e6cca21089955fad7f41893122b;hpb=0f91085e7a561979199a348aba002b265b8e4b48;p=metaproxy-moved-to-github.git diff --git a/src/filter_multi.cpp b/src/filter_multi.cpp index fcf3f5b..f02ecc7 100644 --- a/src/filter_multi.cpp +++ b/src/filter_multi.cpp @@ -1,9 +1,26 @@ -/* $Id: filter_multi.cpp,v 1.17 2006-05-15 13:22:02 adam Exp $ - Copyright (c) 2005-2006, Index Data. +/* $Id: filter_multi.cpp,v 1.28 2007-11-18 10:44:40 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 + #include "config.hpp" #include "filter.hpp" @@ -31,7 +48,10 @@ namespace yf = mp::filter; namespace metaproxy_1 { namespace filter { - + enum multi_merge_type { + round_robin, + serve_order + }; struct Multi::BackendSet { BackendPtr m_backend; int m_count; @@ -57,6 +77,7 @@ namespace metaproxy_1 { ~FrontendSet(); void round_robin(int pos, int number, std::list &job); + void serve_order(int pos, int number, std::list &job); std::list m_backend_sets; std::string m_setname; @@ -95,6 +116,7 @@ namespace metaproxy_1 { friend class Multi; friend struct Frontend; + Rep(); FrontendPtr get_frontend(Package &package); void release_frontend(Package &package); private: @@ -102,10 +124,18 @@ namespace metaproxy_1 { boost::mutex m_mutex; boost::condition m_cond_session_ready; std::map m_clients; + bool m_hide_unavailable; + multi_merge_type m_merge_type; }; } } +yf::Multi::Rep::Rep() +{ + m_hide_unavailable = false; + m_merge_type = round_robin; +} + bool yf::Multi::BackendSet::operator < (const BackendSet &k) const { return m_count < k.m_count; @@ -121,7 +151,7 @@ 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); @@ -146,7 +176,7 @@ 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; @@ -205,7 +235,7 @@ void yf::Multi::Backend::operator() (void) } -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++) @@ -230,6 +260,32 @@ void yf::Multi::Frontend::multi_move(std::list &blist) g.join_all(); } +void yf::Multi::FrontendSet::serve_order(int start, int number, + std::list &jobs) +{ + int i; + for (i = 0; i < number; i++) + { + std::list::const_iterator bsit; + int voffset = 0; + int offset = start + i - 1; + for (bsit = m_backend_sets.begin(); bsit != m_backend_sets.end(); + bsit++) + { + if (offset >= voffset && offset < voffset + bsit->m_count) + { + PresentJob job; + job.m_backend = bsit->m_backend; + job.m_inside_pos = 0; + job.m_pos = offset - voffset + 1; + jobs.push_back(job); + break; + } + voffset += bsit->m_count; + } + } +} + void yf::Multi::FrontendSet::round_robin(int start, int number, std::list &jobs) { @@ -323,13 +379,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; - mp::util::get_vhost_otherinfo(&req->otherInfo, false, targets); + mp::util::get_vhost_otherinfo(req->otherInfo, targets); if (targets.size() < 1) { @@ -353,7 +409,7 @@ 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++) { mp::odr odr; @@ -396,12 +452,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) @@ -431,11 +496,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; @@ -569,7 +645,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; @@ -590,7 +666,21 @@ void yf::Multi::Frontend::present(Package &package, Z_APDU *apdu_req) std::list jobs; int start = *req->resultSetStartPoint; int number = *req->numberOfRecordsRequested; - it->second.round_robin(start, number, jobs); + + if (m_p->m_merge_type == round_robin) + it->second.round_robin(start, number, jobs); + else if (m_p->m_merge_type == serve_order) + it->second.serve_order(start, number, jobs); + + if (0) + { + std::list::const_iterator jit; + for (jit = jobs.begin(); jit != jobs.end(); jit++) + { + yaz_log(YLOG_LOG, "job pos=%d inside_pos=%d", + jit->m_pos, jit->m_inside_pos); + } + } std::list present_backend_list; @@ -684,7 +774,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; @@ -692,17 +782,25 @@ 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) { @@ -793,7 +891,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; @@ -1021,7 +1119,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); @@ -1087,12 +1185,28 @@ void mp::filter::Multi::configure(const xmlNode * ptr) std::cout << "route=" << route << " target=" << target << "\n"; m_p->m_target_route[target] = route; } + else if (!strcmp((const char *) ptr->name, "hideunavailable")) + { + m_p->m_hide_unavailable = true; + } + else if (!strcmp((const char *) ptr->name, "mergetype")) + { + std::string mergetype = mp::xml::get_text(ptr); + if (mergetype == "roundrobin") + m_p->m_merge_type = round_robin; + else if (mergetype == "serveorder") + m_p->m_merge_type = serve_order; + else + throw mp::filter::FilterException + ("Bad mergetype " + mergetype + " in multi filter"); + + } else { throw mp::filter::FilterException ("Bad element " + std::string((const char *) ptr->name) - + " in virt_db filter"); + + " in multi filter"); } } }