From 91f84eaf3ca73d717e7c462359127fd44e795bd9 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Mon, 18 Oct 2004 22:10:57 +0000 Subject: [PATCH] Implement bug #143: Add support for multiple SRW/SRU targets. --- include/yazproxy/proxy.h | 12 ++-- src/yaz-proxy-config.cpp | 142 +++++++++++++++++++++++++++++++++------------- src/yaz-proxy.cpp | 53 +++++++++++++---- 3 files changed, 152 insertions(+), 55 deletions(-) diff --git a/include/yazproxy/proxy.h b/include/yazproxy/proxy.h index 7478351..542ec8a 100644 --- a/include/yazproxy/proxy.h +++ b/include/yazproxy/proxy.h @@ -1,4 +1,4 @@ -/* $Id: proxy.h,v 1.6 2004-08-29 13:01:43 adam Exp $ +/* $Id: proxy.h,v 1.7 2004-10-18 22:10:57 adam Exp $ Copyright (c) 1998-2004, Index Data. This file is part of the yaz-proxy. @@ -73,9 +73,10 @@ public: Odr_oid *syntax, Z_RecordComposition *comp, char **addinfo, char **stylesheet, char **schema, char **backend_type, char **backend_charset); - char *get_explain(ODR odr, const char *name, const char *db, - int *len); -private: + char *get_explain_doc(ODR odr, const char *name, const char *db, + int *len); + const char *get_explain_name(const char *db, const char **backend_db); + private: void operator=(const Yaz_ProxyConfig &conf); class Yaz_ProxyConfigP *m_cp; }; @@ -158,9 +159,10 @@ class YAZ_EXPORT Yaz_Proxy : public Yaz_Z_Assoc { char *get_proxy(Z_OtherInformation **otherInfo); Yaz_ProxyClient *get_client(Z_APDU *apdu, const char *cookie, const char *proxy_host); + void srw_get_client(const char *db, const char **backend_db); Z_APDU *result_set_optimize(Z_APDU *apdu); void shutdown(); - + void releaseClient(); Yaz_ProxyClient *m_client; IYaz_PDU_Observable *m_PDU_Observable; Yaz_ProxyClient *m_clientPool; diff --git a/src/yaz-proxy-config.cpp b/src/yaz-proxy-config.cpp index 2102e9a..21497ec 100644 --- a/src/yaz-proxy-config.cpp +++ b/src/yaz-proxy-config.cpp @@ -1,4 +1,4 @@ -/* $Id: yaz-proxy-config.cpp,v 1.6 2004-08-29 13:01:43 adam Exp $ +/* $Id: yaz-proxy-config.cpp,v 1.7 2004-10-18 22:10:57 adam Exp $ Copyright (c) 1998-2004, Index Data. This file is part of the yaz-proxy. @@ -60,6 +60,8 @@ class Yaz_ProxyConfigP { char **addinfo); int check_type_1_structure(ODR odr, xmlNodePtr ptr, Z_RPNStructure *q, char **addinfo); + int get_explain_ptr(const char *host, const char *db, + xmlNodePtr *ptr_target, xmlNodePtr *ptr_explain); #endif }; @@ -773,57 +775,119 @@ void Yaz_ProxyConfig::get_generic_info(int *log_mask, #endif } -char *Yaz_ProxyConfig::get_explain(ODR odr, const char *name, const char *db, - int *len) -{ #if HAVE_XSLT - xmlNodePtr ptr = m_cp->find_target_node(name, db); - if (ptr) +int Yaz_ProxyConfigP::get_explain_ptr(const char *host, const char *db, + xmlNodePtr *ptr_target, + xmlNodePtr *ptr_explain) +{ + xmlNodePtr ptr; + if (!m_proxyPtr) + return 0; + if (!db) + return 0; + for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next) { - ptr = ptr->children; - for (; ptr; ptr = ptr->next) - if (ptr->type == XML_ELEMENT_NODE && - !strcmp((const char *) ptr->name, "explain")) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "target")) + { + *ptr_target = ptr; + xmlNodePtr ptr = (*ptr_target)->children; + for (; ptr; ptr = ptr->next) { - xmlNodePtr ptr1 = ptr->children; - if (db) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "explain")) { - for (; ptr1; ptr1 = ptr1->next) - if (ptr1->type == XML_ELEMENT_NODE && - !strcmp((const char *) ptr1->name, "serverInfo")) + *ptr_explain = ptr; + xmlNodePtr ptr = (*ptr_explain)->children; + + for (; ptr; ptr = ptr->next) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "serverInfo")) break; - if (!ptr1) + if (!ptr) continue; - for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next) - if (ptr1->type == XML_ELEMENT_NODE && - !strcmp((const char *) ptr1->name, "database")) + for (ptr = ptr->children; ptr; ptr = ptr->next) + if (ptr->type == XML_ELEMENT_NODE && + !strcmp((const char *) ptr->name, "database")) break; - if (!ptr1) + if (!ptr) continue; - for (ptr1 = ptr1->children; ptr1; ptr1 = ptr1->next) - if (ptr1->type == XML_TEXT_NODE && - ptr1->content && - !strcmp((const char *) ptr1->content, db)) + for (ptr = ptr->children; ptr; ptr = ptr->next) + if (ptr->type == XML_TEXT_NODE && + ptr->content && + !strcmp((const char *) ptr->content, db)) break; - if (!ptr1) + if (!ptr) continue; + return 1; } - xmlNodePtr ptr2 = xmlCopyNode(ptr, 1); - - xmlDocPtr doc = xmlNewDoc((const xmlChar *) "1.0"); - - xmlDocSetRootElement(doc, ptr2); - - xmlChar *buf_out; - xmlDocDumpMemory(doc, &buf_out, len); - char *content = (char*) odr_malloc(odr, *len); - memcpy(content, buf_out, *len); - - xmlFree(buf_out); - xmlFreeDoc(doc); - return content; } + } + } + return 0; +} +#endif + +const char *Yaz_ProxyConfig::get_explain_name(const char *db, + const char **backend_db) +{ +#if HAVE_XSLT + xmlNodePtr ptr_target, ptr_explain; + if (m_cp->get_explain_ptr(0, db, &ptr_target, &ptr_explain) + && ptr_target) + { + struct _xmlAttr *attr; + const char *name = 0; + + for (attr = ptr_target->properties; attr; attr = attr->next) + if (!strcmp((const char *) attr->name, "name") + && attr->children + && attr->children->type==XML_TEXT_NODE + && attr->children->content + && attr->children->content[0]) + { + name = (const char *)attr->children->content; + break; + } + if (name) + { + for (attr = ptr_target->properties; attr; attr = attr->next) + if (!strcmp((const char *) attr->name, "database")) + { + if (attr->children + && attr->children->type==XML_TEXT_NODE + && attr->children->content) + *backend_db = (const char *) attr->children->content; + } + return name; + } + } +#endif + return 0; +} + +char *Yaz_ProxyConfig::get_explain_doc(ODR odr, const char *name, + const char *db, int *len) +{ +#if HAVE_XSLT + xmlNodePtr ptr_target, ptr_explain; + if (m_cp->get_explain_ptr(0 /* host */, db, &ptr_target, &ptr_explain)) + { + xmlNodePtr ptr2 = xmlCopyNode(ptr_explain, 1); + + xmlDocPtr doc = xmlNewDoc((const xmlChar *) "1.0"); + + xmlDocSetRootElement(doc, ptr2); + + xmlChar *buf_out; + xmlDocDumpMemory(doc, &buf_out, len); + char *content = (char*) odr_malloc(odr, *len); + memcpy(content, buf_out, *len); + + xmlFree(buf_out); + xmlFreeDoc(doc); + return content; } #endif return 0; diff --git a/src/yaz-proxy.cpp b/src/yaz-proxy.cpp index 3b43840..fce34ac 100644 --- a/src/yaz-proxy.cpp +++ b/src/yaz-proxy.cpp @@ -1,4 +1,4 @@ -/* $Id: yaz-proxy.cpp,v 1.6 2004-08-29 13:01:43 adam Exp $ +/* $Id: yaz-proxy.cpp,v 1.7 2004-10-18 22:10:57 adam Exp $ Copyright (c) 1998-2004, Index Data. This file is part of the yaz-proxy. @@ -40,6 +40,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include #include #include +#include #if HAVE_XSLT #include @@ -181,10 +182,10 @@ Yaz_Proxy::~Yaz_Proxy() nmem_destroy(m_mem_invalid_session); nmem_destroy(m_referenceId_mem); - xfree (m_proxyTarget); - xfree (m_default_target); - xfree (m_proxy_authentication); - xfree (m_optimize); + xfree(m_proxyTarget); + xfree(m_default_target); + xfree(m_proxy_authentication); + xfree(m_optimize); #if HAVE_XSLT if (m_stylesheet_xsp) @@ -390,8 +391,8 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu, const char *cookie, #endif xfree(m_default_target); m_default_target = xstrdup(proxy_host); - proxy_host = m_default_target; } + proxy_host = m_default_target; int client_idletime = -1; const char *cql2rpn_fname = 0; url[0] = m_default_target; @@ -975,8 +976,8 @@ int Yaz_Proxy::send_srw_explain_response(Z_SRW_diagnostic *diagnostics, if (cfg) { int len; - char *b = cfg->get_explain(odr_encode(), 0 /* target */, - m_s2z_database, &len); + char *b = cfg->get_explain_doc(odr_encode(), 0 /* target */, + m_s2z_database, &len); if (b) { Z_SRW_PDU *res = yaz_srw_get(odr_encode(), Z_SRW_explain_response); @@ -1246,7 +1247,6 @@ Z_APDU *Yaz_Proxy::result_set_optimize(Z_APDU *apdu) return 0; } Z_NamePlusRecordList *npr; - int oclass = 0; #if 0 yaz_log(LOG_LOG, "%sCache lookup %d+%d syntax=%s", m_session_str, start, toget, yaz_z3950oid_to_str( @@ -1792,6 +1792,25 @@ Z_ElementSetNames *Yaz_Proxy::mk_esn_from_schema(ODR o, const char *schema) return esn; } +void Yaz_Proxy::srw_get_client(const char *db, const char **backend_db) +{ + const char *t = 0; + Yaz_ProxyConfig *cfg = check_reconfigure(); + if (cfg) + t = cfg->get_explain_name(db, backend_db); + + if (m_client && m_default_target && t && strcmp(m_default_target, t)) + { + releaseClient(); + } + + if (t) + { + xfree(m_default_target); + m_default_target = xstrdup(t); + } +} + void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) { if (m_s2z_odr_init) @@ -1849,6 +1868,9 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) { Z_SRW_searchRetrieveRequest *srw_req = srw_pdu->u.request; + const char *backend_db = srw_req->database; + srw_get_client(srw_req->database, &backend_db); + m_s2z_database = odr_strdup(m_s2z_odr_init, srw_req->database); // recordXPath unsupported. if (srw_req->recordXPath) @@ -1899,7 +1921,7 @@ void Yaz_Proxy::handle_incoming_HTTP(Z_HTTP_Request *hreq) z_searchRequest->databaseNames = (char**) odr_malloc(m_s2z_odr_search, sizeof(char *)); z_searchRequest->databaseNames[0] = odr_strdup(m_s2z_odr_search, - srw_req->database); + backend_db); // query transformation Z_Query *query = (Z_Query *) @@ -2245,8 +2267,10 @@ void Yaz_Proxy::connectNotify() { } -void Yaz_Proxy::shutdown() +void Yaz_Proxy::releaseClient() { + xfree(m_proxyTarget); + m_proxyTarget = 0; m_invalid_session = 0; // only keep if keep_alive flag is set... if (m_client && @@ -2265,6 +2289,7 @@ void Yaz_Proxy::shutdown() // Tell client (if any) that no server connection is there.. m_client->m_server = 0; m_invalid_session = 0; + m_client = 0; } else if (m_client) { @@ -2273,6 +2298,7 @@ void Yaz_Proxy::shutdown() m_client->get_hostname()); assert (m_client->m_waiting != 2); delete m_client; + m_client = 0; } else if (!m_parent) { @@ -2287,6 +2313,11 @@ void Yaz_Proxy::shutdown() } if (m_parent) m_parent->pre_init(); +} + +void Yaz_Proxy::shutdown() +{ + releaseClient(); delete this; } -- 1.7.10.4