1 /* $Id: filter_session_shared.cpp,v 1.8 2006-05-15 10:34:40 adam Exp $
2 Copyright (c) 2005-2006, Index Data.
10 #include "package.hpp"
12 #include <boost/thread/mutex.hpp>
13 #include <boost/thread/condition.hpp>
14 #include <boost/shared_ptr.hpp>
17 #include "filter_session_shared.hpp"
21 #include <yaz/otherinfo.h>
22 #include <yaz/diagbib1.h>
27 namespace mp = metaproxy_1;
28 namespace yf = mp::filter;
30 namespace metaproxy_1 {
33 int memcmp2(const void *buf1, int len1, const void *buf2, int len2);
35 class SessionShared::InitKey {
37 bool operator < (const SessionShared::InitKey &k) const;
38 InitKey(Z_InitRequest *req);
40 char *m_idAuthentication_buf;
41 int m_idAuthentication_size;
42 char *m_otherInfo_buf;
46 std::list<std::string> m_targets;
48 class SessionShared::BackendClass {
49 yazpp_1::GDU m_init_response;
51 struct SessionShared::Frontend {
52 void init(Package &package, Z_GDU *gdu);
55 mp::Session m_session;
59 void close(Package &package);
62 class SessionShared::Rep {
63 friend class SessionShared;
64 friend struct Frontend;
66 FrontendPtr get_frontend(Package &package);
67 void release_frontend(Package &package);
70 boost::condition m_cond_session_ready;
71 std::map<mp::Session, FrontendPtr> m_clients;
73 typedef std::map<InitKey,BackendClass> BackendClassMap;
74 BackendClassMap m_backend_map;
79 int yf::memcmp2(const void *buf1, int len1,
80 const void *buf2, int len2)
84 // compare buffer (common length)
85 int c = memcmp(buf1, buf2, d > 0 ? len2 : len1);
91 // compare (remaining bytes)
99 yf::SessionShared::InitKey::InitKey(Z_InitRequest *req)
101 Z_IdAuthentication *t = req->idAuthentication;
103 z_IdAuthentication(m_odr, &t, 1, 0);
104 m_idAuthentication_buf =
105 odr_getbuf(m_odr, &m_idAuthentication_size, 0);
107 Z_OtherInformation *o = req->otherInfo;
108 z_OtherInformation(m_odr, &o, 1, 0);
109 m_otherInfo_buf = odr_getbuf(m_odr, &m_otherInfo_size, 0);
112 bool yf::SessionShared::InitKey::operator < (const SessionShared::InitKey &k)
116 c = memcmp2((void*) m_idAuthentication_buf, m_idAuthentication_size,
117 (void*) k.m_idAuthentication_buf, k.m_idAuthentication_size);
123 c = memcmp2((void*) m_otherInfo_buf, m_otherInfo_size,
124 (void*) k.m_otherInfo_buf, k.m_otherInfo_size);
132 void yf::SessionShared::Frontend::init(Package &package, Z_GDU *gdu)
134 Z_InitRequest *req = gdu->u.z3950->u.initRequest;
136 std::list<std::string> targets;
138 mp::util::get_vhost_otherinfo(&req->otherInfo, false, targets);
140 if (targets.size() < 1)
148 yf::SessionShared::SessionShared() : m_p(new SessionShared::Rep)
152 yf::SessionShared::~SessionShared() {
156 yf::SessionShared::Frontend::Frontend(Rep *rep) : m_is_virtual(false), m_p(rep)
160 void yf::SessionShared::Frontend::close(Package &package)
163 std::list<BackendPtr>::const_iterator b_it;
165 for (b_it = m_backend_list.begin(); b_it != m_backend_list.end(); b_it++)
167 (*b_it)->m_backend_session.close();
168 Package close_package((*b_it)->m_backend_session, package.origin());
169 close_package.copy_filter(package);
170 close_package.move((*b_it)->m_route);
172 m_backend_list.clear();
177 yf::SessionShared::Frontend::~Frontend()
181 yf::SessionShared::FrontendPtr yf::SessionShared::Rep::get_frontend(Package &package)
183 boost::mutex::scoped_lock lock(m_mutex);
185 std::map<mp::Session,yf::SessionShared::FrontendPtr>::iterator it;
189 it = m_clients.find(package.session());
190 if (it == m_clients.end())
193 if (!it->second->m_in_use)
195 it->second->m_in_use = true;
198 m_cond_session_ready.wait(lock);
200 FrontendPtr f(new Frontend(this));
201 m_clients[package.session()] = f;
206 void yf::SessionShared::Rep::release_frontend(Package &package)
208 boost::mutex::scoped_lock lock(m_mutex);
209 std::map<mp::Session,yf::SessionShared::FrontendPtr>::iterator it;
211 it = m_clients.find(package.session());
212 if (it != m_clients.end())
214 if (package.session().is_closed())
216 it->second->close(package);
221 it->second->m_in_use = false;
223 m_cond_session_ready.notify_all();
228 void yf::SessionShared::process(Package &package) const
230 FrontendPtr f = m_p->get_frontend(package);
232 Z_GDU *gdu = package.request().get();
234 if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
235 Z_APDU_initRequest && !f->m_is_virtual)
237 f->init(package, gdu);
239 else if (!f->m_is_virtual)
241 else if (gdu && gdu->which == Z_GDU_Z3950)
243 Z_APDU *apdu = gdu->u.z3950;
244 if (apdu->which == Z_APDU_initRequest)
248 package.response() = odr.create_close(
250 Z_Close_protocolError,
253 package.session().close();
259 package.response() = odr.create_close(
260 apdu, Z_Close_protocolError,
261 "unsupported APDU in filter_session_shared");
263 package.session().close();
266 m_p->release_frontend(package);
269 static mp::filter::Base* filter_creator()
271 return new mp::filter::SessionShared;
275 struct metaproxy_1_filter_struct metaproxy_1_filter_session_shared = {
285 * indent-tabs-mode: nil
286 * c-file-style: "stroustrup"
288 * vim: shiftwidth=4 tabstop=8 expandtab