[-]
[+]
|
Changed |
crossroads.spec
|
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/ChangeLog
^
|
@@ -1,3 +1,45 @@
+2.63 [KK 2010-01-11]
+- Previous 2.62 stamped as stable, 2.63 will be the new development
+ trunk.
+
+2.62 [KK 2010-01-08]
+- Fixed possible coredump cause in Balancer::serve(), which might
+ explain some troubles during high load (many really concurrent requests).
+
+2.61 [KK 2009-11-17]
+- Netbuffer::netwrite() will abort after 5 attempts that yield 0
+ written bytes. Probable cause of CPU hogging - thx Franz J. for
+ reporting.
+- Fixed potential cause of crashes in base class for Dispatcher
+ (algorithm handler would not get initialized in the constructors).
+
+2.60 [KK 2009-11-02]
+- Some errors demoted to informational messages to choke the amount of
+ log information that's generated.
+
+2.59 [KK 2009-10-14]
+- Bugfix in logger handling of xrctl, read
+ http://xrforum.org/viewtopic.php?t=495 if you fancy. Thanks Hobbit
+ for reporting this!
+
+2.58 [KK 2009-10-14]
+- Added test/ftp.xml as a sample ftp service configuration.
+- Implemented URL-based dispatching: flag --url-match/-j, present in
+ xrctl, tested in test/urlmatch.xml, added to web interface
+- Usage information now shows long versions of flags first.
+
+2.57 [KK 2009-09-14]
+- Output of "xrctl status" colorized when a service is not running,
+ thanks Frederik D. for the suggestion and the code!
+- Small cleanup of xrctl's usage information.
+
+2.56 [KK 2009-05-26]
+- Bugfix in cleaning of IPStore map
+- Implemented flag --remove-reservations (xrctl: tag: removereservations)
+- Timeouts adjusted: all read time outs set to 30, client-write set to
+ 5, backend-write set to 3
+- Implemented tag prefixtimestamp in system block to force timestamping.
+
2.55 [KK 2009-05-13]
- Implemented connection error counting of back ends.
- Select-handling revised: atomic readability and writeability checks,
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/Makefile
^
|
@@ -1,7 +1,7 @@
# Top-level Makefile for XR
# -------------------------
-VER = 2.55
+VER = 2.63
PREFIX = $(DESTDIR)/usr
BINDIR = $(PREFIX)/sbin
MANDIR = $(PREFIX)/share/man
|
|
Changed |
crossroads-devel.tar.gz/doc/xr.odt
^
|
|
Changed |
crossroads-devel.tar.gz/doc/xr.pdf
^
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/doc/xrctl.xml.5
^
|
@@ -45,6 +45,9 @@
<maxlogsize>100000</maxlogsize>
- How many history logs to keep?
<loghistory>10</loghistory> -->
+ <!-- To force log line timestamping, add:
+ <prefixtimestamp>true</prefixtimestamp>
+ Or turn it off with value "false". -->
</system>
<!-- Service descriptions: This section defines all balancing
@@ -151,6 +154,9 @@
<denyfrom>192.168.1.100</denyfrom>
</acl>
+ <!-- For a nonstandard buffer size (default is 2k), use: -->
+ <buffersize>4096</buffersize>
+
<dosprotection>
<!-- Here is some basic DOS protection. Connections from IP's
are counted over timeinterval seconds (here: 2 sec). When a
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/test/ftp.xml
^
|
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration>
+ <system>
+ <uselogger>false</uselogger>
+ <logdir>/tmp</logdir>
+ </system>
+
+ <service>
+ <name>ftp</name>
+ <server>
+ <type>tcp</type>
+ <address>127.0.0.1:21</address>
+ <dispatchmode>first-available</dispatchmode>
+ <verbose>true</verbose>
+ </server>
+ <backend>
+ <address>172.16.238.1:21</address>
+ <debug>true</debug>
+ </backend>
+ </service>
+
+ <service>
+ <name>ftpdata</name>
+ <server>
+ <type>tcp</type>
+ <address>127.0.0.1:20</address>
+ <dispatchmode>first-available</dispatchmode>
+ <verbose>true</verbose>
+ <debug>true</debug>
+ </server>
+ <backend>
+ <address>172.16.238.1:20</address>
+ </backend>
+ </service>
+
+</configuration>
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/test/multi-ip.xml
^
|
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <system>
+ <uselogger>true</uselogger>
+ <logger>clpipe /var/log/xr.clog</logger>
+ <path>/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/local/bin:/opt/local/sbin</path>
+ </system>
+
+ <service>
+ <name>first</name>
+ <server>
+ <type>tcp</type>
+ <address>192.168.2.5:10000</address>
+ <dispatchmode>first-available</dispatchmode>
+ <webinterface>192.168.2.5:10001</webinterface>
+ <verbose>yes</verbose>
+ <debug>yes</debug>
+ </server>
+ <backend>
+ <address>www.google.nl:80</address>
+ </backend>
+ <backend>
+ <address>www.thedailywtf.com:80</address>
+ </backend>
+ </service>
+
+ <service>
+ <name>second</name>
+ <server>
+ <type>tcp</type>
+ <address>172.16.89.1:10000</address>
+ <dispatchmode>first-available</dispatchmode>
+ <webinterface>172.16.89.1:10001</webinterface>
+ <verbose>yes</verbose>
+ <debug>yes</debug>
+ </server>
+ <backend>
+ <address>kubat.nl:80</address>
+ </backend>
+ <backend>
+ <address>slashdot.org:80</address>
+ </backend>
+ </service>
+
+</configuration>
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/test/urlmatch.xml
^
|
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <system>
+ <uselogger>false</uselogger>
+ <logdir>/tmp</logdir>
+ <path>/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/local/bin:/opt/local/sbin</path>
+ </system>
+
+ <service>
+ <name>urlmatch</name>
+ <server>
+ <type>http</type>
+ <address>0:20000</address>
+ <webinterface>0:20001</webinterface>
+ <verbose>yes</verbose>
+ <debug>yes</debug>
+ </server>
+ <backend>
+ <address>server1:10000</address>
+ <urlmatch>/$</urlmatch>
+ </backend>
+ <backend>
+ <address>server2:10000</address>
+ <urlmatch>/pages/fch</urlmatch>
+ </backend>
+ <backend>
+ <address>server3:10000</address>
+ <urlmatch>/pages/[^f][^c][^h]</urlmatch>
+ </backend>
+ </service>
+</configuration>
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/leastconn/target.cc
^
|
@@ -5,25 +5,46 @@
PROFILE("Leastconn::target");
msg (Mstr("Starting least-connections dispatcher\n"));
+
+ if (config.debug()) {
+ ostringstream o;
+ o << "Back end target list:";
+ for (unsigned i = 0; i < targetlist.size(); i++)
+ o << ' ' << targetlist[i];
+ o << '\n';
+ _debugmsg(o.str());
+ }
bool found = false;
unsigned best_weighted = 0, t = 0;
for (unsigned i = 0; i < targetlist.size(); i++) {
- if (! balancer.backend(targetlist[i]).available())
+ if (! balancer.backend(targetlist[i]).available()) {
+ debugmsg(Mstr("Back end ") +
+ Mstr(balancer.backend(targetlist[i]).description()) +
+ " is NOT available\n");
continue;
- unsigned this_weight =
- (balancer.backend(targetlist[i]).connections() +
- IPStore::anticipated(targetlist[i])) *
- balancer.backend(targetlist[i]).adjustedweight();
+ }
+ unsigned connections = balancer.backend(targetlist[i]).connections();
+ unsigned anticipated = IPStore::anticipated(targetlist[i]);
+ unsigned adjweight = balancer.backend(targetlist[i]).adjustedweight();
+ unsigned this_weight = (connections + anticipated) * adjweight;
+ ostringstream o;
+
+ if (config.debug())
+ o << "Back end " << balancer.backend(targetlist[i]).description()
+ << ": connections=" << connections << ", anticipated=" << anticipated
+ << ", adjweight=" << adjweight << ", thisweight=" << this_weight;
+
if (!found || this_weight < best_weighted) {
t = targetlist[i];
best_weighted = this_weight;
found = true;
- }
+ debugmsg(Mstr(o.str()) + Mstr(" is best so far\n"));
+ } else
+ debugmsg(Mstr(o.str()) + Mstr(" skipped, got a better one\n"));
}
-
if (!found)
throw Error("Least-connections algorithm: no available back ends");
return (t);
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/storedip/target.cc
^
|
@@ -29,5 +29,28 @@
// their preferred back end is down (and we're in lax mode ofc).
// Treat as new connection.
Leastconn l;
- return l.target(clientip, targetlist);
+
+ if (!config.removereservations())
+ return l.target(clientip, targetlist);
+ else {
+ BackendVector tlist = targetlist;
+ while (true) {
+ try {
+ return l.target(clientip, tlist);
+ } catch (...) {
+ // We're out of back ends and need to clear up the IP store to retry.
+ // We give it a sec, remove the oldest entry, and rebuild the
+ // target list for the least-connections dispatch algorithm.
+ warnmsg("Out of back ends, releasing oldest client entry and retrying\n");
+ IPStore::clearoldest();
+ sleep(1);
+ BackendVector newlist;
+ for (unsigned int i = 0; i < balancer.nbackends(); i++)
+ if (balancer.backend(i).available())
+ newlist.add(i);
+ tlist = newlist;
+ }
+ }
+ }
}
+
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/Dispatchers/dispatcher/dispatcher1.cc
^
|
@@ -2,7 +2,7 @@
Dispatcher::Dispatcher(int cfd, struct in_addr cip):
Thread(), client_ip(cip), target_backend(-1), client_fd(cfd),
- backend_fd(-1), target_list(), clientip_str() {
+ backend_fd(-1), algo(0), target_list(), clientip_str() {
start_dispatcher();
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/Dispatchers/dispatcher/dispatcher3.cc
^
|
@@ -2,7 +2,7 @@
Dispatcher::Dispatcher(int fd):
Thread(), target_backend(-1), client_fd(fd),
- backend_fd(-1), target_list(), clientip_str() {
+ backend_fd(-1), algo(0), target_list(), clientip_str() {
start_dispatcher();
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/Dispatchers/httpdispatcher/dispatch.cc
^
|
@@ -5,6 +5,7 @@
unsigned stickytarget;
string host_header = "";
+ string url = "";
// Try to dispatch. Since we're in HTTP mode, we must return an
// error page when dispatching fails.
@@ -13,37 +14,57 @@
// Get the client's request. May need for cookie inspection or for the
// host header.
while (!buf().headersreceived())
- if (!buf().netread(clientfd(), config.client_read_timeout()))
- throw Error("Didn't receive a valid client request.");
+ if (!buf().netread(clientfd(), config.client_read_timeout())) {
+ msg ("Didn't receive a valid client request, stopping");
+ return;
+ }
msg ("Received client request: '" + buf().firstline() + "'\n");
- // See if hostmatching is used. This is true when a backend
- // matches against a non-dot host.
+ // See if hostmatching or urlmatching is used.
+ // This is true when hosts or urls are matched against non-dot.
bool hostmatchused = false;
- for (unsigned i = 0; i < balancer.nbackends(); i++)
- if (balancer.backend(i).hostmatch() != ".") {
+ bool urlmatchused = false;
+ for (unsigned i = 0; i < balancer.nbackends(); i++) {
+ if (balancer.backend(i).hostmatch() != ".")
hostmatchused = true;
- break;
- }
- // Build new target list if host matching applies.
- if (hostmatchused) {
- host_header = buf().headerval ("Host");
- msg ("Will try to dispatch request for host '" +
- host_header + "'\n");
-
- // We need to build tcpdispatcher's target list now!
- // Construct locally and poke into TcpDispatcher.
- msg ("Creating host-based target list for the HTTP dispatcher\n");
+ if (balancer.backend(i).urlmatch() != ".")
+ urlmatchused = true;
+ }
+
+ // Build new target list if host- or url matching applies.
+ if (hostmatchused || urlmatchused) {
+ msg ("Creating matched target list for the HTTP dispatcher\n");
+
+ if (hostmatchused)
+ host_header = buf().headerval("Host");
+ if (urlmatchused)
+ url = buf().url();
+
BackendVector v;
v.isdefined(true);
+
for (unsigned i = 0; i < balancer.nbackends(); i++) {
- if ( (balancer.backend(i).available()) &&
- (!regexec (&(balancer.backend(i).hostregex()),
- host_header.c_str(), 0, 0, 0)) ) {
+ if (! balancer.backend(i).available())
+ continue;
+ bool host_allowed = true, url_allowed = true;
+ if (hostmatchused &&
+ regexec(&(balancer.backend(i).hostregex()),
+ host_header.c_str(), 0, 0, 0)) {
+ debugmsg("Back end " + balancer.backend(i).description() +
+ " forbidden due to hostmatch\n");
+ host_allowed = false;
+ }
+ if (urlmatchused &&
+ regexec(&(balancer.backend(i).urlregex()),
+ url.c_str(), 0, 0, 0)) {
+ debugmsg("Back end " + balancer.backend(i).description() +
+ " forbidden due to urlmatch\n");
+ url_allowed = false;
+ }
+ if (host_allowed && url_allowed) {
v.add(i);
- if (config.verbose())
- msg (" Candidate target: " +
- balancer.backend(i).description() + "\n");
+ msg("Candidate target: " +
+ balancer.backend(i).description() + "\n");
}
}
targetlist(v);
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/Dispatchers/tcpdispatcher/execute.cc
^
|
@@ -10,6 +10,7 @@
msg ((Mstr("Dispatch request for client fd ") + clientfd()) + "\n");
+ // Try to determine the back end.
try {
Threadlist::desc("Dispatching");
dispatch();
@@ -22,6 +23,16 @@
return;
}
+ // Verify that the target is within the allowed set.
+ if (targetbackend() < 0 || targetbackend() >= (int)balancer.nbackends()) {
+ cerr << "WARNING: target back end " << targetbackend()
+ << " out of range\n";
+ socketclose(clientfd());
+ socketclose(backendfd());
+ return;
+ }
+
+ // Dispatch!
msg ((Mstr("Dispatching client fd ") + clientfd()) +
(Mstr(" to ") + balancer.backend(targetbackend()).description()) +
(Mstr(", fd ") + backendfd()) + "\n");
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backend/backend
^
|
@@ -50,6 +50,10 @@
void hostmatch(string const &s) { bdef.hostmatch(s); }
regex_t const &hostregex() const { return bdef.hostregex(); }
+ string const &urlmatch() const { return bdef.urlmatch(); }
+ void urlmatch(string const &u) { bdef.urlmatch(u); }
+ regex_t const &urlregex() const { return bdef.urlregex(); }
+
unsigned weight() const { return bdef.weight(); }
void weight (unsigned w) { bdef.weight(w); }
unsigned adjustedweight() const { return bdef.adjustedweight(); }
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backend/backend1.cc
^
|
@@ -1,7 +1,7 @@
#include "backend"
Backend::Backend () :
- islive(true), isup(true), clsocket(-1),
+ bdef(), islive(true), isup(true), clsocket(-1),
nconn(0), totconn(0), nconnerr(0),
bytes_served(0),
loadaverage(0.1), dnsentry(), index(-1) {
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backenddef/backenddef
^
|
@@ -5,13 +5,18 @@
#include "error/error"
#include "profiler/profiler"
#include "backendcheck/backendcheck"
+#include "ThreadsAndMutexes/mutex/mutex"
using namespace std;
class BackendDef {
public:
- BackendDef(): srv(""), prt(-1), max(0),
- host_match(""), wt(1), backend_check() {}
+ BackendDef():
+ srv(""), prt(-1), max(0), host_match(""), url_match(""),
+ wt(1), backend_check() {
+ hostmatch("");
+ urlmatch("");
+ }
BackendDef(string s, string p, string m = "", string w = "1");
void server(string s) { srv = s; }
@@ -25,12 +30,17 @@
unsigned weight() const { return wt; }
void weight (unsigned w);
- unsigned adjustedweight() const { return min_wt + max_wt - wt; }
+ unsigned adjustedweight() const { return min_wt +
+ max_wt - wt; }
void hostmatch(string const &s);
string const &hostmatch() const { return (host_match); }
regex_t const &hostregex() const { return (host_regex); }
+ void urlmatch(string const &u);
+ string const &urlmatch() const { return (url_match); }
+ regex_t const &urlregex() const { return (url_regex); }
+
BackendCheck const &backendcheck() { return backend_check; }
void backendcheck(BackendCheck const &b) { backend_check = b; }
@@ -40,6 +50,8 @@
unsigned max;
string host_match;
regex_t host_regex;
+ string url_match;
+ regex_t url_regex;
unsigned wt;
static unsigned min_wt, max_wt;
static bool minmax_wt_set;
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backenddef/backenddef1.cc
^
|
@@ -6,7 +6,8 @@
BackendDef::BackendDef (string server, string port,
string maxclients, string w) :
- srv(server), prt(-1), max(0), host_match(""), wt(1) {
+ srv(server), prt(-1), max(0), host_match(""), url_match(""),
+ wt(1), backend_check() {
if (sscanf (port.c_str(), "%d", &prt) < 1)
throw Error("Bad backend port specifier: '" + port +
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backenddef/hostmatch.cc
^
|
@@ -2,10 +2,8 @@
void BackendDef::hostmatch (string const &s) {
PROFILE("BackendDef::hostmatch");
-
- host_match = s;
- if (host_match == "")
- host_match = ".";
+
+ host_match = (s == "" ? "." : s);
if (regcomp (&host_regex, host_match.c_str(),
REG_EXTENDED | REG_ICASE | REG_NOSUB))
throw Error("Host match specifier '" +
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/backenddef/urlmatch.cc
^
|
@@ -0,0 +1,11 @@
+#include "backenddef"
+
+void BackendDef::urlmatch (string const &s) {
+ PROFILE("BackendDef::urlmatch");
+
+ url_match = (s == "" ? "." : s);
+ if (regcomp (&url_regex, url_match.c_str(),
+ REG_EXTENDED | REG_ICASE | REG_NOSUB))
+ throw Error("Url match specifier '" +
+ url_match + "' isn't a valid regular expression");
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backenddef/weight.cc
^
|
@@ -3,6 +3,7 @@
void BackendDef::weight(unsigned w) {
wt = w;
+ Mutex::lock(&minmax_wt_set);
if (!minmax_wt_set) {
min_wt = w;
max_wt = w;
@@ -13,4 +14,5 @@
if (max_wt > w)
max_wt = w;
}
+ Mutex::unlock(&minmax_wt_set);
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/balancer/balancer
^
|
@@ -28,13 +28,15 @@
void deletebackend(unsigned i);
void serve();
- unsigned nbackends() { return (backends.size()); }
- Backend &backend (unsigned i) { return (backends[i]); }
- bool terminate() const { return (term); }
+ unsigned nbackends() { return backends.size(); }
+ Backend &backend (unsigned i) { return backends[i]; }
+ bool terminate() const { return term; }
void terminate (bool t) { term = t; }
- bool report() const { return (rep); }
+ bool report() const { return rep; }
void report (bool r) { rep = r; }
- long requestnr() const { return (request_nr); }
+ void restart(bool t) { rest = t; }
+ bool restart() const { return rest; }
+ long requestnr() const { return request_nr; }
unsigned connections();
@@ -47,6 +49,7 @@
vector<Backend> backends;
bool term;
bool rep;
+ bool rest;
};
extern Balancer balancer;
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/balancer/balancer1.cc
^
|
@@ -1,5 +1,6 @@
#include "balancer"
Balancer::Balancer () :
- server_fd(-1), request_nr(0), backends(), term(false), rep(false) {
+ server_fd(-1), request_nr(0), backends(),
+ term(false), rep(false), rest(false) {
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/balancer/serve.cc
^
|
@@ -3,6 +3,8 @@
#include "Dispatchers/httpdispatcher/httpdispatcher"
#include "Dispatchers/udpdispatcher/udpdispatcher"
+// #define SHOWDEBUG
+
void Balancer::serve() {
int clsock = -1;
@@ -70,8 +72,11 @@
report (false);
reportmsg ("*** XR STATUS REPORT ENDS ***\n");
continue;
+ } else if (restart()) {
+ msg ("Restart requested\n");
+ config.restart();
} else {
- msg ("Non-meaningful interrupt, resuming\n");
+ msg ("Non-meaningful interrupt or select timeout, resuming\n");
continue;
}
}
@@ -143,6 +148,11 @@
_debugmsg (Mstr("Allocation boundary at dispatcher start: ") +
mem + "\n");
}
+ #ifdef SHOWDEBUG
+ void *mem = malloc(16);
+ free (mem);
+ cout << "XR allocation at dispatcher start: " << mem << '\n';
+ #endif
d->start();
} else {
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/config
^
|
@@ -35,6 +35,12 @@
int backends() const { return (blist.size()); }
+ /* PID file */
+ void pidfile(string const &s);
+ string const &pidfile() {
+ return pid_file;
+ }
+
/* Client timeouts */
unsigned client_read_timeout() const {
return (c_timeout);
@@ -93,9 +99,6 @@
return (external_algorithm);
}
- string const &pidfile() const { return (pid_file); }
- void pidfile (string const &p);
-
bool prefixtimestamp() const { return (prefix_timestamp); }
void prefixtimestamp (bool p);
@@ -158,6 +161,12 @@
string dispatchmodestr() const {
return (dmode.modestr());
}
+ bool removereservations() const {
+ return remove_reservations;
+ }
+ void removereservations(bool b) {
+ remove_reservations = b;
+ }
string const &softmaxconnexcess() const {
return soft_maxconn_excess_prog;
@@ -179,15 +188,19 @@
void onfail(string s) { on_fail = s; }
string const &onfail() const { return on_fail; }
+ /* Restart of program */
+ void restart();
private:
void setbackend (string const &s, string const &hostmatch,
+ string const &urlmatch,
BackendCheck const &bc);
void setwebinterface (string s);
void setserver (string s);
void setdispatchmode (string s);
int setinteger (string s) const;
+ static string pid_file;
static bool verbose_flag;
static int lport;
static Servertype styp;
@@ -207,7 +220,6 @@
static bool replace_host_header;
static unsigned max_conn;
static string external_algorithm;
- static string pid_file;
static bool prefix_timestamp;
static vector<string> serverheaders;
static vector<struct in_addr> allowlist;
@@ -227,6 +239,8 @@
static string hard_maxconn_excess_prog;
static unsigned dns_cache_timeout;
static string on_start, on_end, on_fail;
+ static bool remove_reservations;
+ static char **org_argv;
};
extern Config config;
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/config1.cc
^
|
@@ -7,8 +7,8 @@
vector<BackendDef> Config::blist;
Dispatchmode Config::dmode;
unsigned Config::c_timeout = 30;
-unsigned Config::b_timeout = 3;
-unsigned Config::c_write_timeout = 30;
+unsigned Config::c_write_timeout = 5;
+unsigned Config::b_timeout = 30;
unsigned Config::b_write_timeout = 3;
unsigned Config::wakeup = 5;
unsigned Config::checkup = 0;
@@ -43,6 +43,8 @@
string Config::on_start = "";
string Config::on_end = "";
string Config::on_fail = "";
+bool Config::remove_reservations = false;
+char **Config::org_argv = 0;
Config::Config () {
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/parsecmdline.cc
^
|
@@ -4,6 +4,9 @@
using namespace std;
void Config::parsecmdline (int ac, char **av) {
+ // Remember original argv.
+ org_argv = av;
+
// Prepare invoking command line.
string cmdline;
for (int i = 0; i < ac; i++) {
@@ -15,8 +18,8 @@
if (ac == 1)
throw Error("Bad command line '" + cmdline + "'\n" + USAGE);
-# define OPTSTRING "?a:A:B:b:c:CDd:E:e:fF:g:hH:Il:" \
- "m:M:nPp:Q:r:R:Ss:t:T:u:U:vVW:w:xXy:z:Z:"
+# define OPTSTRING "?a:A:B:b:c:CDd:E:e:fF:Gg:hH:Ij:l:" \
+ "m:M:nPQ:r:R:Ss:t:T:u:U:vVW:w:xXy:z:Z:"
# ifdef HAVE_GETOPT_LONG
static struct option longopts[] = {
{ "allow-from", required_argument, 0, 'a' },
@@ -31,16 +34,18 @@
{ "soft-maxconn-excess", required_argument, 0, 'e' },
{ "dns-cache-timeout", required_argument, 0, 'F' },
{ "foreground", no_argument, 0, 'f' },
+ { "remove-reservations", no_argument, 0, 'G' },
{ "backend-check", required_argument, 0, 'g' },
{ "help", no_argument, 0, 'h' },
{ "add-server-header", required_argument, 0, 'H' },
{ "replace-host-header", no_argument, 0, 'I' },
+ { "url-match", required_argument, 0, 'j' },
{ "log-traffic-dir", required_argument, 0, 'l' },
{ "max-connections", required_argument, 0, 'm' },
{ "host-match", required_argument, 0, 'M' },
{ "tryout", no_argument, 0, 'n' },
- { "prefix-timestamp", no_argument, 0, 'P' },
{ "pidfile", required_argument, 0, 'p' },
+ { "prefix-timestamp", no_argument, 0, 'P' },
{ "soft-maxconnrate", required_argument, 0, 'r' },
{ "quit-after", required_argument, 0, 'Q' },
{ "hard-maxconnrate", required_argument, 0, 'R' },
@@ -67,6 +72,7 @@
bool backend_set = false;
bool tryout = false, wakeup_used = false;
string current_hostmatch = "";
+ string current_urlmatch = "";
BackendCheck current_backendcheck;
vector<string> parts;
@@ -84,7 +90,8 @@
adddeny (optarg);
break;
case 'b':
- setbackend (optarg, current_hostmatch, current_backendcheck);
+ setbackend (optarg, current_hostmatch, current_urlmatch,
+ current_backendcheck);
backend_set = true;
break;
case 'B':
@@ -115,6 +122,9 @@
case 'f':
foreground_mode = true;
break;
+ case 'G':
+ removereservations(true);
+ break;
case 'g':
current_backendcheck.parse(optarg);
break;
@@ -128,6 +138,9 @@
case 'I':
replacehostheader(true);
break;
+ case 'j':
+ current_urlmatch = optarg;
+ break;
case 'l':
dumpdir (optarg);
break;
@@ -143,9 +156,6 @@
case 'P':
prefix_timestamp = true;
break;
- case 'p':
- pid_file = optarg;
- break;
case 'Q':
quit_after = (unsigned) setinteger(optarg);
break;
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/restart.cc
^
|
@@ -0,0 +1,11 @@
+#include "config"
+
+void Config::restart() {
+ for (int i = 0; org_argv[i]; i++)
+ cout << "Arg " << i << ": " << org_argv[i] << '\n';
+ execvp("xr", org_argv);
+ ostringstream o;
+ o << "Failed to restart: errno=" << errno << ", "
+ << strerror(errno);
+ throw Error(o.str());
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/setbackend.cc
^
|
@@ -1,6 +1,7 @@
#include "config"
void Config::setbackend (string const &str, string const &host,
+ string const &url,
BackendCheck const &backend_check) {
vector<string> parts = str2parts (str, ':');
if (parts.size() < 2 || parts.size() > 4)
@@ -18,6 +19,7 @@
if (!bdp)
throw Error("Memory fault in Config::setbackend");
bdp->hostmatch(host);
+ bdp->urlmatch(url);
bdp->backendcheck(backend_check);
blist.push_back (*bdp);
delete bdp;
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/etc/status-nosavebutton.xslt
^
|
@@ -722,7 +722,28 @@
<td>
<input type="text" size="8" name="sethostmatch{nr}"
id="sethostmatch{nr}" value="{hostmatch}"
- onchange="goto('/backend/{nr}/hostmatch/', 'sethostmatch{nr}');"/>
+ onchange="goto('/backend/{nr}/hostmatch/',
+ 'sethostmatch{nr}');"/>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>URL match</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="urlmatch = '.'">
+ any url request
+ </xsl:when>
+ <xsl:otherwise>
+ (. for any url)
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td>
+ <input type="text" size="8" name="seturlmatch{nr}"
+ id="seturlmatch{nr}" value="{urlmatch}"
+ onchange="goto('/backend/{nr}/urlmatch/',
+ 'seturlmatch{nr}');"/>
</td>
</tr>
</xsl:if>
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/etc/usage.txt
^
|
@@ -3,26 +3,65 @@
Usage: xr [flags], where the flags may be the following (long versions
may not exist on your platform):
- -a MASK, --allow-from MASK
+ --add-server-header HDR, -H HDR
+ Inserts HDR into back end bound HTTP messages. The header value is
+ appended when a pre-existing header is present.
+ --add-x-forwarded-for, -x
+ Adds X-Forwarded-For with external IP address to back end streams in
+ HTTP messages.
+ --add-xr-version, -X
+ Adds an XR version header to client and back end streams in HTTP
+ messages.
+ --allow-from MASK, -a MASH
Allow only clients that match MASK. MASK is e.g. 192.168.255.255, which
would allow the class B network 192.168.*.*
- -A MASK, --deny-from MASK
- Deny clients that match MASK.
- -b ADDRESS:PORT[:MAX[:WEIGHT]], --backend ADDRESS:PORT[:MAX[:WEIGHT]]
+ --backend ADDRESS:PORT[:MAX[:WEIGHT]], -b ADDRESS:PORT[:MAX[:WEIGHT]]
Specifies a back end, use multiple -b... to specify several back ends.
- At least one -b... must be given. Specifier MAX is optional: when given,
- defines the maximum connections for the back end. WEIGHT is optional:
- when given, specifies the weight (bigger means better server, default 1).
- -B SIZE, --buffer-size SIZE
+ At least one backend must be given. Specifier MAX is optional:
+ when given, defines the maximum connections for the back end.
+ WEIGHT is optional: when given, specifies the weight (bigger
+ means better server, default 1)
+ --backend-check METHOD, -g METHOD
+ Defines how back ends are checked. This flag must be specified
+ PRIOR to defining back ends with -b... The checker will then
+ apply to all next back ends. Alternatives are:
+ connect:IP:PORT - successful TCP connects at IP:PORT indicate
+ that the back end is alive. When IP is not stated, the back
+ end's IP is assumed.
+ get:IP:PORT/URI - A HTTP GET is sent to IP:PORT/URI. When an
+ HTTP status 200 is seen, the back end is assumed alive. When
+ /URI is not given, then "/" is assumed.
+ external:PROGRAM - The PROGRAM is called with the arguments
+ "IP:PORT", availability as "available" or "unavailable", and
+ the number of connections. The program must echo 0 to indicate
+ that the back end is alive.
+ The default behavior is a TCP connect, to the back end's IP, at
+ the back end's port. Use "--backend-check connect::" to reset
+ previous flags to the default.
+ --backend-timeout SEC, -t SEC
+ Defines network read timeouts for back ends, default 30 sec. Use 0 to
+ prevent timing out. Use "--backend-timeout RSEC:WSEC" to
+ specify separate timeouts for reads and writes, default 30:3.
+ --buffer-size SIZE, -B size
Sets the network buffer size, default is 2048 (in bytes)
- -C, --close-sockets-fast
- Sockets are closed faster to avoid TIME_WAIT states.
- -c SEC, --checkup-interval SEC
+ --checkup-interval SEC, -c SEC
Defines the back end checking period. Each SEC seconds, every back end
is checked whether it is alive. Default is 0 (off).
- -D, --debug
- Sets debugging on, more verbosity on top of -v
- -d METHOD, --dispatch-mode METHOD
+ --client-timeout SEC, -T SEC
+ Defines network read timeouts for clients, default 30 sec. Use 0 to
+ prevent timing out. Use "--client-timeout RSEC:WSEC" to specify
+ separate timeouts for reads and writes, default 30:5
+ --close-sockets-fast, -C
+ Sockets are closed faster to avoid TIME_WAIT states.
+ --debug, -D
+ Sets debugging on, more verbosity on top of --verbose
+ --defer-time USEC, -u USEC
+ If a connection is going to be deferred due to hitting the "soft" rate
+ (see --soft-maxconnrate), then this option sets how long the deferral
+ will last, in microseconds. Default is 500000 (0.5 seconds).
+ --deny-from MASK, -A mask
+ Deny clients that match MASK.
+ --dispatch-mode METHOD, -d METHOD
Defines how to dispatch over back ends, the method may be:
f, first-available - first live back end gets all traffic
e:EXT, external:EXT - external program EXT is queried
@@ -46,126 +85,97 @@
end definition, eg. "10.1.1.1:80"; <b0-availablility> is "available" or
"unavailable", <b0-connections> is the nr. of connections. The program
must reply with a back end number (0..max) on stdout.
- -E PROGRAM, --hard-maxconn-excess PROGRAM
- When a client exceeds the hard maxconnection rate, PROGRAM is
- invoked with the client's IP as argument. The program may e.g.
- invoke iptables to block the offending IP.
- -e PROGRAM, --soft-maxconn-excess PROGRAM
- When a client exceeds the soft maxconnection rate, PROGRAM is
- invoked with the client's IP as argument.
- -F SEC, --dns-cache-timeout SEC
+ --dns-cache-timeout SEC, -F SEC
DNS results for back end hostnames are cached for SEC seconds.
The default is 3600 (1 hour). Use 0 to suppress.
- -f, --foreground
+ --foreground, -f
Suppresses forking/threading, only for debugging. Also suppresses
- wakeups (-w), checkups (-c) and the webinterface (-W).
- -g METHOD, --backend-check METHOD
- Defines how back ends are checked. This flag must be specified
- PRIOR to defining back ends with -b... The checker will then
- apply to all next back ends. Alternatives are:
- connect:IP:PORT - successful TCP connects at IP:PORT indicate
- that the back end is alive. When IP is not stated, the back
- end's IP is assumed.
- get:IP:PORT/URI - A HTTP GET is sent to IP:PORT/URI. When an
- HTTP status 200 is seen, the back end is assumed alive. When
- /URI is not given, then "/" is assumed.
- external:PROGRAM - The PROGRAM is called with the arguments
- "IP:PORT", availability as "available" or "unavailable", and
- the number of connections. The program must echo 0 to indicate
- that the back end is alive.
- The default behavior is a TCP connect, to the back end's IP, at
- the back end's port. Use "-g connect::" to reset previous flags
- to the default.
- -h, -?, --help
+ wakeups (--wakeup-interval), checkups (--checkup-interval) and
+ the webinterface (--web-interface).
+ --hard-maxconn-excess PROGRAM, -E PROGRAM
+ When a client exceeds the hard maxconnection rate, PROGRAM is
+ invoked with the client's IP as argument. The program may e.g.
+ invoke iptables to block the offending IP.
+ --hard-maxconnrate MAXCONS, -R MAXCONS
+ Sets the "HARD" maximum average number of connections per IP allowed
+ within a given time period (see -U, --time-interval). If a
+ particular IP exceeds this number, then their connection is
+ immediately closed. Default is 0 (disabled). If both the
+ "soft" and "hard" rates are set, and the "hard" rate is lower
+ than the "soft" rate, then only the "hard" rate is obeyed.
+ --help, -?, -h
This text.
- -H HDR, --add-server-header HDR
- Inserts HDR into back end bound HTTP messages. The header value is
- appended when a pre-existing header is present.
- -I HDR, --replace-host-header HDR
- Inserts "Host: <backend>" into back end bound HTTP messages.
- Pre-existing Host headers are overwritten. The value of <backend> is
- the server name as in the setting of --backend (-b).
- -l DIR, --log-traffic-dir DIR
+ --host-match HOST, -M HOST
+ Subsequently stated backends only apply when clients request a
+ matching host. Only available when the server is in http mode.
+ --log-traffic-dir DIR, -l DIR
Log passing traffic with dumps in DIR. Only for debugging, slows
down the balancer.
- -m MAX, --max-connections MAX
+ --max-connections MAX, -m MAX
Sets the maximum number of connections to the balancer. Default is 0,
no maximum.
- -M HOST, --host-match HOST
- Subsequently stated backends only apply when clients request a
- matching host. Only available when the server is in http mode.
- -n, --tryout
- Validates all flags and stops; does not start the balancer.
- -P, --prefix-timestamp
+ --onend CMD, -Z CMD
+ Runs CMD after successful termination of a client. For the
+ arguments of CMD see -y.
+ --onfail CMD, -y CMD
+ Runs CMD when XR fails to connect to a back end. The arguments
+ to the command are: the client's IP address, and the back end address.
+ --onstart CMD, -z CMD
+ Runs CMD just before letting a back end handle a client's connection.
+ For the arguments of CMD see -y.
+ --pidfile FILE, -p FILE
+ FILE is written with the process id of XR upon startup, and
+ removed upon exit.
+ --prefix-timestamp, -P
Messages (verbose, debug, error etc.) are prefixed with a time stamp.
- -p FILE, --pidfile FILE
- FILE is written with the PID of XR upon startup
- -Q REQUESTS, --quit-after REQUESTS
+ --quit-after REQUESTS, -Q REQUESTS
Stops the balancer after REQUESTS hits. For debugging / loadtesting.
- -r MAXCONS, --soft-maxconnrate MAXCONS
+ --remove-reservations, -G
+ In stored-ip algorithms, outstanding reservations for expected
+ clients are removed when no more back ends are available.
+ --replace-host-header HDR, -I HDR
+ Inserts "Host: <backend>" into back end bound HTTP messages.
+ Pre-existing Host headers are overwritten. The value of <backend> is
+ the server name as in the setting of --backend (-b).
+ --server TYPE:IPADDRESS:PORT, -S TYPE:IPADDRESS:PORT
+ Specifies the server. TYPE is tcp or http or udp. IPADDRESS is the IP
+ address to listen to. PORT defines the TCP port to listen; when port
+ is 0, XR will listen to stdin (inetd-mode, not available for udp).
+ Default: tcp:0:10000 (TCP balancing, on all interfaces, via port 10000).
+ --soft-maxconn-excess PROGRAM, -e PROGRAM
+ When a client exceeds the soft maxconnection rate, PROGRAM is
+ invoked with the client's IP as argument.
+ --soft-maxconnrate MAXCONS, -r MAXCONS
Sets the "SOFT" maximum average number of connections per IP allowed
within a given time period (see -U, --time-interval). If a
particular IP exceeds this number, then their connection is
deferred (see -u, --defer-time). Default is 0 (disabled).
- -R MAXCONS, --hard-maxconnrate MAXCONS
- Sets the "HARD" maximum average number of connections per IP allowed
- within a given time period (see -U, --time-interval). If a
- particular IP exceeds this number, then their connection is
- immediately closed. Default is 0 (disabled). If both the
- "soft" and "hard" rates are set, and the "hard" rate is lower
- than the "soft" rate, then only the "hard" rate is obeyed.
- -S, --sticky-http
+ --sticky-http, -S
Enables sticky HTTP sessions by injecting XRTarget cookies into HTTP
- streams. Only effective with -s http:....
- -s TYPE:IPADDRESS:PORT, --server TYPE:IPADDRESS:PORT
- Specifies the server. TYPE is tcp or http or udp. IPADDRESS is the IP
- address to listen to. PORT defines the TCP port to listen; when port
- is 0, XR will listen to stdin (inetd-mode, not available for udp).
- Default: tcp:0:10000 (TCP balancing, on all interfaces, via port 10000).
- -t SEC, --backend-timeout SEC
- Defines network timeouts for back ends, default 3 sec. Use 0 to
- prevent timing out. SEC is the timeout for reads and writes.
- Use -t RSEC:WSEC to specify separate timeouts for reads and writes.
- -T SEC, --client-timeout SEC
- Defines network timeouts for clients, default 30 sec. Use 0 to
- prevent timing out. Use -T RSEC:WSEC to specify separate
- timeouts for reads and writes.
- -u USEC, --defer-time USEC
- If a connection is going to be deferred due to hitting the "soft" rate
- (see --soft-maxconnrate), then this option sets how long the deferral
- will last, in microseconds. Default is 500000 (0.5 seconds).
- -U SEC, --time-interval SEC
+ streams. Only effective with "--server http:...."
+ --time-interval SEC, -U SEC
If either --soft-maxconnrate or --hard-maxconnrate is specified, this
option allows you to specify the time period to which those numbers of
- connections apply. For example, "-r 200 -U 60" would trigger the "soft"
- limit on any IP attempting more than 200 connections in any 60 second
- period. Default is 1 (second).
- -v, --verbose
+ connections apply. For example,
+ "--soft-maxconnrate 200 --time-interval 60" would trigger the
+ "soft" limit on any IP attempting more than 200 connections in
+ any 60 second period. Default is 1 (second).
+ --tryout, -n
+ Validates all flags and stops; does not start the balancer.
+ --url-match URL, -j URL
+ Subsequently stated backends only apply when clients request a
+ matching URL. Only available when the server is in http mode.
+ --web-interface IP:PORT, -W IP:PORT
+ Starts a web interface on specified IP address and port.
+ --verbose, -v
Increases verbosity, default is silent operation.
- -V, --version
+ --version, -V
Shows the version info, and author/maintainer contacts (for reporting
bugs).
- -w SEC, --wakeup-interval SEC
+ --wakeup-interval SEC, -w SEC
Defines wakeup period (rechecking) in seconds, of unavailable back
ends. Default is 5. Use -w0 to suppress.
- -W IP:PORT, --web-interface IP:PORT
- Starts a web interface on specified IP address and port.
- -X, --add-xr-version
- Adds an XR version header to client and back end streams in HTTP
- messages.
- -x, --add-x-forwarded-for
- Adds X-Forwarded-For with external IP address to back end streams in
- HTTP messages.
- -y CMD, --onfail CMD
- Runs CMD when XR fails to connect to a back end. The arguments
- to the command are: the client's IP address, and the back end address.
- -z CMD, --onstart CMD
- Runs CMD just before letting a back end handle a client's connection.
- For the arguments of CMD see -y.
- -Z CMD, --onend CMD
- Runs CMD after successful termination of a client. For the
- arguments of CMD see -y.
XR's messages are sent to stderr. Invoke XR daemons using something like
-"xr -b ... [other flags] 2>&1 | logger &", or use xrctl.
+"xr --backend ... [other flags] 2>&1 | logger &", or use xrctl.
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/fdset/wait.cc
^
|
@@ -53,13 +53,27 @@
throw Error(o.str());
}
- // More debugging
+ // More debugging: What has become readable, what has become
+ // writeable, also state if no change was seen
if (config.debug()) {
+ bool statechanged = false;
for (unsigned int i = 0; i < FD_SETSIZE; i++) {
- if (FD_ISSET(i, &readset))
+ if (FD_ISSET(i, &readset)) {
_debugmsg(Mstr("Fd ") + Mstr(i) + " is readable\n");
- if (FD_ISSET(i, &writeset))
+ statechanged = true;
+ }
+ if (FD_ISSET(i, &writeset)) {
_debugmsg(Mstr("Fd ") + Mstr(i) + " is writeable\n");
+ statechanged = true;
+ }
}
+ if (!statechanged) {
+ ostringstream o;
+ o << "Select timeout: neither of the fd's ";
+ for (unsigned int i = 0; i < set.size(); i++)
+ o << set[i] << ' ';
+ o << "has shown activity in " << tsec << " sec\n";
+ _debugmsg(o.str());
+ }
}
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/httpbuffer/httpbuffer
^
|
@@ -21,6 +21,7 @@
string headerval (string const &var);
string &firstline();
+ string url();
bool setversion(char v);
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/httpbuffer/url.cc
^
|
@@ -0,0 +1,33 @@
+#include "httpbuffer"
+
+static string methods[] = {
+ "HEAD", "GET", "POST", "PUT", "DELETE", "TRACE", "OPTIONS", "CONNECT"
+};
+
+string Httpbuffer::url() {
+ if (firstline().empty())
+ return "";
+
+ // The first line must be a method, followed by the URL, followed
+ // by optional mush, as in: GET /index.html HTTP/1.1.
+ // Match the method first.
+ unsigned url_start = 0;
+ for (unsigned i = 0; i < sizeof(methods) / sizeof(string) ; i++)
+ if (firstline().substr(0, methods[i].size()) == methods[i]) {
+ url_start = methods[i].size();
+ break;
+ }
+ if (!url_start)
+ return "";
+ while (firstline()[url_start] == ' ' && url_start < firstline().size())
+ url_start++;
+
+ string ret;
+ for (unsigned i = url_start;
+ firstline()[i] != ' ' && i < firstline().size();
+ i++)
+ ret += firstline()[i];
+
+ debugmsg("URL of request: " + ret + "\n");
+ return ret;
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ipstore/anticipated.cc
^
|
@@ -3,7 +3,11 @@
unsigned IPStore::anticipated(unsigned b) {
if (!onoff || b >= balancer.nbackends())
return 0;
-
+
+ // Weed store for decisions later
+ weed();
+
+ // Get number of anticipated clients for given back end
unsigned ret = 0;
Mutex::lock(&store);
@@ -13,7 +17,9 @@
if ((*iter).second.targetbackend == (int)b)
ret++;
Mutex::unlock(&store);
-
+
+ debugmsg(Mstr("Anticipated connections for back end ") + Mstr(b) + ": " +
+ Mstr(ret) + "\n");
return ret;
}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ipstore/clearoldest.cc
^
|
@@ -0,0 +1,36 @@
+#include "ipstore"
+
+void IPStore::clearoldest() {
+ time_t oldest_time = time(0) + 100;
+ StoreMap::iterator oldest_entry;
+ bool found = false;
+
+ Mutex::lock(&store);
+
+ dump();
+
+ // Find oldest entry.
+ for (StoreMap::iterator iter = store.begin();
+ iter != store.end();
+ iter++) {
+ if ((*iter).second.lastaccess < oldest_time) {
+ oldest_time = (*iter).second.lastaccess;
+ oldest_entry = iter;
+ found = true;
+ }
+ }
+
+ // Kill it if we got it.
+ if (found) {
+ if (config.debug()) {
+ Timestamp tm((*oldest_entry).second.lastaccess);
+ _debugmsg(Mstr("Erasing oldest IP store entry: ") +
+ Mstr(inet_ntoa(oldest_entry->first)) + " on " +
+ tm.desc() + "\n");
+ }
+ store.erase(oldest_entry);
+ }
+
+ Mutex::unlock(&store);
+ dump();
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ipstore/dump.cc
^
|
@@ -0,0 +1,18 @@
+#include "ipstore"
+
+void IPStore::dump() {
+ if (!config.debug())
+ return;
+
+ _debugmsg(Mstr("IPStore dump:\n"));
+ for (StoreMap::iterator iter = store.begin();
+ iter != store.end();
+ iter++) {
+ Timestamp tm((*iter).second.lastaccess);
+ ostringstream o;
+ o << "Client IP " << inet_ntoa(iter->first) << " on "
+ << tm.desc() << " to back end " << (*iter).second.targetbackend
+ << '\n';
+ _debugmsg(o.str());
+ }
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ipstore/ipstore
^
|
@@ -29,11 +29,15 @@
static void activity(struct in_addr clientip, unsigned curbackend);
static unsigned anticipated(unsigned bckend);
static void clear(struct in_addr clientip);
+ static void clearoldest();
static void on() { onoff = true; }
static void off() { onoff = false; }
private:
+ static void dump();
+ static void weed();
+
static StoreMap store;
static bool onoff;
};
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ipstore/target.cc
^
|
@@ -4,30 +4,8 @@
bool IPStore::onoff = false;
int IPStore::target(struct in_addr clientip) {
- time_t now = time(0);
-
- // Weed out store. Done first, because the store should be up to date
- // for some decisions below.
- bool done = false;
- Mutex::lock(&store);
- while (!done) {
- done = true;
- for (StoreMap::iterator iter = store.begin();
- iter != store.end();
- iter++) {
- if (now - ((*iter).second.lastaccess) > config.ipstoretimeout()) {
- if (config.debug()) {
- done = false;
- Timestamp tm((*iter).second.lastaccess);
- debugmsg (Mstr(inet_ntoa(iter->first)) +
- Mstr(" visited on ") + tm.desc() + ", erasing\n");
- }
- store.erase(iter);
- break;
- }
- }
- }
- Mutex::unlock(&store);
+ // Weed out the store, for decisions later
+ weed();
// Let's see if we know the client.
if (store.count(clientip) > 0) {
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ipstore/weed.cc
^
|
@@ -0,0 +1,29 @@
+#include "ipstore"
+
+void IPStore::weed() {
+ time_t now = time(0);
+ bool done = false;
+
+ Mutex::lock(&store);
+
+ while (!done) {
+ done = true;
+ for (StoreMap::iterator iter = store.begin();
+ iter != store.end();
+ iter++) {
+ if (now - ((*iter).second.lastaccess) > config.ipstoretimeout()) {
+ if (config.debug()) {
+ Timestamp tm((*iter).second.lastaccess);
+ _debugmsg (Mstr("Stale entry: ") + Mstr(inet_ntoa(iter->first)) +
+ Mstr(" visited on ") + tm.desc() +
+ ", erasing\n");
+ }
+ done = false;
+ store.erase(iter);
+ break;
+ }
+ }
+ }
+
+ Mutex::unlock(&store);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/netbuffer/netread.cc
^
|
@@ -8,10 +8,10 @@
set.add(fd);
set.wait_r();
if (! set.readable(fd)) {
- ostringstream o;
- o << "Fd " << fd << " failed to become readable within "
- << int(timeout) << " sec";
- throw Error(o.str());
+ msg(Mstr("Fd ") + Mstr(fd) +
+ Mstr(" failed to become readable within ") + Mstr(timeout) +
+ Mstr(" sec"));
+ return 0;
}
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/netbuffer/netwrite.cc
^
|
@@ -27,8 +27,16 @@
}
// Send to the socket
- unsigned totwritten = 0;
+ unsigned totwritten = 0, ntries = 0;
while (totwritten < buf_sz) {
+ // Don't go beyond 5 tries.
+ if (++ntries > 4) {
+ ostringstream o;
+ o << "Network writing to fd " << fd << " failed, "
+ << totwritten << " bytes sent of " << buf_sz;
+ throw Error(o.str());
+ }
+
// Wait for the socket to become writeable.
if (timeout) {
Fdset set (timeout);
@@ -50,6 +58,7 @@
// EINVAL / EINPROGRESS errors are handled as: retry
// All other errors mean the link is broken
if (nwritten >= 1) {
+ ntries = 0;
if (config.debug()) {
ostringstream o;
o << "Sent " << nwritten << " bytes to fd " << fd << ": ";
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/sys/main.cc
^
|
@@ -46,16 +46,27 @@
}
}
+static int org_argc;
+static char **org_argv;
static void sigcatcher (int sig) {
debugmsg ("Seen signal " + sig + '\n');
- if (sig == SIGHUP)
+ switch (sig) {
+ case SIGHUP:
+ /* Generate a report to the log. Somewhat stale given the
+ * web interface. */
balancer.report(true);
- else if (sig != SIGPIPE && sig != SIGSTOP)
+ break;
+ case SIGPIPE:
+ case SIGSTOP:
+ /* SIGPIPE is ignored (See below). Leaving in place for future
+ * versions. SIGSTOP is used for stopping separarte treads. */
balancer.terminate(true);
- // Actually we wouldn't need to test for SIGPIPE, it's ignored (see below).
- // Leaving the test in place for future versions, better an extra if
- // than forgetting it later.
- // SIGSTOP is used for stopping separare threads.
+ break;
+ case SIGSEGV:
+ /* Production-grade protection - don't ever crash! */
+ balancer.restart(true);
+ break;
+ }
}
int main (int argc, char **argv) {
@@ -63,10 +74,15 @@
PROFILE("main");
static int relevant_sig[] = {
- SIGHUP, SIGINT, SIGQUIT, SIGABRT, SIGTERM, SIGSTOP
+ SIGHUP, SIGINT, SIGQUIT, SIGABRT, SIGTERM, SIGSTOP,
+ // SIGSEGV
};
try {
+ // Save original commandline
+ org_argc = argc;
+ org_argv = argv;
+
// Load configuration from the commandline, promote verbosity
config.parsecmdline (argc, argv);
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/webinterface/answer.cc
^
|
@@ -4,8 +4,7 @@
Threadinfo info = Threadlist::info(id);
msg((Mstr("Stopping thread ") + id) +
(Mstr(" (backend socket ") + info.backendfd()) +
- (Mstr(", client socket ") + info.clientfd()) +
- ")\n");
+ (Mstr(", client socket ") + info.clientfd()) + ")\n");
socketclose(info.backendfd());
socketclose(info.clientfd());
Threadlist::deregister(id);
@@ -518,6 +517,16 @@
answer_status();
return;
}
+
+ // /backend/NR/urlmatch/EXPRESSION
+ // /backend/NR/urlmatch
+ if (parts.size() == 4 &&
+ parts[0] == "backend" && parts[2] == "urlmatch") {
+ unsigned ind = backendindex(parts[1]);
+ balancer.backend(ind).urlmatch(parts[3]);
+ answer_status();
+ return;
+ }
// /backend/NR/up/BOOL
if (parts.size() == 4 && parts[0] == "backend" && parts[2] == "up") {
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/webinterface/answerstatus.cc
^
|
@@ -23,6 +23,7 @@
" <backendreadtimeout>" << config.backend_read_timeout() << "</backendreadtimeout>\n"
" <backendwritetimeout>" << config.backend_write_timeout() << "</backendwritetimeout>\n"
" <dispatchmode>" << config.dispatchmodestr() << "</dispatchmode>\n"
+ " <removereservations>" << config.removereservations() << "</removereservations>\n"
" <webinterface>" << config.webinterfaceip() << ':' << config.webinterfaceport() << "</webinterface>\n"
" <dnscachetimeout>" << config.dnscachetimeout() << "</dnscachetimeout>\n"
" <buffersize>" << config.buffersize() << "</buffersize>\n"
@@ -107,6 +108,7 @@
" <bytesserved>" << balancer.backend(i).bytesserved() << "</bytesserved>\n"
" <clientsserved>" << balancer.backend(i).clientsserved() << "</clientsserved>\n"
" <hostmatch>" << balancer.backend(i).hostmatch() << "</hostmatch>\n"
+ " <urlmatch>" << balancer.backend(i).urlmatch() << "</urlmatch>\n"
" <backendcheck>" << balancer.backend(i).backendcheck().setting() << "</backendcheck>\n"
" </backend>\n"
;
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xrctl/xrctl
^
|
@@ -1,6 +1,7 @@
#!/usr/bin/perl
use strict;
use Getopt::Std;
+use Term::ANSIColor qw(:constants);
# Versioning
my $VER = "__VER__";
@@ -11,6 +12,7 @@
# Default configuration file to read and default logging facility
my $default_conf = '/etc/xrctl.xml';
my $default_logger = 'logger';
+my $default_prefixtimestamp = undef;
# Default settings, must match xr's defaults
my $default_dispatchmode = 'least-connections';
@@ -26,6 +28,7 @@
my $default_checkupinterval = 0;
my $default_weight = 1;
my $default_hostmatch = '.';
+my $default_urlmatch = '.';
my $default_backendcheck = 'connect::';
my $default_timeinterval = 1;
my $default_hardmaxconnrate = 0;
@@ -57,7 +60,7 @@
if ($sysblock ne '') {
my $sysxp = new XMLParser($xp->data('system'));
for my $tag qw(pscmd logger uselogger logdir
- maxlogsize loghistory path) {
+ maxlogsize loghistory path prefixtimestamp) {
$sysconf{$tag} = $sysxp->data($tag);
msg("System config $tag: $sysconf{$tag}\n") if ($sysconf{$tag} ne '');
}
@@ -78,6 +81,15 @@
}
}
msg ("PS command: $sysconf{pscmd}\n");
+
+ if ($sysconf{prefixtimestamp}) {
+ $default_prefixtimestamp = 1 if istrue($sysconf{prefixtimestamp});
+ } else {
+ $default_prefixtimestamp = 1
+ if (!istrue($sysconf{uselogger}) or !find_bin('logger'));
+ }
+ msg ("Log lines will be prefixed with a timestamp\n")
+ if ($default_prefixtimestamp);
}
# Load up the service names.
@@ -227,13 +239,13 @@
sub cmd_status {
for my $s (@_) {
print ("Service $s: ");
- print ("not ") unless (is_running($s));
+ print (BOLD, RED, "not ", RESET) unless (is_running($s));
print ("running\n");
}
}
sub cmd_rotate {
- if ($sysconf{uselogger} and find_bin($default_logger)) {
+ if (istrue($sysconf{uselogger}) and find_bin($default_logger)) {
print ("Rotating not necessary, logging goes via logger\n");
return;
}
@@ -325,7 +337,7 @@
-v increases verbosity
-c CONFIG specifies the configuration, default $default_conf
Actions are:
- configtest builds invocations from the configuration file and validates them
+ configtest validates the configuration
list shows the xr command line
start starts the service(s) if they are not yet running
stop gracefully stops the service(s) if they are running
@@ -365,8 +377,8 @@
# Unconditionally start a given service
sub start_service {
my $s = shift;
- my @args = xr_cmdarr($s);
my $xr = xfind_bin('xr');
+ my @args = xr_cmdarr($s);
my $logstr = log_file($s);
my $logtype = substr($logstr, 0, 1);
my $logout = substr($logstr, 1);
@@ -436,9 +448,10 @@
my $service = shift;
my $logger = find_bin($default_logger);
if (istrue($sysconf{uselogger}) and defined($logger)) {
- if ($logger eq 'logger') {
+ if ($default_logger eq 'logger') {
return ("|$logger -t 'xr-$service'");
} else {
+ $logger =~ s/\{service\}/$service/g;
return ("|$logger");
}
} else {
@@ -472,7 +485,7 @@
my @cmd;
push (@cmd, "xr-$service");
push (@cmd, '--prefix-timestamp')
- if (!istrue($sysconf{uselogger}) or !find_bin('logger'));
+ if ($default_prefixtimestamp);
# Fetch the <service> block for this service
my $sp = xml_serviceparser($service)
@@ -490,7 +503,8 @@
# Flags that should go on the command line if the bool-tag is true
my %boolflags = (closesocketsfast => '--close-sockets-fast',
verbose => '--verbose',
- debug => '--debug');
+ debug => '--debug',
+ removereservations => '--remove-reservations');
# Handle general flags and boolflags
push (@cmd,
@@ -576,7 +590,8 @@
}
# The <backend> blocks for this service
- my $last_hostmatch = $default_hostmatch;
+ my $last_hostmatch = $default_hostmatch;
+ my $last_urlmatch = $default_urlmatch;
my $last_backendcheck = $default_backendcheck;
for (my $i = 0; ; $i++) {
my $bp = xml_backendparser($sp, $i) or last;
@@ -588,7 +603,16 @@
} elsif ($hm eq '' and $last_hostmatch ne '') {
push (@cmd, '--host-match', $default_hostmatch);
}
- $last_hostmatch = $hm;
+ $last_hostmatch = $hm;
+
+ # Handle url match
+ my $um = $bp->data('urlmatch');
+ if ($um and $um ne $last_urlmatch) {
+ push (@cmd, '--url-match', $um);
+ } elsif ($um eq '' and $last_urlmatch ne '') {
+ push (@cmd, '--url-match', $default_urlmatch);
+ }
+ $last_urlmatch = $um;
# Handle back end checks
my $bc = $bp->data('backendcheck');
|