/* This file is part of Metaproxy.
- Copyright (C) 2005-2009 Index Data
+ Copyright (C) 2005-2011 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
#include "config.hpp"
-#include "filter.hpp"
-#include "package.hpp"
-#include "util.hpp"
#include "filter_z3950_client.hpp"
+#include <metaproxy/package.hpp>
+#include <metaproxy/util.hpp>
#include <map>
#include <stdexcept>
void failNotify();
void timeoutNotify();
void recv_GDU(Z_GDU *gdu, int len);
+ void fixup_nsd(ODR odr, Z_Records *records);
yazpp_1::IPDU_Observer* sessionNotify(
yazpp_1::IPDU_Observable *the_PDU_Observable,
int fd);
bool m_waiting;
bool m_destroyed;
bool m_connected;
+ bool m_has_closed;
int m_queue_len;
int m_time_elapsed;
int m_time_max;
// number of seconds to wait before we give up request
int m_timeout_sec;
int m_max_sockets;
+ bool m_force_close;
std::string m_default_target;
std::string m_force_target;
boost::mutex m_mutex;
: Z_Assoc(PDU_Observable),
m_socket_manager(socket_manager), m_PDU_Observable(PDU_Observable),
m_package(0), m_in_use(true), m_waiting(false),
- m_destroyed(false), m_connected(false), m_queue_len(1),
+ m_destroyed(false), m_connected(false), m_has_closed(false),
+ m_queue_len(1),
m_time_elapsed(0), m_time_max(timeout_sec), m_time_connect_max(10),
m_host(host)
{
}
}
+void yf::Z3950Client::Assoc::fixup_nsd(ODR odr, Z_Records *records)
+{
+ if (records && records->which == Z_Records_NSD)
+ {
+ Z_DefaultDiagFormat *nsd = records->u.nonSurrogateDiagnostic;
+ if (nsd->which == Z_DiagRec_defaultFormat)
+ {
+ std::string addinfo;
+
+ if (nsd->u.v2Addinfo)
+ {
+ addinfo.assign(nsd->u.v2Addinfo);
+ addinfo += " ";
+ }
+ addinfo += "(backend=" + m_host + ")";
+ nsd->u.v2Addinfo = odr_strdup(odr, addinfo.c_str());
+ }
+ }
+}
+
void yf::Z3950Client::Assoc::recv_GDU(Z_GDU *gdu, int len)
{
m_waiting = false;
if (m_package)
+ {
+ mp::odr odr; // must be in scope for response() = assignment
+ if (gdu && gdu->which == Z_GDU_Z3950)
+ {
+ Z_APDU *apdu = gdu->u.z3950;
+ switch (apdu->which)
+ {
+ case Z_APDU_searchResponse:
+ fixup_nsd(odr, apdu->u.searchResponse->records);
+ break;
+ case Z_APDU_presentResponse:
+ fixup_nsd(odr, apdu->u.presentResponse->records);
+ break;
+ }
+ }
m_package->response() = gdu;
+ }
}
yazpp_1::IPDU_Observer *yf::Z3950Client::Assoc::sessionNotify(
{
m_p->m_timeout_sec = 30;
m_p->m_max_sockets = 0;
+ m_p->m_force_close = false;
}
yf::Z3950Client::~Z3950Client() {
std::map<mp::Session,yf::Z3950Client::Assoc *>::iterator it;
Z_GDU *gdu = package.request().get();
- // only deal with Z39.50
- if (!gdu || gdu->which != Z_GDU_Z3950)
- {
- package.move();
- return 0;
- }
int max_sockets = package.origin().get_max_sockets();
if (max_sockets == 0)
m_cond_session_ready.wait(lock);
}
}
+ if (!gdu || gdu->which != Z_GDU_Z3950)
+ {
+ package.move();
+ return 0;
+ }
// new Z39.50 session ..
Z_APDU *apdu = gdu->u.z3950;
// check that it is init. If not, close
for (; it != m_clients.end(); it++)
{
yf::Z3950Client::Assoc *as = it->second;
- if (!strcmp(as->get_hostname(), host.c_str()))
+ if (!strcmp(as->m_host.c_str(), host.c_str()))
{
number++;
if (!as->m_in_use)
void yf::Z3950Client::Rep::send_and_receive(Package &package,
yf::Z3950Client::Assoc *c)
{
- Z_GDU *gdu = package.request().get();
-
if (c->m_destroyed)
return;
+ c->m_package = &package;
+
+ if (package.session().is_closed() && c->m_connected && !c->m_has_closed
+ && m_force_close)
+ {
+ mp::odr odr;
+
+ package.request() = odr.create_close(
+ 0, Z_Close_finished, "z3950_client");
+ c->m_package = 0; // don't inspect response
+ }
+ Z_GDU *gdu = package.request().get();
+
if (!gdu || gdu->which != Z_GDU_Z3950)
return;
+ if (gdu->u.z3950->which == Z_APDU_close)
+ c->m_has_closed = true;
+
+ // prepare connect
c->m_time_elapsed = 0;
- c->m_package = &package;
c->m_waiting = true;
if (!c->m_connected)
{
- c->client(c->m_host.c_str());
+ if (c->client(c->m_host.c_str()))
+ {
+ mp::odr odr;
+ package.response() =
+ odr.create_close(gdu->u.z3950, Z_Close_peerAbort, 0);
+ package.session().close();
+ return;
+ }
c->timeout(1); // so timeoutNotify gets called once per second
+
while (!c->m_destroyed && c->m_waiting
&& c->m_socket_manager->processEvent() > 0)
int len;
c->send_GDU(gdu, &len);
- switch(gdu->u.z3950->which)
+ switch (gdu->u.z3950->which)
{
case Z_APDU_triggerResourceControlRequest:
// request only..
it = m_clients.find(package.session());
if (it != m_clients.end())
{
- Z_GDU *gdu = package.request().get();
- if (gdu && gdu->which == Z_GDU_Z3950)
- { // only Z39.50 packages lock in get_assoc.. release it
- it->second->m_in_use = false;
- it->second->m_queue_len--;
- }
+ it->second->m_in_use = false;
+ it->second->m_queue_len--;
if (package.session().is_closed())
{
if (c)
{
m_p->send_and_receive(package, c);
+ m_p->release_assoc(package);
}
- m_p->release_assoc(package);
}
-void yf::Z3950Client::configure(const xmlNode *ptr, bool test_only)
+void yf::Z3950Client::configure(const xmlNode *ptr, bool test_only,
+ const char *path)
{
for (ptr = ptr->children; ptr; ptr = ptr->next)
{
continue;
if (!strcmp((const char *) ptr->name, "timeout"))
{
- m_p->m_timeout_sec = mp::xml::get_int(ptr->children, 30);
+ m_p->m_timeout_sec = mp::xml::get_int(ptr, 30);
}
else if (!strcmp((const char *) ptr->name, "default_target"))
{
}
else if (!strcmp((const char *) ptr->name, "max-sockets"))
{
- m_p->m_max_sockets = mp::xml::get_int(ptr->children, 0);
+ m_p->m_max_sockets = mp::xml::get_int(ptr, 0);
+ }
+ else if (!strcmp((const char *) ptr->name, "force_close"))
+ {
+ m_p->m_force_close = mp::xml::get_bool(ptr, 0);
}
else
{