summaryrefslogtreecommitdiff
path: root/storage/ndb/tools/old_dirs/ndbnet/ndbnetd.pl
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb/tools/old_dirs/ndbnet/ndbnetd.pl')
-rw-r--r--storage/ndb/tools/old_dirs/ndbnet/ndbnetd.pl400
1 files changed, 400 insertions, 0 deletions
diff --git a/storage/ndb/tools/old_dirs/ndbnet/ndbnetd.pl b/storage/ndb/tools/old_dirs/ndbnet/ndbnetd.pl
new file mode 100644
index 00000000000..95fa5322abc
--- /dev/null
+++ b/storage/ndb/tools/old_dirs/ndbnet/ndbnetd.pl
@@ -0,0 +1,400 @@
+#! /usr/local/bin/perl
+
+use strict;
+use POSIX();
+use Socket;
+use Getopt::Long;
+use File::Basename;
+use File::Spec;
+
+use NDB::Net;
+
+# save argv for restart via client
+my @origargv = @ARGV;
+
+# get options and environment
+
+my $log = NDB::Util::Log->instance;
+
+sub printhelp {
+ print <<END;
+ndbnetd -- ndbnet daemon
+usage: ndbnetd [options]
+--help print this text and exit
+--base dir ndb installation, default \$NDB_BASE
+--netcfg file net config, default \$NDB_BASE/etc/ndbnet.xml
+--port num port number (if more than 1 server on this host)
+--stop kill any existing server
+--restart kill any existing server and start a new one
+--fg run in foreground (test option)
+--log prio debug/info/notice/warn/error/fatal, default info
+END
+ exit(0);
+}
+
+my $progopts = {};
+anon: {
+ local $SIG{__WARN__} = sub {
+ my $errstr = "@_";
+ while (chomp($errstr)) {}
+ $log->put("$errstr (try --help)")->fatal;
+ };
+ Getopt::Long::Configure(qw(
+ default no_getopt_compat no_ignore_case no_require_order
+ ));
+ GetOptions($progopts, qw(
+ help base=s netcfg=s port=i stop restart fg log=s
+ ));
+}
+$progopts->{help} && printhelp();
+if (defined(my $prio = $progopts->{log})) {
+ $log->setprio($prio);
+}
+@ARGV and $log->put("extra args on command line")->fatal;
+
+my $netenv = NDB::Net::Env->instance(
+ base => $progopts->{base},
+ netcfg => $progopts->{netcfg},
+);
+$netenv or $log->fatal;
+$netenv->hasbase or $log->put("need NDB_BASE")->fatal;
+
+# load net config and find our entry
+
+my $netcfg = NDB::Net::Config->new(file => $netenv->getnetcfg)
+ or $log->push->fatal;
+my $server;
+
+sub loadnetcfg {
+ $netcfg->load or $log->push->fatal;
+ my $servers = $netcfg->getservers or $log->fatal;
+ my $host = $netenv->gethostname;
+ my $port = $progopts->{port} || 0;
+ my $list = NDB::Net::ServerINET->match($host, $port, $servers)
+ or $log->push->fatal;
+ @$list == 1
+ or $log->push->fatal;
+ $server = $list->[0];
+ $server->setlocal;
+}
+loadnetcfg();
+$log->put("this server")->push($server)->debug;
+
+# check if server already running
+
+my $lock;
+anon: {
+ my $dir = NDB::Util::Dir->new(path => File::Spec->catfile($netenv->getbase, "run"));
+ $dir->mkdir or $log->fatal;
+ my $name = sprintf("ndbnet%s.pid", $server->getid);
+ $lock = $dir->getfile($name)->getlock;
+ my $ret;
+ $ret = $lock->test;
+ defined($ret) or $log->fatal;
+ if ($ret) {
+ if ($progopts->{stop} || $progopts->{restart}) {
+ $log->put("stopping server %s pid=%s", $netenv->gethostname, $lock->getpid)->info;
+ if ($^O ne 'MSWin32') {
+ kill -15, $lock->getpid;
+ } else {
+ kill 15, $lock->getpid;
+ }
+ while (1) {
+ sleep 1;
+ $ret = $lock->test;
+ defined($ret) or $log->fatal;
+ if ($ret) {
+ if (! kill(0, $lock->getpid) && $! == Errno::ESRCH) {
+ $log->put("locked but gone (linux bug?)")->info;
+ $lock->unlink;
+ $ret = 0;
+ }
+ }
+ if (! $ret) {
+ if ($progopts->{stop}) {
+ $log->put("stopped")->info;
+ exit(0);
+ }
+ $log->put("restarting server %s", $netenv->gethostname)->info;
+ last;
+ }
+ }
+ }
+ else {
+ $log->put("already running pid=%s", $lock->getpid)->fatal;
+ }
+ }
+ else {
+ if ($progopts->{stop}) {
+ $log->put("not running")->info;
+ exit(0);
+ }
+ }
+ $lock->set or $log->fatal;
+}
+
+# become daemon, re-obtain the lock, direct log to file
+
+anon: {
+ $log->setpart(time => 1, pid => 1, prio => 1, line => 1);
+ $progopts->{fg} && last anon;
+ $lock->close;
+ my $dir = NDB::Util::Dir->new(path => $netenv->getbase . "/log");
+ $dir->mkdir or $log->fatal;
+ my $pid = fork();
+ defined($pid) or $log->put("fork failed: $!")->fatal;
+ if ($pid) {
+ exit(0);
+ }
+ $lock->set or $log->fatal;
+ if ($^O ne 'MSWin32') {
+ POSIX::setsid() or $log->put("setsid failed: $!")->fatal;
+ }
+ open(STDIN, "</dev/null");
+ my $name = sprintf("ndbnet%s.log", $server->getid);
+ $log->setfile($dir->getfile($name)->getpath) or $log->fatal;
+}
+$log->put("ndbnetd started pid=$$ port=%s", $server->getport)->info;
+
+# create server socket and event
+
+my $socket = NDB::Util::SocketINET->new or $log->fatal;
+my $event = NDB::Util::Event->new;
+
+# commands
+
+sub cmd_server_fg {
+ my($cmd) = @_;
+ my $action = $cmd->getarg(0);
+ if (! $cmd->getopt('local')) {
+ return 1;
+ }
+ if ($action eq 'restart') {
+ my $prog = $netenv->getbase . "/bin/ndbnetd";
+ my @argv = @origargv;
+ if (! grep(/^--restart$/, @argv)) {
+ push(@argv, "--restart");
+ }
+ unshift(@argv, basename($prog));
+ $lock->close;
+ $socket->close;
+ $log->put("restart: @argv")->push($server)->user;
+ $log->put("server restart")->putvalue(1)->user;
+ exec $prog @argv;
+ die "restart failed: $!";
+ }
+ if ($action eq 'stop') {
+ $log->put("stop by request")->push($server)->user;
+ $log->put("server stop")->putvalue(1)->user;
+ exit(0);
+ }
+ if ($action eq 'ping') {
+ return 1;
+ }
+ $log->put("$action: unimplemented");
+ return undef;
+}
+
+sub cmd_server_bg {
+ my($cmd) = @_;
+ loadnetcfg() or return undef;
+ my $action = $cmd->getarg(0);
+ if (! $cmd->getopt('local')) {
+ $cmd->setopt('local')
+ or $log->push, return undef;
+ my $servers = $netcfg->getservers or $log->fatal;
+ my $list;
+ if ($cmd->getopt('all')) {
+ $list = $servers;
+ }
+ else {
+ $list = [];
+ for my $id (@{$cmd->getarglist(1)}) {
+ if (my $s = NDB::Net::ServerINET->get($id)) {
+ push(@$list, $s);
+ next;
+ }
+ if (my $s = NDB::Net::ServerINET->match($id, undef, $servers)) {
+ if (@$s) {
+ push(@$list, @$s);
+ next;
+ }
+ }
+ $log->push;
+ return undef;
+ }
+ }
+ my $fail = 0;
+ for my $s (@$list) {
+ if (! $s->request($cmd)) {
+ $log->push->user;
+ $fail++;
+ }
+ }
+ if ($fail) {
+ $log->put("failed %d/%d", $fail, scalar(@$list));
+ return undef;
+ }
+ return 1;
+ }
+ if ($action eq 'restart') {
+ return 1;
+ }
+ if ($action eq 'stop') {
+ return 1;
+ }
+ if ($action eq 'ping') {
+ $log->put("is alive")->push($server)->user;
+ return 1;
+ }
+ $log->put("$action: unimplemented");
+ return undef;
+}
+
+sub cmd_start_bg {
+ my($cmd) = @_;
+ loadnetcfg() or return undef;
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ $db->start($cmd->getopts) or return undef;
+ return 1;
+}
+
+sub cmd_startnode_bg {
+ my($cmd) = @_;
+ loadnetcfg() or return undef;
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ my $node = $db->getnode($cmd->getarg(1)) or return undef;
+ $node->start($cmd->getopts) or return undef;
+ return 1;
+}
+
+sub cmd_stop_bg {
+ my($cmd) = @_;
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ $db->stop($cmd->getopts) or return undef;
+ return 1;
+}
+
+sub cmd_stopnode_bg {
+ my($cmd) = @_;
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ my $node = $db->getnode($cmd->getarg(1)) or return undef;
+ $node->stop($cmd->getopts) or return undef;
+ return 1;
+}
+
+sub cmd_kill_bg {
+ my($cmd) = @_;
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ $db->kill($cmd->getopts) or return undef;
+ return 1;
+}
+
+sub cmd_killnode_bg {
+ my($cmd) = @_;
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ my $node = $db->getnode($cmd->getarg(1)) or return undef;
+ $node->kill($cmd->getopts) or return undef;
+ return 1;
+}
+
+sub cmd_statnode_bg {
+ my($cmd) = @_;
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ my $node = $db->getnode($cmd->getarg(1)) or return undef;
+ my $ret = $node->stat($cmd->getopts) or return undef;
+ return $ret;
+}
+
+sub cmd_list_bg {
+ my($cmd) = @_;
+ loadnetcfg() or return undef;
+ my $dblist;
+ if ($cmd->getarg(0)) {
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ $dblist = [ $db ];
+ } else {
+ $dblist = $netcfg->getdatabases or return undef;
+ }
+ my $ret = {};
+ for my $db (@$dblist) {
+ my $status = $db->list($cmd->getopts) || "error";
+ $ret->{$db->getname} = $status;
+ }
+ return $ret;
+}
+
+sub cmd_writenode_bg {
+ my($cmd) = @_;
+ my $db = $netcfg->getdatabase($cmd->getarg(0)) or return undef;
+ my $node = $db->getnode($cmd->getarg(1)) or return undef;
+ my $ret = $node->write($cmd->getopts, $cmd->getarg(2)) or return undef;
+ return $ret;
+}
+
+# main program
+
+sub checkchild {
+ while ((my $pid = waitpid(-1, &POSIX::WNOHANG)) > 0) {
+ $log->put("harvested pid=$pid")->info;
+ }
+}
+
+my $gotterm = 0;
+$SIG{INT} = sub { $gotterm = 1 };
+$SIG{TERM} = sub { $gotterm = 1 };
+
+$socket->setopt(SOL_SOCKET, SO_REUSEADDR, 1) or $log->fatal;
+$socket->bind($server->getport) or $log->fatal;
+$socket->listen or $log->fatal;
+$event->set($socket, 'r');
+
+loop: {
+ try: {
+ my $n = $event->poll(10);
+ if ($gotterm) {
+ $log->put("terminate on signal")->info;
+ last try;
+ }
+ if (! defined($n)) {
+ $log->error;
+ sleep 1;
+ last try;
+ }
+ if (! $n) {
+ $log->debug;
+ last try;
+ }
+ if (! $event->test($socket, 'r')) {
+ last try;
+ }
+ my $csocket = $socket->accept(10);
+ if (! defined($csocket)) {
+ $log->error;
+ last try;
+ }
+ if (! $csocket) {
+ $log->warn;
+ last try;
+ }
+ my $client = NDB::Net::Client->new(
+ socket => $csocket,
+ serversocket => $socket,
+ serverlock => $lock,
+ event => $event,
+ context => 'main',
+ );
+ $client or $log->fatal;
+ }
+ loadnetcfg() or $log->fatal;
+ NDB::Net::Client->processall;
+ if ($gotterm) {
+ last loop;
+ }
+ redo loop;
+}
+
+$log->put("ndbnetd done")->info;
+
+1;
+# vim:set sw=4: