X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Ffilter_sort.cpp;h=c1ee448fe5d453f11778cce5ccf349742b55b7d0;hb=b0ce7b47a0490c7edbb2f2c0794279db970a2102;hp=5f09492d6590f363137ad3c62774be7087ff9d6f;hpb=9bdca8ff2274385c4cb76dd69a6e3e12cf294168;p=metaproxy-moved-to-github.git diff --git a/src/filter_sort.cpp b/src/filter_sort.cpp index 5f09492..c1ee448 100644 --- a/src/filter_sort.cpp +++ b/src/filter_sort.cpp @@ -1,5 +1,5 @@ /* This file is part of Metaproxy. - Copyright (C) 2005-2012 Index Data + Copyright (C) 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 @@ -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,14 +63,14 @@ 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); + bool operator < (const Record &rhs) const; }; class Sort::RecordList : boost::noncopyable { Odr_oid *syntax; @@ -77,6 +78,7 @@ 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); @@ -84,7 +86,7 @@ namespace metaproxy_1 { 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 { @@ -109,6 +111,7 @@ namespace metaproxy_1 { Odr_int start_pos, ResultSetPtr s, Odr_oid *syntax, + Z_RecordComposition *comp, const char *resultSetId); public: Frontend(Impl *impl); @@ -122,37 +125,37 @@ static void print_xpath_nodes(xmlNodeSetPtr nodes, FILE* output) xmlNodePtr cur; int size; int i; - + assert(output); size = nodes ? nodes->nodeNr : 0; - + fprintf(output, "Result (%d nodes):\n", size); for (i = 0; i < size; ++i) { assert(nodes->nodeTab[i]); - + if (nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr)nodes->nodeTab[i]; cur = (xmlNodePtr)ns->next; if (cur->ns) - fprintf(output, "= namespace \"%s\"=\"%s\" for node %s:%s\n", + fprintf(output, "= namespace \"%s\"=\"%s\" for node %s:%s\n", ns->prefix, ns->href, cur->ns->href, cur->name); else - fprintf(output, "= namespace \"%s\"=\"%s\" for node %s\n", + fprintf(output, "= namespace \"%s\"=\"%s\" for node %s\n", ns->prefix, ns->href, cur->name); } else if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) { - cur = nodes->nodeTab[i]; + cur = nodes->nodeTab[i]; if (cur->ns) - fprintf(output, "= element node \"%s:%s\"\n", + fprintf(output, "= element node \"%s:%s\"\n", cur->ns->href, cur->name); else fprintf(output, "= element node \"%s\"\n", cur->name); } else { - cur = nodes->nodeTab[i]; + cur = nodes->nodeTab[i]; fprintf(output, "= node \"%s\": type %d\n", cur->name, cur->type); } } @@ -165,15 +168,15 @@ bool yf::Sort::Record::register_namespaces(xmlXPathContextPtr xpathCtx, xmlChar* prefix; xmlChar* href; xmlChar* next; - + assert(xpathCtx); assert(nsList); nsListDup = xmlStrdup((const xmlChar *) nsList); if (!nsListDup) return false; - - next = nsListDup; + + next = nsListDup; while (next) { /* skip spaces */ @@ -190,13 +193,13 @@ bool yf::Sort::Record::register_namespaces(xmlXPathContextPtr xpathCtx, xmlFree(nsListDup); return false; } - *next++ = '\0'; - + *next++ = '\0'; + /* find href */ href = next; next = (xmlChar*)xmlStrchr(next, ' '); if (next) - *next++ = '\0'; + *next++ = '\0'; /* do register namespace */ if (xmlXPathRegisterNs(xpathCtx, prefix, href) != 0) @@ -205,7 +208,7 @@ bool yf::Sort::Record::register_namespaces(xmlXPathContextPtr xpathCtx, return false; } } - + xmlFree(nsListDup); return true; } @@ -213,17 +216,19 @@ 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) - { + { register_namespaces(xpathCtx, namespaces); xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((const xmlChar *) expr, xpathCtx); if (xpathObj) { xmlNodeSetPtr nodes = xpathObj->nodesetval; + if (debug) + print_xpath_nodes(nodes, yaz_log_file()); if (nodes) { int i; @@ -240,7 +245,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; @@ -255,7 +260,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) { @@ -269,7 +275,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); } } @@ -280,7 +286,7 @@ yf::Sort::Record::~Record() { } -bool yf::Sort::Record::operator < (const Record &rhs) +bool yf::Sort::Record::operator < (const Record &rhs) const { if (strcmp(this->score.c_str(), rhs.score.c_str()) < 0) return true; @@ -289,8 +295,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) @@ -301,9 +308,9 @@ yf::Sort::RecordList::RecordList(Odr_oid *syntax, yf::Sort::RecordList::~RecordList() { - + } - + bool yf::Sort::RecordList::cmp(Odr_oid *syntax) { if ((!this->syntax && !syntax) @@ -322,7 +329,7 @@ void yf::Sort::RecordList::add(Z_NamePlusRecord *s) { ODR oi = m_odr; Z_NamePlusRecord *npr = yaz_clone_z_NamePlusRecord(s, oi->mem); - Record record(npr, namespaces.c_str(), xpath_expr.c_str()); + Record record(npr, namespaces.c_str(), xpath_expr.c_str(), debug); npr_list.push_back(record); } @@ -365,7 +372,7 @@ void yf::Sort::process(mp::Package &package) const } -yf::Sort::Frontend::Frontend(Impl *impl) : +yf::Sort::Frontend::Frontend(Impl *impl) : m_p(impl), m_is_virtual(false), m_in_use(true) { } @@ -375,12 +382,12 @@ 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) { } yf::Sort::Impl::~Impl() -{ +{ } yf::Sort::FrontendPtr yf::Sort::Impl::get_frontend(mp::Package &package) @@ -388,13 +395,13 @@ yf::Sort::FrontendPtr yf::Sort::Impl::get_frontend(mp::Package &package) boost::mutex::scoped_lock lock(m_mutex); std::map::iterator it; - + while(true) { it = m_clients.find(package.session()); if (it == m_clients.end()) break; - + if (!it->second->m_in_use) { it->second->m_in_use = true; @@ -412,7 +419,7 @@ void yf::Sort::Impl::release_frontend(mp::Package &package) { boost::mutex::scoped_lock lock(m_mutex); std::map::iterator it; - + it = m_clients.find(package.session()); if (it != m_clients.end()) { @@ -435,8 +442,8 @@ 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) { @@ -446,7 +453,7 @@ void yf::Sort::Impl::configure(const xmlNode *ptr, bool test_only, if (m_prefetch < 0) { throw mp::filter::FilterException( - "Bad or missing value for attribute " + + "Bad or missing value for attribute " + std::string((const char *) attr->name)); } } @@ -458,18 +465,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( @@ -480,7 +482,7 @@ void yf::Sort::Impl::configure(const xmlNode *ptr, bool test_only, else { throw mp::filter::FilterException - ("Bad element " + ("Bad element " + std::string((const char *) ptr->name) + " in sort filter"); } @@ -499,6 +501,7 @@ void yf::Sort::Frontend::handle_records(mp::Package &package, Odr_int start_pos, ResultSetPtr s, Odr_oid *syntax, + Z_RecordComposition *comp, const char *resultSetId) { if (records && records->which == Z_Records_DBOSD && start_pos == 1) @@ -515,7 +518,8 @@ void yf::Sort::Frontend::handle_records(mp::Package &package, 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]); @@ -537,6 +541,7 @@ void yf::Sort::Frontend::handle_records(mp::Package &package, *p_req->numberOfRecordsRequested = end_pos - pos + 1; p_req->preferredRecordSyntax = syntax; p_req->resultSetId = odr_strdup(odr, resultSetId); + p_req->recordComposition = comp; present_package.request() = p_apdu; present_package.move(); @@ -566,28 +571,32 @@ void yf::Sort::Frontend::handle_records(mp::Package &package, void yf::Sort::Frontend::handle_search(mp::Package &package, Z_APDU *apdu_req) { - Z_SearchRequest *req = apdu_req->u.searchRequest; + Z_SearchRequest *req = apdu_req->u.searchRequest; 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); if (sets_it != m_sets.end()) { - // result set already exist + // result set already exist // if replace indicator is off: we return diagnostic if // result set already exist. if (*req->replaceIndicator == 0) { - Z_APDU *apdu = + Z_APDU *apdu = odr.create_searchResponse( apdu_req, YAZ_BIB1_RESULT_SET_EXISTS_AND_REPLACE_INDICATOR_OFF, 0); package.response() = apdu; return; - } + } m_sets.erase(resultSetId); } ResultSetPtr s(new ResultSet); @@ -598,25 +607,33 @@ void yf::Sort::Frontend::handle_search(mp::Package &package, Z_APDU *apdu_req) Z_APDU_searchResponse) { Z_SearchResponse *res = gdu_res->u.z3950->u.searchResponse; + Z_RecordComposition *record_comp = + mp::util::piggyback_to_RecordComposition(odr, + *res->resultCount, req); s->hit_count = *res->resultCount; handle_records(b_package, apdu_req, res->records, 1, s, - req->preferredRecordSyntax, resultSetId.c_str()); + syntax, record_comp, resultSetId.c_str()); package.response() = gdu_res; } } void yf::Sort::Frontend::handle_present(mp::Package &package, Z_APDU *apdu_req) { - Z_PresentRequest *req = apdu_req->u.presentRequest; + Z_PresentRequest *req = apdu_req->u.presentRequest; 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); if (sets_it == m_sets.end()) { - Z_APDU *apdu = + Z_APDU *apdu = odr.create_presentResponse( apdu_req, YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST, @@ -629,7 +646,7 @@ void yf::Sort::Frontend::handle_present(mp::Package &package, Z_APDU *apdu_req) for (; it != rset->record_lists.end(); it++) if ((*it)->cmp(req->preferredRecordSyntax)) { - if (*req->resultSetStartPoint - 1 + *req->numberOfRecordsRequested + if (*req->resultSetStartPoint - 1 + *req->numberOfRecordsRequested <= (*it)->size()) { int i; @@ -638,9 +655,9 @@ void yf::Sort::Frontend::handle_present(mp::Package &package, Z_APDU *apdu_req) *p_res->nextResultSetPosition = *req->resultSetStartPoint + *req->numberOfRecordsRequested; - *p_res->numberOfRecordsReturned = + *p_res->numberOfRecordsReturned = *req->numberOfRecordsRequested; - p_res->records = (Z_Records *) + p_res->records = (Z_Records *) odr_malloc(odr, sizeof(*p_res->records)); p_res->records->which = Z_Records_DBOSD; Z_NamePlusRecordList *nprl = (Z_NamePlusRecordList *) @@ -665,9 +682,9 @@ void yf::Sort::Frontend::handle_present(mp::Package &package, Z_APDU *apdu_req) Z_APDU_presentResponse) { Z_PresentResponse *res = gdu_res->u.z3950->u.presentResponse; - handle_records(b_package, apdu_req, res->records, - *req->resultSetStartPoint, rset, - req->preferredRecordSyntax, resultSetId.c_str()); + handle_records(b_package, apdu_req, res->records, + start, rset, syntax, req->recordComposition, + resultSetId.c_str()); package.response() = gdu_res; } }