Began work on virtual database filter
[metaproxy-moved-to-github.git] / src / filter_virt_db.cpp
1 /* $Id: filter_virt_db.cpp,v 1.1 2005-10-24 14:33:30 adam Exp $
2    Copyright (c) 2005, Index Data.
3
4 %LICENSE%
5  */
6
7 #include "config.hpp"
8
9 #include "filter.hpp"
10 #include "router.hpp"
11 #include "package.hpp"
12
13 #include <boost/thread/mutex.hpp>
14
15 #include "filter_virt_db.hpp"
16
17 #include <yaz/zgdu.h>
18 #include <yaz/log.h>
19 #include <yaz/otherinfo.h>
20 #include <yaz/diagbib1.h>
21
22 #include <list>
23 #include <iostream>
24
25 namespace yf = yp2::filter;
26
27 namespace yp2 {
28     namespace filter {
29         struct Virt_db_session {
30             Virt_db_session(yp2::Session &id, bool use_vhost);
31             yp2::Session m_session;
32             bool m_use_vhost;
33         };
34         struct Virt_db_map {
35             Virt_db_map(std::string database, std::string vhost);
36             std::string m_database;
37             std::string m_vhost;
38         };
39         class Virt_db::Rep {
40             friend class Virt_db;
41             
42             void release_session(Package &package);
43             void init(Package &package, Z_APDU *apdu);
44             void search(Package &package, Z_APDU *apdu);
45         private:
46             std::list<Virt_db_session>m_sessions;
47             std::list<Virt_db_map>m_maps;
48         };
49     }
50 }
51
52 yf::Virt_db_map::Virt_db_map(std::string database, std::string vhost)
53     : m_database(database), m_vhost(vhost) 
54 {
55 }
56
57 yf::Virt_db_session::Virt_db_session(yp2::Session &id,
58                                      bool use_vhost) :
59     m_session(id) , m_use_vhost(use_vhost)
60 {
61
62 }
63
64 yf::Virt_db::Virt_db() {
65     m_p = new Virt_db::Rep;
66 }
67
68 yf::Virt_db::~Virt_db() {
69     delete m_p;
70 }
71
72 void yf::Virt_db::Rep::release_session(Package &package)
73 {
74     
75 }
76
77 void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu)
78 {
79     Z_SearchRequest *req = apdu->u.searchRequest;
80
81     std::list<Virt_db_session>::iterator it;
82     for (it = m_sessions.begin(); it != m_sessions.end(); it++)
83     {
84         if (package.session() == (*it).m_session)
85             break;
86     }
87     if (it == m_sessions.end())
88         return;
89     if ((*it).m_use_vhost)
90         package.move();
91     else
92     {
93         if (req->num_databaseNames != 1)
94         {
95             ODR odr = odr_createmem(ODR_ENCODE);
96             Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
97             
98             Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
99             apdu->u.searchResponse->records = rec;
100             rec->which = Z_Records_NSD;
101             rec->u.nonSurrogateDiagnostic =
102                 zget_DefaultDiagFormat(
103                     odr, YAZ_BIB1_TOO_MANY_DATABASES_SPECIFIED, 0);
104             package.response() = apdu;
105             
106             odr_destroy(odr);
107         }
108         const char *database = req->databaseNames[0];
109     }
110 }
111
112 void yf::Virt_db::Rep::init(Package &package, Z_APDU *apdu)
113 {
114     std::list<Virt_db_session>::iterator it;
115
116     for (it = m_sessions.begin(); it != m_sessions.end(); it++)
117     {
118         if (package.session() == (*it).m_session)
119             break;
120     }
121     if (it != m_sessions.end())
122         m_sessions.erase(it);
123
124     Z_InitRequest *req = apdu->u.initRequest;
125     
126     const char *vhost =
127         yaz_oi_get_string_oidval(&req->otherInfo, VAL_PROXY, 1, 0);
128     if (!vhost)
129     {
130         ODR odr = odr_createmem(ODR_ENCODE);
131         
132         Z_APDU *apdu = zget_APDU(odr, Z_APDU_initResponse);
133         Z_InitResponse *resp = apdu->u.initResponse;
134         
135         int i;
136         static const int masks[] = {
137             Z_Options_search, Z_Options_present, 0 
138         };
139         for (i = 0; masks[i]; i++)
140             if (ODR_MASK_GET(req->options, masks[i]))
141                 ODR_MASK_SET(resp->options, masks[i]);
142         
143         package.response() = apdu;
144         
145         odr_destroy(odr);
146
147         m_sessions.push_back(Virt_db_session(package.session(), false));
148     }
149     else
150     {
151         m_sessions.push_back(Virt_db_session(package.session(), true));
152         package.move();
153     }
154 }
155
156 void yf::Virt_db::add_map_db2vhost(std::string db, std::string vhost)
157 {
158     m_p->m_maps.push_back(Virt_db_map(db, vhost));
159 }
160
161 void yf::Virt_db::process(Package &package) const
162 {
163     Z_GDU *gdu = package.request().get();
164
165     if (!gdu || gdu->which != Z_GDU_Z3950)
166         package.move();
167     else
168     {
169         Z_APDU *apdu = gdu->u.z3950;
170         if (apdu->which == Z_APDU_initRequest)
171         {
172             m_p->init(package, apdu);
173         }
174         else if (apdu->which == Z_APDU_searchRequest)
175         {
176             m_p->search(package, apdu);
177         }
178         else
179         {
180             ODR odr = odr_createmem(ODR_ENCODE);
181             
182             Z_APDU *apdu = zget_APDU(odr, Z_APDU_close);
183             
184             *apdu->u.close->closeReason = Z_Close_protocolError;
185             
186             package.response() = apdu;
187             package.session().close();
188             odr_destroy(odr);
189         }
190     }
191     m_p->release_session(package);
192 }
193
194
195 /*
196  * Local variables:
197  * c-basic-offset: 4
198  * indent-tabs-mode: nil
199  * c-file-style: "stroustrup"
200  * End:
201  * vim: shiftwidth=4 tabstop=8 expandtab
202  */