#include <boost/thread/mutex.hpp>
+#include <yaz/diagbib1.h>
+#include <yaz/log.h>
#include <yaz/zgdu.h>
// remove max macro if already defined (defined later in <limits>)
unsigned int deads;
unsigned int cost() {
unsigned int c = sessions + packages + deads;
- //std::cout << "stats c:" << c
- // << " s:" << sessions
- // << " p:" << packages
- // << " d:" << deads
- // <<"\n";
return c;
}
};
void yf::LoadBalance::Impl::process(mp::Package &package)
{
-
bool is_closed_front = false;
- bool is_closed_back = false;
-
+
// checking for closed front end packages
if (package.session().is_closed())
{
// target selecting only on Z39.50 init request
if (gdu_req->u.z3950->which == Z_APDU_initRequest)
{
+ yazpp_1::GDU base_req(gdu_req);
+ Z_APDU *apdu = base_req.get()->u.z3950;
+
+ Z_InitRequest *org_init = base_req.get()->u.z3950->u.initRequest;
mp::odr odr_en(ODR_ENCODE);
- Z_InitRequest *org_init = gdu_req->u.z3950->u.initRequest;
- // extracting virtual hosts
std::list<std::string> vhosts;
-
mp::util::remove_vhost_otherinfo(&(org_init->otherInfo), vhosts);
-
- // choosing one target according to load-balancing algorithm
-
- if (vhosts.size())
+ // get lowest of all vhosts.. Remove them if individually if
+ // they turn out to be bad..
+ while (1)
{
std::string target;
+ std::list<std::string>::iterator ivh = vhosts.begin();
+
+ Package init_pkg(package.session(), package.origin());
+ init_pkg.copy_filter(package);
+
unsigned int cost = std::numeric_limits<unsigned int>::max();
- { //locking scope for local databases
+ {
boost::mutex::scoped_lock scoped_lock(m_mutex);
- // load-balancing algorithm goes here
- //target = *vhosts.begin();
- for (std::list<std::string>::const_iterator ivh
- = vhosts.begin();
- ivh != vhosts.end();
- ivh++)
+ for (; ivh != vhosts.end(); )
{
if ((*ivh).size() != 0)
{
unsigned int vhcost
= yf::LoadBalance::Impl::cost(*ivh);
+ yaz_log(YLOG_LOG, "Consider %s cost=%u vhcost=%u",
+ (*ivh).c_str(), cost, vhcost);
if (cost > vhcost)
{
cost = vhcost;
target = *ivh;
+ ivh = vhosts.erase(ivh);
}
+ else
+ ivh++;
}
- }
-
- // updating local database
- add_session(package.session().id(), target);
- yf::LoadBalance::Impl::cost(target);
- add_package(package.session().id());
+ else
+ ivh++;
+ }
}
-
+ if (target.length() == 0)
+ break;
// copying new target into init package
- mp::util::set_vhost_otherinfo(&(org_init->otherInfo),
+
+ yazpp_1::GDU init_gdu(base_req);
+ Z_InitRequest *init_req = init_gdu.get()->u.z3950->u.initRequest;
+
+ mp::util::set_vhost_otherinfo(&(init_req->otherInfo),
odr_en, target, 1);
- package.request() = gdu_req;
+
+ init_pkg.request() = init_gdu;
+
+ // moving all package types
+ init_pkg.move();
+
+ // checking for closed back end packages
+ if (!init_pkg.session().is_closed())
+ {
+ add_session(package.session().id(), target);
+
+ package.response() = init_pkg.response();
+ return;
+ }
}
+ mp::odr odr;
+ package.response() = odr.create_initResponse(
+ apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
+ "load_balance: no available targets");
+ package.session().close();
+ return;
}
// frontend Z39.50 close request is added to statistics and marked
else if (gdu_req->u.z3950->which == Z_APDU_close)
add_package(package.session().id());
}
}
-
+
// moving all package types
package.move();
+ bool is_closed_back = false;
+
// checking for closed back end packages
if (package.session().is_closed())
is_closed_back = true;
}
}
-//void yf::LoadBalance::Impl::clear_dead(unsigned long session_id){
-// std::cout << "clear_dead " << session_id << "\n";
-//};
-
void yf::LoadBalance::Impl::add_package(unsigned long session_id)
{
std::string target = find_session_target(session_id);
< std::numeric_limits<unsigned int>::max())
{
itarg->second.packages += 1;
- // std:.cout << "add_package " << session_id << " " << target
- // << " p:" << itarg->second.packages << "\n";
}
}
}
&& itarg->second.packages > 0)
{
itarg->second.packages -= 1;
- // std:.cout << "remove_package " << session_id << " " << target
- // << " p:" << itarg->second.packages << "\n";
}
}
}
{
TargetStat stat;
stat.sessions = 1;
- stat.packages = 0; // no idea why the defaut constructor TargetStat()
- stat.deads = 0; // is not initializig this correctly to zero ??
+ stat.packages = 0;
+ stat.deads = 0;
m_target_stat.insert(std::make_pair(target, stat));
- // std:.cout << "add_session " << session_id << " " << target
- // << " s:1\n";
}
else if (itarg->second.sessions < std::numeric_limits<unsigned int>::max())
{
itarg->second.sessions += 1;
- // std:.cout << "add_session " << session_id << " " << target
- // << " s:" << itarg->second.sessions << "\n";
}
}
if (itarg->second.sessions > 0)
itarg->second.sessions -= 1;
- // std:.cout << "remove_session " << session_id << " " << target
- // << " s:" << itarg->second.sessions << "\n";
-
- // clearing empty sessions and targets
if (itarg->second.sessions == 0 && itarg->second.deads == 0)
{
m_target_stat.erase(itarg);
if (itarg != m_target_stat.end())
cost = itarg->second.cost();
}
-
- //std::cout << "cost " << target << " c:" << cost << "\n";
return cost;
}
if (itarg != m_target_stat.end())
dead = itarg->second.deads;
}
-
- //std::cout << "dead " << target << " d:" << dead << "\n";
return dead;
}