From 992092493a6c094605d83cd6c5823614f384a779 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Wed, 18 Jan 2006 14:10:47 +0000 Subject: [PATCH] First merging scan --- src/filter_multi.cpp | 251 +++++++++++++++++++++++++++++++++++++++++++++++++- src/filter_multi.hpp | 4 +- src/util.cpp | 17 +++- 3 files changed, 262 insertions(+), 10 deletions(-) diff --git a/src/filter_multi.cpp b/src/filter_multi.cpp index 6866f3d..a339959 100644 --- a/src/filter_multi.cpp +++ b/src/filter_multi.cpp @@ -1,4 +1,4 @@ -/* $Id: filter_multi.cpp,v 1.8 2006-01-18 10:57:27 adam Exp $ +/* $Id: filter_multi.cpp,v 1.9 2006-01-18 14:10:47 adam Exp $ Copyright (c) 2005, Index Data. %LICENSE% @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -33,6 +35,15 @@ namespace yp2 { BackendPtr m_backend; int m_count; bool operator < (const BackendSet &k) const; + bool operator == (const BackendSet &k) const; + }; + struct Multi::ScanTermInfo { + std::string m_norm_term; + std::string m_display_term; + int m_count; + bool operator < (const ScanTermInfo &) const; + bool operator == (const ScanTermInfo &) const; + Z_Entry *get_entry(ODR odr); }; struct Multi::FrontendSet { struct PresentJob { @@ -69,7 +80,8 @@ 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); + void scan1(Package &package, Z_APDU *apdu); + void scan2(Package &package, Z_APDU *apdu); Rep *m_p; }; struct Multi::Map { @@ -202,6 +214,7 @@ void yf::Multi::Backend::operator() (void) m_package->move(m_route); } + void yf::Multi::Frontend::close(Package &package) { std::list::const_iterator bit; @@ -659,7 +672,7 @@ 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) +void yf::Multi::Frontend::scan1(Package &package, Z_APDU *apdu_req) { if (m_backend_list.size() > 1) { @@ -716,6 +729,236 @@ void yf::Multi::Frontend::scan(Package &package, Z_APDU *apdu_req) } } +bool yf::Multi::ScanTermInfo::operator < (const ScanTermInfo &k) const +{ + return m_norm_term < k.m_norm_term; +} + +bool yf::Multi::ScanTermInfo::operator == (const ScanTermInfo &k) const +{ + return m_norm_term == k.m_norm_term; +} + +Z_Entry *yf::Multi::ScanTermInfo::get_entry(ODR odr) +{ + Z_Entry *e = (Z_Entry *)odr_malloc(odr, sizeof(*e)); + e->which = Z_Entry_termInfo; + Z_TermInfo *t; + t = e->u.termInfo = (Z_TermInfo *) odr_malloc(odr, sizeof(*t)); + t->suggestedAttributes = 0; + t->displayTerm = 0; + t->alternativeTerm = 0; + t->byAttributes = 0; + t->otherTermInfo = 0; + t->globalOccurrences = odr_intdup(odr, m_count); + t->term = (Z_Term *) + odr_malloc(odr, sizeof(*t->term)); + t->term->which = Z_Term_general; + Odr_oct *o; + t->term->u.general = o = (Odr_oct *)odr_malloc(odr, sizeof(Odr_oct)); + + o->len = o->size = m_norm_term.size(); + o->buf = (unsigned char *) odr_malloc(odr, o->len); + memcpy(o->buf, m_norm_term.c_str(), o->len); + return e; +} + +void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req) +{ + Z_ScanRequest *req = apdu_req->u.scanRequest; + int no_targets = 0; + + 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); + no_targets++; + } + multi_move(m_backend_list); + + ScanTermInfoList entries_before; + ScanTermInfoList entries_after; + int no_before = 0; + int no_after = 0; + + 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) + { + Z_ScanResponse *res = gdu->u.z3950->u.scanResponse; + if (res->entries && res->entries->entries) + { + Z_Entry **entries = res->entries->entries; + int num_entries = res->entries->num_entries; + int position = 1; + if (req->preferredPositionInResponse) + position = *req->preferredPositionInResponse; + if (res->positionOfTerm) + position = *res->positionOfTerm; + + // before + int i; + for (i = 0; iwhich == Z_Entry_termInfo) + { + ScanTermInfo my; + + int *occur = ent->u.termInfo->globalOccurrences; + my.m_count = occur ? *occur : 0; + + if (ent->u.termInfo->term->which == Z_Term_general) + { + my.m_norm_term = std::string( + (const char *) + ent->u.termInfo->term->u.general->buf, + ent->u.termInfo->term->u.general->len); + } + if (my.m_norm_term.length()) + { + ScanTermInfoList::iterator it = + entries_before.begin(); + while (it != entries_before.end() && my <*it) + it++; + if (my == *it) + { + it->m_count += my.m_count; + } + else + { + entries_before.insert(it, my); + no_before++; + } + } + } + } + // after + for (i = position-1; iwhich == Z_Entry_termInfo) + { + ScanTermInfo my; + + int *occur = ent->u.termInfo->globalOccurrences; + my.m_count = occur ? *occur : 0; + + if (ent->u.termInfo->term->which == Z_Term_general) + { + my.m_norm_term = std::string( + (const char *) + ent->u.termInfo->term->u.general->buf, + ent->u.termInfo->term->u.general->len); + } + if (my.m_norm_term.length()) + { + ScanTermInfoList::iterator it = + entries_after.begin(); + while (it != entries_after.end() && *it < my) + it++; + if (my == *it) + { + it->m_count += my.m_count; + } + else + { + entries_after.insert(it, my); + no_after++; + } + } + } + } + + } + } + else + { + // if any target does not return scan response - return that + package.response() = p->response(); + return; + } + } + + + if (false) + { + std::cout << "BEFORE\n"; + ScanTermInfoList::iterator it = entries_before.begin(); + for(; it != entries_before.end(); it++) + { + std::cout << " " << it->m_norm_term << " " << it->m_count << "\n"; + } + + std::cout << "AFTER\n"; + it = entries_after.begin(); + for(; it != entries_after.end(); it++) + { + std::cout << " " << it->m_norm_term << " " << it->m_count << "\n"; + } + } + + if (false) + { + yp2::odr odr; + Z_APDU *f_apdu = odr.create_scanResponse(apdu_req, 1, "not implemented"); + package.response() = f_apdu; + } + else + { + yp2::odr odr; + Z_APDU *f_apdu = odr.create_scanResponse(apdu_req, 0, 0); + Z_ScanResponse *resp = f_apdu->u.scanResponse; + + int number_returned = *req->numberOfTermsRequested; + int position_returned = *req->preferredPositionInResponse; + + resp->positionOfTerm = odr_intdup(odr, position_returned); + resp->numberOfEntriesReturned = odr_intdup(odr, number_returned); + + resp->entries->num_entries = number_returned; + resp->entries->entries = (Z_Entry**) + odr_malloc(odr, sizeof(Z_Entry*) * number_returned); + int i; + + ScanTermInfoList::iterator it = entries_before.begin(); + for (i = 0; ientries->entries[i] = it->get_entry(odr); + } + it = entries_after.begin(); + for (i = position_returned-1; ientries->entries[i] = it->get_entry(odr); + } + package.response() = f_apdu; + } +} + + void yf::Multi::process(Package &package) const { FrontendPtr f = m_p->get_frontend(package); @@ -753,7 +996,7 @@ void yf::Multi::process(Package &package) const } else if (apdu->which == Z_APDU_scanRequest) { - f->scan(package, apdu); + f->scan2(package, apdu); } else { diff --git a/src/filter_multi.hpp b/src/filter_multi.hpp index fc6eda3..4f6376a 100644 --- a/src/filter_multi.hpp +++ b/src/filter_multi.hpp @@ -1,4 +1,4 @@ -/* $Id: filter_multi.hpp,v 1.2 2006-01-16 01:10:19 adam Exp $ +/* $Id: filter_multi.hpp,v 1.3 2006-01-18 14:10:47 adam Exp $ Copyright (c) 2005, Index Data. %LICENSE% @@ -24,6 +24,8 @@ namespace yp2 { class FrontendSet; class Backend; class BackendSet; + class ScanTermInfo; + typedef std::list ScanTermInfoList; typedef boost::shared_ptr BackendPtr; typedef boost::shared_ptr FrontendPtr; typedef boost::shared_ptr PackagePtr; diff --git a/src/util.cpp b/src/util.cpp index dd80df0..d745065 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,4 +1,4 @@ -/* $Id: util.cpp,v 1.10 2006-01-18 10:57:27 adam Exp $ +/* $Id: util.cpp,v 1.11 2006-01-18 14:10:47 adam Exp $ Copyright (c) 2005, Index Data. %LICENSE% @@ -282,6 +282,7 @@ Z_APDU *yp2::odr::create_presentResponse(Z_APDU *in_apdu, { Z_Records *rec = (Z_Records *) odr_malloc(m_odr, sizeof(Z_Records)); apdu->u.presentResponse->records = rec; + rec->which = Z_Records_NSD; rec->u.nonSurrogateDiagnostic = zget_DefaultDiagFormat(m_odr, error, addinfo); @@ -294,20 +295,26 @@ Z_APDU *yp2::odr::create_scanResponse(Z_APDU *in_apdu, int error, const char *addinfo) { Z_APDU *apdu = create_APDU(Z_APDU_scanResponse, in_apdu); + Z_ScanResponse *res = apdu->u.scanResponse; + res->entries = (Z_ListEntries *) odr_malloc(m_odr, sizeof(*res->entries)); + res->entries->num_entries = 0; + res->entries->entries = 0; + if (error) { - Z_ScanResponse *res = apdu->u.scanResponse; - res->entries = (Z_ListEntries *) odr_malloc(m_odr, sizeof(*res->entries)); *res->scanStatus = Z_Scan_failure; - res->entries->num_entries = 0; - res->entries->entries = 0; res->entries->num_nonsurrogateDiagnostics = 1; res->entries->nonsurrogateDiagnostics = (Z_DiagRec **) odr_malloc(m_odr, sizeof(Z_DiagRec *)); res->entries->nonsurrogateDiagnostics[0] = zget_DiagRec(m_odr, error, addinfo); } + else + { + res->entries->num_nonsurrogateDiagnostics = 0; + res->entries->nonsurrogateDiagnostics = 0; + } return apdu; } -- 1.7.10.4