diff options
Diffstat (limited to 'storage/ndb/tools/old_dirs/ndbnet/ndbnetd.pl')
-rw-r--r-- | storage/ndb/tools/old_dirs/ndbnet/ndbnetd.pl | 400 |
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: |