X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fyaz-proxy.cpp;h=e7c1ad2e505b738c08f0b46bc2f956853e811dbf;hb=8cd77956b745e79b984bc0c9b74989aeae8dd49d;hp=81e987e7858184479ae5d65d4fcb648b89cb2ff8;hpb=28588b9224eb5189af32b10f440ef2a917a05ea2;p=yazpp-moved-to-github.git diff --git a/src/yaz-proxy.cpp b/src/yaz-proxy.cpp index 81e987e..e7c1ad2 100644 --- a/src/yaz-proxy.cpp +++ b/src/yaz-proxy.cpp @@ -2,7 +2,7 @@ * Copyright (c) 1998-2003, Index Data. * See the file LICENSE for details. * - * $Id: yaz-proxy.cpp,v 1.48 2003-10-01 13:13:51 adam Exp $ + * $Id: yaz-proxy.cpp,v 1.52 2003-10-08 09:32:49 adam Exp $ */ #include @@ -50,7 +50,6 @@ static const char *apdu_name(Z_APDU *apdu) return "other"; } - Yaz_Proxy::Yaz_Proxy(IYaz_PDU_Observable *the_PDU_Observable) : Yaz_Z_Assoc(the_PDU_Observable), m_bw_stat(60), m_pdu_stat(60) { @@ -159,6 +158,35 @@ char *Yaz_Proxy::get_proxy(Z_OtherInformation **otherInfo) return 0; } +const char *Yaz_Proxy::load_balance(const char **url) +{ + int zurl_in_use[MAX_ZURL_PLEX]; + Yaz_ProxyClient *c; + int i; + + for (i = 0; im_clientPool; c; c = c->m_next) + { + for (i = 0; url[i]; i++) + if (!strcmp(url[i], c->get_hostname())) + zurl_in_use[i]++; + } + int min = 100000; + const char *ret = 0; + for (i = 0; url[i]; i++) + { + yaz_log(LOG_LOG, "%s zurl=%s use=%d", + m_session_str, url[i], zurl_in_use[i]); + if (min > zurl_in_use[i]) + { + ret = url[i]; + min = zurl_in_use[i]; + } + } + return ret; +} + Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu) { assert (m_parent); @@ -171,20 +199,31 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu) if (!m_proxyTarget) { + const char *url[MAX_ZURL_PLEX]; const char *proxy_host = get_proxy(oi); - if (!proxy_host) + if (proxy_host) + { + xfree(m_default_target); + m_default_target = xstrdup(proxy_host); proxy_host = m_default_target; + } - const char *url = 0; - m_config.get_target_info(proxy_host, &url, &m_keepalive, &m_bw_max, - &m_pdu_max, &m_max_record_retrieve); - - if (!url) + int client_idletime = -1; + m_config.get_target_info(proxy_host, url, &m_keepalive, &m_bw_max, + &m_pdu_max, &m_max_record_retrieve, + &m_target_idletime, &client_idletime, + &parent->m_max_clients); + if (client_idletime != -1) + { + m_client_idletime = client_idletime; + timeout(m_client_idletime); + } + if (!url[0]) { yaz_log(LOG_LOG, "%s No default target", m_session_str); return 0; } - m_proxyTarget = (char*) xstrdup(url); + m_proxyTarget = (char*) xstrdup(load_balance(url)); } if (cookie && *cookie) { @@ -648,7 +687,7 @@ Z_APDU *Yaz_Proxy::result_set_optimize(Z_APDU *apdu) } } } - else + else // query doesn't match { delete m_client->m_last_query; m_client->m_last_query = this_query; @@ -724,6 +763,108 @@ void Yaz_Proxy::handle_max_record_retrieve(Z_APDU *apdu) } } +Z_Records *Yaz_Proxy::create_nonSurrogateDiagnostics(ODR odr, + int error, + const char *addinfo) +{ + Z_Records *rec = (Z_Records *) + odr_malloc (odr, sizeof(*rec)); + int *err = (int *) + odr_malloc (odr, sizeof(*err)); + Z_DiagRec *drec = (Z_DiagRec *) + odr_malloc (odr, sizeof(*drec)); + Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *) + odr_malloc (odr, sizeof(*dr)); + *err = error; + rec->which = Z_Records_NSD; + rec->u.nonSurrogateDiagnostic = dr; + dr->diagnosticSetId = + yaz_oidval_to_z3950oid (odr, CLASS_DIAGSET, VAL_BIB1); + dr->condition = err; + dr->which = Z_DefaultDiagFormat_v2Addinfo; + dr->u.v2Addinfo = odr_strdup (odr, addinfo ? addinfo : ""); + return rec; +} + +Z_APDU *Yaz_Proxy::handle_query_validation(Z_APDU *apdu) +{ + if (apdu->which == Z_APDU_searchRequest) + { + Z_SearchRequest *sr = apdu->u.searchRequest; + int err; + char *addinfo = 0; + err = m_config.check_query(odr_encode(), m_default_target, sr->query, + &addinfo); + if (err) + { + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse); + + new_apdu->u.searchResponse->referenceId = sr->referenceId; + new_apdu->u.searchResponse->records = + create_nonSurrogateDiagnostics(odr_encode(), err, addinfo); + *new_apdu->u.searchResponse->searchStatus = 0; + + send_to_client(new_apdu); + + return 0; + } + } + return apdu; +} + +Z_APDU *Yaz_Proxy::handle_syntax_validation(Z_APDU *apdu) +{ + if (apdu->which == Z_APDU_searchRequest) + { + Z_SearchRequest *sr = apdu->u.searchRequest; + if (*sr->smallSetUpperBound > 0 || *sr->largeSetLowerBound > 1) + { + int err; + char *addinfo = 0; + err = m_config.check_syntax(odr_encode(), m_default_target, + sr->preferredRecordSyntax, + &addinfo); + if (err) + { + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse); + + new_apdu->u.searchResponse->referenceId = sr->referenceId; + new_apdu->u.searchResponse->records = + create_nonSurrogateDiagnostics(odr_encode(), err, addinfo); + *new_apdu->u.searchResponse->searchStatus = 0; + + send_to_client(new_apdu); + + return 0; + } + } + } + else if (apdu->which == Z_APDU_presentRequest) + { + Z_PresentRequest *pr = apdu->u.presentRequest; + int err; + char *addinfo = 0; + err = m_config.check_syntax(odr_encode(), m_default_target, + pr->preferredRecordSyntax, + &addinfo); + if (err) + { + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentResponse); + + new_apdu->u.presentResponse->referenceId = pr->referenceId; + new_apdu->u.presentResponse->records = + create_nonSurrogateDiagnostics(odr_encode(), err, addinfo); + *new_apdu->u.presentResponse->presentStatus = + Z_PresentStatus_failure; + + send_to_client(new_apdu); + + return 0; + } + } + return apdu; +} + void Yaz_Proxy::recv_Z_PDU_0(Z_APDU *apdu) { // Determine our client. @@ -737,6 +878,15 @@ void Yaz_Proxy::recv_Z_PDU_0(Z_APDU *apdu) if (apdu->which == Z_APDU_initRequest) { + if (apdu->u.initRequest->implementationId) + yaz_log(LOG_LOG, "%s implementationId: %s", + m_session_str, apdu->u.initRequest->implementationId); + if (apdu->u.initRequest->implementationName) + yaz_log(LOG_LOG, "%s implementationName: %s", + m_session_str, apdu->u.initRequest->implementationName); + if (apdu->u.initRequest->implementationVersion) + yaz_log(LOG_LOG, "%s implementationVersion: %s", + m_session_str, apdu->u.initRequest->implementationVersion); if (m_client->m_init_flag) { Z_APDU *apdu = m_client->m_initResponse; @@ -751,9 +901,20 @@ void Yaz_Proxy::recv_Z_PDU_0(Z_APDU *apdu) } handle_max_record_retrieve(apdu); - apdu = result_set_optimize(apdu); + if (apdu) + apdu = handle_syntax_validation(apdu); + + if (apdu) + apdu = handle_query_validation(apdu); + + if (apdu) + apdu = result_set_optimize(apdu); if (!apdu) + { + m_client->timeout(m_target_idletime); // mark it active even + // though we didn't use it return; + } // delete other info part from PDU before sending to target Z_OtherInformation **oi; @@ -944,6 +1105,21 @@ void Yaz_ProxyClient::recv_Z_PDU(Z_APDU *apdu, int len) odr_reset (m_init_odr); nmem_transfer (m_init_odr->mem, nmem); m_initResponse = apdu; + + Z_InitResponse *ir = apdu->u.initResponse; + char *im0 = ir->implementationName; + + char *im1 = (char*) + odr_malloc(m_init_odr, 20 + (im0 ? strlen(im0) : 0)); + *im1 = '\0'; + if (im0) + { + strcat(im1, im0); + strcat(im1, " "); + } + strcat(im1, "(YAZ Proxy)"); + ir->implementationName = im1; + nmem_destroy (nmem); } if (apdu->which == Z_APDU_searchResponse) @@ -978,7 +1154,8 @@ void Yaz_ProxyClient::recv_Z_PDU(Z_APDU *apdu, int len) sr->numberOfRecordsReturned = pr->numberOfRecordsReturned; apdu = new_apdu; } - if (pr->records->which == Z_Records_DBOSD && m_resultSetStartPoint) + if (pr->records && + pr->records->which == Z_Records_DBOSD && m_resultSetStartPoint) { m_cache.add(odr_decode(), pr->records->u.databaseOrSurDiagnostics,