-/* $Id: filter_virt_db.cpp,v 1.26 2006-01-16 15:51:56 adam Exp $
+/* $Id: filter_virt_db.cpp,v 1.35 2006-02-02 11:33:46 adam Exp $
Copyright (c) 2005, Index Data.
%LICENSE%
};
struct Virt_db::Backend {
yp2::Session m_backend_session;
-#if 0
- std::string m_backend_database;
-#endif
std::list<std::string> m_frontend_databases;
std::list<std::string> m_targets;
std::string m_route;
yp2::Session m_session;
bool m_is_virtual;
bool m_in_use;
+ yazpp_1::GDU m_init_gdu;
std::list<BackendPtr> m_backend_list;
std::map<std::string,Virt_db::Set> m_sets;
BackendPtr lookup_backend_from_databases(
std::list<std::string> databases);
BackendPtr create_backend_from_databases(
- std::list<std::string> databases);
+ std::list<std::string> databases,
+ int &error_code,
+ std::string &failing_database);
BackendPtr init_backend(std::list<std::string> database,
Package &package,
};
class Virt_db::Rep {
friend class Virt_db;
- friend class Frontend;
+ friend struct Frontend;
FrontendPtr get_frontend(Package &package);
void release_frontend(Package &package);
}
yf::Virt_db::BackendPtr yf::Virt_db::Frontend::create_backend_from_databases(
- std::list<std::string> 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_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++)
{
map_it = m_p->m_maps.find(*db_it);
if (map_it == m_p->m_maps.end()) // database not found
{
+ error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
+ addinfo = *db_it;
BackendPtr ptr;
return ptr;
}
map_it->second.m_targets.begin();
for (; t_it != map_it->second.m_targets.end(); t_it++)
targets_dedup[*t_it] = true;
+
+ // see if we have a route conflict.
+ if (!first_route && b->m_route != map_it->second.m_route)
+ {
+ // we have a conflict..
+ error_code = YAZ_BIB1_COMBI_OF_SPECIFIED_DATABASES_UNSUPP;
+ BackendPtr ptr;
+ return ptr;
+ }
b->m_route = map_it->second.m_route;
+ first_route = false;
}
std::map<std::string,bool>::const_iterator tm_it = targets_dedup.begin();
for (; tm_it != targets_dedup.end(); tm_it++)
b->m_targets.push_back(tm_it->first);
-#if 0
- const char *sep = strchr(b->m_vhost.c_str(), '/');
- std::string backend_database;
- if (sep)
- b->m_backend_database = std::string(sep+1);
- else
- b->m_backend_database = database;
-#endif
+
return b;
}
std::list<std::string> databases, Package &package,
int &error_code, std::string &addinfo)
{
- BackendPtr b = create_backend_from_databases(databases);
+ BackendPtr b = create_backend_from_databases(databases, error_code,
+ addinfo);
if (!b)
- {
- error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
- // addinfo = database;
return b;
- }
Package init_package(b->m_backend_session, package.origin());
init_package.copy_filter(package);
yp2::odr odr;
Z_APDU *init_apdu = zget_APDU(odr, Z_APDU_initRequest);
-
- std::list<std::string>::const_iterator t_it = b->m_targets.begin();
- int cat = 1;
- for (; t_it != b->m_targets.end(); t_it++, cat++)
- {
- yaz_oi_set_string_oidval(&init_apdu->u.initRequest->otherInfo, odr,
- VAL_PROXY, cat, t_it->c_str());
- }
+
+ yp2::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;
+
ODR_MASK_SET(req->options, Z_Options_search);
ODR_MASK_SET(req->options, Z_Options_present);
ODR_MASK_SET(req->options, Z_Options_namedResultSets);
init_package.request() = init_apdu;
init_package.move(b->m_route); // sending init
-
- if (init_package.session().is_closed())
- {
- error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
- // addinfo = database;
- BackendPtr null;
- return null;
- }
+
Z_GDU *gdu = init_package.response().get();
// we hope to get an init response
if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
Z_APDU_initResponse)
{
- if (ODR_MASK_GET(gdu->u.z3950->u.initResponse->options,
- Z_Options_namedResultSets))
+ 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)
+ {
+ yp2::util::get_init_diagnostics(res, error_code, addinfo);
+ BackendPtr null;
+ return null;
+ }
}
else
{
BackendPtr null;
return null;
}
+ if (init_package.session().is_closed())
+ {
+ error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
+ // addinfo = database;
+ BackendPtr null;
+ return null;
+ }
+
m_backend_list.push_back(b);
return b;
}
req->resultSetName = odr_strdup(odr, backend_setname.c_str());
}
-#if 0
- const char *backend_database = b->m_backend_database.c_str();
- req->databaseNames[0] = odr_strdup(odr, backend_database);
-#endif
+ // pick first targets spec and move the databases from it ..
+ std::list<std::string>::const_iterator t_it = b->m_targets.begin();
+ if (t_it != b->m_targets.end())
+ {
+ yp2::util::set_databases_from_zurl(odr, *t_it,
+ &req->num_databaseNames,
+ &req->databaseNames);
+ }
*req->replaceIndicator = 1;
if (search_package.session().is_closed())
{
- Z_APDU *apdu =
- odr.create_searchResponse(
- apdu_req, YAZ_BIB1_DATABASE_UNAVAILABLE, 0);
- package.response() = apdu;
+ package.response() = search_package.response();
+ package.session().close();
return;
}
package.response() = search_package.response();
// sending present to backend
Package present_package(*id, package.origin());
present_package.copy_filter(package);
+
+ req->resultSetId = odr_strdup(odr, sets_it->second.m_setname.c_str());
- req->resultSetId = odr_strdup(odr, "default");
present_package.request() = yazpp_1::GDU(apdu_req);
- present_package.move();
+ present_package.move(sets_it->second.m_backend->m_route);
if (present_package.session().is_closed())
{
- Z_APDU *apdu =
- odr.create_presentResponse(
- apdu_req,
- YAZ_BIB1_RESULT_SET_NO_LONGER_EXISTS_UNILATERALLY_DELETED_BY_,
- resultSetId.c_str());
- package.response() = apdu;
- m_sets.erase(resultSetId);
+ package.response() = present_package.response();
+ package.session().close();
+ return;
}
else
{
scan_package.copy_filter(package);
-#if 0
- const char *backend_database = b->m_backend_database.c_str();
- req->databaseNames[0] = odr_strdup(odr, backend_database);
-#endif
-
+ // pick first targets spec and move the databases from it ..
+ std::list<std::string>::const_iterator t_it = b->m_targets.begin();
+ if (t_it != b->m_targets.end())
+ {
+ yp2::util::set_databases_from_zurl(odr, *t_it,
+ &req->num_databaseNames,
+ &req->databaseNames);
+ }
scan_package.request() = yazpp_1::GDU(apdu_req);
scan_package.move(b->m_route);
if (scan_package.session().is_closed())
{
- Z_APDU *apdu =
- odr.create_scanResponse(
- apdu_req, YAZ_BIB1_DATABASE_UNAVAILABLE, 0);
- package.response() = apdu;
+ package.response() = scan_package.response();
+ package.session().close();
return;
}
package.response() = scan_package.response();
{
Z_InitRequest *req = gdu->u.z3950->u.initRequest;
- const char *vhost =
- yaz_oi_get_string_oidval(&req->otherInfo, VAL_PROXY, 1, 0);
- if (!vhost)
+ std::list<std::string> vhosts;
+ yp2::util::get_vhost_otherinfo(&req->otherInfo, false, vhosts);
+ if (vhosts.size() == 0)
{
+ f->m_init_gdu = gdu;
+
yp2::odr odr;
Z_APDU *apdu = odr.create_initResponse(gdu->u.z3950, 0, 0);
Z_InitResponse *resp = apdu->u.initResponse;
}
std::string route = yp2::xml::get_route(ptr);
add_map_db2targets(database, targets, route);
-#if 0
- std::cout << "Add " << database << "->" << target
- << "," << route << "\n";
-#endif
}
else
{