X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fyaz-proxy.cpp;h=ab518e728cf2fb532b13336a8cfcf7f55beeaa8d;hb=3e85e9f144d417835d0a6d46bc1526ee3c655078;hp=f61547abae8f6dbf654a52851f463846ed2344a0;hpb=e31c7057460f8c707301e00bf12065695b444995;p=yazpp-moved-to-github.git diff --git a/src/yaz-proxy.cpp b/src/yaz-proxy.cpp index f61547a..ab518e7 100644 --- a/src/yaz-proxy.cpp +++ b/src/yaz-proxy.cpp @@ -1,8 +1,8 @@ /* - * Copyright (c) 1998-2001, Index Data. + * Copyright (c) 1998-2003, Index Data. * See the file LICENSE for details. * - * $Id: yaz-proxy.cpp,v 1.37 2002-10-23 10:15:18 adam Exp $ + * $Id: yaz-proxy.cpp,v 1.47 2003-09-03 11:30:26 adam Exp $ */ #include @@ -22,7 +22,7 @@ Yaz_Proxy::Yaz_Proxy(IYaz_PDU_Observable *the_PDU_Observable) : m_keepalive = 1; m_proxyTarget = 0; m_proxy_authentication = 0; - m_max_clients = 50; + m_max_clients = 150; m_seed = time(0); m_idletime = 600; m_optimize = xstrdup ("1"); @@ -124,7 +124,7 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu) { assert (c->m_prev); assert (*c->m_prev == c); - if (!strcmp(cookie,c->m_cookie) && + if (c->m_cookie && !strcmp(cookie,c->m_cookie) && !strcmp(m_proxyTarget, c->get_hostname())) { cc = c; @@ -145,21 +145,52 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu) c->m_init_flag = 0; c->m_last_ok = 0; + c->m_cache.clear(); c->m_last_resultCount = 0; c->m_sr_transform = 0; c->m_waiting = 0; + c->m_resultSetStartPoint = 0; c->timeout(m_idletime); } c->m_seqno = parent->m_seqno; if (c->m_server && c->m_server != this) c->m_server->m_client = 0; c->m_server = this; - c->m_seqno = parent->m_seqno; (parent->m_seqno)++; yaz_log (LOG_DEBUG, "get_client 1 %p %p", this, c); return c; } } + else if (!c) + { + Yaz_ProxyClient *cc = 0; + + for (c = parent->m_clientPool; c; c = c->m_next) + { + assert (c->m_prev); + assert (*c->m_prev == c); + if (c->m_server == 0 && c->m_cookie == 0 && + !strcmp(m_proxyTarget, c->get_hostname())) + { + cc = c; + } + } + if (cc) + { + // found it in cache + c = cc; + + yaz_log (LOG_LOG, "Reuse session %d to %d %s", + c->m_seqno, parent->m_seqno, c->get_hostname()); + + c->m_seqno = parent->m_seqno; + assert(c->m_server == 0); + c->m_server = this; + + (parent->m_seqno)++; + return c; + } + } if (!m_client) { if (apdu->which != Z_APDU_initRequest) @@ -188,11 +219,13 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu) Yaz_ProxyClient *c_min = 0; int min_seq = -1; int no_of_clients = 0; - yaz_log (LOG_LOG, "Existing sessions"); + if (parent->m_clientPool) + yaz_log (LOG_LOG, "Existing sessions"); for (c = parent->m_clientPool; c; c = c->m_next) { - yaz_log (LOG_LOG, " Session %-3d wait=%d %s", c->m_seqno, - c->m_waiting, c->get_hostname()); + yaz_log (LOG_LOG, " Session %-3d wait=%d %s cookie=%s", c->m_seqno, + c->m_waiting, c->get_hostname(), + c->m_cookie ? c->m_cookie : ""); no_of_clients++; if (min_seq < 0 || c->m_seqno < min_seq) { @@ -213,12 +246,12 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu) } else { - yaz_log (LOG_LOG, "Reuse session %d to %d", - c->m_seqno, parent->m_seqno); + yaz_log (LOG_LOG, "Move session %d to %d %s", + c->m_seqno, parent->m_seqno, c->get_hostname()); + xfree (c->m_cookie); + c->m_cookie = 0; if (cookie) - strcpy (c->m_cookie, cookie); - else - c->m_cookie[0] = '\0'; + c->m_cookie = xstrdup(cookie); c->m_seqno = parent->m_seqno; if (c->m_server && c->m_server != this) { @@ -241,18 +274,22 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu) parent->m_clientPool = c; c->m_prev = &parent->m_clientPool; } + + xfree (c->m_cookie); + c->m_cookie = 0; if (cookie) - strcpy (c->m_cookie, cookie); - else - c->m_cookie[0] = '\0'; + c->m_cookie = xstrdup(cookie); + yaz_log (LOG_LOG, "Connecting to %s", m_proxyTarget); c->m_seqno = parent->m_seqno; c->client(m_proxyTarget); c->m_init_flag = 0; c->m_last_resultCount = 0; c->m_last_ok = 0; + c->m_cache.clear(); c->m_sr_transform = 0; c->m_waiting = 0; + c->m_resultSetStartPoint = 0; c->timeout(20); (parent->m_seqno)++; @@ -263,10 +300,43 @@ Yaz_ProxyClient *Yaz_Proxy::get_client(Z_APDU *apdu) Z_APDU *Yaz_Proxy::result_set_optimize(Z_APDU *apdu) { + if (*m_parent->m_optimize == '0') + return apdu; // don't optimize result sets.. + if (apdu->which == Z_APDU_presentRequest) + { + Z_PresentRequest *pr = apdu->u.presentRequest; + Z_NamePlusRecordList *npr; + int toget = *pr->numberOfRecordsRequested; + int start = *pr->resultSetStartPoint; + + if (m_client->m_last_resultSetId && + !strcmp(m_client->m_last_resultSetId, pr->resultSetId)) + { + if (m_client->m_cache.lookup (odr_encode(), &npr, start, toget, + pr->preferredRecordSyntax, + pr->recordComposition)) + { + yaz_log (LOG_LOG, "Returned cache records for present request"); + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentResponse); + new_apdu->u.presentResponse->referenceId = pr->referenceId; + + new_apdu->u.presentResponse->numberOfRecordsReturned + = odr_intdup(odr_encode(), toget); + + new_apdu->u.presentResponse->records = (Z_Records*) + odr_malloc(odr_encode(), sizeof(Z_Records)); + new_apdu->u.presentResponse->records->which = Z_Records_DBOSD; + new_apdu->u.presentResponse->records->u.databaseOrSurDiagnostics = npr; + new_apdu->u.presentResponse->nextResultSetPosition = + odr_intdup(odr_encode(), start+toget); + send_Z_PDU(new_apdu); + return 0; + } + } + } + if (apdu->which != Z_APDU_searchRequest) return apdu; - if (*m_parent->m_optimize != '1') - return apdu; Z_SearchRequest *sr = apdu->u.searchRequest; Yaz_Z_Query *this_query = new Yaz_Z_Query; Yaz_Z_Databases this_databases; @@ -285,24 +355,60 @@ Z_APDU *Yaz_Proxy::result_set_optimize(Z_APDU *apdu) if (m_client->m_last_resultCount > *sr->smallSetUpperBound && m_client->m_last_resultCount < *sr->largeSetLowerBound) { - // medium Set - // send present request (medium size) - yaz_log (LOG_LOG, "Optimizing search for medium set"); - Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentRequest); - Z_PresentRequest *pr = new_apdu->u.presentRequest; - pr->referenceId = sr->referenceId; - pr->resultSetId = sr->resultSetName; - pr->preferredRecordSyntax = sr->preferredRecordSyntax; - *pr->numberOfRecordsRequested = *sr->mediumSetPresentNumber; + Z_NamePlusRecordList *npr; + int toget = *sr->mediumSetPresentNumber; + Z_RecordComposition *comp = 0; + + if (toget > m_client->m_last_resultCount) + toget = m_client->m_last_resultCount; + if (sr->mediumSetElementSetNames) { - pr->recordComposition = (Z_RecordComposition *) + comp = (Z_RecordComposition *) odr_malloc(odr_encode(), sizeof(Z_RecordComposition)); - pr->recordComposition->which = Z_RecordComp_simple; - pr->recordComposition->u.simple = sr->mediumSetElementSetNames; + comp->which = Z_RecordComp_simple; + comp->u.simple = sr->mediumSetElementSetNames; + } + + if (m_client->m_cache.lookup (odr_encode(), &npr, 1, toget, + sr->preferredRecordSyntax, comp)) + { + yaz_log (LOG_LOG, "Returned cache records for medium set"); + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse); + new_apdu->u.searchResponse->referenceId = sr->referenceId; + new_apdu->u.searchResponse->resultCount = + &m_client->m_last_resultCount; + + new_apdu->u.searchResponse->numberOfRecordsReturned + = odr_intdup(odr_encode(), toget); + + new_apdu->u.searchResponse->presentStatus = + odr_intdup(odr_encode(), Z_PresentStatus_success); + new_apdu->u.searchResponse->records = (Z_Records*) + odr_malloc(odr_encode(), sizeof(Z_Records)); + new_apdu->u.searchResponse->records->which = Z_Records_DBOSD; + new_apdu->u.searchResponse->records->u.databaseOrSurDiagnostics = npr; + new_apdu->u.searchResponse->nextResultSetPosition = + odr_intdup(odr_encode(), toget+1); + send_Z_PDU(new_apdu); + return 0; + } + else + { + // medium Set + // send present request (medium size) + yaz_log (LOG_LOG, "Optimizing search for medium set"); + + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentRequest); + Z_PresentRequest *pr = new_apdu->u.presentRequest; + pr->referenceId = sr->referenceId; + pr->resultSetId = sr->resultSetName; + pr->preferredRecordSyntax = sr->preferredRecordSyntax; + *pr->numberOfRecordsRequested = toget; + pr->recordComposition = comp; + m_client->m_sr_transform = 1; + return new_apdu; } - m_client->m_sr_transform = 1; - return new_apdu; } else if (m_client->m_last_resultCount >= *sr->largeSetLowerBound || m_client->m_last_resultCount <= 0) @@ -318,24 +424,56 @@ Z_APDU *Yaz_Proxy::result_set_optimize(Z_APDU *apdu) } else { + Z_NamePlusRecordList *npr; + int toget = m_client->m_last_resultCount; + Z_RecordComposition *comp = 0; // small set // send a present request (small set) - yaz_log (LOG_LOG, "Optimizing search for small set"); - Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentRequest); - Z_PresentRequest *pr = new_apdu->u.presentRequest; - pr->referenceId = sr->referenceId; - pr->resultSetId = sr->resultSetName; - pr->preferredRecordSyntax = sr->preferredRecordSyntax; - *pr->numberOfRecordsRequested = m_client->m_last_resultCount; + if (sr->smallSetElementSetNames) { - pr->recordComposition = (Z_RecordComposition *) + comp = (Z_RecordComposition *) odr_malloc(odr_encode(), sizeof(Z_RecordComposition)); - pr->recordComposition->which = Z_RecordComp_simple; - pr->recordComposition->u.simple = sr->smallSetElementSetNames; + comp->which = Z_RecordComp_simple; + comp->u.simple = sr->smallSetElementSetNames; + } + + if (m_client->m_cache.lookup (odr_encode(), &npr, 1, toget, + sr->preferredRecordSyntax, comp)) + { + yaz_log (LOG_LOG, "Returned cache records for small set"); + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse); + new_apdu->u.searchResponse->referenceId = sr->referenceId; + new_apdu->u.searchResponse->resultCount = + &m_client->m_last_resultCount; + + new_apdu->u.searchResponse->numberOfRecordsReturned + = odr_intdup(odr_encode(), toget); + + new_apdu->u.searchResponse->presentStatus = + odr_intdup(odr_encode(), Z_PresentStatus_success); + new_apdu->u.searchResponse->records = (Z_Records*) + odr_malloc(odr_encode(), sizeof(Z_Records)); + new_apdu->u.searchResponse->records->which = Z_Records_DBOSD; + new_apdu->u.searchResponse->records->u.databaseOrSurDiagnostics = npr; + new_apdu->u.searchResponse->nextResultSetPosition = + odr_intdup(odr_encode(), toget+1); + send_Z_PDU(new_apdu); + return 0; + } + else + { + yaz_log (LOG_LOG, "Optimizing search for small set"); + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_presentRequest); + Z_PresentRequest *pr = new_apdu->u.presentRequest; + pr->referenceId = sr->referenceId; + pr->resultSetId = sr->resultSetName; + pr->preferredRecordSyntax = sr->preferredRecordSyntax; + *pr->numberOfRecordsRequested = toget; + pr->recordComposition = comp; + m_client->m_sr_transform = 1; + return new_apdu; } - m_client->m_sr_transform = 1; - return new_apdu; } } else @@ -343,6 +481,8 @@ Z_APDU *Yaz_Proxy::result_set_optimize(Z_APDU *apdu) delete m_client->m_last_query; m_client->m_last_query = this_query; m_client->m_last_ok = 0; + m_client->m_cache.clear(); + m_client->m_resultSetStartPoint = 0; xfree (m_client->m_last_resultSetId); m_client->m_last_resultSetId = xstrdup (sr->resultSetName); @@ -369,6 +509,24 @@ static const char *apdu_name(Z_APDU *apdu) return "presentRequest"; case Z_APDU_presentResponse: return "presentResponse"; + case Z_APDU_deleteResultSetRequest: + return "deleteResultSetRequest"; + case Z_APDU_deleteResultSetResponse: + return "deleteResultSetResponse"; + case Z_APDU_scanRequest: + return "scanRequest"; + case Z_APDU_scanResponse: + return "scanResponse"; + case Z_APDU_sortRequest: + return "sortRequest"; + case Z_APDU_sortResponse: + return "sortResponse"; + case Z_APDU_extendedServicesRequest: + return "extendedServicesRequest"; + case Z_APDU_extendedServicesResponse: + return "extendedServicesResponse"; + case Z_APDU_close: + return "close"; } return "other"; } @@ -391,7 +549,7 @@ void Yaz_Proxy::recv_Z_PDU(Z_APDU *apdu) { Z_APDU *apdu = m_client->m_initResponse; apdu->u.initResponse->otherInfo = 0; - if (m_client->m_cookie) + if (m_client->m_cookie && *m_client->m_cookie) set_otherInformationString(apdu, VAL_COOKIE, 1, m_client->m_cookie); send_Z_PDU(apdu); @@ -412,6 +570,15 @@ void Yaz_Proxy::recv_Z_PDU(Z_APDU *apdu) if (oi) *oi = 0; + if (apdu->which == Z_APDU_presentRequest && + m_client->m_resultSetStartPoint == 0) + { + Z_PresentRequest *pr = apdu->u.presentRequest; + m_client->m_resultSetStartPoint = *pr->resultSetStartPoint; + m_client->m_cache.copy_presentRequest(apdu->u.presentRequest); + } else { + m_client->m_resultSetStartPoint = 0; + } if (m_client->send_Z_PDU(apdu) < 0) { delete m_client; @@ -428,15 +595,14 @@ void Yaz_Proxy::connectNotify() void Yaz_Proxy::shutdown() { - // only keep if keep_alive flag and cookie is set... - if (m_keepalive && m_client && m_client->m_cookie[0]) + // only keep if keep_alive flag is set... + if (m_keepalive && m_client && m_client->m_waiting == 0) { yaz_log (LOG_LOG, "shutdown (client to proxy) keepalive %s", m_client->get_hostname()); assert (m_client->m_waiting != 2); // Tell client (if any) that no server connection is there.. m_client->m_server = 0; - } else if (m_client) { @@ -498,6 +664,7 @@ Yaz_ProxyClient::~Yaz_ProxyClient() odr_destroy(m_init_odr); delete m_last_query; xfree (m_last_resultSetId); + xfree (m_cookie); } void Yaz_Proxy::timeoutNotify() @@ -515,7 +682,7 @@ void Yaz_ProxyClient::timeoutNotify() Yaz_ProxyClient::Yaz_ProxyClient(IYaz_PDU_Observable *the_PDU_Observable) : Yaz_Z_Assoc (the_PDU_Observable) { - m_cookie[0] = 0; + m_cookie = 0; m_next = 0; m_prev = 0; m_init_flag = 0; @@ -527,6 +694,7 @@ Yaz_ProxyClient::Yaz_ProxyClient(IYaz_PDU_Observable *the_PDU_Observable) : m_waiting = 0; m_init_odr = odr_createmem (ODR_DECODE); m_initResponse = 0; + m_resultSetStartPoint = 0; } const char *Yaz_Proxy::option(const char *name, const char *value) @@ -556,31 +724,53 @@ void Yaz_ProxyClient::recv_Z_PDU(Z_APDU *apdu) } if (apdu->which == Z_APDU_searchResponse) { - m_last_resultCount = *apdu->u.searchResponse->resultCount; - int status = *apdu->u.searchResponse->searchStatus; - if (status && - (!apdu->u.searchResponse->records || - apdu->u.searchResponse->records->which == Z_Records_DBOSD)) + Z_SearchResponse *sr = apdu->u.searchResponse; + m_last_resultCount = *sr->resultCount; + int status = *sr->searchStatus; + if (status && (!sr->records || sr->records->which == Z_Records_DBOSD)) + { m_last_ok = 1; + + if (sr->records && sr->records->which == Z_Records_DBOSD) + { + m_cache.add(odr_decode(), + sr->records->u.databaseOrSurDiagnostics, 1, + *sr->resultCount); + } + } } - if (apdu->which == Z_APDU_presentResponse && m_sr_transform) + if (apdu->which == Z_APDU_presentResponse) { - m_sr_transform = 0; Z_PresentResponse *pr = apdu->u.presentResponse; - Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse); - Z_SearchResponse *sr = new_apdu->u.searchResponse; - sr->referenceId = pr->referenceId; - *sr->resultCount = m_last_resultCount; - sr->records = pr->records; - sr->nextResultSetPosition = pr->nextResultSetPosition; - sr->numberOfRecordsReturned = pr->numberOfRecordsReturned; - apdu = new_apdu; + if (m_sr_transform) + { + m_sr_transform = 0; + Z_APDU *new_apdu = create_Z_PDU(Z_APDU_searchResponse); + Z_SearchResponse *sr = new_apdu->u.searchResponse; + sr->referenceId = pr->referenceId; + *sr->resultCount = m_last_resultCount; + sr->records = pr->records; + sr->nextResultSetPosition = pr->nextResultSetPosition; + sr->numberOfRecordsReturned = pr->numberOfRecordsReturned; + apdu = new_apdu; + } + if (pr->records->which == Z_Records_DBOSD && m_resultSetStartPoint) + { + m_cache.add(odr_decode(), + pr->records->u.databaseOrSurDiagnostics, + m_resultSetStartPoint, -1); + m_resultSetStartPoint = 0; + } } - if (m_cookie && *m_cookie) + if (m_cookie) set_otherInformationString (apdu, VAL_COOKIE, 1, m_cookie); if (m_server) { yaz_log (LOG_LOG, "Sending %s to client", apdu_name(apdu)); m_server->send_Z_PDU(apdu); } + if (apdu->which == Z_APDU_close) + { + shutdown(); + } }