crossroads

Git mirror of https://crossroads.e-tunity.com/
git clone git://git.finwo.net/app/crossroads
Log | Files | Refs | LICENSE

commit 43053c5d479561e3ebab14caa88bdbbb460ed0a6
parent 3651f75185e9babc65a5e61ad297e2d34c2ae8d4
Author: finwo <finwo@pm.me>
Date:   Sat,  3 Jan 2026 19:35:05 +0100

2.05

Diffstat:
MChangeLog | 5+++++
MMakefile | 15++++++++-------
Mtest/xr-test | 2+-
Axr/Checkers/checkupthread/checkupthread | 14++++++++++++++
Rxr/checkupthread/execute.cc -> xr/Checkers/checkupthread/execute.cc | 0
Rxr/wakeupthread/execute.cc -> xr/Checkers/wakeupthread/execute.cc | 0
Axr/Checkers/wakeupthread/wakeupthread | 14++++++++++++++
Axr/DispatchAlgorithms/algorithm/algorithm | 12++++++++++++
Rxr/algorithm/algorithm.cc -> xr/DispatchAlgorithms/algorithm/algorithm.cc | 0
Axr/DispatchAlgorithms/external/external | 15+++++++++++++++
Axr/DispatchAlgorithms/external/target.cc | 34++++++++++++++++++++++++++++++++++
Axr/DispatchAlgorithms/firstactive/firstactive | 14++++++++++++++
Axr/DispatchAlgorithms/firstactive/target.cc | 9+++++++++
Axr/DispatchAlgorithms/hashedip/hashedip | 16++++++++++++++++
Axr/DispatchAlgorithms/hashedip/target.cc | 40++++++++++++++++++++++++++++++++++++++++
Axr/DispatchAlgorithms/leastconn/leastconn | 14++++++++++++++
Axr/DispatchAlgorithms/leastconn/target.cc | 23+++++++++++++++++++++++
Axr/DispatchAlgorithms/roundrobin/roundrobin | 14++++++++++++++
Axr/DispatchAlgorithms/roundrobin/target.cc | 27+++++++++++++++++++++++++++
Axr/DispatchAlgorithms/storedip/storedip | 16++++++++++++++++
Axr/DispatchAlgorithms/storedip/target.cc | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mxr/Makefile | 16++++++++--------
Dxr/algorithm/algorithm | 12------------
Mxr/backend/connect.cc | 15+++++++++------
Mxr/backenddef/backenddef1.cc | 8++++----
Mxr/balancer/balancer | 20+++++++++++---------
Mxr/balancer/serve.cc | 12+++++++-----
Mxr/buffer/add.cc | 2+-
Mxr/buffer/copy.cc | 2+-
Mxr/buffer/insertat2.cc | 2+-
Mxr/buffer/set.cc | 2+-
Dxr/checkupthread/checkupthread | 14--------------
Mxr/config/addallow.cc | 2+-
Mxr/config/adddeny.cc | 2+-
Mxr/config/parsecmdline.cc | 27++++++++++++++++-----------
Mxr/config/setbackend.cc | 4++--
Mxr/config/setdispatcmode.cc | 4++--
Mxr/config/setinteger.cc | 4++--
Mxr/config/setserver.cc | 3++-
Mxr/error/error | 2+-
Dxr/error/txt.cc | 10----------
Axr/error/what.cc | 10++++++++++
Mxr/etc/Makefile.class | 9++++++---
Dxr/external/external | 15---------------
Dxr/external/target.cc | 33---------------------------------
Mxr/fdset/readable.cc | 7++++---
Mxr/fdset/readwriteable.cc | 8++++----
Mxr/fdset/writeable.cc | 7++++---
Dxr/firstactive/firstactive | 14--------------
Dxr/firstactive/target.cc | 9---------
Dxr/hashedip/hashedip | 16----------------
Dxr/hashedip/target.cc | 40----------------------------------------
Mxr/httpdispatcher/dispatch.cc | 2+-
Dxr/leastconn/leastconn | 14--------------
Dxr/leastconn/target.cc | 23-----------------------
Dxr/roundrobin/roundrobin | 14--------------
Dxr/roundrobin/target.cc | 26--------------------------
Mxr/servertype/type1.cc | 4++--
Dxr/stopthread/execute.cc | 29-----------------------------
Dxr/stopthread/stopthread | 13-------------
Dxr/storedip/storedip | 16----------------
Dxr/storedip/target.cc | 84-------------------------------------------------------------------------------
Mxr/sys/main.cc | 18++++++------------
Mxr/sys/serversocket.cc | 21++++++++++-----------
Mxr/sys/sys | 1+
Mxr/tcpdispatcher/execute.cc | 8++++----
Mxr/tcpdispatcher/readchunk.cc | 2+-
Mxr/tcpdispatcher/tcpdispatcher | 22+++++++++++-----------
Mxr/tcpdispatcher/writechunk.cc | 2+-
Mxr/thread/lock.cc | 12+++++++++---
Mxr/thread/start.cc | 16+++++++++-------
Mxr/thread/thread | 1+
Mxr/thread/thread1.cc | 5+----
Mxr/thread/unlock.cc | 6+++---
Dxr/wakeupthread/wakeupthread | 14--------------
75 files changed, 519 insertions(+), 534 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,8 @@ +2.05 [KK 2008-08-15] +Thrown errors now based on std::exeception. +"xr -V" shows compilation settings. +Code reorganized into directory hierarchy. + 2.04 [KK 2008-08-11] Mutex in Thread class is now a static. Implemented dispatching algorithm "stored clent ip", in the variants diff --git a/Makefile b/Makefile @@ -1,11 +1,12 @@ # Top-level Makefile for XR # ------------------------- -VER = 2.04 +VER = 2.05 BINDIR = /usr/sbin TAR = /tmp/crossroads-$(VER).tar.gz AUTHOR = Karel Kubat <karel@kubat.nl> MAINTAINER = Karel Kubat <karel@kubat.nl> +BASE = $(shell pwd) foo: @echo @@ -21,18 +22,18 @@ local: mkdir -p xr/build xr/etc/gettools /usr/local/bin xr/etc c-conf e-ver xr/etc/e-ver ChangeLog $(VER) - AUTHOR='$(AUTHOR)' MAINTAINER='$(MAINTAINER)' VER='$(VER)'\ - $(MAKE) -C xr + BASE=$(BASE) AUTHOR='$(AUTHOR)' MAINTAINER='$(MAINTAINER)' \ + VER='$(VER)' $(MAKE) -C xr install: local mkdir -p $(BINDIR) - AUTHOR='$(AUTHOR)' MAINTAINER='$(MAINTAINER)' \ + BASE=$(BASE) AUTHOR='$(AUTHOR)' MAINTAINER='$(MAINTAINER)' \ VER='$(VER)' BINDIR=$(BINDIR) $(MAKE) -C xr install @echo @echo ' The balancer program xr is now installed to $(BINDIR).' - @echo ' Consider configuring xrctl/xrctl and copying it to $(BINDIR) too.' - @echo ' The helper xrctl is not installed automatically.' - @echo ' Have fun with Crossroads $(VER)!' + @echo ' Consider configuring xrctl/xrctl and copying it to $(BINDIR).' + @echo ' The helper xrctl is not installed automatically!!' + @echo ' Have fun with Crossroads $(VER),' @echo ' -- $(MAINTAINER)' @echo diff --git a/test/xr-test b/test/xr-test @@ -30,7 +30,7 @@ while ($n < $ARGV[1]) { } sleep (0.1); printf ("\rN: %5d Tot:%8.3g Avg:%8.3g", $n, $totaltime, $totaltime / $n) - if (! ($n % 50)); + if (! ($n % 10)); } print ("\n"); diff --git a/xr/Checkers/checkupthread/checkupthread b/xr/Checkers/checkupthread/checkupthread @@ -0,0 +1,14 @@ +#ifndef _CHECKUPTHREAD_ +#define _CHECKUPTHREAD_ + +#include "sys/sys" +#include "thread/thread" +#include "balancer/balancer" +#include "error/error" + +class Checkupthread: public Thread { +public: + void execute(); +}; + +#endif diff --git a/xr/checkupthread/execute.cc b/xr/Checkers/checkupthread/execute.cc diff --git a/xr/wakeupthread/execute.cc b/xr/Checkers/wakeupthread/execute.cc diff --git a/xr/Checkers/wakeupthread/wakeupthread b/xr/Checkers/wakeupthread/wakeupthread @@ -0,0 +1,14 @@ +#ifndef _WAKEUPTHREAD_ +#define _WAKEUPTHREAD_ + +#include "sys/sys" +#include "thread/thread" +#include "balancer/balancer" +#include "error/error" + +class Wakeupthread: public Thread { +public: + void execute(); +}; + +#endif diff --git a/xr/DispatchAlgorithms/algorithm/algorithm b/xr/DispatchAlgorithms/algorithm/algorithm @@ -0,0 +1,12 @@ +#ifndef _ALGORITHM_ +#define _ALGORITHM_ + +#include "thread/thread" + +class Algorithm: public Thread { +public: + virtual ~Algorithm(); + virtual int target(struct in_addr clientip) = 0; +}; + +#endif diff --git a/xr/algorithm/algorithm.cc b/xr/DispatchAlgorithms/algorithm/algorithm.cc diff --git a/xr/DispatchAlgorithms/external/external b/xr/DispatchAlgorithms/external/external @@ -0,0 +1,15 @@ +#ifndef _EXTERNAL_ +#define _EXTERNAL_ + +#include "sys/sys" +#include "error/error" +#include "DispatchAlgorithms/algorithm/algorithm" +#include "balancer/balancer" +#include "config/config" + +class External: public Algorithm { +public: + int target(struct in_addr clientip); +}; + +#endif diff --git a/xr/DispatchAlgorithms/external/target.cc b/xr/DispatchAlgorithms/external/target.cc @@ -0,0 +1,34 @@ +#include "external" + +int External::target(struct in_addr clientip) { + // Prepare command to run + ostringstream o; + o << config.externalalgorithm() << ' ' << balancer.nbackends(); + for (unsigned i = 0; i < balancer.nbackends(); i++) + o << ' ' << balancer.backend(i).description() << ' ' + << balancer.backend(i).availablestr() + << ' ' << balancer.backend(i).connections(); + msg ("External algorithm: invoking '" + o.str() + "'\n"); + + FILE *f; + if (! (f = popen (o.str().c_str(), "r")) ) + throw static_cast<Error>("Cannot start '") + o.str() + "': " + + strerror(errno); + int i; + if (fscanf (f, "%d", &i) < 1) + throw static_cast<Error>("External algorithm '") + o.str() + + "' did not reply with a number"; + + ostringstream n; + n << i; + msg ("External algorithm says: " + n.str() + "\n"); + + if (i < 0 || i >= (int)balancer.nbackends()) + throw static_cast<Error>("External algorithm '") + o.str() + + "': answer " + n.str() + " out of bounds"; + if (pclose (f)) + throw static_cast<Error>("External algorithm '") + o.str() + + "' terminated with error"; + + return (i); +} diff --git a/xr/DispatchAlgorithms/firstactive/firstactive b/xr/DispatchAlgorithms/firstactive/firstactive @@ -0,0 +1,14 @@ +#ifndef _FIRSTACTIVE_ +#define _FIRSTACTIVE_ + +#include "sys/sys" +#include "error/error" +#include "DispatchAlgorithms/algorithm/algorithm" +#include "balancer/balancer" + +class Firstactive: public Algorithm { +public: + int target(struct in_addr clientip); +}; + +#endif diff --git a/xr/DispatchAlgorithms/firstactive/target.cc b/xr/DispatchAlgorithms/firstactive/target.cc @@ -0,0 +1,9 @@ +#include "firstactive" + +int Firstactive::target(struct in_addr clientip) { + for (unsigned i = 0; i < balancer.nbackends(); i++) + if (balancer.backend(i).available()) + return ( (int) i); + throw static_cast<Error>("First-active algorithm: no available back ends"); +} + diff --git a/xr/DispatchAlgorithms/hashedip/hashedip b/xr/DispatchAlgorithms/hashedip/hashedip @@ -0,0 +1,16 @@ +#ifndef _HASHEDIP_ +#define _HASHEDIP_ + +#include "sys/sys" +#include "error/error" +#include "balancer/balancer" +#include "config/config" +#include "DispatchAlgorithms/algorithm/algorithm" +#include "DispatchAlgorithms/leastconn/leastconn" + +class HashedIp: public Algorithm { +public: + int target(struct in_addr clientip); +}; + +#endif diff --git a/xr/DispatchAlgorithms/hashedip/target.cc b/xr/DispatchAlgorithms/hashedip/target.cc @@ -0,0 +1,40 @@ +#include "hashedip" + +int HashedIp::target(struct in_addr clientip) { + // Hash the client's IP into an index + unsigned h = 0; + for (char *cp = (char*)&clientip; + unsigned(cp - (char*)&clientip) < sizeof(struct in_addr); + cp++) { + h += *cp; + h %= balancer.nbackends(); + } + int index = int(h); + + if (config.verbose()) { + ostringstream o; + o << index; + msg ("Client IP " + (string)inet_ntoa(clientip) + " hashes to " + + o.str() + ", back end " + + balancer.backend(index).description() + + "\n"); + } + + // In strict mode, back end must be available, or don't proceed + // In lax mode, fall back to least-connections dispatching + if (! balancer.backend(index).available()) { + if (config.dispatchmode() == Dispatchmode::m_strict_hashed_ip) + throw static_cast<Error>("Hashed-IP algorithm: target back end ") + + balancer.backend(index).description() + " unavailable"; + else { + msg ("Hashed-IP algorithm: target back end " + + balancer.backend(index).description() + " unavailable, " + "falling back to least-connections\n"); + Leastconn l; + index = l.target(clientip); + } + } + + // Got it + return (index); +} diff --git a/xr/DispatchAlgorithms/leastconn/leastconn b/xr/DispatchAlgorithms/leastconn/leastconn @@ -0,0 +1,14 @@ +#ifndef _LEASTCONN_ +#define _LEASTCONN_ + +#include "sys/sys" +#include "error/error" +#include "balancer/balancer" +#include "DispatchAlgorithms/algorithm/algorithm" + +class Leastconn: public Algorithm { +public: + int target(struct in_addr clientip); +}; + +#endif diff --git a/xr/DispatchAlgorithms/leastconn/target.cc b/xr/DispatchAlgorithms/leastconn/target.cc @@ -0,0 +1,23 @@ +#include "leastconn" + +int Leastconn::target(struct in_addr clientip) { + bool found = false; + unsigned nconn; + int t; + + for (unsigned i = 0; i < balancer.nbackends(); i++) { + if (!balancer.backend(i).available()) + continue; + if (!found || + balancer.backend(i).connections() < nconn) { + nconn = balancer.backend(i).connections(); + t = i; + found = true; + } + } + + if (!found) + throw static_cast<Error> + ("Least-connections algorithm: no available back ends"); + return (t); +} diff --git a/xr/DispatchAlgorithms/roundrobin/roundrobin b/xr/DispatchAlgorithms/roundrobin/roundrobin @@ -0,0 +1,14 @@ +#ifndef _ROUNDROBIN_ +#define _ROUNDROBIN_ + +#include "sys/sys" +#include "error/error" +#include "balancer/balancer" +#include "DispatchAlgorithms/algorithm/algorithm" + +class Roundrobin: public Algorithm { +public: + int target(struct in_addr clientip); +}; + +#endif diff --git a/xr/DispatchAlgorithms/roundrobin/target.cc b/xr/DispatchAlgorithms/roundrobin/target.cc @@ -0,0 +1,27 @@ +#include "roundrobin" + +int Roundrobin::target(struct in_addr clientip) { + static int last = -1; + int t = last + 1; + + if (last == -1) { + lock(); + last = 0; + unlock(); + } + + while (1) { + if (balancer.backend(t).available()) { + lock(); + last = t; + unlock(); + return (t); + } + t++; + t %= balancer.nbackends(); + if (t == last) + throw static_cast<Error> + ("Round-robin algorithm: no available back ends"); + } +} + diff --git a/xr/DispatchAlgorithms/storedip/storedip b/xr/DispatchAlgorithms/storedip/storedip @@ -0,0 +1,16 @@ +#ifndef _STOREDIP_ +#define _STOREDIP_ + +#include "sys/sys" +#include "error/error" +#include "balancer/balancer" +#include "config/config" +#include "DispatchAlgorithms/algorithm/algorithm" +#include "DispatchAlgorithms/leastconn/leastconn" + +class StoredIp: public Algorithm { +public: + int target(struct in_addr clientip); +}; + +#endif diff --git a/xr/DispatchAlgorithms/storedip/target.cc b/xr/DispatchAlgorithms/storedip/target.cc @@ -0,0 +1,85 @@ +#include "storedip" + +struct ClientData { + int targetbackend; + time_t lastaccess; +}; + +struct ClientDataCmp { + bool operator() (struct in_addr a, struct in_addr b) const { + long la = *((long*)&a); + long lb = *((long*)&b); + return (la - lb) < 0; + } +}; + +static map<struct in_addr, ClientData, ClientDataCmp> store; + +int StoredIp::target(struct in_addr clientip) { + int target; + time_t now = time(0); + + // Is the client already known in the map, and not timed out? + map<struct in_addr, ClientData, ClientDataCmp>::iterator hit = + store.find(clientip); + if (store.count(clientip) > 0) { + time_t diff = now - store[clientip].lastaccess; + ostringstream o; + o << diff; + msg ("Client IP " + string(inet_ntoa(clientip)) + + " last visited on " + timestamp(store[clientip].lastaccess) + + ", " + o.str() + " sec ago, and went to " + + balancer.backend(store[clientip].targetbackend).description() + + "\n"); + if (diff <= config.ipstoretimeout()) { + // Recent 'nuff + target = store[clientip].targetbackend; + if (! balancer.backend(target).available()) { + // Historical target down - get new one if in lax mode + if (config.dispatchmode() == Dispatchmode::m_strict_stored_ip) + throw static_cast<Error> + ("Stored-IP algorithm: target back end ") + + balancer.backend(target).description() + + "unavailable"; + else { + msg ("Stored IP algorithm: target back end " + + balancer.backend(target).description() + + " unavailable, falling back to least-connections\n"); + Leastconn l; + target = l.target(clientip); + } + } + } else { + // Not recent anymore + msg ("Visit too long ago, re-dispatching with least-connections\n"); + Leastconn l; + target = l.target(clientip); + } + } else { + // Historical target unknown, fetch new one + msg ("New visit from " + (string)inet_ntoa(clientip) + "\n"); + Leastconn l; + target = l.target(clientip); + } + + // Update the info. + ClientData entry = {target, now}; + store[clientip] = entry; + + // Weed out store + map<struct in_addr, ClientData, ClientDataCmp>::iterator + iter = store.begin(); + while (iter != store.end()) { + if (config.debug()) + debugmsg ("Stored-IP: " + + (string)inet_ntoa((*iter).first) + " visited on " + + timestamp((*iter).second.lastaccess) + "\n"); + if (now - ((*iter).second.lastaccess) > config.ipstoretimeout()) + store.erase(iter); + else + iter++; + } + + // Return target to caller + return (target); +} diff --git a/xr/Makefile b/xr/Makefile @@ -1,12 +1,13 @@ # Configuration -DIRS = $(shell find . -mindepth 1 -maxdepth 1 -type d) +DIRS = $(shell find . -mindepth 1 -type d | grep -v .svn) BUILDDIR = build BIN = $(BUILDDIR)/xr LIB = $(BUILDDIR)/libxr.a -CC = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache c++-compiler) TMPXR = /tmp/xr-$(shell whoami) - +CONF_CC = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache c++-compiler) +CONF_LIB = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache lib \ + ucb nsl pthread socket m alf) foo: $(MAKE) subdirs $(MAKE) $(BIN) @@ -22,9 +23,10 @@ subdirs: $(BUILDDIR)/usage.h @for f in $(DIRS) ; \ do \ echo "Making: $$f"; \ - CC=$(CC) BUILDDIR=$(BUILDDIR) VER='$(VER)' \ + BASE=$(BASE) CC=$(CONF_CC) BUILDDIR=$(BUILDDIR) VER='$(VER)' \ AUTHOR='$(AUTHOR)' MAINTAINER='$(MAINTAINER)' \ - $(MAKE) -C $$f -f ../etc/Makefile.class \ + CONF_CC='$(CONF_CC)' CONF_LIB='$(CONF_LIB)' \ + $(MAKE) -C $$f -f $(BASE)/xr//etc/Makefile.class \ || exit 1; \ done ar rs $(LIB) */*.o @@ -33,9 +35,7 @@ $(BUILDDIR)/usage.h: etc/usage.txt etc/e-txt2c USAGE <etc/usage.txt >$(BUILDDIR)/usage.h $(BIN): $(BUILDDIR)/libxr.a - $(CC) -g -o $(BIN) -L$(BUILDDIR) -lxr \ - $(shell etc/c-conf -vc $(BUILDDIR)/config.cache lib \ - ucb nsl pthread socket m alf) + $(CONF_CC) -g -o $(BIN) -L$(BUILDDIR) -lxr $(CONF_LIB) clean: rm -f $(BIN) $(LIB) core obj/*.o etc/usage.h $(BUILDDIR)/config.cache diff --git a/xr/algorithm/algorithm b/xr/algorithm/algorithm @@ -1,12 +0,0 @@ -#ifndef _ALGORITHM_ -#define _ALGORITHM_ - -#include "../thread/thread" - -class Algorithm: public Thread { -public: - virtual ~Algorithm(); - virtual int target(struct in_addr clientip) = 0; -}; - -#endif diff --git a/xr/backend/connect.cc b/xr/backend/connect.cc @@ -6,12 +6,14 @@ bool Backend::connect() { // Create client socket if ( (clsocket = socket (PF_INET, SOCK_STREAM, 0)) < 0 ) - throw ((Error)"Failed to create client socket: " + strerror(errno)); + throw static_cast<Error>("Failed to create client socket: ") + + strerror(errno); // Resolve hostname, prepare binding struct hostent *hostaddr; if (! (hostaddr = gethostbyname(bdef.server().c_str())) ) - throw ((Error)"Failed to resolve backend host '" + bdef.server()); + throw static_cast<Error>("Failed to resolve backend host '") + + bdef.server(); struct sockaddr_in backendaddr; backendaddr.sin_family = AF_INET; backendaddr.sin_port = htons(bdef.port()); @@ -22,9 +24,10 @@ bool Backend::connect() { // and enforce a timeout later. int flags; if ( (flags = fcntl (clsocket, F_GETFL, 0)) == -1 ) - throw ((Error) "Failed to get fd flags: " + strerror(errno)); + throw static_cast<Error>("Failed to get fd flags: ") + strerror(errno); if (fcntl (clsocket, F_SETFL, flags | O_NONBLOCK) == -1) - throw ((Error) "Failed to fd in nonblocking mode: " + strerror(errno)); + throw static_cast<Error>("Failed to fd in nonblocking mode: ") + + strerror(errno); // Do the connect int conres = ::connect (clsocket, (struct sockaddr *)&backendaddr, @@ -33,8 +36,8 @@ bool Backend::connect() { // Put socket again in blocking mode. if (fcntl (clsocket, F_SETFL, flags) == -1) - throw ((Error) "Failed to put fd in blocking mode: " + - strerror(errno)); + throw static_cast<Error>("Failed to put fd in blocking mode: ") + + strerror(errno); // Check on the outcome of the connect if (!conres || conerrno == EINPROGRESS) { diff --git a/xr/backenddef/backenddef1.cc b/xr/backenddef/backenddef1.cc @@ -4,10 +4,10 @@ BackendDef::BackendDef (string server, string port, string maxclients) : srv(server), prt(0), max(0) { if (sscanf (port.c_str(), "%d", &prt) < 1) - throw ((Error) "Bad backend port specifier: '" + port + - "' is not a number"); + throw static_cast<Error>("Bad backend port specifier: '") + port + + "' is not a number"; if (maxclients.size() && sscanf (maxclients.c_str(), "%u", &max) < 1) - throw ((Error) "Bad maximum connections specifier: '" + - maxclients + "' is not a number"); + throw static_cast<Error>("Bad maximum connections specifier: '") + + maxclients + "' is not a number"; } diff --git a/xr/balancer/balancer b/xr/balancer/balancer @@ -1,15 +1,17 @@ #ifndef _BALANCER_ #define _BALANCER_ -#include "../sys/sys" - -#include "../backend/backend" -#include "../backenddef/backenddef" -#include "../config/config" -#include "../wakeupthread/wakeupthread" -#include "../checkupthread/checkupthread" -#include "../fdset/fdset" -#include "../error/error" +#include "sys/sys" + +#include "backend/backend" +#include "backenddef/backenddef" +#include "config/config" +#include "fdset/fdset" +#include "error/error" + +// Check ups of back ends +#include "Checkers/wakeupthread/wakeupthread" +#include "Checkers/checkupthread/checkupthread" using namespace std; diff --git a/xr/balancer/serve.cc b/xr/balancer/serve.cc @@ -21,8 +21,8 @@ void Balancer::serve() { if (config.pidfile() != "") { FILE *f; if (! (f = fopen (config.pidfile().c_str(), "w")) ) - throw ((Error) "Cannot write pid file " + config.pidfile() + - ": " + strerror(errno)); + throw static_cast<Error>("Cannot write pid file ") + + config.pidfile() + ": " + strerror(errno); fprintf (f, "%u\n", getpid()); fclose (f); } @@ -90,7 +90,7 @@ void Balancer::serve() { size = sizeof(clname); if ( (clsock = accept (server_fd, (struct sockaddr *) &clname, (socklen_t*) &size)) < 0 ) - throw ((Error)"Failed to accept network connection"); + throw static_cast<Error>("Failed to accept network connection"); string clientip = inet_ntoa(clname.sin_addr); @@ -167,7 +167,8 @@ void Balancer::serve() { d = new HttpDispatcher (clsock, clname.sin_addr); break; default: - throw ((Error) "Internal error, can't choose dispatcher"); + throw static_cast<Error>("Internal error, " + "can't choose dispatcher"); break; } @@ -195,7 +196,8 @@ void Balancer::serve() { d = new HttpDispatcher (server_fd, dummy); break; default: - throw ((Error) "Internal error, can't choose dispatcher"); + throw static_cast<Error>("Internal error, " + "can't choose dispatcher"); break; } d->execute(); diff --git a/xr/buffer/add.cc b/xr/buffer/add.cc @@ -5,7 +5,7 @@ void Buffer::add (char const *b, unsigned len) { set (b, len); else { if (! (buf_data = (char*)realloc (buf_data, buf_len + len)) ) - throw ((Error) "Memory fault in Buffer::add"); + throw static_cast<Error>("Memory fault in Buffer::add"); memcpy (buf_data + buf_len, b, len); buf_len += len; } diff --git a/xr/buffer/copy.cc b/xr/buffer/copy.cc @@ -6,7 +6,7 @@ void Buffer::copy (Buffer const &other) { buf_len = 0; } else { if (! (buf_data = (char*)malloc (other.buf_len)) ) - throw ((Error) "Memory fault in Buffer::copy"); + throw static_cast<Error>("Memory fault in Buffer::copy"); memcpy (buf_data, other.buf_data, other.buf_len); buf_len = other.buf_len; } diff --git a/xr/buffer/insertat2.cc b/xr/buffer/insertat2.cc @@ -4,7 +4,7 @@ void Buffer::insertat (unsigned index, char const *s, unsigned len) { if (index >= buf_len) return; if (! (buf_data = (char*)realloc (buf_data, buf_len + len)) ) - throw ((Error) "Memory fault in Buffer::insertat"); + throw static_cast<Error>("Memory fault in Buffer::insertat"); memmove (buf_data + index + len, buf_data + index, buf_len - index); diff --git a/xr/buffer/set.cc b/xr/buffer/set.cc @@ -3,7 +3,7 @@ void Buffer::set (char const *b, unsigned len) { destroy(); if (! (buf_data = (char*)malloc (len)) ) - throw ((Error) "Memory fault in Buffer::set"); + throw static_cast<Error>("Memory fault in Buffer::set"); memcpy (buf_data, b, len); buf_len = len; } diff --git a/xr/checkupthread/checkupthread b/xr/checkupthread/checkupthread @@ -1,14 +0,0 @@ -#ifndef _CHECKUPTHREAD_ -#define _CHECKUPTHREAD_ - -#include "../sys/sys" -#include "../thread/thread" -#include "../balancer/balancer" -#include "../error/error" - -class Checkupthread: public Thread { -public: - void execute(); -}; - -#endif diff --git a/xr/config/addallow.cc b/xr/config/addallow.cc @@ -3,6 +3,6 @@ void Config::addallow (string a) { struct in_addr in; if (!inet_aton (a.c_str(), &in)) - throw ((Error) "Bad allow-from specfier '" + a + "'"); + throw static_cast<Error>("Bad allow-from specfier '") + a + "'"; allowlist.push_back (in); } diff --git a/xr/config/adddeny.cc b/xr/config/adddeny.cc @@ -3,6 +3,6 @@ void Config::adddeny (string d) { struct in_addr in; if (!inet_aton (d.c_str(), &in)) - throw ((Error) "Bad deny-from specfier '" + d + "'"); + throw static_cast<Error>("Bad deny-from specfier '") + d + "'"; denylist.push_back (in); } diff --git a/xr/config/parsecmdline.cc b/xr/config/parsecmdline.cc @@ -13,7 +13,8 @@ void Config::parsecmdline (int ac, char **av) { } // Not a single argument? Usage. if (ac == 1) - throw ((Error) "Bad command line '" + cmdline + "'\n" + USAGE); + throw static_cast<Error>("Bad command line '") + + cmdline + "'\n" + USAGE; static struct option longopts[] = { { "allow-from", required_argument, 0, 'a' }, @@ -80,7 +81,7 @@ void Config::parsecmdline (int ac, char **av) { foreground_mode = true; break; case 'h': - throw ((Error) USAGE); + throw static_cast<Error>(USAGE); break; case 'H': addserverheader (optarg); @@ -113,10 +114,13 @@ void Config::parsecmdline (int ac, char **av) { verbose_flag = true; break; case 'V': - cout << "This is XR V" << VER << "\n" - << "Written by: " << AUTHOR << "\n" - << "Maintained by: " << MAINTAINER << "\n" - << "Please report bugs to the maintainer.\n"; + cout << "XR version : " << VER << "\n" + << "Written by : " << AUTHOR << "\n" + << "Maintained by : " << MAINTAINER << "\n" + << "Compiled with :\n" + << "C++ compiler : " << CONF_CC << "\n" + << "Libraries : " << CONF_LIB << "\n" + ; exit (0); case 'w': wakeup = setinteger (optarg); @@ -128,18 +132,19 @@ void Config::parsecmdline (int ac, char **av) { add_x_forwarded_for = true; break; default: - throw ((Error) "Unknown flag, try 'xr -h' for usage"); + throw static_cast<Error>("Unknown flag, try 'xr -h' for usage"); break; } } if (ac != optind) - throw ((Error) "Bad command line '" + cmdline + "'\n" + USAGE); + throw static_cast<Error>("Bad command line '") + cmdline + "'\n" + + USAGE; if (!backend_set) - throw ((Error) - "No backend defined, use '-b...' at least once, " - "or try 'xr -h' for usage"); + throw static_cast<Error> + ("No backend defined, use '-b...' at least once, " + "or try 'xr -h' for usage"); // In tryout mode, stop now. if (tryout) diff --git a/xr/config/setbackend.cc b/xr/config/setbackend.cc @@ -11,8 +11,8 @@ void Config::setbackend (string str) { if (str.length() > 0) parts.push_back (str); if (parts.size() < 2 || parts.size() > 3) - throw((Error) "Bad back end specifier in '-b" + str + - "', expected: SERVER:PORT or SERVER:PORT:MAXCONNECTIONS"); + throw static_cast<Error>("Bad back end specifier in '-b") + str + + "', expected: SERVER:PORT or SERVER:PORT:MAXCONNECTIONS"; if (parts.size() == 2) { BackendDef bd (parts[0], parts[1]); blist.push_back (bd); diff --git a/xr/config/setdispatcmode.cc b/xr/config/setdispatcmode.cc @@ -30,9 +30,9 @@ void Config::setdispatchmode (string s) { dmode.mode (Dispatchmode::m_strict_stored_ip); ipstoretimeout(setinteger(s.substr(14))); } else - throw ((Error) "Bad dispatch mode -d" + s); + throw static_cast<Error>("Bad dispatch mode -d") + s; if (dmode.mode() == Dispatchmode::m_external && external_algorithm.size() < 1) - throw ((Error) "External algorithm handler missing"); + throw static_cast<Error>("External algorithm handler missing"); } diff --git a/xr/config/setinteger.cc b/xr/config/setinteger.cc @@ -3,7 +3,7 @@ int Config::setinteger (string s) const { int ret; if (sscanf (s.c_str(), "%d", &ret) < 1) - throw ((Error) "Bad numeric specifier in '" + s + - ": not a number"); + throw static_cast<Error>("Bad numeric specifier in '") + s + + ": not a number"; return (ret); } diff --git a/xr/config/setserver.cc b/xr/config/setserver.cc @@ -12,7 +12,8 @@ void Config::setserver (string str) { if (str.length() > 0) parts.push_back (str); if (parts.size() != 3) - throw((Error) "Bad server specifier, expected: TYPE:IPADDRESS:PORT"); + throw static_cast<Error> + ("Bad server specifier, expected: TYPE:IPADDRESS:PORT"); // Store type, IP and port styp.type (parts[0]); diff --git a/xr/error/error b/xr/error/error @@ -12,7 +12,7 @@ public: Error &operator+ (Error const &other); Error &operator+ (string const s); Error &operator+ (int i); - string txt() const; + char const *what() const throw (); private: string desc; diff --git a/xr/error/txt.cc b/xr/error/txt.cc @@ -1,10 +0,0 @@ -#include "error" -#include "../config/config" - -string Error::txt() const { - ostringstream o; - if (config.prefixtimestamp()) - o << timestamp() << ' '; - o << pthread_self() << " ERROR: " << desc; - return (o.str()); -} diff --git a/xr/error/what.cc b/xr/error/what.cc @@ -0,0 +1,10 @@ +#include "error" +#include "../config/config" + +char const *Error::what() const throw (){ + ostringstream o; + if (config.prefixtimestamp()) + o << timestamp() << ' '; + o << pthread_self() << " ERROR: " << desc; + return (o.str().c_str()); +} diff --git a/xr/etc/Makefile.class b/xr/etc/Makefile.class @@ -1,9 +1,12 @@ SRC = $(wildcard *.cc) -OBJ = $(patsubst %.cc, ../$(BUILDDIR)/$(DIR)_%.o, $(SRC)) +OBJ = $(patsubst %.cc, $(BASE)/xr/$(BUILDDIR)/$(DIR)_%.o, $(SRC)) DIR = $(shell pwd | sed 's:.*/::') class-compile: $(OBJ) -../$(BUILDDIR)/$(DIR)_%.o: %.cc +$(BASE)/xr/$(BUILDDIR)/$(DIR)_%.o: %.cc $(CC) -DVER='"$(VER)"' -DAUTHOR='"$(AUTHOR)"' \ - -DMAINTAINER='"$(MAINTAINER)"' -c -g -Wall -o $@ $< + -DMAINTAINER='"$(MAINTAINER)"' \ + -DCONF_CC='"$(CONF_CC)"' -DCONF_LIB='"$(CONF_LIB)"' \ + -I$(BASE)/xr \ + -c -g -Wall -o $@ $< diff --git a/xr/external/external b/xr/external/external @@ -1,15 +0,0 @@ -#ifndef _EXTERNAL_ -#define _EXTERNAL_ - -#include "../sys/sys" -#include "../error/error" -#include "../algorithm/algorithm" -#include "../balancer/balancer" -#include "../config/config" - -class External: public Algorithm { -public: - int target(struct in_addr clientip); -}; - -#endif diff --git a/xr/external/target.cc b/xr/external/target.cc @@ -1,33 +0,0 @@ -#include "external" - -int External::target(struct in_addr clientip) { - // Prepare command to run - ostringstream o; - o << config.externalalgorithm() << ' ' << balancer.nbackends(); - for (unsigned i = 0; i < balancer.nbackends(); i++) - o << ' ' << balancer.backend(i).description() << ' ' - << balancer.backend(i).availablestr() - << ' ' << balancer.backend(i).connections(); - msg ("External algorithm: invoking '" + o.str() + "'\n"); - - FILE *f; - if (! (f = popen (o.str().c_str(), "r")) ) - throw ((Error) "Cannot start '" + o.str() + "': " + strerror(errno)); - int i; - if (fscanf (f, "%d", &i) < 1) - throw ((Error) "External algorithm '" + o.str() + "' did not reply " - "with a number"); - - ostringstream n; - n << i; - msg ("External algorithm says: " + n.str() + "\n"); - - if (i < 0 || i >= (int)balancer.nbackends()) - throw ((Error) "External algorithm '" + o.str() + "': answer " + - n.str() + " out of bounds"); - if (pclose (f)) - throw ((Error) "External algorithm '" + o.str() + "' terminated " - "with error"); - - return (i); -} diff --git a/xr/fdset/readable.cc b/xr/fdset/readable.cc @@ -28,8 +28,9 @@ int Fdset::readable() const { // the caller can handle them gracefully. if (select (FD_SETSIZE, &readset, 0, &exceptset, tvp) < 0) { if (errno != EINTR) - throw ((Error) "Select failure: " - "failed to wait for readable state: " + strerror(errno)); + throw static_cast<Error> + ("Select failure: failed to wait for readable state: ") + + strerror(errno); else return (-1); } @@ -37,7 +38,7 @@ int Fdset::readable() const { // Check for exceptions. for (unsigned i = 0; i < set.size(); i++) if (FD_ISSET (set[i], &exceptset)) - throw ((Error) "Exception on fd/socket " + set[i]); + throw static_cast<Error>("Exception on fd/socket ") + set[i]; // Check what's readable. for (unsigned i = 0; i < set.size(); i++) diff --git a/xr/fdset/readwriteable.cc b/xr/fdset/readwriteable.cc @@ -29,9 +29,9 @@ int Fdset::readwriteable() const { // Run the select. if (select (FD_SETSIZE, &readset, &writeset, &exceptset, tvp) < 0) { if (errno != EINTR) - throw ((Error) "Select failure: " - "failed to wait for read/writeablestate: " - + strerror(errno)); + throw static_cast<Error> + ("Select failure: failed to wait for read/writeablestate: ") + + strerror(errno); else return (-1); } @@ -39,7 +39,7 @@ int Fdset::readwriteable() const { // Check for exceptions. for (unsigned i = 0; i < set.size(); i++) if (FD_ISSET (set[i], &exceptset)) - throw ((Error) "Exception on fd/socket " + set[i]); + throw static_cast<Error>("Exception on fd/socket ") + set[i]; // Check what's active. for (unsigned i = 0; i < set.size(); i++) diff --git a/xr/fdset/writeable.cc b/xr/fdset/writeable.cc @@ -27,8 +27,9 @@ int Fdset::writeable() const { // Run the select. if (select (FD_SETSIZE, 0, &writeset, &exceptset, tvp) < 0) { if (errno != EINTR) - throw ((Error) "Select failure: failed to wait for " - "writable state: " + strerror(errno)); + throw static_cast<Error> + ("Select failure: failed to wait for writable state: ") + + strerror(errno); else return (-1); } @@ -36,7 +37,7 @@ int Fdset::writeable() const { // Check for exceptions. for (unsigned i = 0; i < set.size(); i++) if (FD_ISSET (set[i], &exceptset)) - throw ((Error) "Exception on fd/socket " + set[i]); + throw static_cast<Error>("Exception on fd/socket ") + set[i]; // Check what's writeable. for (unsigned i = 0; i < set.size(); i++) diff --git a/xr/firstactive/firstactive b/xr/firstactive/firstactive @@ -1,14 +0,0 @@ -#ifndef _FIRSTACTIVE_ -#define _FIRSTACTIVE_ - -#include "../sys/sys" -#include "../error/error" -#include "../algorithm/algorithm" -#include "../balancer/balancer" - -class Firstactive: public Algorithm { -public: - int target(struct in_addr clientip); -}; - -#endif diff --git a/xr/firstactive/target.cc b/xr/firstactive/target.cc @@ -1,9 +0,0 @@ -#include "firstactive" - -int Firstactive::target(struct in_addr clientip) { - for (unsigned i = 0; i < balancer.nbackends(); i++) - if (balancer.backend(i).available()) - return ( (int) i); - throw ((Error) "First-active algorithm: no available back ends"); -} - diff --git a/xr/hashedip/hashedip b/xr/hashedip/hashedip @@ -1,16 +0,0 @@ -#ifndef _HASHEDIP_ -#define _HASHEDIP_ - -#include "../sys/sys" -#include "../error/error" -#include "../algorithm/algorithm" -#include "../balancer/balancer" -#include "../config/config" -#include "../leastconn/leastconn" - -class HashedIp: public Algorithm { -public: - int target(struct in_addr clientip); -}; - -#endif diff --git a/xr/hashedip/target.cc b/xr/hashedip/target.cc @@ -1,40 +0,0 @@ -#include "hashedip" - -int HashedIp::target(struct in_addr clientip) { - // Hash the client's IP into an index - unsigned h = 0; - for (char *cp = (char*)&clientip; - unsigned(cp - (char*)&clientip) < sizeof(struct in_addr); - cp++) { - h += *cp; - h %= balancer.nbackends(); - } - int index = int(h); - - if (config.verbose()) { - ostringstream o; - o << index; - msg ("Client IP " + (string)inet_ntoa(clientip) + " hashes to " + - o.str() + ", back end " + - balancer.backend(index).description() + - "\n"); - } - - // In strict mode, back end must be available, or don't proceed - // In lax mode, fall back to least-connections dispatching - if (! balancer.backend(index).available()) { - if (config.dispatchmode() == Dispatchmode::m_strict_hashed_ip) - throw ((Error) "Hashed-IP algorithm: target back end " + - balancer.backend(index).description() + " unavailable"); - else { - msg ("Hashed-IP algorithm: target back end " + - balancer.backend(index).description() + " unavailable, " - "falling back to least-connections\n"); - Leastconn l; - index = l.target(clientip); - } - } - - // Got it - return (index); -} diff --git a/xr/httpdispatcher/dispatch.cc b/xr/httpdispatcher/dispatch.cc @@ -5,7 +5,7 @@ void HttpDispatcher::dispatch() { // Get the client's request. May need for cookie inspection. if (!getclientrequest()) - throw ((Error) "Didn't receive a valid client request.\n"); + throw static_cast<Error>("Didn't receive a valid client request.\n"); // Dispatch as a normal backend if sticky HTTP is off, or if the // sticky target is badly specified. diff --git a/xr/leastconn/leastconn b/xr/leastconn/leastconn @@ -1,14 +0,0 @@ -#ifndef _LEASTCONN_ -#define _LEASTCONN_ - -#include "../sys/sys" -#include "../error/error" -#include "../algorithm/algorithm" -#include "../balancer/balancer" - -class Leastconn: public Algorithm { -public: - int target(struct in_addr clientip); -}; - -#endif diff --git a/xr/leastconn/target.cc b/xr/leastconn/target.cc @@ -1,23 +0,0 @@ -#include "leastconn" - -int Leastconn::target(struct in_addr clientip) { - bool found = false; - unsigned nconn; - int t; - - for (unsigned i = 0; i < balancer.nbackends(); i++) { - if (!balancer.backend(i).available()) - continue; - if (!found || - balancer.backend(i).connections() < nconn) { - nconn = balancer.backend(i).connections(); - t = i; - found = true; - } - } - - if (!found) - throw ((Error) "Least-connections algorithm: " - "no available back ends"); - return (t); -} diff --git a/xr/roundrobin/roundrobin b/xr/roundrobin/roundrobin @@ -1,14 +0,0 @@ -#ifndef _ROUNDROBIN_ -#define _ROUNDROBIN_ - -#include "../sys/sys" -#include "../error/error" -#include "../algorithm/algorithm" -#include "../balancer/balancer" - -class Roundrobin: public Algorithm { -public: - int target(struct in_addr clientip); -}; - -#endif diff --git a/xr/roundrobin/target.cc b/xr/roundrobin/target.cc @@ -1,26 +0,0 @@ -#include "roundrobin" - -int Roundrobin::target(struct in_addr clientip) { - static int last = -1; - int t = last + 1; - - if (last == -1) { - lock(); - last = 0; - unlock(); - } - - while (1) { - if (balancer.backend(t).available()) { - lock(); - last = t; - unlock(); - return (t); - } - t++; - t %= balancer.nbackends(); - if (t == last) - throw ((Error) "Round-robin algorithm: no available back ends"); - } -} - diff --git a/xr/servertype/type1.cc b/xr/servertype/type1.cc @@ -6,6 +6,6 @@ void Servertype::type (string id) { else if (id == "http") t = t_http; else - throw ((Error) "Bad server type '" + id + - "', supported are 'tcp' or 'http'"); + throw static_cast<Error>("Bad server type '") + id + + "', supported are 'tcp' or 'http'"; } diff --git a/xr/stopthread/execute.cc b/xr/stopthread/execute.cc @@ -1,29 +0,0 @@ -#include "stopthread" - -void Stopthread::execute() { - static int stopping; - int loc_stopping; - - if ( (loc_stopping = stopping) ) { - msg ("XR is waiting to shut down.\n"); - return; - } - - lock(); - stopping++; - unlock(); - msg ("XR will shut down.\n"); - - while (1) { - if (balancer.connections()) { - ostringstream o; - o << balancer.connections(); - msg ("There are still " + o.str() + " connections, " - "XR will stop when they do.\n"); - sleep (1); - continue; - } - msg ("No active connections, terminating XR.\n"); - exit (0); - } -} diff --git a/xr/stopthread/stopthread b/xr/stopthread/stopthread @@ -1,13 +0,0 @@ -#ifndef _STOPTHREAD_ -#define _STOPTHREAD_ - -#include "../sys/sys" -#include "../thread/thread" -#include "../balancer/balancer" - -class Stopthread: public Thread { -public: - void execute(); -}; - -#endif diff --git a/xr/storedip/storedip b/xr/storedip/storedip @@ -1,16 +0,0 @@ -#ifndef _STOREDIP_ -#define _STOREDIP_ - -#include "../sys/sys" -#include "../error/error" -#include "../algorithm/algorithm" -#include "../balancer/balancer" -#include "../config/config" -#include "../leastconn/leastconn" - -class StoredIp: public Algorithm { -public: - int target(struct in_addr clientip); -}; - -#endif diff --git a/xr/storedip/target.cc b/xr/storedip/target.cc @@ -1,84 +0,0 @@ -#include "storedip" - -struct ClientData { - int targetbackend; - time_t lastaccess; -}; - -struct ClientDataCmp { - bool operator() (struct in_addr a, struct in_addr b) const { - long la = *((long*)&a); - long lb = *((long*)&b); - return (la - lb) < 0; - } -}; - -static map<struct in_addr, ClientData, ClientDataCmp> store; - -int StoredIp::target(struct in_addr clientip) { - int target; - time_t now = time(0); - - // Is the client already known in the map, and not timed out? - map<struct in_addr, ClientData, ClientDataCmp>::iterator hit = - store.find(clientip); - if (store.count(clientip) > 0) { - time_t diff = now - store[clientip].lastaccess; - ostringstream o; - o << diff; - msg ("Client IP " + string(inet_ntoa(clientip)) + - " last visited on " + timestamp(store[clientip].lastaccess) + - ", " + o.str() + " sec ago, and went to " + - balancer.backend(store[clientip].targetbackend).description() + - "\n"); - if (diff <= config.ipstoretimeout()) { - // Recent 'nuff - target = store[clientip].targetbackend; - if (! balancer.backend(target).available()) { - // Historical target down - get new one if in lax mode - if (config.dispatchmode() == Dispatchmode::m_strict_stored_ip) - throw ((Error) "Stored-IP algorithm: target back end " + - balancer.backend(target).description() + - "unavailable"); - else { - msg ("Stored IP algorithm: target back end " + - balancer.backend(target).description() + - " unavailable, falling back to least-connections\n"); - Leastconn l; - target = l.target(clientip); - } - } - } else { - // Not recent anymore - msg ("Visit too long ago, re-dispatching with least-connections\n"); - Leastconn l; - target = l.target(clientip); - } - } else { - // Historical target unknown, fetch new one - msg ("New visit from " + (string)inet_ntoa(clientip) + "\n"); - Leastconn l; - target = l.target(clientip); - } - - // Update the info. - ClientData entry = {target, now}; - store[clientip] = entry; - - // Weed out store - map<struct in_addr, ClientData, ClientDataCmp>::iterator - iter = store.begin(); - while (iter != store.end()) { - if (config.debug()) - debugmsg ("Stored-IP: " + - (string)inet_ntoa((*iter).first) + " visited on " + - timestamp((*iter).second.lastaccess) + "\n"); - if (now - ((*iter).second.lastaccess) > config.ipstoretimeout()) - store.erase(iter); - else - iter++; - } - - // Return target to caller - return (target); -} diff --git a/xr/sys/main.cc b/xr/sys/main.cc @@ -1,9 +1,8 @@ -#include "../sys/sys" -#include "../config/config" -#include "../balancer/balancer" -#include "../error/error" -#include "../stopthread/stopthread" +#include "sys/sys" +#include "config/config" +#include "balancer/balancer" +#include "error/error" using namespace std; @@ -17,11 +16,6 @@ static void sigcatcher (int sig) { balancer.terminate(true); } -static void out_of_memory() { - cerr << "ERROR: Out of memory\n"; - exit (1); -} - int main (int argc, char **argv) { static int relevant_sig[] = { SIGHUP, SIGINT, SIGQUIT, SIGABRT, SIGTERM, SIGSTOP, SIGPIPE @@ -42,8 +36,8 @@ int main (int argc, char **argv) { // Configure the balancer and start serving. balancer.init(); balancer.serve(); - } catch (Error e) { - cerr << e.txt() << endl; + } catch (Error const &e) { + cerr << e.what() << endl; return (1); } catch (...) { cerr << "ERROR: Unidentified exception caught" << endl; diff --git a/xr/sys/serversocket.cc b/xr/sys/serversocket.cc @@ -6,12 +6,12 @@ int serversocket (string addr, int port, string desc) { // Create the server socket, set options if ( (sock = socket (PF_INET, SOCK_STREAM, 0)) < 0 ) - throw ((Error) "Failed to create " + desc + " socket: " + - strerror(errno)); + throw static_cast<Error>("Failed to create ") + desc + " socket: " + + strerror(errno); int val = 1; if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) - throw ((Error) "Failed to set socket options for " + desc + ": " + - strerror(errno)); + throw static_cast<Error>("Failed to set socket options for ") + + desc + ": " + strerror(errno); // Prepare binding struct sockaddr_in saddr; @@ -24,8 +24,8 @@ int serversocket (string addr, int port, string desc) { if (addr[0] != '0') { msg ("Binding balancer to specific IP address " + addr + "\n"); if ( (saddr.sin_addr.s_addr = inet_addr (addr.c_str())) == INADDR_NONE ) - throw ((Error) "Cannot convert " + desc + " IP '" + addr + - "' to network bytes"); + throw static_cast<Error>("Cannot convert ") + desc + " IP '" + + addr + "' to network bytes"; display_ip << addr; } else { saddr.sin_addr.s_addr = htonl (INADDR_ANY); @@ -35,14 +35,13 @@ int serversocket (string addr, int port, string desc) { // Bind and listen if (bind (sock, (sockaddr*) &saddr, sizeof(saddr)) < 0) - throw ((Error) "Failed to bind " + desc + " to " + display_ip.str() + - ": " + strerror(errno)); + throw static_cast<Error>("Failed to bind ") + desc + " to " + + display_ip.str() + ": " + strerror(errno); if (listen (sock, 5) < 0) - throw ((Error) "Failed to listen to " + desc + " IP " + - display_ip.str() + ": " + strerror(errno)); + throw static_cast<Error>("Failed to listen to ") + desc + " IP " + + display_ip.str() + ": " + strerror(errno); msg ("TCP server for " + desc + " listening to " + display_ip.str() + "\n"); return (sock); } - diff --git a/xr/sys/sys b/xr/sys/sys @@ -24,6 +24,7 @@ #include <sys/types.h> // C++ +#include <exception> #include <iostream> #include <map> #include <sstream> diff --git a/xr/tcpdispatcher/execute.cc b/xr/tcpdispatcher/execute.cc @@ -7,8 +7,8 @@ void TcpDispatcher::execute() { try { dispatch(); - } catch (Error e) { - cerr << e.txt() << "\n"; + } catch (Error const &e) { + cerr << e.what() << "\n"; socketclose (clientfd()); return; } @@ -27,8 +27,8 @@ void TcpDispatcher::execute() { try { handle(); - } catch (Error e) { - cerr << e.txt() << "\n"; + } catch (Error const &e) { + cerr << e.what() << "\n"; } lock(); diff --git a/xr/tcpdispatcher/readchunk.cc b/xr/tcpdispatcher/readchunk.cc @@ -3,7 +3,7 @@ unsigned TcpDispatcher::readchunk (int src) { ssize_t nread = read (src, data_buf, config.buffersize()); if (nread < 0) - throw ((Error) "Read failed on fd " + src); + throw static_cast<Error>("Read failed on fd ") + src; if (config.debug() && nread) { ostringstream o; diff --git a/xr/tcpdispatcher/tcpdispatcher b/xr/tcpdispatcher/tcpdispatcher @@ -1,19 +1,19 @@ #ifndef _TCPDISPATCHER_ #define _TCPDISPATCHER_ -#include "../sys/sys" -#include "../balancer/balancer" -#include "../config/config" -#include "../thread/thread" +#include "sys/sys" +#include "balancer/balancer" +#include "config/config" +#include "thread/thread" // Dispatching algorithm workers -#include "../algorithm/algorithm" -#include "../roundrobin/roundrobin" -#include "../firstactive/firstactive" -#include "../leastconn/leastconn" -#include "../external/external" -#include "../hashedip/hashedip" -#include "../storedip/storedip" +#include "DispatchAlgorithms/algorithm/algorithm" +#include "DispatchAlgorithms/roundrobin/roundrobin" +#include "DispatchAlgorithms/firstactive/firstactive" +#include "DispatchAlgorithms/leastconn/leastconn" +#include "DispatchAlgorithms/external/external" +#include "DispatchAlgorithms/hashedip/hashedip" +#include "DispatchAlgorithms/storedip/storedip" class TcpDispatcher: public Thread { public: diff --git a/xr/tcpdispatcher/writechunk.cc b/xr/tcpdispatcher/writechunk.cc @@ -10,7 +10,7 @@ unsigned TcpDispatcher::writechunk (int dst, char const *b, unsigned blen) { ssize_t nwritten = write (dst, (void*) (b + totwritten), blen - totwritten); if (nwritten < 1) - throw ((Error) "Write failed"); + throw static_cast<Error>("Write failed"); balancer.backend(targetbackend()).addbytes (nwritten); diff --git a/xr/thread/lock.cc b/xr/thread/lock.cc @@ -1,7 +1,13 @@ #include "thread" void Thread::lock() { - int res; - if ( (res = pthread_mutex_lock (&thread_mutex)) ) - throw ((Error) "Failed to obtain mutex lock: " + strerror(res)); + if (!initialized) { + if (int res = pthread_mutex_init (&thread_mutex, 0)) + throw static_cast<Error>("Failed to initialize mutex: ") + + strerror(res); + initialized = true; + } + if (int res = pthread_mutex_lock (&thread_mutex)) + throw static_cast<Error>("Failed to obtain mutex lock: ") + + strerror(res); } diff --git a/xr/thread/start.cc b/xr/thread/start.cc @@ -5,8 +5,8 @@ static void *_run (void *data) { try { t->execute(); - } catch (Error e) { - cerr << e.txt() << "\n"; + } catch (Error const &e) { + cerr << e.what() << "\n"; } // Cleanups @@ -26,9 +26,9 @@ void Thread::start() { int res; if (pthread_attr_init (&attr)) - throw ((Error) "Cannot initialize thread attributes"); + throw static_cast<Error>("Cannot initialize thread attributes"); if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED)) - throw ((Error) "Cannot set thread state as detached"); + throw static_cast<Error>("Cannot set thread state as detached"); for (int i = 0; i < 3; i++) { res = pthread_create (&th, &attr, _run, (void*) this); if (!res) { @@ -41,11 +41,13 @@ void Thread::start() { continue; } else { pthread_attr_destroy (&attr); - throw ((Error) "Failed to start thread: " + strerror(res)); + throw static_cast<Error>("Failed to start thread: ") + + strerror(res); } } - throw ((Error) "Failed to start thread: " - "Resources unavailable after 3 tries, giving up"); + throw static_cast<Error>("Failed to start thread: " + "Resources unavailable after 3 tries, " + "giving up"); } } diff --git a/xr/thread/thread b/xr/thread/thread @@ -17,6 +17,7 @@ public: virtual void execute(); private: static pthread_mutex_t thread_mutex; + static bool initialized; }; #endif diff --git a/xr/thread/thread1.cc b/xr/thread/thread1.cc @@ -1,9 +1,6 @@ #include "thread" pthread_mutex_t Thread::thread_mutex; +bool Thread::initialized = false; Thread::Thread() { - int res; - - if ( (res = pthread_mutex_init (&thread_mutex, 0)) ) - throw ((Error) "Failed to initialize mutex: " + strerror(res)); } diff --git a/xr/thread/unlock.cc b/xr/thread/unlock.cc @@ -1,7 +1,7 @@ #include "thread" void Thread::unlock() { - int res; - if ( (res = pthread_mutex_unlock (&thread_mutex)) ) - throw ((Error) "Failed to release mutex lock: " + strerror(res)); + if (int res = pthread_mutex_unlock (&thread_mutex)) + throw static_cast<Error>("Failed to release mutex lock: ") + + strerror(res); } diff --git a/xr/wakeupthread/wakeupthread b/xr/wakeupthread/wakeupthread @@ -1,14 +0,0 @@ -#ifndef _WAKEUPTHREAD_ -#define _WAKEUPTHREAD_ - -#include "../sys/sys" -#include "../thread/thread" -#include "../balancer/balancer" -#include "../error/error" - -class Wakeupthread: public Thread { -public: - void execute(); -}; - -#endif