X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fp2_msg.cpp;fp=src%2Fp2_msg.cpp;h=e113a21c0699ed65eb264f8dc868a1d0876d4572;hb=42cd2c5dddd315dd85b626b125a750e8203c739a;hp=0000000000000000000000000000000000000000;hpb=5108598ba9fe27a03aad0371d28bb7062b6463fc;p=yazproxy-moved-to-github.git diff --git a/src/p2_msg.cpp b/src/p2_msg.cpp new file mode 100644 index 0000000..e113a21 --- /dev/null +++ b/src/p2_msg.cpp @@ -0,0 +1,387 @@ +/* $Id: p2_msg.cpp,v 1.1 2005-10-05 12:07:14 adam Exp $ + Copyright (c) 1998-2005, Index Data. + +This file is part of the yaz-proxy. + +YAZ proxy 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 +Software Foundation; either version 2, or (at your option) any later +version. + +YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with YAZ proxy; see the file LICENSE. If not, write to the +Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + */ + +#include +#include +#include "p2_backend.h" +#include "p2_frontend.h" +#include "p2_config.h" +#include "p2_modules.h" + +using namespace yazpp_1; +using namespace std; + +IP2_BackendSet::~IP2_BackendSet() +{ +} + +IP2_Backend::~IP2_Backend() +{ + +} + +P2_Backend::P2_Backend(P2_ConfigTarget *cfg, IP2_Backend *backend_int) +{ + m_configTarget = new P2_ConfigTarget; + *m_configTarget = *cfg; + m_busy = false; + m_int = backend_int; +} + +P2_Backend::~P2_Backend() +{ + delete m_configTarget; +} + +P2_BackendResultSet::P2_BackendResultSet() +{ + m_int = 0; +} + +P2_BackendResultSet::~P2_BackendResultSet() +{ + delete m_int; +} + +P2_Backend *P2_Msg::select_backend(string db, + Yaz_Z_Query *query, + P2_BackendResultSet **bset) +{ + P2_Config *cfg = m_server->lockConfig(); + + // see if some target has done this query before + + *bset = 0; + P2_Backend *backend = 0; + + list::const_iterator it; + for (it = m_server->m_backend_list.begin(); + it != m_server->m_backend_list.end(); it++) + { + if ((*it)->m_busy) + continue; + + if (db != (*it)->m_configTarget->m_virt_database) + continue; + backend = *it; + + if (query) + { + list::const_iterator is; + for (is = (*it)->m_resultSets.begin(); + is != (*it)->m_resultSets.end(); is++) + { + if (query->match(&(*is)->m_query)) + { + *bset = *is; + break; + } + } + } + if (bset) + break; + } + if (!backend) + { + P2_ConfigTarget *target_cfg = cfg->find_target(db); + + if (!target_cfg) + { + yaz_log(YLOG_WARN, "No backend for database %s", + db.c_str()); + } + else + { + P2_ModuleInterface0 *int0 = + reinterpret_cast + (m_server->m_modules->get_interface(target_cfg->m_type.c_str(), + 0)); + IP2_Backend *bint = 0; + + if (int0) + bint = int0->create(target_cfg->m_target_address.c_str()); + + if (bint) + backend = new P2_Backend(target_cfg, bint); + + if (backend) + m_server->m_backend_list.push_back(backend); + } + } + if (backend) + backend->m_busy = true; + m_server->unlockConfig(); + return backend; +} + +void P2_FrontResultSet::setQuery(Z_Query *z_query) +{ + m_query.set_Z_Query(z_query); +} + +void P2_FrontResultSet::setDatabases(char **db, int num) +{ + m_db_list.clear(); + + int i; + for (i = 0; iu.searchRequest; + list::iterator it; + P2_FrontResultSet *s = 0; + + string id = req->resultSetName; + for (it = m_front->m_resultSets.begin(); it != m_front->m_resultSets.end(); it++) + { + if ((*it)->m_resultSetId == id) + { + s = *it; + break; + } + } + if (s) + { + // result set already exists + *rset = s; + if (req->replaceIndicator && *req->replaceIndicator) + { // replace indicator true + s->setQuery(req->query); + s->setDatabases(req->databaseNames, req->num_databaseNames); + return 0; + } + Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse); + Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records)); + apdu->u.searchResponse->records = rec; + rec->which = Z_Records_NSD; + rec->u.nonSurrogateDiagnostic = + zget_DefaultDiagFormat( + odr, YAZ_BIB1_RESULT_SET_EXISTS_AND_REPLACE_INDICATOR_OFF, + req->resultSetName); + + return apdu; + } + // does not exist + s = new P2_FrontResultSet(req->resultSetName); + s->setQuery(req->query); + s->setDatabases(req->databaseNames, req->num_databaseNames); + m_front->m_resultSets.push_back(s); + *rset = s; + return 0; +} + +Z_APDU *P2_Msg::frontend_search_apdu(Z_APDU *request_apdu, ODR odr) +{ + P2_FrontResultSet *rset; + Z_APDU *response_apdu = frontend_search_resultset(request_apdu, odr, + &rset); + if (response_apdu) + return response_apdu; + + // no immediate error (yet) + size_t i; + for (i = 0; im_db_list.size(); i++) + { + string db = rset->m_db_list[i]; + P2_BackendResultSet *bset; + P2_Backend *b = select_backend(db, &rset->m_query, &bset); + if (!b) + { + Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse); + Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records)); + apdu->u.searchResponse->records = rec; + rec->which = Z_Records_NSD; + rec->u.nonSurrogateDiagnostic = + zget_DefaultDiagFormat( + odr, YAZ_BIB1_DATABASE_UNAVAILABLE, db.c_str()); + return apdu; + } + if (!bset) + { // new set + bset = new P2_BackendResultSet(); + + bset->m_query.set_Z_Query(request_apdu->u.searchRequest->query); + bset->m_db_list.push_back(db); + + b->m_int->search(&bset->m_query, &bset->m_int, &bset->m_hit_count); + b->m_resultSets.push_back(bset); + } + else + { + bset->m_int->get(1, 1); + } + response_apdu = zget_APDU(odr, Z_APDU_searchResponse); + *response_apdu->u.searchResponse->resultCount = bset->m_hit_count; + b->m_busy = false; + } + if (!response_apdu) + { + Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse); + Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records)); + apdu->u.searchResponse->records = rec; + rec->which = Z_Records_NSD; + rec->u.nonSurrogateDiagnostic = + zget_DefaultDiagFormat(odr, YAZ_BIB1_UNSUPP_SEARCH, 0); + return apdu; + } + return response_apdu; +} + +Z_APDU *P2_Msg::frontend_present_resultset(Z_APDU *z_gdu, ODR odr, + P2_FrontResultSet **rset) +{ + Z_PresentRequest *req = z_gdu->u.presentRequest; + list::iterator it; + P2_FrontResultSet *s = 0; + + string id = req->resultSetId; + for (it = m_front->m_resultSets.begin(); it != m_front->m_resultSets.end(); it++) + { + if ((*it)->m_resultSetId == id) + { + s = *it; + break; + } + } + *rset = s; + if (s) + return 0; // fine result set exists + + Z_APDU *apdu = zget_APDU(odr, Z_APDU_presentResponse); + + Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records)); + apdu->u.presentResponse->records = rec; + rec->which = Z_Records_NSD; + rec->u.nonSurrogateDiagnostic = + zget_DefaultDiagFormat( + odr, + YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST, + req->resultSetId); + return apdu; +} + +Z_APDU *P2_Msg::frontend_present_apdu(Z_APDU *request_apdu, ODR odr) +{ + P2_FrontResultSet *rset; + Z_APDU *response_apdu = frontend_present_resultset(request_apdu, odr, + &rset); + if (response_apdu) + return response_apdu; + return zget_APDU(odr, Z_APDU_presentResponse); +} + +IMsg_Thread *P2_Msg::handle() +{ + ODR odr = odr_createmem(ODR_ENCODE); + yaz_log(YLOG_LOG, "P2_Msg:handle begin"); + Z_GDU *request_gdu = m_gdu->get(); + + if (request_gdu->which == Z_GDU_Z3950) + { + Z_APDU *request_apdu = request_gdu->u.z3950; + Z_APDU *response_apdu = 0; + switch(request_apdu->which) + { + case Z_APDU_initRequest: + response_apdu = zget_APDU(odr, Z_APDU_initResponse); + ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_triggerResourceCtrl); + ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_search); + ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_present); + ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_namedResultSets); + break; + case Z_APDU_searchRequest: + response_apdu = frontend_search_apdu(request_apdu, odr); + break; + case Z_APDU_presentRequest: + response_apdu = frontend_present_apdu(request_apdu, odr); + break; + case Z_APDU_triggerResourceControlRequest: + break; + default: + response_apdu = zget_APDU(odr, Z_APDU_close); + m_close_flag = 1; + break; + } + if (response_apdu) + m_output = new GDU(response_apdu); + } + yaz_log(YLOG_LOG, "P2_Msg:handle end"); + odr_destroy(odr); + return this; +} + +void P2_Msg::result() +{ + m_front->m_no_requests--; + if (!m_front->m_delete_flag) + { + if (m_output) + { + int len; + m_front->send_GDU(m_output->get(), &len); + } + if (m_close_flag) + { + m_front->close(); + m_front->m_delete_flag = 1; + } + } + if (m_front->m_delete_flag && m_front->m_no_requests == 0) + delete m_front; + delete this; +} + +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */