<?xml version="1.0"?>
-<!-- $Id: config.xml,v 1.3 2003-12-20 22:44:30 adam Exp $ -->
+<!-- $Id: config.xml,v 1.4 2003-12-22 15:16:23 adam Exp $ -->
<proxy>
<target name="bagel">
- <!-- default target -->
<url>indexdata.dk</url>
<target-timeout>240</target-timeout>
<client-timeout>180</client-timeout>
</target>
<target default="1" name="localhost">
<url>localhost:9999</url>
+ <url>localhost:9998</url>
<target-timeout>300</target-timeout>
<client-timeout>180</client-timeout>
<keepalive/> <!-- keepalive enabled -->
<syntax type="*" error="238"/>
<preinit>2</preinit>
<cql2rpn>pqf.properties</cql2rpn>
+ <explain>
+ <serverInfo>
+ <host>myhost</host>
+ </serverInfo>
+ </explain>
<zeerex>zeerex.xml</zeerex>
</target>
<target name="*">
<!-- everything else -->
</target>
<max-clients>50</max-clients>
+ <log>client-requests server-requests</log>
</proxy>
* Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: proxy.h,v 1.23 2003-12-20 22:44:30 adam Exp $
+ * $Id: proxy.h,v 1.24 2003-12-22 15:16:23 adam Exp $
*/
+#include <sys/time.h>
#include <yaz++/z-assoc.h>
#include <yaz++/z-query.h>
#include <yaz++/z-databases.h>
int *keepalive_limit_bw,
int *keepalive_limit_pdu,
int *pre_init,
- const char **cql2rpn,
- const char **zeerex);
+ const char **cql2rpn);
void get_generic_info(int *log_mask, int *max_clients);
int *max_clients,
int *keepalive_limit_bw, int *keepalive_limit_pdu,
int *pre_init,
- const char **cql2rpn,
- const char **zeerex);
+ const char **cql2rpn);
int check_query(ODR odr, const char *name, Z_Query *query, char **addinfo);
int check_syntax(ODR odr, const char *name,
Odr_oid *syntax, char **addinfo);
+ char *get_explain(ODR odr, const char *name, const char *db,
+ int *len);
private:
void operator=(const Yaz_ProxyConfig &conf);
int mycmp(const char *hay, const char *item, size_t len);
int *limit_bw, int *limit_pdu, int *limit_req,
int *target_idletime, int *client_idletime,
int *keepalive_limit_bw, int *keepalive_limit_pdu,
- int *pre_init, const char **cql2rpn,
- const char **zeerex);
+ int *pre_init, const char **cql2rpn);
void return_limit(xmlNodePtr ptr,
int *limit_bw, int *limit_pdu, int *limit_req);
int check_type_1(ODR odr, xmlNodePtr ptr, Z_RPNQuery *query,
char **addinfo);
- xmlNodePtr find_target_node(const char *name);
+ xmlNodePtr find_target_node(const char *name, const char *db);
+ xmlNodePtr find_target_db(xmlNodePtr ptr, const char *db);
const char *get_text(xmlNodePtr ptr);
int check_type_1_attributes(ODR odr, xmlNodePtr ptr,
Z_AttributeList *attrs,
int m_http_keepalive;
const char *m_http_version;
Yaz_cql2rpn m_cql2rpn;
- const char *m_zeerex_fname;
+ struct timeval m_time_tv;
+ void logtime();
public:
Yaz_Proxy(IYaz_PDU_Observable *the_PDU_Observable,
Yaz_Proxy *parent = 0);
~Yaz_Proxy();
+ void inc_request_no();
void recv_GDU(Z_GDU *apdu, int len);
void handle_incoming_HTTP(Z_HTTP_Request *req);
void handle_incoming_Z_PDU(Z_APDU *apdu);
* Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-proxy-config.cpp,v 1.16 2003-12-20 22:44:30 adam Exp $
+ * $Id: yaz-proxy-config.cpp,v 1.17 2003-12-22 15:16:23 adam Exp $
*/
#include <ctype.h>
int *keepalive_limit_bw,
int *keepalive_limit_pdu,
int *pre_init,
- const char **cql2rpn,
- const char **zeerex)
+ const char **cql2rpn)
{
*pre_init = 0;
int no_url = 0;
if (t)
*cql2rpn = t;
}
- if (ptr->type == XML_ELEMENT_NODE
- && !strcmp((const char *) ptr->name, "zeerex"))
- {
- const char *t = get_text(ptr);
- if (t)
- *zeerex = t;
- }
}
}
#endif
#if HAVE_XML2
xmlNodePtr ptr;
- ptr = find_target_node(name);
+ ptr = find_target_node(name, 0);
if (ptr)
{
if (query->which == Z_Query_type_1 || query->which == Z_Query_type_101)
#if HAVE_XML2
xmlNodePtr ptr;
- ptr = find_target_node(name);
+ ptr = find_target_node(name, 0);
if (!ptr)
return 0;
for(ptr = ptr->children; ptr; ptr = ptr->next)
}
#if HAVE_XML2
-xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name)
+xmlNodePtr Yaz_ProxyConfig::find_target_db(xmlNodePtr ptr, const char *db)
+{
+ xmlNodePtr dptr;
+ if (!db)
+ return ptr;
+ if (!ptr)
+ return 0;
+ for (dptr = ptr->children; dptr; dptr = dptr->next)
+ if (dptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) dptr->name, "database"))
+ {
+ struct _xmlAttr *attr;
+ for (attr = dptr->properties; attr; attr = attr->next)
+ if (!strcmp((const char *) attr->name, "name"))
+ {
+ if (attr->children
+ && attr->children->type==XML_TEXT_NODE
+ && attr->children->content
+ && (!strcmp((const char *) attr->children->content, db)
+ || !strcmp((const char *) attr->children->content,
+ "*")))
+ return dptr;
+ }
+ }
+ return ptr;
+}
+
+xmlNodePtr Yaz_ProxyConfig::find_target_node(const char *name, const char *db)
{
xmlNodePtr ptr;
if (!m_proxyPtr)
{
xmlChar *t = attr->children->content;
if (!t || *t == '1')
- return ptr;
+ {
+ return find_target_db(ptr, db);
+ }
}
}
else
|| !strcmp((const char *) attr->children->content,
"*")))
{
- return ptr;
+ return find_target_db(ptr, db);
}
}
}
int *keepalive_limit_bw,
int *keepalive_limit_pdu,
int *pre_init,
- const char **cql2rpn,
- const char **zeerex)
+ const char **cql2rpn)
{
#if HAVE_XML2
xmlNodePtr ptr;
return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
target_idletime, client_idletime,
keepalive_limit_bw, keepalive_limit_pdu,
- pre_init, cql2rpn, zeerex);
+ pre_init, cql2rpn);
return 1;
}
i++;
#endif
}
+char *Yaz_ProxyConfig::get_explain(ODR odr, const char *name, const char *db,
+ int *len)
+{
+#if HAVE_XML2
+ xmlNodePtr ptr = find_target_node(name, db);
+ if (ptr)
+ {
+ ptr = ptr->children;
+ for (; ptr; ptr = ptr->next)
+ if (ptr->type == XML_ELEMENT_NODE &&
+ !strcmp((const char *) ptr->name, "explain"))
+ {
+ xmlNodePtr ptr2 = xmlCopyNode(ptr, 1);
+
+ xmlDocPtr doc = xmlNewDoc((const xmlChar *) "1.0");
+
+ xmlDocSetRootElement(doc, ptr2);
+
+ xmlChar *buf_out;
+ int len_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;
+ }
+ }
+ else
+ yaz_log(LOG_WARN, "No explain node 1");
+
+#endif
+ yaz_log(LOG_WARN, "No explain node");
+ return 0;
+}
+
void Yaz_ProxyConfig::get_target_info(const char *name,
const char **url,
int *limit_bw,
int *keepalive_limit_bw,
int *keepalive_limit_pdu,
int *pre_init,
- const char **cql2rpn,
- const char **zeerex)
+ const char **cql2rpn)
{
#if HAVE_XML2
xmlNodePtr ptr;
}
}
}
- ptr = find_target_node(name);
+ ptr = find_target_node(name, 0);
if (ptr)
{
if (name)
return_target_info(ptr, url, limit_bw, limit_pdu, limit_req,
target_idletime, client_idletime,
keepalive_limit_bw, keepalive_limit_pdu,
- pre_init, cql2rpn, zeerex);
+ pre_init, cql2rpn);
}
#else
*url = name;
* Copyright (c) 1998-2003, Index Data.
* See the file LICENSE for details.
*
- * $Id: yaz-proxy.cpp,v 1.72 2003-12-20 22:44:30 adam Exp $
+ * $Id: yaz-proxy.cpp,v 1.73 2003-12-22 15:16:23 adam Exp $
*/
#include <assert.h>
m_http_version = 0;
m_soap_ns = 0;
m_s2z_packing = Z_SRW_recordPacking_string;
- m_zeerex_fname = 0;
+ m_time_tv.tv_sec = 0;
+ m_time_tv.tv_usec = 0;
}
Yaz_Proxy::~Yaz_Proxy()
&m_keepalive_limit_bw,
&m_keepalive_limit_pdu,
&pre_init,
- &cql2rpn_fname,
- &m_zeerex_fname);
+ &cql2rpn_fname);
}
if (client_idletime != -1)
{
yaz_marc_destroy(mt);
}
+void Yaz_Proxy::logtime()
+{
+ if (m_time_tv.tv_sec)
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ long diff = (tv.tv_sec - m_time_tv.tv_sec)*1000000 +
+ (tv.tv_usec - m_time_tv.tv_usec);
+ if (diff >= 0)
+ yaz_log(LOG_LOG, "%sElapsed %ld.%03ld", m_session_str,
+ diff/1000000, (diff/1000)%1000);
+ }
+ m_time_tv.tv_sec = 0;
+ m_time_tv.tv_usec = 0;
+}
+
int Yaz_Proxy::send_http_response(int code)
{
ODR o = odr_encode();
if (m_http_version)
hres->version = odr_strdup(o, m_http_version);
m_http_keepalive = 0;
+ if (m_log_mask & PROXY_LOG_REQ_CLIENT)
+ {
+ yaz_log (LOG_LOG, "%sSending %s to client", m_session_str,
+ gdu_name(gdu));
+ }
int len;
- return send_GDU(gdu, &len);
+ int r = send_GDU(gdu, &len);
+ logtime();
+ return r;
}
int Yaz_Proxy::send_srw_response(Z_SRW_PDU *srw_pdu)
int ret = z_soap_codec_enc(o, &soap_package,
&hres->content_buf, &hres->content_len,
soap_handlers, 0);
+ if (m_log_mask & PROXY_LOG_REQ_CLIENT)
+ {
+ yaz_log (LOG_LOG, "%sSending %s to client", m_session_str,
+ gdu_name(gdu));
+ }
int len;
- return send_GDU(gdu, &len);
+ int r = send_GDU(gdu, &len);
+ logtime();
+ return r;
}
int Yaz_Proxy::send_to_srw_client_error(int srw_error)
Z_SRW_PDU *res = yaz_srw_get(odr_encode(), Z_SRW_explain_response);
Z_SRW_explainResponse *er = res->u.explain_response;
- if (m_zeerex_fname)
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+ if (cfg)
{
- FILE *inf = fopen(m_zeerex_fname, "rb");
- if (inf)
+ int len;
+ assert (m_proxyTarget);
+ char *b = cfg->get_explain(odr_encode(), 0 /* target */,
+ 0 /* db */, &len);
+ if (b)
{
- fseek(inf, 0L, SEEK_END);
- long sz = ftell(inf);
- fseek(inf, 0L, SEEK_SET);
- if (sz > 0)
- {
- er->record.recordData_buf =
- (char*) odr_malloc(odr_encode(), sz);
- size_t s = fread(er->record.recordData_buf, 1,sz, inf);
- if (s > 0)
- er->record.recordData_len = s;
- }
- else
- yaz_log(LOG_WARN|LOG_ERRNO, "zeerex file: ftell");
- fclose(inf);
+ er->record.recordData_buf = b;
+ er->record.recordData_len = len;
+ er->record.recordPacking = m_s2z_packing;
}
- else
- yaz_log(LOG_WARN|LOG_ERRNO, "zeerex file: fopen");
}
- else
- yaz_log(LOG_LOG, "zeerex file: not defined");
return send_srw_response(res);
}
}
}
else
- return send_Z_PDU(apdu, len);
+ {
+ if (m_log_mask & PROXY_LOG_REQ_CLIENT)
+ yaz_log (LOG_LOG, "%sSending %s to client", m_session_str,
+ apdu_name(apdu));
+ int r = send_Z_PDU(apdu, len);
+ logtime();
+ return r;
+ }
return 0;
}
int r = send_PDU_convert(apdu, &len);
if (r)
return r;
- if (m_log_mask & PROXY_LOG_APDU_CLIENT)
- yaz_log (LOG_DEBUG, "%sSending %s to client %d bytes", m_session_str,
- apdu_name(apdu), len);
m_bytes_sent += len;
m_bw_stat.add_bytes(len);
if (kill_session)
}
-void Yaz_Proxy::recv_GDU(Z_GDU *apdu, int len)
+void Yaz_Proxy::inc_request_no()
{
char *cp = strchr(m_session_str, ' ');
m_request_no++;
if (cp)
sprintf(cp+1, "%d ", m_request_no);
+}
+
+void Yaz_Proxy::recv_GDU(Z_GDU *apdu, int len)
+{
+ inc_request_no();
m_bytes_recv += len;
m_bw_stat.add_bytes(len);
m_pdu_stat.add_bytes(1);
+ gettimeofday(&m_time_tv, 0);
+
int bw_total = m_bw_stat.get_total();
int pdu_total = m_pdu_stat.get_total();
}
else if (srw_pdu->which == Z_SRW_explain_request)
{
+ Z_SRW_explainRequest *srw_req = srw_pdu->u.explain_request;
+
+ if (srw_req->recordPacking &&
+ !strcmp(srw_req->recordPacking, "xml"))
+ m_s2z_packing = Z_SRW_recordPacking_XML;
+ else
+ m_s2z_packing = Z_SRW_recordPacking_string;
+
if (!m_client)
{
yaz_log(LOG_LOG, "handle_incoming: initRequest");
void Yaz_Proxy::failNotify()
{
+ inc_request_no();
yaz_log (LOG_LOG, "%sConnection closed by client",
get_session_str());
shutdown();
void Yaz_ProxyClient::failNotify()
{
+ if (m_server)
+ m_server->inc_request_no();
yaz_log (LOG_LOG, "%sConnection closed by target %s",
get_session_str(), get_hostname());
shutdown();
&keepalive_limit_bw,
&keepalive_limit_pdu,
&pre_init,
- &cql2rpn,
- &zeerex) ; i++)
+ &cql2rpn) ; i++)
{
if (pre_init)
{
}
else
{
+ inc_request_no();
+
yaz_log (LOG_LOG, "%sTimeout (client to proxy)", m_session_str);
shutdown();
}
void Yaz_ProxyClient::timeoutNotify()
{
+ if (m_server)
+ m_server->inc_request_no();
+
yaz_log (LOG_LOG, "%sTimeout (proxy to target) %s", get_session_str(),
get_hostname());
m_waiting = 1;