X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Ffilter_backend_test.cpp;h=e025cf9429c483983e1224f79b2416c13777aa28;hb=a0158b296868f0ebccd31910eed80f2a2f5878cc;hp=dda5135d08533c68a21f3bd247d4d771e6c5ebc5;hpb=a19294f809fc1e5481ad596faa5e604a6c84aa83;p=metaproxy-moved-to-github.git diff --git a/src/filter_backend_test.cpp b/src/filter_backend_test.cpp index dda5135..e025cf9 100644 --- a/src/filter_backend_test.cpp +++ b/src/filter_backend_test.cpp @@ -1,51 +1,199 @@ -/* $Id: filter_backend_test.cpp,v 1.3 2005-10-25 16:01:36 adam Exp $ - Copyright (c) 2005, Index Data. +/* $Id: filter_backend_test.cpp,v 1.23 2007-03-08 09:38:31 adam Exp $ + Copyright (c) 2005-2007, Index Data. -%LICENSE% + See the LICENSE file for details */ #include "config.hpp" #include "filter.hpp" -#include "router.hpp" #include "package.hpp" +#include "util.hpp" +#include "filter_backend_test.hpp" -#include +#include +#include +#include +#include -#include "filter_backend_test.hpp" +#include #include #include #include #include -#include -#include -#include - -namespace yf = yp2::filter; +namespace mp = metaproxy_1; +namespace yf = mp::filter; +using namespace mp; -namespace yp2 { +namespace metaproxy_1 { namespace filter { - class Backend_test::Rep { - friend class Backend_test; - - private: + class Session_info { + int dummy; + }; + class BackendTest::Rep { + friend class BackendTest; + + Z_Records *fetch( + ODR odr, Odr_oid *preferredRecordSyntax, + Z_ElementSetNames *esn, + int start, int number, int &error_code, std::string &addinfo, + int *number_returned, int *next_position); + bool m_support_named_result_sets; + + session_map m_sessions; }; } } -yf::Backend_test::Backend_test() { - m_p = new Backend_test::Rep; + +static const int result_set_size = 42; + +// an ISO2709 USMARC/MARC21 record that we return.. +static const char *marc_record = + "\x30\x30\x33\x36\x36\x6E\x61\x6D\x20\x20\x32\x32\x30\x30\x31\x36" + "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30" + "\x30\x30\x30\x30\x30\x30\x33\x30\x30\x30\x34\x30\x30\x30\x31\x33" + "\x30\x30\x35\x30\x30\x31\x37\x30\x30\x30\x31\x37\x30\x30\x38\x30" + "\x30\x34\x31\x30\x30\x30\x33\x34\x30\x31\x30\x30\x30\x31\x37\x30" + "\x30\x31\x37\x39\x30\x34\x30\x30\x30\x31\x33\x30\x30\x30\x37\x35" + "\x30\x35\x30\x30\x30\x31\x32\x30\x30\x30\x38\x38\x31\x30\x30\x30" + "\x30\x31\x37\x30\x30\x31\x30\x30\x32\x34\x35\x30\x30\x33\x30\x30" + "\x30\x31\x31\x37\x32\x36\x30\x30\x30\x31\x32\x30\x30\x31\x34\x37" + "\x32\x36\x33\x30\x30\x30\x39\x30\x30\x31\x35\x39\x33\x30\x30\x30" + "\x30\x31\x31\x30\x30\x31\x36\x38\x1E\x20\x20\x20\x31\x31\x32\x32" + "\x34\x34\x36\x36\x20\x1E\x44\x4C\x43\x1E\x30\x30\x30\x30\x30\x30" + "\x30\x30\x30\x30\x30\x30\x30\x30\x2E\x30\x1E\x39\x31\x30\x37\x31" + "\x30\x63\x31\x39\x39\x31\x30\x37\x30\x31\x6E\x6A\x75\x20\x20\x20" + "\x20\x20\x20\x20\x20\x20\x20\x20\x30\x30\x30\x31\x30\x20\x65\x6E" + "\x67\x20\x20\x1E\x20\x20\x1F\x61\x44\x4C\x43\x1F\x63\x44\x4C\x43" + "\x1E\x30\x30\x1F\x61\x31\x32\x33\x2D\x78\x79\x7A\x1E\x31\x30\x1F" + "\x61\x4A\x61\x63\x6B\x20\x43\x6F\x6C\x6C\x69\x6E\x73\x1E\x31\x30" + "\x1F\x61\x48\x6F\x77\x20\x74\x6F\x20\x70\x72\x6F\x67\x72\x61\x6D" + "\x20\x61\x20\x63\x6F\x6D\x70\x75\x74\x65\x72\x1E\x31\x20\x1F\x61" + "\x50\x65\x6E\x67\x75\x69\x6E\x1E\x20\x20\x1F\x61\x38\x37\x31\x30" + "\x1E\x20\x20\x1F\x61\x70\x2E\x20\x63\x6D\x2E\x1E\x20\x20\x1F\x61" + "\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x1D"; + + +yf::BackendTest::BackendTest() : m_p(new BackendTest::Rep) { m_p->m_support_named_result_sets = false; } -yf::Backend_test::~Backend_test() { - delete m_p; +yf::BackendTest::~BackendTest() { } -void yf::Backend_test::process(Package &package) const +Z_Records *yf::BackendTest::Rep::fetch( + ODR odr, Odr_oid *preferredRecordSyntax, + Z_ElementSetNames *esn, + int start, int number, int &error_code, std::string &addinfo, + int *number_returned, int *next_position) +{ + oident *prefformat; + oid_value form; + const char *element_set_name = "F"; // default to use + + if (number + start - 1 > result_set_size || start < 1) + { + error_code = YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE; + return 0; + } + + if (!(prefformat = oid_getentbyoid(preferredRecordSyntax))) + form = VAL_NONE; + else + form = prefformat->value; + switch(form) + { + case VAL_NONE: + form = VAL_USMARC; + break; + case VAL_USMARC: + case VAL_TEXT_XML: + break; + default: + error_code = YAZ_BIB1_RECORD_SYNTAX_UNSUPP; + return 0; + } + + // no element set, "B" and "F" are supported + if (esn) + { + if (esn->which != Z_ElementSetNames_generic) + { + error_code + = YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_; + return 0; + } + element_set_name = esn->u.generic; + } + if (!strcmp(element_set_name, "B") && form == VAL_USMARC) + ; // Brief + else if (!strcmp(element_set_name, "F") && form == VAL_USMARC) + ; // Full + else if (!strncmp(element_set_name, "FF", 2) && form == VAL_TEXT_XML) + ; // Huge XML test record + else + { + error_code + = YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_; + addinfo = std::string(element_set_name); + return 0; + } + Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records)); + rec->which = Z_Records_DBOSD; + rec->u.databaseOrSurDiagnostics = (Z_NamePlusRecordList *) + odr_malloc(odr, sizeof(Z_NamePlusRecordList)); + rec->u.databaseOrSurDiagnostics->num_records = number; + rec->u.databaseOrSurDiagnostics->records = (Z_NamePlusRecord **) + odr_malloc(odr, sizeof(Z_NamePlusRecord *) * number); + int i; + for (i = 0; iu.databaseOrSurDiagnostics->records[i] = (Z_NamePlusRecord *) + odr_malloc(odr, sizeof(Z_NamePlusRecord)); + Z_NamePlusRecord *npr = rec->u.databaseOrSurDiagnostics->records[i]; + npr->databaseName = 0; + npr->which = Z_NamePlusRecord_databaseRecord; + + if (!strncmp(element_set_name, "FF", 2)) + { // Huge XML test record + size_t sz = 1024; + if (element_set_name[2]) + sz = atoi(element_set_name+2) * 1024; + if (sz < 10) + sz = 10; + char *tmp_rec = (char*) xmalloc(sz); + + memset(tmp_rec, 'a', sz); + memcpy(tmp_rec, "", 3); + memcpy(tmp_rec + sz - 4, "", 4); + + npr->u.databaseRecord = z_ext_record(odr, VAL_TEXT_XML, tmp_rec, sz); + xfree(tmp_rec); + } + else + { + char *tmp_rec = odr_strdup(odr, marc_record); + char offset_str[30]; + sprintf(offset_str, "test__%09d_", i+start); + memcpy(tmp_rec+186, offset_str, strlen(offset_str)); + npr->u.databaseRecord = z_ext_record(odr, VAL_USMARC, + tmp_rec, strlen(tmp_rec)); + } + + } + *number_returned = number; + if (start + number > result_set_size) + *next_position = 0; + else + *next_position = start + number; + return rec; +} + +void yf::BackendTest::process(Package &package) const { Z_GDU *gdu = package.request().get(); @@ -55,27 +203,34 @@ void yf::Backend_test::process(Package &package) const { Z_APDU *apdu_req = gdu->u.z3950; Z_APDU *apdu_res = 0; - ODR odr = odr_createmem(ODR_ENCODE); - if (apdu_req->which == Z_APDU_initRequest) + mp::odr odr; + + if (apdu_req->which != Z_APDU_initRequest && + !m_p->m_sessions.exist(package.session())) { - apdu_res = zget_APDU(odr, Z_APDU_initResponse); + apdu_res = odr.create_close(apdu_req, + Z_Close_protocolError, + "no init for filter_backend_test"); + package.session().close(); + } + else if (apdu_req->which == Z_APDU_initRequest) + { + apdu_res = odr.create_initResponse(apdu_req, 0, 0); Z_InitRequest *req = apdu_req->u.initRequest; Z_InitResponse *resp = apdu_res->u.initResponse; + + resp->implementationName = "backend_test"; + if (ODR_MASK_GET(req->options, Z_Options_namedResultSets)) + m_p->m_support_named_result_sets = true; int i; static const int masks[] = { - Z_Options_search, Z_Options_present, -1 + Z_Options_search, Z_Options_present, + Z_Options_namedResultSets, -1 }; for (i = 0; masks[i] != -1; i++) if (ODR_MASK_GET(req->options, masks[i])) ODR_MASK_SET(resp->options, masks[i]); - if (m_p->m_support_named_result_sets) - { - if (ODR_MASK_GET(req->options, Z_Options_namedResultSets)) - ODR_MASK_SET(resp->options, Z_Options_namedResultSets); - else - m_p->m_support_named_result_sets = false; - } static const int versions[] = { Z_ProtocolVersion_1, Z_ProtocolVersion_2, @@ -88,44 +243,141 @@ void yf::Backend_test::process(Package &package) const else break; + Session_info info; + m_p->m_sessions.create(info, package.session()); } else if (apdu_req->which == Z_APDU_searchRequest) - { - apdu_res = zget_APDU(odr, Z_APDU_searchResponse); + { Z_SearchRequest *req = apdu_req->u.searchRequest; - Z_SearchResponse *resp = apdu_res->u.searchResponse; - + if (!m_p->m_support_named_result_sets && strcmp(req->resultSetName, "default")) { - Z_Records *rec = (Z_Records *) - odr_malloc(odr, sizeof(Z_Records)); - resp->records = rec; - rec->which = Z_Records_NSD; - rec->u.nonSurrogateDiagnostic = - zget_DefaultDiagFormat( - odr, YAZ_BIB1_RESULT_SET_NAMING_UNSUPP, 0); + apdu_res = + odr.create_searchResponse( + apdu_req, YAZ_BIB1_RESULT_SET_NAMING_UNSUPP, 0); } else - *resp->resultCount = 42; + { + Z_Records *records = 0; + int number_returned = 0; + int next_position = 0; + int error_code = 0; + std::string addinfo; + + int number = 0; + mp::util::piggyback(*req->smallSetUpperBound, + *req->largeSetLowerBound, + *req->mediumSetPresentNumber, + result_set_size, + number); + + if (number) + { // not a large set for sure + Z_ElementSetNames *esn; + if (number > *req->smallSetUpperBound) + esn = req->mediumSetElementSetNames; + else + esn = req->smallSetElementSetNames; + records = m_p->fetch( + odr, req->preferredRecordSyntax, esn, + 1, number, + error_code, addinfo, + &number_returned, + &next_position); + } + if (error_code) + { + apdu_res = + odr.create_searchResponse( + apdu_req, error_code, addinfo.c_str()); + Z_SearchResponse *resp = apdu_res->u.searchResponse; + *resp->resultCount = result_set_size; + } + else + { + apdu_res = + odr.create_searchResponse(apdu_req, 0, 0); + Z_SearchResponse *resp = apdu_res->u.searchResponse; + *resp->resultCount = result_set_size; + *resp->numberOfRecordsReturned = number_returned; + *resp->nextResultSetPosition = next_position; + resp->records = records; + } + } } else if (apdu_req->which == Z_APDU_presentRequest) { - apdu_res = zget_APDU(odr, Z_APDU_presentResponse); + Z_PresentRequest *req = apdu_req->u.presentRequest; + int number_returned = 0; + int next_position = 0; + int error_code = 0; + std::string addinfo; + Z_ElementSetNames *esn = 0; + + if (req->recordComposition) + { + if (req->recordComposition->which == Z_RecordComp_simple) + esn = req->recordComposition->u.simple; + else + { + apdu_res = + odr.create_presentResponse( + apdu_req, + YAZ_BIB1_ONLY_A_SINGLE_ELEMENT_SET_NAME_SUPPORTED, + 0); + package.response() = apdu_res; + return; + } + } + Z_Records *records = m_p->fetch( + odr, req->preferredRecordSyntax, esn, + *req->resultSetStartPoint, *req->numberOfRecordsRequested, + error_code, addinfo, + &number_returned, + &next_position); + + if (error_code) + { + apdu_res = + odr.create_presentResponse(apdu_req, error_code, + addinfo.c_str()); + } + else + { + apdu_res = + odr.create_presentResponse(apdu_req, 0, 0); + Z_PresentResponse *resp = apdu_res->u.presentResponse; + resp->records = records; + *resp->numberOfRecordsReturned = number_returned; + *resp->nextResultSetPosition = next_position; + } } else { - apdu_res = zget_APDU(odr, Z_APDU_close); - *apdu_res->u.close->closeReason = Z_Close_protocolError; - apdu_res->u.close->diagnosticInformation = - odr_strdup(odr, "bad APDU in filter_backend_test"); - + apdu_res = odr.create_close(apdu_req, + Z_Close_protocolError, + "backend_test: unhandled APDU"); package.session().close(); } if (apdu_res) package.response() = apdu_res; - odr_destroy(odr); } + if (package.session().is_closed()) + m_p->m_sessions.release(package.session()); +} + +static mp::filter::Base* filter_creator() +{ + return new mp::filter::BackendTest; +} + +extern "C" { + struct metaproxy_1_filter_struct metaproxy_1_filter_backend_test = { + 0, + "backend_test", + filter_creator + }; }