X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Ffilter_z3950_client.cpp;h=d0d04427595889803b216b9322c8c04b344f0451;hb=fcce42024d4c6fa3ddaefc1a140ee22016db8ab7;hp=0c775e74fe1659d10c6c1ddfc67e56f19ff57270;hpb=79100c2ae2dac4bdde4f4d46b69e147562b4ec6c;p=metaproxy-moved-to-github.git diff --git a/src/filter_z3950_client.cpp b/src/filter_z3950_client.cpp index 0c775e7..d0d0442 100644 --- a/src/filter_z3950_client.cpp +++ b/src/filter_z3950_client.cpp @@ -1,8 +1,20 @@ -/* $Id: filter_z3950_client.cpp,v 1.24 2006-03-16 10:40:59 adam Exp $ - Copyright (c) 2005-2006, Index Data. +/* This file is part of Metaproxy. + Copyright (C) 2005-2008 Index Data -%LICENSE% - */ +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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "config.hpp" @@ -18,15 +30,16 @@ #include #include +#include #include #include #include #include -#include -#include -#include +#include +#include +#include namespace mp = metaproxy_1; namespace yf = mp::filter; @@ -62,7 +75,11 @@ namespace metaproxy_1 { class Z3950Client::Rep { public: + // number of seconds to wait before we give up request int m_timeout_sec; + int m_max_sockets; + std::string m_default_target; + std::string m_force_target; boost::mutex m_mutex; boost::condition m_cond_session_ready; std::map m_clients; @@ -166,6 +183,7 @@ yazpp_1::IPDU_Observer *yf::Z3950Client::Assoc::sessionNotify( yf::Z3950Client::Z3950Client() : m_p(new yf::Z3950Client::Rep) { m_p->m_timeout_sec = 30; + m_p->m_max_sockets = 0; } yf::Z3950Client::~Z3950Client() { @@ -192,6 +210,7 @@ yf::Z3950Client::Assoc *yf::Z3950Client::Rep::get_assoc(Package &package) while(true) { #if 0 + // double init .. NOT working yet if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which == Z_APDU_initRequest) { @@ -224,41 +243,82 @@ yf::Z3950Client::Assoc *yf::Z3950Client::Rep::get_assoc(Package &package) package.session().close(); return 0; } - std::list vhosts; - mp::util::get_vhost_otherinfo(&apdu->u.initRequest->otherInfo, - true, vhosts); - size_t no_vhosts = vhosts.size(); - if (no_vhosts == 0) - { - mp::odr odr; - package.response() = odr.create_initResponse( - apdu, - YAZ_BIB1_INIT_NEGOTIATION_OPTION_REQUIRED, - "z3950_client: No virtal host given"); - - package.session().close(); - return 0; - } - if (no_vhosts > 1) + std::string target = m_force_target; + if (!target.length()) { - mp::odr odr; - package.response() = odr.create_initResponse( - apdu, - YAZ_BIB1_COMBI_OF_SPECIFIED_DATABASES_UNSUPP, - "z3950_client: Can not cope with multiple vhosts"); - package.session().close(); - return 0; + target = m_default_target; + std::list vhosts; + mp::util::remove_vhost_otherinfo(&apdu->u.initRequest->otherInfo, + vhosts); + size_t no_vhosts = vhosts.size(); + if (no_vhosts == 1) + { + std::list::const_iterator v_it = vhosts.begin(); + target = *v_it; + } + else if (no_vhosts == 0) + { + if (!target.length()) + { + // no default target. So we don't know where to connect + mp::odr odr; + package.response() = odr.create_initResponse( + apdu, + YAZ_BIB1_INIT_NEGOTIATION_OPTION_REQUIRED, + "z3950_client: No virtal host given"); + + package.session().close(); + return 0; + } + } + else if (no_vhosts > 1) + { + mp::odr odr; + package.response() = odr.create_initResponse( + apdu, + YAZ_BIB1_COMBI_OF_SPECIFIED_DATABASES_UNSUPP, + "z3950_client: Can not cope with multiple vhosts"); + package.session().close(); + return 0; + } } - std::list::const_iterator v_it = vhosts.begin(); + std::list dblist; std::string host; - mp::util::split_zurl(*v_it, host, dblist); + mp::util::split_zurl(target, host, dblist); if (dblist.size()) { ; // z3950_client: Databases in vhost ignored } + while (m_max_sockets) + { + int number = 0; + it = m_clients.begin(); + for (; it != m_clients.end(); it++) + { + yf::Z3950Client::Assoc *as = it->second; + if (!strcmp(as->get_hostname(), host.c_str())) + number++; + } + if (number < m_max_sockets) + break; + boost::xtime xt; + xtime_get(&xt, boost::TIME_UTC); + + xt.sec += 15; + if (!m_cond_session_ready.timed_wait(lock, xt)) + { + mp::odr odr; + + package.response() = odr.create_initResponse( + apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, "max sessions"); + package.session().close(); + return 0; + } + } + yazpp_1::SocketManager *sm = new yazpp_1::SocketManager; yazpp_1::PDU_Assoc *pdu_as = new yazpp_1::PDU_Assoc(sm); yf::Z3950Client::Assoc *as = new yf::Z3950Client::Assoc(sm, pdu_as, @@ -285,7 +345,7 @@ void yf::Z3950Client::Rep::send_and_receive(Package &package, if (!c->m_connected) { c->client(c->m_host.c_str()); - c->timeout(1); + c->timeout(1); // so timeoutNotify gets called once per second while (!c->m_destroyed && c->m_waiting && c->m_socket_manager->processEvent() > 0) @@ -341,7 +401,7 @@ void yf::Z3950Client::Rep::release_assoc(Package &package) // wait until no one is waiting for it. while (it->second->m_queue_len) m_cond_session_ready.wait(lock); - + // the Z_Assoc and PDU_Assoc must be destroyed before // the socket manager.. so pull that out.. first.. yazpp_1::SocketManager *s = it->second->m_socket_manager; @@ -363,7 +423,7 @@ void yf::Z3950Client::process(Package &package) const m_p->release_assoc(package); } -void yf::Z3950Client::configure(const xmlNode *ptr) +void yf::Z3950Client::configure(const xmlNode *ptr, bool test_only) { for (ptr = ptr->children; ptr; ptr = ptr->next) { @@ -371,12 +431,19 @@ void yf::Z3950Client::configure(const xmlNode *ptr) continue; if (!strcmp((const char *) ptr->name, "timeout")) { - std::string timeout_str = mp::xml::get_text(ptr); - int timeout_sec = atoi(timeout_str.c_str()); - if (timeout_sec < 2) - throw mp::filter::FilterException("Bad timeout value " - + timeout_str); - m_p->m_timeout_sec = timeout_sec; + m_p->m_timeout_sec = mp::xml::get_int(ptr->children, 30); + } + else if (!strcmp((const char *) ptr->name, "default_target")) + { + m_p->m_default_target = mp::xml::get_text(ptr); + } + else if (!strcmp((const char *) ptr->name, "force_target")) + { + m_p->m_force_target = mp::xml::get_text(ptr); + } + else if (!strcmp((const char *) ptr->name, "max-sockets")) + { + m_p->m_max_sockets = mp::xml::get_int(ptr->children, 0); } else {