X-Git-Url: http://sru.miketaylor.org.uk/?a=blobdiff_plain;f=src%2Ffilter_sort.cpp;h=784c6f9d6bbb621040c86817bb822a079b565eca;hb=9ec9630d5b143f0fc57e999a7b7b1710f990e19f;hp=c91d8a8fa763802703922aa61620a9934775c0a4;hpb=19f9ce0629754d3c379a7c9676d91ba69d4275d8;p=metaproxy-moved-to-github.git diff --git a/src/filter_sort.cpp b/src/filter_sort.cpp index c91d8a8..784c6f9 100644 --- a/src/filter_sort.cpp +++ b/src/filter_sort.cpp @@ -51,6 +51,7 @@ namespace metaproxy_1 { std::string m_xpath_expr; std::string m_namespaces; bool m_ascending; + bool m_debug; boost::mutex m_mutex; boost::condition m_cond_session_ready; std::map m_clients; @@ -62,12 +63,12 @@ namespace metaproxy_1 { Z_NamePlusRecord *npr; std::string score; void get_xpath(xmlDoc *doc, const char *namespaces, - const char *expr); + const char *expr, bool debug); bool register_namespaces(xmlXPathContextPtr xpathCtx, const char *nsList); public: Record(Z_NamePlusRecord *n, const char *namespaces, - const char *expr); + const char *expr, bool debug); ~Record(); bool operator < (const Record &rhs); }; @@ -77,12 +78,15 @@ namespace metaproxy_1 { mp::odr m_odr; std::string namespaces; std::string xpath_expr; + bool debug; public: + bool cmp(Odr_oid *syntax); void add(Z_NamePlusRecord *s); - Z_NamePlusRecord *get(int i); + int size(); + Z_NamePlusRecord *get(int i, bool ascending); void sort(); RecordList(Odr_oid *, std::string namespaces, - std::string xpath_expr); + std::string xpath_expr, bool debug); ~RecordList(); }; class Sort::ResultSet : boost::noncopyable { @@ -211,7 +215,7 @@ bool yf::Sort::Record::register_namespaces(xmlXPathContextPtr xpathCtx, void yf::Sort::Record::get_xpath(xmlDoc *doc, const char *namespaces, - const char *expr) + const char *expr, bool debug) { xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc); if (xpathCtx) @@ -222,6 +226,8 @@ void yf::Sort::Record::get_xpath(xmlDoc *doc, const char *namespaces, if (xpathObj) { xmlNodeSetPtr nodes = xpathObj->nodesetval; + if (debug) + print_xpath_nodes(nodes, yaz_log_file()); if (nodes) { int i; @@ -238,7 +244,7 @@ void yf::Sort::Record::get_xpath(xmlDoc *doc, const char *namespaces, { content = mp::xml::get_text(ptr); } - if (content.c_str()) + if (content.length()) { score = content; break; @@ -253,7 +259,8 @@ void yf::Sort::Record::get_xpath(xmlDoc *doc, const char *namespaces, yf::Sort::Record::Record(Z_NamePlusRecord *n, const char *namespaces, - const char *expr) : npr(n) + const char *expr, + bool debug) : npr(n) { if (npr->which == Z_NamePlusRecord_databaseRecord) { @@ -267,7 +274,7 @@ yf::Sort::Record::Record(Z_NamePlusRecord *n, ext->u.octet_aligned->len); if (doc) { - get_xpath(doc, namespaces, expr); + get_xpath(doc, namespaces, expr, debug); xmlFreeDoc(doc); } } @@ -287,8 +294,9 @@ bool yf::Sort::Record::operator < (const Record &rhs) yf::Sort::RecordList::RecordList(Odr_oid *syntax, std::string a_namespaces, - std::string a_xpath_expr) - : namespaces(a_namespaces), xpath_expr(a_xpath_expr) + std::string a_xpath_expr, + bool a_debug) + : namespaces(a_namespaces), xpath_expr(a_xpath_expr), debug(a_debug) { if (syntax) @@ -302,21 +310,39 @@ yf::Sort::RecordList::~RecordList() } +bool yf::Sort::RecordList::cmp(Odr_oid *syntax) +{ + if ((!this->syntax && !syntax) + || + (this->syntax && syntax && !oid_oidcmp(this->syntax, syntax))) + return true; + return false; +} + +int yf::Sort::RecordList::size() +{ + return npr_list.size(); +} + void yf::Sort::RecordList::add(Z_NamePlusRecord *s) { ODR oi = m_odr; - Record record(yaz_clone_z_NamePlusRecord(s, oi->mem), - namespaces.c_str(), - xpath_expr.c_str()); + Z_NamePlusRecord *npr = yaz_clone_z_NamePlusRecord(s, oi->mem); + Record record(npr, namespaces.c_str(), xpath_expr.c_str(), debug); npr_list.push_back(record); } -Z_NamePlusRecord *yf::Sort::RecordList::get(int i) +Z_NamePlusRecord *yf::Sort::RecordList::get(int pos, bool ascending) { std::list::const_iterator it = npr_list.begin(); + int i = pos; + if (!ascending) + i = npr_list.size() - pos - 1; for (; it != npr_list.end(); it++, --i) if (i <= 0) + { return it->npr; + } return 0; } @@ -355,7 +381,7 @@ yf::Sort::Frontend::~Frontend() } -yf::Sort::Impl::Impl() : m_prefetch(20), m_ascending(true) +yf::Sort::Impl::Impl() : m_prefetch(20), m_ascending(true), m_debug(false) { } @@ -415,7 +441,7 @@ void yf::Sort::Impl::configure(const xmlNode *ptr, bool test_only, { if (ptr->type != XML_ELEMENT_NODE) continue; - if (!strcmp((const char *) ptr->name, "config")) + if (!strcmp((const char *) ptr->name, "sort")) { const struct _xmlAttr *attr; for (attr = ptr->properties; attr; attr = attr->next) @@ -438,18 +464,13 @@ void yf::Sort::Impl::configure(const xmlNode *ptr, bool test_only, { m_namespaces = mp::xml::get_text(attr->children); } - else if (!strcmp((const char *) attr->name, "sortorder")) + else if (!strcmp((const char *) attr->name, "ascending")) { - std::string t = mp::xml::get_text(attr->children); - if (t == "ascending") - m_ascending = true; - else if (t == "descending") - m_ascending = false; - else - throw mp::filter::FilterException( - "Bad attribute value " + t + " for attribute " + - std::string((const char *) attr->name)); - + m_ascending = mp::xml::get_bool(attr->children, true); + } + else if (!strcmp((const char *) attr->name, "debug")) + { + m_debug = mp::xml::get_bool(attr->children, false); } else throw mp::filter::FilterException( @@ -483,13 +504,20 @@ void yf::Sort::Frontend::handle_records(mp::Package &package, { if (records && records->which == Z_Records_DBOSD && start_pos == 1) { + std::list::const_iterator it = s->record_lists.begin(); + + for (; it != s->record_lists.end(); it++) + if ((*it)->cmp(syntax)) + return; + Z_NamePlusRecordList *nprl = records->u.databaseOrSurDiagnostics; int i; // i is number of records fetched in last response int pos = 1; RecordListPtr rlp(new RecordList(syntax, m_p->m_namespaces.c_str(), - m_p->m_xpath_expr.c_str())); + m_p->m_xpath_expr.c_str(), + m_p->m_debug)); for (i = 0; i < nprl->num_records; i++, pos++) rlp->add(nprl->records[i]); @@ -534,10 +562,7 @@ void yf::Sort::Frontend::handle_records(mp::Package &package, rlp->sort(); for (i = 0; i < nprl->num_records; i++) - if (m_p->m_ascending) - nprl->records[i] = rlp->get(i); - else - nprl->records[nprl->num_records - i - 1] = rlp->get(i); + nprl->records[i] = rlp->get(i, m_p->m_ascending); } } @@ -547,6 +572,10 @@ void yf::Sort::Frontend::handle_search(mp::Package &package, Z_APDU *apdu_req) std::string resultSetId = req->resultSetName; Package b_package(package.session(), package.origin()); mp::odr odr; + Odr_oid *syntax = 0; + + if (req->preferredRecordSyntax) + syntax = odr_oiddup(odr, req->preferredRecordSyntax); b_package.copy_filter(package); Sets_it sets_it = m_sets.find(req->resultSetName); @@ -577,7 +606,8 @@ void yf::Sort::Frontend::handle_search(mp::Package &package, Z_APDU *apdu_req) Z_SearchResponse *res = gdu_res->u.z3950->u.searchResponse; s->hit_count = *res->resultCount; handle_records(b_package, apdu_req, res->records, 1, s, - req->preferredRecordSyntax, resultSetId.c_str()); + syntax, resultSetId.c_str()); + package.response() = gdu_res; } } @@ -587,6 +617,11 @@ void yf::Sort::Frontend::handle_present(mp::Package &package, Z_APDU *apdu_req) std::string resultSetId = req->resultSetId; Package b_package(package.session(), package.origin()); mp::odr odr; + Odr_oid *syntax = 0; + Odr_int start = *req->resultSetStartPoint; + + if (req->preferredRecordSyntax) + syntax = odr_oiddup(odr, req->preferredRecordSyntax); b_package.copy_filter(package); Sets_it sets_it = m_sets.find(resultSetId); @@ -600,6 +635,41 @@ void yf::Sort::Frontend::handle_present(mp::Package &package, Z_APDU *apdu_req) package.response() = apdu; return; } + ResultSetPtr rset = sets_it->second; + std::list::const_iterator it = rset->record_lists.begin(); + for (; it != rset->record_lists.end(); it++) + if ((*it)->cmp(req->preferredRecordSyntax)) + { + if (*req->resultSetStartPoint - 1 + *req->numberOfRecordsRequested + <= (*it)->size()) + { + int i; + Z_APDU *p_apdu = zget_APDU(odr, Z_APDU_presentResponse); + Z_PresentResponse *p_res = p_apdu->u.presentResponse; + + *p_res->nextResultSetPosition = *req->resultSetStartPoint + + *req->numberOfRecordsRequested; + *p_res->numberOfRecordsReturned = + *req->numberOfRecordsRequested; + p_res->records = (Z_Records *) + odr_malloc(odr, sizeof(*p_res->records)); + p_res->records->which = Z_Records_DBOSD; + Z_NamePlusRecordList *nprl = (Z_NamePlusRecordList *) + odr_malloc(odr, sizeof(*nprl)); + p_res->records->u.databaseOrSurDiagnostics = nprl; + nprl->num_records = *req->numberOfRecordsRequested; + nprl->records = (Z_NamePlusRecord **) + odr_malloc(odr, nprl->num_records * sizeof(*nprl->records)); + for (i = 0; i < nprl->num_records; i++) + { + int pos = i + *req->resultSetStartPoint - 1; + nprl->records[i] = (*it)->get(pos, m_p->m_ascending); + } + package.response() = p_apdu; + return; + } + break; + } package.move(); Z_GDU *gdu_res = package.response().get(); if (gdu_res && gdu_res->which == Z_GDU_Z3950 && gdu_res->u.z3950->which == @@ -607,8 +677,8 @@ void yf::Sort::Frontend::handle_present(mp::Package &package, Z_APDU *apdu_req) { Z_PresentResponse *res = gdu_res->u.z3950->u.presentResponse; handle_records(b_package, apdu_req, res->records, - *req->resultSetStartPoint, sets_it->second, - req->preferredRecordSyntax, resultSetId.c_str()); + start, rset, syntax, resultSetId.c_str()); + package.response() = gdu_res; } }