added first shot on load balance filter which removes all but one vhost from Z39...
[metaproxy-moved-to-github.git] / src / filter_load_balance.cpp
1 /* $Id: filter_load_balance.cpp,v 1.1 2007-01-02 15:35:36 marc Exp $
2    Copyright (c) 2005-2006, Index Data.
3
4    See the LICENSE file for details
5  */
6
7 #include "config.hpp"
8 #include "filter.hpp"
9 #include "filter_load_balance.hpp"
10 #include "package.hpp"
11 #include "util.hpp"
12
13 #include <boost/thread/mutex.hpp>
14 #include <boost/date_time/posix_time/posix_time.hpp>
15
16 #include <yaz/zgdu.h>
17
18 #include <iostream>
19
20 namespace mp = metaproxy_1;
21 namespace yf = mp::filter;
22
23 namespace metaproxy_1 {
24     namespace filter {
25         class LoadBalance::Impl {
26         public:
27             Impl();
28             ~Impl();
29             void process(metaproxy_1::Package & package);
30             void configure(const xmlNode * ptr);
31         private:
32             boost::mutex m_mutex;
33         };
34     }
35 }
36
37 // define Pimpl wrapper forwarding to Impl
38  
39 yf::LoadBalance::LoadBalance() : m_p(new Impl)
40 {
41 }
42
43 yf::LoadBalance::~LoadBalance()
44 {  // must have a destructor because of boost::scoped_ptr
45 }
46
47 void yf::LoadBalance::configure(const xmlNode *xmlnode)
48 {
49     m_p->configure(xmlnode);
50 }
51
52 void yf::LoadBalance::process(mp::Package &package) const
53 {
54     m_p->process(package);
55 }
56
57
58 // define Implementation stuff
59
60
61
62 yf::LoadBalance::Impl::Impl()
63 {
64 }
65
66 yf::LoadBalance::Impl::~Impl()
67
68 }
69
70 void yf::LoadBalance::Impl::configure(const xmlNode *xmlnode)
71 {
72 }
73
74 void yf::LoadBalance::Impl::process(mp::Package &package)
75 {
76     Z_GDU *gdu_req = package.request().get();
77
78
79     // passing anything but z3950 packages
80     if (!gdu_req 
81         || !(gdu_req->which == Z_GDU_Z3950))
82     {
83         package.move();
84         return;
85     }
86
87
88     // target selecting only on Z39.50 init request
89     if (gdu_req->u.z3950->which == Z_APDU_initRequest){
90
91         mp::odr odr_en(ODR_ENCODE);
92         Z_InitRequest *org_init = gdu_req->u.z3950->u.initRequest;
93
94         // extracting virtual hosts
95         std::list<std::string> vhosts;
96
97         mp::util::remove_vhost_otherinfo(&(org_init->otherInfo), vhosts);
98
99         //std::cout << "LoadBalance::Impl::process() vhosts: " 
100         //          << vhosts.size()  << "\n";
101         //std::cout << "LoadBalance::Impl::process()" << *gdu_req << "\n";
102         
103         // choosing one target according to load-balancing algorithm  
104         
105         if (vhosts.size()){
106             std::string target;
107             
108             // getting timestamp for receiving of package
109             boost::posix_time::ptime receive_time
110                 = boost::posix_time::microsec_clock::local_time();
111             
112             // //<< receive_time << " "
113             // //<< to_iso_string(receive_time) << " "
114             //<< to_iso_extended_string(receive_time) << " "
115             // package.session().id();
116             
117             { // scope for locking local target database  
118                 boost::mutex::scoped_lock scoped_lock(m_mutex);
119                 target = *vhosts.begin();
120             }
121             
122             
123             // copying new target into init package
124             mp::util::set_vhost_otherinfo(&(org_init->otherInfo), odr_en, target); 
125             package.request() = gdu_req;
126         }
127         
128     }
129     
130         
131     // moving all Z39.50 package typess 
132     package.move();
133         
134
135
136     //boost::posix_time::ptime send_time
137     //    = boost::posix_time::microsec_clock::local_time();
138
139     //boost::posix_time::time_duration duration = send_time - receive_time;
140
141
142     //    { // scope for locking local target database  
143     //        boost::mutex::scoped_lock scoped_lock(m_mutex);
144     //        target = *vhosts.begin();
145     //    }
146
147
148 }
149
150
151 static mp::filter::Base* filter_creator()
152 {
153     return new mp::filter::LoadBalance;
154 }
155
156 extern "C" {
157     struct metaproxy_1_filter_struct metaproxy_1_filter_load_balance = {
158         0,
159         "load_balance",
160         filter_creator
161     };
162 }
163
164
165 /*
166  * Local variables:
167  * c-basic-offset: 4
168  * indent-tabs-mode: nil
169  * c-file-style: "stroustrup"
170  * End:
171  * vim: shiftwidth=4 tabstop=8 expandtab
172  */