1 /* $Id: filter_virt_db.cpp,v 1.2 2005-10-24 21:01:53 adam Exp $
2 Copyright (c) 2005, Index Data.
11 #include "package.hpp"
13 #include <boost/thread/mutex.hpp>
15 #include "filter_virt_db.hpp"
19 #include <yaz/otherinfo.h>
20 #include <yaz/diagbib1.h>
26 namespace yf = yp2::filter;
31 Virt_db_set(yp2::Session &id, Z_InternationalString *setname,
35 yp2::Session m_session;
36 std::string m_setname;
39 struct Virt_db_session {
40 Virt_db_session(yp2::Session &id, bool use_vhost);
41 yp2::Session m_session;
43 std::list<Virt_db_set> m_sets;
46 Virt_db_map(std::string vhost);
53 void release_session(Package &package);
54 void init(Package &package, Z_APDU *apdu, bool &move_later);
55 void search(Package &package, Z_APDU *apdu, bool &move_later);
57 boost::mutex m_sessions_mutex;
58 std::list<Virt_db_session>m_sessions;
59 std::map<std::string, Virt_db_map>m_maps;
64 yf::Virt_db_set::Virt_db_set(yp2::Session &id, Z_InternationalString *setname,
66 : m_session(id), m_setname(setname), m_vhost(vhost)
70 yf::Virt_db_set::~Virt_db_set()
74 yf::Virt_db_map::Virt_db_map(std::string vhost)
79 yf::Virt_db_map::Virt_db_map()
83 yf::Virt_db_session::Virt_db_session(yp2::Session &id,
85 m_session(id) , m_use_vhost(use_vhost)
90 yf::Virt_db::Virt_db() {
91 m_p = new Virt_db::Rep;
94 yf::Virt_db::~Virt_db() {
98 void yf::Virt_db::Rep::release_session(Package &package)
100 if (package.session().is_closed())
102 boost::mutex::scoped_lock lock(m_sessions_mutex);
104 std::list<Virt_db_session>::iterator it;
105 for (it = m_sessions.begin(); it != m_sessions.end(); it++)
107 if (package.session() == (*it).m_session)
110 if (it == m_sessions.end())
112 m_sessions.erase(it);
116 void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu, bool &move_later)
118 Z_SearchRequest *req = apdu->u.searchRequest;
120 std::string database;
123 boost::mutex::scoped_lock lock(m_sessions_mutex);
125 std::list<Virt_db_session>::iterator it;
126 for (it = m_sessions.begin(); it != m_sessions.end(); it++)
128 if (package.session() == (*it).m_session)
131 if (it == m_sessions.end())
133 // error should be returned
137 if ((*it).m_use_vhost)
142 if (req->num_databaseNames != 1)
143 { // exactly one database must be specified
144 ODR odr = odr_createmem(ODR_ENCODE);
145 Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
147 Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
148 apdu->u.searchResponse->records = rec;
149 rec->which = Z_Records_NSD;
150 rec->u.nonSurrogateDiagnostic =
151 zget_DefaultDiagFormat(
152 odr, YAZ_BIB1_TOO_MANY_DATABASES_SPECIFIED, 0);
153 package.response() = apdu;
158 database = req->databaseNames[0];
159 std::map<std::string, Virt_db_map>::iterator map_it;
160 map_it = m_maps.find(database);
161 if (map_it == m_maps.end())
162 { // no map for database: return diagnostic
163 ODR odr = odr_createmem(ODR_ENCODE);
164 Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
166 Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
167 apdu->u.searchResponse->records = rec;
168 rec->which = Z_Records_NSD;
169 rec->u.nonSurrogateDiagnostic =
170 zget_DefaultDiagFormat(
171 odr, YAZ_BIB1_DATABASE_UNAVAILABLE, database.c_str());
172 package.response() = apdu;
177 vhost = map_it->second.m_vhost;
179 (*it).m_sets.push_back(Virt_db_set(*id, req->resultSetName, vhost));
181 const char *vhost_cstr = vhost.c_str();
183 { // sending init to backend
184 Package init_package(*id, package.origin());
185 init_package.copy_filter(package);
187 ODR odr = odr_createmem(ODR_ENCODE);
188 Z_APDU *init_apdu = zget_APDU(odr, Z_APDU_initRequest);
190 yaz_oi_set_string_oidval(&init_apdu->u.initRequest->otherInfo, odr,
191 VAL_PROXY, 1, vhost_cstr);
193 init_package.request() = init_apdu;
196 init_package.move(); // send init
198 if (init_package.session().is_closed())
200 ODR odr = odr_createmem(ODR_ENCODE);
201 Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
203 Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
204 apdu->u.searchResponse->records = rec;
205 rec->which = Z_Records_NSD;
206 rec->u.nonSurrogateDiagnostic =
207 zget_DefaultDiagFormat(
208 odr, YAZ_BIB1_DATABASE_UNAVAILABLE, database.c_str());
209 package.response() = apdu;
215 // sending search to backend
216 Package search_package(*id, package.origin());
217 search_package.copy_filter(package);
218 const char *sep = strchr(vhost_cstr, '/');
219 ODR odr = odr_createmem(ODR_ENCODE);
221 req->databaseNames[0] = odr_strdup(odr, sep+1);
223 search_package.request() = yazpp_1::GDU(apdu);
227 search_package.move();
229 package.response() = search_package.response();
232 void yf::Virt_db::Rep::init(Package &package, Z_APDU *apdu, bool &move_later)
234 boost::mutex::scoped_lock lock(m_sessions_mutex);
235 std::list<Virt_db_session>::iterator it;
237 for (it = m_sessions.begin(); it != m_sessions.end(); it++)
239 if (package.session() == (*it).m_session)
242 if (it != m_sessions.end())
243 m_sessions.erase(it);
245 Z_InitRequest *req = apdu->u.initRequest;
248 yaz_oi_get_string_oidval(&req->otherInfo, VAL_PROXY, 1, 0);
251 ODR odr = odr_createmem(ODR_ENCODE);
253 Z_APDU *apdu = zget_APDU(odr, Z_APDU_initResponse);
254 Z_InitResponse *resp = apdu->u.initResponse;
257 static const int masks[] = {
258 Z_Options_search, Z_Options_present, 0
260 for (i = 0; masks[i]; i++)
261 if (ODR_MASK_GET(req->options, masks[i]))
262 ODR_MASK_SET(resp->options, masks[i]);
264 package.response() = apdu;
268 m_sessions.push_back(Virt_db_session(package.session(), false));
272 m_sessions.push_back(Virt_db_session(package.session(), true));
277 void yf::Virt_db::add_map_db2vhost(std::string db, std::string vhost)
279 m_p->m_maps[db] = Virt_db_map(vhost);
282 void yf::Virt_db::process(Package &package) const
284 Z_GDU *gdu = package.request().get();
286 if (!gdu || gdu->which != Z_GDU_Z3950)
290 bool move_later = false;
291 Z_APDU *apdu = gdu->u.z3950;
292 if (apdu->which == Z_APDU_initRequest)
294 m_p->init(package, apdu, move_later);
296 else if (apdu->which == Z_APDU_searchRequest)
298 m_p->search(package, apdu, move_later);
302 ODR odr = odr_createmem(ODR_ENCODE);
304 Z_APDU *apdu = zget_APDU(odr, Z_APDU_close);
306 *apdu->u.close->closeReason = Z_Close_protocolError;
308 package.response() = apdu;
309 package.session().close();
315 m_p->release_session(package);
322 * indent-tabs-mode: nil
323 * c-file-style: "stroustrup"
325 * vim: shiftwidth=4 tabstop=8 expandtab