X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Ffilter_sru_to_z3950.cpp;h=09b48b1859fd4b36476ef5da031e496bcd350e6c;hb=069d404cfe3b0d51d1b49edf57cdb3cec180afee;hp=7dd70a82109fde6c7d426a3bc1836866bcbe2090;hpb=9263a36f12d300b625f5dbf6aa2c0f118290e08c;p=metaproxy-moved-to-github.git diff --git a/src/filter_sru_to_z3950.cpp b/src/filter_sru_to_z3950.cpp index 7dd70a8..09b48b1 100644 --- a/src/filter_sru_to_z3950.cpp +++ b/src/filter_sru_to_z3950.cpp @@ -1,5 +1,5 @@ /* This file is part of Metaproxy. - Copyright (C) 2005-2010 Index Data + Copyright (C) 2005-2012 Index Data Metaproxy 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 @@ -48,25 +48,39 @@ namespace yf = mp::filter; namespace metaproxy_1 { namespace filter { + class SRUtoZ3950::Frontend : boost::noncopyable { + friend class Impl; + bool m_in_use; + public: + Frontend(); + ~Frontend(); + }; class SRUtoZ3950::Impl { public: void configure(const xmlNode *xmlnode); void process(metaproxy_1::Package &package); private: + FrontendPtr get_frontend(mp::Package &package); + void release_frontend(mp::Package &package); std::map m_database_explain; typedef std::map ActiveUrlMap; - boost::mutex m_mutex; + boost::mutex m_url_mutex; boost::condition m_cond_url_ready; ActiveUrlMap m_active_urls; + + + boost::mutex m_mutex_session; + boost::condition m_cond_session_ready; + std::map m_clients; private: void sru(metaproxy_1::Package &package, Z_GDU *zgdu_req); - bool z3950_build_query( + int z3950_build_query( mp::odr &odr_en, Z_Query *z_query, const Z_SRW_searchRetrieveRequest *req ) const; - + bool z3950_init_request( mp::Package &package, mp::odr &odr_en, @@ -116,7 +130,8 @@ yf::SRUtoZ3950::~SRUtoZ3950() { // must have a destructor because of boost::scoped_ptr } -void yf::SRUtoZ3950::configure(const xmlNode *xmlnode, bool test_only) +void yf::SRUtoZ3950::configure(const xmlNode *xmlnode, bool test_only, + const char *path) { m_p->configure(xmlnode); } @@ -156,7 +171,7 @@ void yf::SRUtoZ3950::Impl::configure(const xmlNode *confignode) } // assigning explain node to database name - no check yet m_database_explain.insert(std::make_pair(database, explainnode)); - } + } } } @@ -210,6 +225,7 @@ void yf::SRUtoZ3950::Impl::sru(mp::Package &package, Z_GDU *zgdu_req) return; } + bool enable_package_log = false; std::string zurl; Z_SRW_extra_arg *arg; @@ -222,15 +238,24 @@ void yf::SRUtoZ3950::Impl::sru(mp::Package &package, Z_GDU *zgdu_req) { package.origin().set_max_sockets(atoi(arg->value)); } - + else if (!strcmp(arg->name, "x-session-id")) + { + package.origin().set_custom_session(arg->value); + } + else if (!strcmp(arg->name, "x-log-enable")) + { + if (*arg->value == '1') + { + enable_package_log = true; + package.log_enable(); + } + } assert(sru_pdu_req); // filter acts as sink for SRU explain requests if (sru_pdu_req->which == Z_SRW_explain_request) { Z_SRW_explainRequest *er_req = sru_pdu_req->u.explain_request; - //mp_util::build_simple_explain(package, odr_en, sru_pdu_res, - // sruinfo, er_req); mp_util::build_sru_explain(package, odr_en, sru_pdu_res, sruinfo, explainnode, er_req); } @@ -284,57 +309,128 @@ void yf::SRUtoZ3950::Impl::sru(mp::Package &package, Z_GDU *zgdu_req) YAZ_SRW_UNSUPP_OPERATION, "unknown"); } + if (enable_package_log) + { + std::string l; + package.log_reset(l); + if (l.length()) + { + mp::wrbuf w; + + wrbuf_puts(w, "\n"); + wrbuf_xmlputs(w, l.c_str()); + wrbuf_puts(w, ""); + + sru_pdu_res->extraResponseData_len = w.len(); + sru_pdu_res->extraResponseData_buf = + odr_strdup(odr_en, wrbuf_cstr(w)); + } + } + // build and send SRU response mp_util::build_sru_response(package, odr_en, soap, sru_pdu_res, charset, stylesheet); } -void yf::SRUtoZ3950::Impl::process(mp::Package &package) +yf::SRUtoZ3950::Frontend::Frontend() : m_in_use(true) { - Z_GDU *zgdu_req = package.request().get(); +} - // ignoring all non HTTP_Request packages - if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)) +yf::SRUtoZ3950::Frontend::~Frontend() +{ +} + + +yf::SRUtoZ3950::FrontendPtr yf::SRUtoZ3950::Impl::get_frontend( + mp::Package &package) +{ + boost::mutex::scoped_lock lock(m_mutex_session); + + std::map::iterator it; + + while (true) { - package.move(); - return; + it = m_clients.find(package.session()); + if (it == m_clients.end()) + break; + + if (!it->second->m_in_use) + { + it->second->m_in_use = true; + return it->second; + } + m_cond_session_ready.wait(lock); } + FrontendPtr f(new Frontend); + m_clients[package.session()] = f; + f->m_in_use = true; + return f; +} + +void yf::SRUtoZ3950::Impl::release_frontend(mp::Package &package) +{ + boost::mutex::scoped_lock lock(m_mutex_session); + std::map::iterator it; - // only working on HTTP_Request packages now + it = m_clients.find(package.session()); + if (it != m_clients.end()) + { + if (package.session().is_closed()) + { + m_clients.erase(it); + } + else + { + it->second->m_in_use = false; + } + m_cond_session_ready.notify_all(); + } +} + +void yf::SRUtoZ3950::Impl::process(mp::Package &package) +{ + FrontendPtr f = get_frontend(package); + + Z_GDU *zgdu_req = package.request().get(); - // see if HTTP request is already being executed.. - // we consider only the SRU - GET case.. - if (zgdu_req->u.HTTP_Request->content_len == 0) + if (zgdu_req && zgdu_req->which == Z_GDU_HTTP_Request) { - const char *path = zgdu_req->u.HTTP_Request->path; - boost::mutex::scoped_lock lock(m_mutex); - while (1) + if (zgdu_req->u.HTTP_Request->content_len == 0) { - ActiveUrlMap::iterator it = m_active_urls.find(path); - if (it == m_active_urls.end()) + const char *path = zgdu_req->u.HTTP_Request->path; + boost::mutex::scoped_lock lock(m_url_mutex); + while (1) { - m_active_urls[path] = 1; - break; + ActiveUrlMap::iterator it = m_active_urls.find(path); + if (it == m_active_urls.end()) + { + m_active_urls[path] = 1; + break; + } + yaz_log(YLOG_LOG, "Waiting for %s to complete", path); + m_cond_url_ready.wait(lock); } - yaz_log(YLOG_LOG, "Waiting for %s to complete", path); - m_cond_url_ready.wait(lock); + } + sru(package, zgdu_req); + if (zgdu_req && zgdu_req->u.HTTP_Request->content_len == 0) + { + const char *path = zgdu_req->u.HTTP_Request->path; + boost::mutex::scoped_lock lock(m_url_mutex); + + ActiveUrlMap::iterator it = m_active_urls.find(path); + + m_active_urls.erase(it); + m_cond_url_ready.notify_all(); } } - sru(package, zgdu_req); - if (zgdu_req->u.HTTP_Request->content_len == 0) + else { - const char *path = zgdu_req->u.HTTP_Request->path; - boost::mutex::scoped_lock lock(m_mutex); - - ActiveUrlMap::iterator it = m_active_urls.find(path); - - m_active_urls.erase(it); - m_cond_url_ready.notify_all(); + package.move(); } + release_frontend(package); } - bool yf::SRUtoZ3950::Impl::z3950_init_request(mp::Package &package, mp::odr &odr_en, @@ -368,6 +464,9 @@ yf::SRUtoZ3950::Impl::z3950_init_request(mp::Package &package, } init_req->idAuthentication = auth; + + *init_req->preferredMessageSize = 10*1024*1024; + *init_req->maximumRecordSize = 10*1024*1024; ODR_MASK_SET(init_req->options, Z_Options_search); ODR_MASK_SET(init_req->options, Z_Options_present); @@ -407,7 +506,7 @@ yf::SRUtoZ3950::Impl::z3950_init_request(mp::Package &package, if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 && z3950_gdu->u.z3950->which == Z_APDU_initResponse && *z3950_gdu->u.z3950->u.initResponse->result) - return true; + return true; yaz_add_srw_diagnostic(odr_en, &(sru_pdu_res->u.response->diagnostics), @@ -416,27 +515,14 @@ yf::SRUtoZ3950::Impl::z3950_init_request(mp::Package &package, return false; } -bool -yf::SRUtoZ3950::Impl::z3950_close_request(mp::Package &package) const +bool yf::SRUtoZ3950::Impl::z3950_close_request(mp::Package &package) const { - // prepare and close Z3950 package Package z3950_package(package.session(), package.origin()); z3950_package.copy_filter(package); z3950_package.session().close(); - // set close APDU - //mp::odr odr_en(ODR_ENCODE); - //Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_close); - //z3950_package.request() = apdu; - z3950_package.move(); - // check successful close response - //Z_GDU *z3950_gdu = z3950_package.response().get(); - //if (z3950_gdu && z3950_gdu->which == Z_GDU_Z3950 - // && z3950_gdu->u.z3950->which == Z_APDU_close) - // return true; - if (z3950_package.session().is_closed()) { return true; @@ -457,14 +543,16 @@ bool yf::SRUtoZ3950::Impl::z3950_search_request(mp::Package &package, Package z3950_package(package.session(), package.origin()); z3950_package.copy_filter(package); - //add stuff in z3950 apdu Z_APDU *apdu = zget_APDU(odr_en, Z_APDU_searchRequest); Z_SearchRequest *z_searchRequest = apdu->u.searchRequest; + // RecordSyntax will always be XML + z_searchRequest->preferredRecordSyntax + = odr_oiddup(odr_en, yaz_oid_recsyn_xml); if (!mp_util::set_databases_from_zurl(odr_en, zurl, - &z_searchRequest->num_databaseNames, - &z_searchRequest->databaseNames)) + &z_searchRequest->num_databaseNames, + &z_searchRequest->databaseNames)) { z_searchRequest->num_databaseNames = 1; z_searchRequest->databaseNames = (char**) @@ -475,35 +563,29 @@ bool yf::SRUtoZ3950::Impl::z3950_search_request(mp::Package &package, = odr_strdup(odr_en, const_cast(sr_req->database)); else z_searchRequest->databaseNames[0] - = odr_strdup(odr_en, "Default"); + = odr_strdup(odr_en, "Default"); } - // z3950'fy query Z_Query *z_query = (Z_Query *) odr_malloc(odr_en, sizeof(Z_Query)); z_searchRequest->query = z_query; - if (!z3950_build_query(odr_en, z_query, sr_req)) + int sru_diagnostic = z3950_build_query(odr_en, z_query, sr_req); + if (sru_diagnostic) { yaz_add_srw_diagnostic(odr_en, &(sru_pdu_res->u.response->diagnostics), &(sru_pdu_res->u.response->num_diagnostics), - 7, "query"); + sru_diagnostic, + "query"); return false; } z3950_package.request() = apdu; - // send Z39.50 package off to backend z3950_package.move(); - Z_GDU *z3950_gdu = z3950_package.response().get(); - //TODO: check success condition - //int yaz_diag_bib1_to_srw (int bib1_code); - //int yaz_diag_srw_to_bib1(int srw_code); - //Se kode i src/seshigh.c (srw_bend_search, srw_bend_init). - if (!z3950_gdu || z3950_gdu->which != Z_GDU_Z3950 || z3950_gdu->u.z3950->which != Z_APDU_searchResponse || !z3950_gdu->u.z3950->u.searchResponse @@ -512,34 +594,24 @@ bool yf::SRUtoZ3950::Impl::z3950_search_request(mp::Package &package, yaz_add_srw_diagnostic(odr_en, &(sru_pdu_res->u.response->diagnostics), &(sru_pdu_res->u.response->num_diagnostics), - 2, 0); + YAZ_SRW_SYSTEM_TEMPORARILY_UNAVAILABLE, 0); return false; } - // everything fine, continuing Z_SearchResponse *sr = z3950_gdu->u.z3950->u.searchResponse; - // checking non surrogate diagnostics in Z3950 search response package if (!z3950_to_srw_diagnostics_ok(odr_en, sru_pdu_res->u.response, sr->records)) { return false; } - // Finally, roll on and srw'fy number of records - sru_pdu_res->u.response->numberOfRecords + sru_pdu_res->u.response->numberOfRecords = odr_intdup(odr_en, *sr->resultCount); - - // srw'fy nextRecordPosition - //sru_pdu_res->u.response->nextRecordPosition - // = (int *) odr_malloc(odr_en, sizeof(int *)); - //*(sru_pdu_res->u.response->nextRecordPosition) = 1; - return true; } -bool -yf::SRUtoZ3950::Impl::z3950_present_request( +bool yf::SRUtoZ3950::Impl::z3950_present_request( mp::Package &package, mp::odr &odr_en, Z_SRW_PDU *sru_pdu_res, @@ -741,8 +813,9 @@ yf::SRUtoZ3950::Impl::z3950_present_request( return true; } -bool yf::SRUtoZ3950::Impl::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, - const Z_SRW_searchRetrieveRequest *req +int yf::SRUtoZ3950::Impl::z3950_build_query( + mp::odr &odr_en, Z_Query *z_query, + const Z_SRW_searchRetrieveRequest *req ) const { if (req->query_type == Z_SRW_query_type_cql) @@ -758,7 +831,7 @@ bool yf::SRUtoZ3950::Impl::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, z_query->which = Z_Query_type_104; z_query->u.type_104 = ext; - return true; + return 0; } if (req->query_type == Z_SRW_query_type_pqf) @@ -769,26 +842,25 @@ bool yf::SRUtoZ3950::Impl::z3950_build_query(mp::odr &odr_en, Z_Query *z_query, pqf_parser = yaz_pqf_create (); RPNquery = yaz_pqf_parse (pqf_parser, odr_en, req->query.pqf); + + yaz_pqf_destroy(pqf_parser); + if (!RPNquery) - { - std::cout << "TODO: Handeling of bad PQF\n"; - std::cout << "TODO: Diagnostic to be send\n"; - } + return YAZ_SRW_QUERY_SYNTAX_ERROR; + z_query->which = Z_Query_type_1; z_query->u.type_1 = RPNquery; - yaz_pqf_destroy(pqf_parser); - return true; + return 0; } - return false; + return YAZ_SRW_MANDATORY_PARAMETER_NOT_SUPPLIED; } - -bool -yf::SRUtoZ3950::Impl::z3950_to_srw_diagnostics_ok(mp::odr &odr_en, - Z_SRW_searchRetrieveResponse - *sru_res, - Z_Records *records) const +bool yf::SRUtoZ3950::Impl::z3950_to_srw_diagnostics_ok( + mp::odr &odr_en, + Z_SRW_searchRetrieveResponse + *sru_res, + Z_Records *records) const { // checking non surrogate diagnostics in Z3950 present response package if (records @@ -802,11 +874,10 @@ yf::SRUtoZ3950::Impl::z3950_to_srw_diagnostics_ok(mp::odr &odr_en, return true; } - -int -yf::SRUtoZ3950::Impl::z3950_to_srw_diag(mp::odr &odr_en, - Z_SRW_searchRetrieveResponse *sru_res, - Z_DefaultDiagFormat *ddf) const +int yf::SRUtoZ3950::Impl::z3950_to_srw_diag( + mp::odr &odr_en, + Z_SRW_searchRetrieveResponse *sru_res, + Z_DefaultDiagFormat *ddf) const { int bib1_code = *ddf->condition; sru_res->num_diagnostics = 1; @@ -818,8 +889,6 @@ yf::SRUtoZ3950::Impl::z3950_to_srw_diag(mp::odr &odr_en, return 0; } - - static mp::filter::Base* filter_creator() { return new mp::filter::SRUtoZ3950;