#
#
# patch "README"
# from [ac0ae174796b5559a1550aa7ca5f95060dce5fa2]
# to [9d6513187b124d5da68f44aaf14830dd4c7cabb0]
#
# patch "administrator.cc"
# from [e6271c8806d89446734f9c93ce08a24a63dfb4a3]
# to [eba2e7b41eebc17106d65e4e960f6ff879f11655]
#
# patch "administrator.hh"
# from [2e5057dacae5de057174d7424c7b572ab1c72258]
# to [a83c72863bdd49f0d1b0f19c0fe162679a641857]
#
# patch "channel.cc"
# from [c640472ee1249d74eeffcc952e779b2980d555dc]
# to [f63e867befc8845dfbf993d6e638916ce5b2bfe6]
#
# patch "channel.hh"
# from [0416de1474ad63b22f1e662a752e93129e3cf9f2]
# to [d0f7fc0f54521a2e18a2878eafed1d9a7e441a15]
#
# patch "server.cc"
# from [495a7153e9c9d2d314624c99d8edc5dec5c059db]
# to [337aa17cc392eba09b14af9e1a4081ea93fb54c0]
#
# patch "server.hh"
# from [11f759e526dd912e587ab12079cc60752efad741]
# to [393e13acf9ef6b89982a19e6feeb6f0588ef95e7]
#
# patch "server_manager.cc"
# from [444fdd0e31957863451d6ca36706879dfce87c9f]
# to [5c701d81bee22a2275ea098acd51ad7c5ed6f0fb]
#
# patch "server_manager.hh"
# from [1152c59274ff86e1192341696acfe57a15a146a2]
# to [222e58ae1ba6b9ffc74b01cf7eae4a5dfb1cdf03]
#
# patch "sock.hh"
# from [4b136726ab92c01b4378e5bb1c1b56e2a4c11acf]
# to [0d39d1441b34e9dfbc506499fa8a5fe7aa964f3f]
#
# patch "usher.cc"
# from [6489eda7b440f9f5228dbd9b9e13c906cbff8b73]
# to [152cec4e3210169e12a02cc24cbb86c32ea21db3]
#
============================================================
--- README ac0ae174796b5559a1550aa7ca5f95060dce5fa2
+++ README 9d6513187b124d5da68f44aaf14830dd4c7cabb0
@@ -46,6 +46,7 @@
userpass "username" "password"
monotone "mtn" "-k" "my_key"
listenaddr "0.0.0.0:4691"
+automateaddr "127.1.2.3:5541"
adminaddr "127.0.0.1:12345"
logdir "/var/log/usher/"
@@ -83,6 +84,11 @@
Normal address and portnumber on which the usher process should listen for
incoming connections
Default: listenaddr "0.0.0.0:4691"
+
+automateaddr "
:"
+ Normal address and portnumber on which the usher process should listen for
+ incoming automate connections
+ Default: none
logdir "/path/for/logfiles/"
A path (ending in a slash) where logfiles usher produces should be stored.
============================================================
--- administrator.cc e6271c8806d89446734f9c93ce08a24a63dfb4a3
+++ administrator.cc eba2e7b41eebc17106d65e4e960f6ff879f11655
@@ -47,7 +47,7 @@ administrator::administrator(server_mana
}
administrator::administrator(server_manager &sm, string const &cf)
- : port(-1), serverport(-1), manager(sm), conffile(cf)
+ : port(-1), serverport(-1), au_serverport(-1), manager(sm), conffile(cf)
{
reload_conffile();
}
@@ -201,7 +201,8 @@ void
}
void
-administrator::initialize(string const & ap, string const & sp)
+administrator::initialize(string const & ap, string const & sp,
+ string const & au)
{
sock oldport(-1);
if (!ap.empty())
@@ -231,6 +232,20 @@ administrator::initialize(string const &
if (oldport != -1)
oldport.close();
}
+
+ if (!au.empty())
+ {
+ oldport = au_serverport;
+ try {
+ au_serverport = start(au);
+ } catch (errstr & s) {
+ cerr<<"Could not initialize server port: "< > opts = defaults::defaults;
admins.clear();
- string ap, sp;
+ string ap, sp, au;
if (serverport == -1)
sp = defaults::listenport;
for (vector::iterator i = st.items.begin();
@@ -344,6 +359,11 @@ administrator::reload_conffile()
if (!i->values.empty())
sp = i->values[0].parsed;
}
+ else if (i->key == "automateaddr")
+ {
+ if (!i->values.empty())
+ au = i->values[0].parsed;
+ }
else
{
vector vals;
@@ -355,7 +375,7 @@ administrator::reload_conffile()
opts[i->key] = vals;
}
}
- initialize(ap, sp);
+ initialize(ap, sp, au);
manager.set_opts(opts);
manager.reload_servers();
}
============================================================
--- administrator.hh 2e5057dacae5de057174d7424c7b572ab1c72258
+++ administrator.hh a83c72863bdd49f0d1b0f19c0fe162679a641857
@@ -19,6 +19,7 @@ struct administrator
{
sock port;
sock serverport;
+ sock au_serverport;
struct cstate
{
bool auth;
@@ -32,7 +33,8 @@ struct administrator
string conffile;
administrator(server_manager &sm, string const &cf);
bool process(cstate & cs);
- void initialize(string const & ap, string const & sp);
+ void initialize(string const & ap, string const & sp,
+ string const & au);
void add_to_select(int & maxfd, fd_set & rd, fd_set & wr, fd_set & er);
void process_selected(fd_set & rd, fd_set & wr, fd_set & er);
void reload_conffile();
============================================================
--- channel.cc c640472ee1249d74eeffcc952e779b2980d555dc
+++ channel.cc f63e867befc8845dfbf993d6e638916ce5b2bfe6
@@ -34,25 +34,28 @@ string sockname(sock & s)
return out;
}
-channel::channel(sock & c, server_manager &sm)
+channel::channel(sock & c, server_manager &sm, connection_type k)
: num(++counter),
- cli(c), srv(-1),
- have_routed(false), no_server(false),
- manager(sm)
+ cli(c), srv(-1),
+ have_routed(false), no_server(false),
+ manager(sm),
+ kind(k)
{
name = sockname(cli);
- char * dat;
- int size;
- make_packet(greeting, dat, size);
- char *p;
- int n;
- sbuf.getwrite(p, n);
- if (n < size) size = n;
- memcpy(p, dat, size);
- sbuf.fixwrite(size);
- delete[] dat;
+ if (kind == netsync_connection) {
+ char * dat;
+ int size;
+ make_packet(greeting, dat, size);
+ char *p;
+ int n;
+ sbuf.getwrite(p, n);
+ if (n < size) size = n;
+ memcpy(p, dat, size);
+ sbuf.fixwrite(size);
+ delete[] dat;
- cli.write_from(sbuf);
+ cli.write_from(sbuf);
+ }
}
channel::~channel()
@@ -120,25 +123,57 @@ channel::process_selected(fd_set & rd, f
if (c > 0 && FD_ISSET(c, &rd)) {
if (!cli.read_to(cbuf)) c = -1;
if (!have_routed) {
- string reply_srv, reply_pat;
- if (extract_reply(cbuf, reply_srv, reply_pat)) {
- try {
- serversock ss = manager.connect_to_server(reply_srv, reply_pat,
- name);
- srv = ss;
- have_routed = true;
- s = srv;
- } catch (errstr & e) {
- char * dat;
- int size;
- sbuf.getwrite(p, n);
- make_packet("!" + e.name, dat, size);
- if (n < size) size = n;
- memcpy(p, dat, size);
- sbuf.fixwrite(size);
- delete[] dat;
- no_server = true;
+ if (kind == netsync_connection) {
+ string reply_srv, reply_pat;
+ if (extract_reply(cbuf, reply_srv, reply_pat)) {
+ try {
+ serversock ss = manager.connect_to_server(reply_srv, reply_pat,
+ name, kind);
+ srv = ss;
+ have_routed = true;
+ s = srv;
+ } catch (errstr & e) {
+ char * dat;
+ int size;
+ sbuf.getwrite(p, n);
+ make_packet("!" + e.name, dat, size);
+ if (n < size) size = n;
+ memcpy(p, dat, size);
+ sbuf.fixwrite(size);
+ delete[] dat;
+ no_server = true;
+ }
}
+ } else /* kind == automate_connection */ {
+ if (cbuf.canread()) {
+ char *dat;
+ int len;
+ cbuf.getread(dat, len);
+ int eol = 0;
+ while (eol < len && dat[eol] != '\n' && dat[eol] != '\r') {
+ ++eol;
+ }
+ if (eol != len) {
+ string sname(dat, eol);
+ cbuf.fixread(eol);
+ try {
+ serversock ss = manager.connect_to_server(sname, name, kind);
+ srv = ss;
+ have_routed = true;
+ s = srv;
+ } catch (errstr & e) {
+ string err("Cannot connect to server: ");
+ err += e.name;
+ err += "\n";
+ sbuf.getwrite(p, n);
+ int size = err.size();
+ if (n < size) size = n;
+ memcpy(p, err.c_str(), size);
+ sbuf.fixwrite(size);
+ no_server = true;
+ }
+ }
+ }
}
}
}
============================================================
--- channel.hh 0416de1474ad63b22f1e662a752e93129e3cf9f2
+++ channel.hh d0f7fc0f54521a2e18a2878eafed1d9a7e441a15
@@ -14,6 +14,7 @@ struct channel
struct channel
{
+ connection_type kind;
static int counter;
int num;
sock cli;
@@ -24,7 +25,7 @@ struct channel
buffer sbuf;
server_manager &manager;
string name;
- channel(sock & c, server_manager &sm);
+ channel(sock & c, server_manager &sm, connection_type k);
~channel();
bool is_finished();
void add_to_select(int & maxfd, fd_set & rd, fd_set & wr, fd_set & er);
============================================================
--- server.cc 495a7153e9c9d2d314624c99d8edc5dec5c059db
+++ server.cc 337aa17cc392eba09b14af9e1a4081ea93fb54c0
@@ -91,7 +91,7 @@ server::server(server_manager &sm)
}
server::server(server_manager &sm)
- : enabled(true), local(false), pid(-1), port(0),
+ : enabled(true), local(false), pid(-1), port(0), au_port(0),
connection_count(0), last_conn_time(0), manager(sm)
{
}
@@ -143,7 +143,7 @@ check_address_empty(string const & addr,
sockaddr_in a;
memset (&a, 0, sizeof (a));
if (!inet_aton(addr.c_str(), (in_addr *) &a.sin_addr.s_addr))
- throw errstr("bad ip address format", 0);
+ throw errstr("(check_address_empty) bad ip address format", 0);
a.sin_port = htons(port);
a.sin_family = AF_INET;
int r = bind(s, (sockaddr *) &a, sizeof(a));
@@ -188,14 +188,14 @@ make_outgoing(int port, string const & a
a.sin_port = htons(port);
if (!inet_aton(address.c_str(), (in_addr *) &a.sin_addr.s_addr))
- throw errstr("bad ip address format", 0);
+ throw errstr(string("(make outgoing) bad ip address format <") + address + ">", 0);
tosserr(connect(s, (sockaddr *) &a, sizeof (a)), "connect()");
return s;
}
sock
-server::connect(string const &name)
+server::connect(string const &name, connection_type kind)
{
if (!enabled)
throw errstr("This server is disabled.");
@@ -217,9 +217,14 @@ server::connect(string const &name)
for (int i = 0; i < 3 && pid == -1; ++i) {
if (i > 0 || port == 0)
find_addr(addr, port);
+ if (i > 0 || au_port == 0)
+ find_addr(au_addr, au_port);
vector args = opts["monotone"];
args.push_back("serve");
- args.push_back("--bind=" + addr + ":" + lexical_cast(port));
+ args.push_back("--bind=" + addr + ":"
+ + lexical_cast(port));
+ args.push_back("--bind-automate=" + au_addr + ":"
+ + lexical_cast(au_port));
for (vector::iterator j = arguments.begin();
j != arguments.end(); ++j)
args.push_back(*j);
@@ -228,7 +233,12 @@ server::connect(string const &name)
}
if (pid == -1)
throw errstr("Cannot fork server.");
- sock s = make_outgoing(port, addr);
+ sock s(-1);
+ if (kind == netsync_connection) {
+ s = make_outgoing(port, addr);
+ } else {
+ s = make_outgoing(au_port, au_addr);
+ }
++connection_count;
clients.insert(name);
return s;
@@ -326,10 +336,10 @@ int fork_server(string const &logfile, v
exit(6);
} else {
close(err[1]);
- char head[256];
+ char head[1024];
int got = 0;
int r = 0, w = 0;
- bool line = false;
+ int lines = 0;
// the first line output on the server's stderr will be either
// "mtn: beginning service on : " or
// "mtn: network error: bind(2) error: Address already in use"
@@ -339,21 +349,27 @@ int fork_server(string const &logfile, v
// because read() doesn't block on EOF.
do {
usleep(10*1000);
- r = read(err[0], head + got, 256 - got);
+ r = read(err[0], head + got, sizeof(head) - got);
if (r)
cerr<<"Read '"< 0) {
- for (int i = 0; i < r && !line; ++i)
+ for (int i = 0; i < r && lines < 2; ++i)
if (head[got+i] == '\n')
- line = true;
+ ++lines;
got += r;
}
w = waitpid(pid, 0, WNOHANG);
- } while((!w || r > 0) && !line && got < 256);
+ } while((!w || r > 0) && lines < 2 && got < sizeof(head));
head[got] = 0;
close(err[0]);
- if (string(head).find("beginning service") != string::npos)
- return pid;
+ string h(head);
+ string beginning("beginning service");
+ int found = h.find(beginning);
+ if (found != string::npos) {
+ found = h.find(beginning, found + beginning.size());
+ if (found != string::npos)
+ return pid;
+ }
kill(pid, SIGKILL);
int status;
do {r = waitpid(pid, &status, 0);} while (r==-1 && errno == EINTR);
============================================================
--- server.hh 11f759e526dd912e587ab12079cc60752efad741
+++ server.hh 393e13acf9ef6b89982a19e6feeb6f0588ef95e7
@@ -35,8 +35,13 @@ struct server
bool local;
int pid;
vector arguments;
+
string addr;
int port;
+
+ string au_addr;
+ int au_port;
+
int connection_count;
set clients;
int last_conn_time;
@@ -45,7 +50,7 @@ struct server
server(server_manager &sm);
~server();
serverstate get_state();
- sock connect(string const &name);
+ sock connect(string const &name, connection_type kind);
void disconnect(string const &name);
void maybekill();
void yeskill();
============================================================
--- server_manager.cc 444fdd0e31957863451d6ca36706879dfce87c9f
+++ server_manager.cc 5c701d81bee22a2275ea098acd51ad7c5ed6f0fb
@@ -183,7 +183,8 @@ server_manager::connect_to_server(string
serversock
server_manager::connect_to_server(string const &host,
string const &pattern,
- string const &name)
+ string const &name,
+ connection_type kind)
{
if (!connections_allowed)
throw errstr("All servers are disabled.");
@@ -203,7 +204,7 @@ server_manager::connect_to_server(string
}
if (srv)
{
- sock s = srv->connect(name);
+ sock s = srv->connect(name, kind);
serversock ss(s);
map, serverdata>::iterator i = servers.find(srv);
if (i == servers.end())
@@ -220,6 +221,41 @@ server_manager::connect_to_server(string
throw errstr("Could not find a monotone instance for the pattern '" + pattern + "', perhaps make it less generic?.");
}
}
+
+serversock
+server_manager::connect_to_server(string const &srvname,
+ string const &cliname,
+ connection_type kind)
+{
+ if (!connections_allowed)
+ throw errstr("All servers are disabled.");
+
+ shared_ptr srv;
+ map >::iterator i;
+ i = by_name.find(srvname);
+ if (i != by_name.end())
+ srv = i->second;
+
+ if (srv)
+ {
+ sock s = srv->connect(cliname, kind);
+ serversock ss(s);
+ map, serverdata>::iterator i = servers.find(srv);
+ if (i == servers.end())
+ throw errstr("server_manager is inconsistent");
+ ss.srv = i->second.name;
+ ++total_connections;
+ if (srv->local && srv->connection_count == 1)
+ {
+ live.insert(srv);
+ }
+ return ss;
+ }
+ else {
+ throw errstr("Could not find a monotone instance named '" + srvname + "'.");
+ }
+}
+
void
server_manager::disconnect_from_server(serversock const &s,
string const &name)
============================================================
--- server_manager.hh 1152c59274ff86e1192341696acfe57a15a146a2
+++ server_manager.hh 222e58ae1ba6b9ffc74b01cf7eae4a5dfb1cdf03
@@ -70,8 +70,13 @@ public:
void allow_connections(bool allow=true);
string start_stop_server(string const &srv, bool start);
void reload_servers();
- serversock connect_to_server(string const &host, string const &pattern,
- string const &name);
+ serversock connect_to_server(string const &host,
+ string const &pattern,
+ string const &name,
+ connection_type kind);
+ serversock connect_to_server(string const & srvname,
+ string const & cliname,
+ connection_type kind);
void disconnect_from_server(serversock const &s,
string const &name);
string get_server_state(string const &name);
============================================================
--- sock.hh 4b136726ab92c01b4378e5bb1c1b56e2a4c11acf
+++ sock.hh 0d39d1441b34e9dfbc506499fa8a5fe7aa964f3f
@@ -6,6 +6,8 @@ struct buffer;
struct buffer;
+enum connection_type { netsync_connection, automate_connection };
+
struct sock
{
int *s;
============================================================
--- usher.cc 6489eda7b440f9f5228dbd9b9e13c906cbff8b73
+++ usher.cc 152cec4e3210169e12a02cc24cbb86c32ea21db3
@@ -130,7 +130,7 @@ int main (int argc, char **argv)
while(sigaction(SIGTERM, &sa, &sa_old) == -1 && errno == EINTR);
while(sigaction(SIGINT, &sa, &sa_old) == -1 && errno == EINTR);
- if (admin.serverport == -1)
+ if (admin.serverport == -1 || admin.au_serverport == -1)
{
std::cerr<<"Cannot open port.\n";
exit(1);
@@ -146,6 +146,11 @@ int main (int argc, char **argv)
FD_ZERO (&er);
FD_SET (admin.serverport, &rd);
int nfds = admin.serverport;
+ if (admin.au_serverport != -1) {
+ FD_SET (admin.au_serverport, &rd);
+ if (nfds < admin.au_serverport)
+ nfds = admin.au_serverport;
+ }
channel *newchan = 0;
for (std::list::iterator i = channels.begin();
@@ -173,7 +178,7 @@ int main (int argc, char **argv)
sock cli = tosserr(accept(admin.serverport, (struct sockaddr *)
&client_address, &l), "accept()");
if (manager.get_connections_allowed())
- newchan = new channel(cli, manager);
+ newchan = new channel(cli, manager, netsync_connection);
else {
char * dat;
int size;
@@ -185,6 +190,22 @@ int main (int argc, char **argv)
cerr<<"During new connection: "<::iterator> finished;
for (std::list::iterator i = channels.begin();
i != channels.end(); ++i) {