X-Git-Url: http://lists.indexdata.com/cgi-bin?a=blobdiff_plain;f=src%2Ffilter_multi.cpp;h=7e847d46a2268054c4af40da461292a13fdb20e4;hb=a9a65a522caf3161208023338c1350ff215f38c2;hp=468ccdf94f8b51c3007923065895dcea2d0d194e;hpb=63dda9fef8b647d491dd2baef8ec4f4f88ee1b11;p=metaproxy-moved-to-github.git diff --git a/src/filter_multi.cpp b/src/filter_multi.cpp index 468ccdf..7e847d4 100644 --- a/src/filter_multi.cpp +++ b/src/filter_multi.cpp @@ -1,4 +1,4 @@ -/* $Id: filter_multi.cpp,v 1.3 2006-01-16 15:51:56 adam Exp $ +/* $Id: filter_multi.cpp,v 1.7 2006-01-18 09:20:30 adam Exp $ Copyright (c) 2005, Index Data. %LICENSE% @@ -59,7 +59,6 @@ namespace yp2 { struct Multi::Frontend { Frontend(Rep *rep); ~Frontend(); - yp2::Session m_session; bool m_is_multi; bool m_in_use; std::list m_backend_list; @@ -70,6 +69,7 @@ namespace yp2 { void close(Package &package); void search(Package &package, Z_APDU *apdu); void present(Package &package, Z_APDU *apdu); + void scan(Package &package, Z_APDU *apdu); Rep *m_p; }; struct Multi::Map { @@ -87,7 +87,7 @@ namespace yp2 { private: boost::mutex m_sessions_mutex; std::mapm_maps; - + std::map m_target_route; boost::mutex m_mutex; boost::condition m_cond_session_ready; std::map m_clients; @@ -286,20 +286,9 @@ void yf::Multi::Frontend::init(Package &package, Z_GDU *gdu) std::list targets; - int no_targets = 0; - while (true) - { - const char *vhost_cstr = - yaz_oi_get_string_oidval(&req->otherInfo, VAL_PROXY, no_targets+1, - 0); - if (!vhost_cstr) - break; - no_targets++; - if (no_targets > 1000) - return; - targets.push_back(vhost_cstr); - } - if (no_targets < 2) + yp2::util::get_vhost_otherinfo(&req->otherInfo, false, targets); + + if (targets.size() < 1) { package.move(); return; @@ -312,6 +301,7 @@ void yf::Multi::Frontend::init(Package &package, Z_GDU *gdu) Backend *b = new Backend; b->m_vhost = *t_it; + b->m_route = m_p->m_target_route[*t_it]; // b->m_route unset b->m_package = PackagePtr(new Package(s, package.origin())); @@ -335,6 +325,7 @@ void yf::Multi::Frontend::init(Package &package, Z_GDU *gdu) ODR_MASK_SET(req->options, Z_Options_search); ODR_MASK_SET(req->options, Z_Options_present); ODR_MASK_SET(req->options, Z_Options_namedResultSets); + ODR_MASK_SET(req->options, Z_Options_scan); ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_1); ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_2); @@ -403,8 +394,13 @@ void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) { // create search request Z_SearchRequest *req = apdu_req->u.searchRequest; - - // deal with piggy back (for now disable) + + // save these for later + int smallSetUpperBound = *req->smallSetUpperBound; + int largeSetLowerBound = *req->largeSetLowerBound; + int mediumSetPresentNumber = *req->mediumSetPresentNumber; + + // they are altered now - to disable piggyback *req->smallSetUpperBound = 0; *req->largeSetLowerBound = 1; *req->mediumSetPresentNumber = 1; @@ -433,7 +429,7 @@ void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) // look at each response FrontendSet resultSet(std::string(req->resultSetName)); - int total_count = 0; + int result_set_size = 0; Z_Records *z_records_diag = 0; // no diagnostics (yet) for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) { @@ -460,7 +456,7 @@ void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) BackendSet backendSet; backendSet.m_backend = *bit; backendSet.m_count = *b_resp->resultCount; - total_count += *b_resp->resultCount; + result_set_size += *b_resp->resultCount; resultSet.m_backend_sets.push_back(backendSet); } else @@ -475,18 +471,57 @@ void yf::Multi::Frontend::search(Package &package, Z_APDU *apdu_req) Z_APDU *f_apdu = odr.create_searchResponse(apdu_req, 0, 0); Z_SearchResponse *f_resp = f_apdu->u.searchResponse; + *f_resp->resultCount = result_set_size; if (z_records_diag) { // search error f_resp->records = z_records_diag; + package.response() = f_apdu; + return; } - else - { // assume OK - m_sets[resultSet.m_setname] = resultSet; + // assume OK + m_sets[resultSet.m_setname] = resultSet; + + int number; + yp2::util::piggyback(smallSetUpperBound, + largeSetLowerBound, + mediumSetPresentNumber, + result_set_size, + number); + Package pp(package.session(), package.origin()); + if (number > 0) + { + pp.copy_filter(package); + Z_APDU *p_apdu = zget_APDU(odr, Z_APDU_presentRequest); + Z_PresentRequest *p_req = p_apdu->u.presentRequest; + p_req->preferredRecordSyntax = req->preferredRecordSyntax; + p_req->resultSetId = req->resultSetName; + *p_req->resultSetStartPoint = 1; + *p_req->numberOfRecordsRequested = number; + pp.request() = p_apdu; + present(pp, p_apdu); + + if (pp.session().is_closed()) + package.session().close(); + + Z_GDU *gdu = pp.response().get(); + if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which == + Z_APDU_presentResponse) + { + Z_PresentResponse *p_res = gdu->u.z3950->u.presentResponse; + f_resp->records = p_res->records; + *f_resp->numberOfRecordsReturned = + *p_res->numberOfRecordsReturned; + *f_resp->nextResultSetPosition = + *p_res->nextResultSetPosition; + } + else + { + package.response() = pp.response(); + return; + } } - *f_resp->resultCount = total_count; - - package.response() = f_apdu; + package.response() = f_apdu; // in this scope because of p } void yf::Multi::Frontend::present(Package &package, Z_APDU *apdu_req) @@ -622,6 +657,63 @@ void yf::Multi::Frontend::present(Package &package, Z_APDU *apdu_req) package.response() = f_apdu; } +void yf::Multi::Frontend::scan(Package &package, Z_APDU *apdu_req) +{ + if (m_backend_list.size() > 1) + { + yp2::odr odr; + Z_APDU *f_apdu = + odr.create_scanResponse( + apdu_req, YAZ_BIB1_COMBI_OF_SPECIFIED_DATABASES_UNSUPP, 0); + package.response() = f_apdu; + return; + } + Z_ScanRequest *req = apdu_req->u.scanRequest; + + int default_num_db = req->num_databaseNames; + char **default_db = req->databaseNames; + + std::list::const_iterator bit; + for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) + { + PackagePtr p = (*bit)->m_package; + yp2::odr odr; + + if (!yp2::util::set_databases_from_zurl(odr, (*bit)->m_vhost, + &req->num_databaseNames, + &req->databaseNames)) + { + req->num_databaseNames = default_num_db; + req->databaseNames = default_db; + } + p->request() = apdu_req; + p->copy_filter(package); + } + multi_move(m_backend_list); + + for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++) + { + PackagePtr p = (*bit)->m_package; + + if (p->session().is_closed()) // if any backend closes, close frontend + package.session().close(); + + Z_GDU *gdu = p->response().get(); + if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which == + Z_APDU_scanResponse) + { + package.response() = p->response(); + break; + } + else + { + // if any target does not return scan response - return that + package.response() = p->response(); + return; + } + } +} + void yf::Multi::process(Package &package) const { FrontendPtr f = m_p->get_frontend(package); @@ -657,6 +749,10 @@ void yf::Multi::process(Package &package) const { f->present(package, apdu); } + else if (apdu->which == Z_APDU_scanRequest) + { + f->scan(package, apdu); + } else { yp2::odr odr; @@ -677,7 +773,14 @@ void yp2::filter::Multi::configure(const xmlNode * ptr) { if (ptr->type != XML_ELEMENT_NODE) continue; - if (!strcmp((const char *) ptr->name, "virtual")) + if (!strcmp((const char *) ptr->name, "target")) + { + std::string route = yp2::xml::get_route(ptr); + std::string target = yp2::xml::get_text(ptr); + std::cout << "route=" << route << " target=" << target << "\n"; + m_p->m_target_route[target] = route; + } + else if (!strcmp((const char *) ptr->name, "virtual")) { std::list targets; std::string vhost;