+yf::VirtualDB::BackendPtr yf::VirtualDB::Frontend::lookup_backend_from_databases(
+ std::list<std::string> databases)
+{
+ std::list<BackendPtr>::const_iterator map_it;
+ map_it = m_backend_list.begin();
+ for (; map_it != m_backend_list.end(); map_it++)
+ if ((*map_it)->m_frontend_databases == databases)
+ return *map_it;
+ BackendPtr null;
+ return null;
+}
+
+yf::VirtualDB::BackendPtr yf::VirtualDB::Frontend::create_backend_from_databases(
+ std::list<std::string> databases, int &error_code, std::string &addinfo)
+{
+ BackendPtr b(new Backend);
+ std::list<std::string>::const_iterator db_it = databases.begin();
+
+ b->m_number_of_sets = 0;
+ b->m_frontend_databases = databases;
+ b->m_named_result_sets = false;
+
+ bool first_route = true;
+
+ std::map<std::string,bool> targets_dedup;
+ for (; db_it != databases.end(); db_it++)
+ {
+ std::list<VirtualDB::Map>::const_iterator map_it;
+ map_it = m_p->m_maps.begin();
+ while (map_it != m_p->m_maps.end())
+ {
+ if (map_it->match(*db_it))
+ break;
+ map_it++;
+ }
+
+ if (map_it == m_p->m_maps.end()) // database not found
+ {
+ error_code = YAZ_BIB1_DATABASE_DOES_NOT_EXIST;
+ addinfo = *db_it;
+ BackendPtr ptr;
+ return ptr;
+ }
+ std::list<std::string>::const_iterator t_it =
+ map_it->m_targets.begin();
+ for (; t_it != map_it->m_targets.end(); t_it++) {
+ if (!targets_dedup[*t_it])
+ {
+ targets_dedup[*t_it] = true;
+ b->m_targets.push_back(*t_it);
+ }
+ }
+
+ // see if we have a route conflict.
+ if (!first_route && b->m_route != map_it->m_route)
+ {
+ // we have a conflict..
+ error_code = YAZ_BIB1_COMBI_OF_SPECIFIED_DATABASES_UNSUPP;
+ BackendPtr ptr;
+ return ptr;
+ }
+ b->m_route = map_it->m_route;
+ first_route = false;
+ }
+ return b;
+}
+
+yf::VirtualDB::BackendPtr yf::VirtualDB::Frontend::init_backend(
+ std::list<std::string> databases, mp::Package &package,
+ int &error_code, std::string &addinfo)
+{
+ BackendPtr b = create_backend_from_databases(databases, error_code,
+ addinfo);
+ if (!b)
+ return b;
+ Package init_package(b->m_backend_session, package.origin());
+ init_package.copy_filter(package);
+
+ mp::odr odr;
+
+ Z_APDU *init_apdu = zget_APDU(odr, Z_APDU_initRequest);
+
+ mp::util::set_vhost_otherinfo(&init_apdu->u.initRequest->otherInfo, odr,
+ b->m_targets);
+ Z_InitRequest *req = init_apdu->u.initRequest;
+
+ // copy stuff from Frontend Init Request
+ Z_GDU *org_gdu = m_init_gdu.get();
+ Z_InitRequest *org_init = org_gdu->u.z3950->u.initRequest;
+
+ req->idAuthentication = org_init->idAuthentication;
+ req->implementationId = org_init->implementationId;
+ req->implementationName = org_init->implementationName;
+ req->implementationVersion = org_init->implementationVersion;
+ *req->preferredMessageSize = *org_init->preferredMessageSize;
+ *req->maximumRecordSize = *org_init->maximumRecordSize;
+
+ 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);
+ ODR_MASK_SET(req->protocolVersion, Z_ProtocolVersion_3);
+
+ init_package.request() = init_apdu;
+
+ init_package.move(b->m_route); // sending init
+
+ Z_GDU *gdu = init_package.response().get();
+ // we hope to get an init response
+ error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
+ if (gdu && gdu->which == Z_GDU_Z3950
+ && gdu->u.z3950->which == Z_APDU_initResponse
+ && *gdu->u.z3950->u.initResponse->result)
+ {
+ Z_InitResponse *res = gdu->u.z3950->u.initResponse;
+ if (ODR_MASK_GET(res->options, Z_Options_namedResultSets))
+ {
+ b->m_named_result_sets = true;
+ }
+ if (*res->result && !init_package.session().is_closed())
+ {
+ m_backend_list.push_back(b);
+ return b;
+ }
+ mp::util::get_init_diagnostics(res, error_code, addinfo);
+ }
+ if (!init_package.session().is_closed())
+ {
+ Package close_package(b->m_backend_session, package.origin());
+ close_package.copy_filter(package);
+ close_package.session().close();
+ close_package.move(b->m_route); // closing it
+ }
+ BackendPtr null;
+ return null;
+}
+
+void yf::VirtualDB::Frontend::search(mp::Package &package, Z_APDU *apdu_req)