version 1.73, 2006/01/27 16:35:13
|
version 1.77, 2007/03/27 19:38:36
|
Line 115 my $LondConnecting = 0; # True wh
|
Line 115 my $LondConnecting = 0; # True wh
|
|
|
|
|
my $DieWhenIdle = 1; # When true children die when trimmed -> 0. |
my $DieWhenIdle = 1; # When true children die when trimmed -> 0. |
|
my $hosts_tab = 1; # True if we are using a static hosts.tab |
my $I_am_child = 0; # True if this is the child process. |
my $I_am_child = 0; # True if this is the child process. |
|
|
# |
# |
Line 198 sub Log {
|
Line 199 sub Log {
|
my $now = time; |
my $now = time; |
my $local = localtime($now); |
my $local = localtime($now); |
my $finalformat = "$local ($$) [$RemoteHost] [$Status] "; |
my $finalformat = "$local ($$) [$RemoteHost] [$Status] "; |
my $finalformat = $finalformat.$format."\n"; |
$finalformat = $finalformat.$format."\n"; |
|
|
# open the file and put the result. |
# open the file and put the result. |
|
|
Line 331 sub child_exit {
|
Line 332 sub child_exit {
|
# during which no listens will be done on the |
# during which no listens will be done on the |
# lonnet client socket. |
# lonnet client socket. |
# |
# |
my $lock_file = GetLoncSocketPath().".lock"; |
my $lock_file = &GetLoncSocketPath().".lock"; |
open(LOCK,">$lock_file"); |
open(LOCK,">$lock_file"); |
print LOCK "Contents not important"; |
print LOCK "Contents not important"; |
close(LOCK); |
close(LOCK); |
|
if ($hosts_tab) { |
|
unlink(&GetLoncSocketPath()); |
|
} |
exit(0); |
exit(0); |
} |
} |
# Now figure out how we exit: |
# Now figure out how we exit: |
Line 1164 sub QueueDelayed {
|
Line 1167 sub QueueDelayed {
|
|
|
Debug(4, "Delayed path: ".$path); |
Debug(4, "Delayed path: ".$path); |
opendir(DIRHANDLE, $path); |
opendir(DIRHANDLE, $path); |
|
|
my @alldelayed = grep /\.$RemoteHost$/, readdir DIRHANDLE; |
my @all_host_ids; |
|
my $host_iterator = &LondConnection::GetHostIterator(); |
|
while (!$host_iterator->end()) { |
|
my ($host_id,$host_name) = @{$host_iterator->get()}[0,3]; |
|
if ($host_name eq $RemoteHost) { |
|
push(@all_host_ids, $host_id); |
|
} |
|
$host_iterator->next(); |
|
} |
|
my $host_id_re = '(?:'.join('|',@all_host_ids).')'; |
|
my @alldelayed = grep(/\.$host_id_re$/, readdir(DIRHANDLE)); |
closedir(DIRHANDLE); |
closedir(DIRHANDLE); |
my $dfname; |
foreach my $dfname (sort(@alldelayed)) { |
my $reqfile; |
my $reqfile = "$path/$dfname"; |
foreach $dfname (sort @alldelayed) { |
my ($host_id) = ($dfname =~ /\.([^.]*)$/); |
$reqfile = "$path/$dfname"; |
Debug(4, "queueing ".$reqfile." for $host_id"); |
Debug(4, "queueing ".$reqfile); |
|
my $Handle = IO::File->new($reqfile); |
my $Handle = IO::File->new($reqfile); |
my $cmd = <$Handle>; |
my $cmd = <$Handle>; |
chomp $cmd; # There may or may not be a newline... |
chomp $cmd; # There may or may not be a newline... |
$cmd = $cmd."\n"; # now for sure there's exactly one newline. |
$cmd = $cmd."\n"; # now for sure there's exactly one newline. |
my $Transaction = LondTransaction->new($cmd); |
my $Transaction = LondTransaction->new("sethost:$host_id:$cmd"); |
$Transaction->SetDeferred($reqfile); |
$Transaction->SetDeferred($reqfile); |
QueueTransaction($Transaction); |
QueueTransaction($Transaction); |
} |
} |
Line 1722 sub ChildProcess {
|
Line 1734 sub ChildProcess {
|
desc => 'Lonc Listener Unix Socket', |
desc => 'Lonc Listener Unix Socket', |
fd => $socket); |
fd => $socket); |
|
|
$Event::Debuglevel = $DebugLevel; |
$Event::DebugLevel = $DebugLevel; |
|
|
Debug(9, "Making initial lond connection for ".$RemoteHost); |
Debug(9, "Making initial lond connection for ".$RemoteHost); |
|
|
Line 1796 sub parent_client_connection {
|
Line 1808 sub parent_client_connection {
|
my ($event) = @_; |
my ($event) = @_; |
my $watcher = $event->w; |
my $watcher = $event->w; |
my $socket = $watcher->fd; |
my $socket = $watcher->fd; |
|
if ($hosts_tab) { |
|
|
# Lookup the host associated with this socket: |
# Lookup the host associated with this socket: |
|
|
my $host = $listening_to{$socket}; |
my $host = $listening_to{$socket}; |
|
|
# Start the child: |
# Start the child: |
|
|
|
|
|
|
|
&Debug(9,"Creating child for $host (parent_client_connection)"); |
|
&CreateChild($host, $socket); |
|
|
|
# Clean up the listen since now the child takes over until it exits. |
|
|
|
$watcher->cancel(); # Nolonger listening to this event |
|
delete($listening_to{$socket}); |
|
delete($parent_dispatchers{$host}); |
|
$socket->close(); |
|
|
|
} else { |
|
my $connection = $socket->accept(); # Accept the client connection. |
|
Event->io(cb => \&get_remote_hostname, |
|
poll => 'r', |
|
data => "", |
|
fd => $connection); |
|
} |
|
} |
|
} |
|
|
|
sub get_remote_hostname { |
|
my ($event) = @_; |
|
my $watcher = $event->w; |
|
my $socket = $watcher->fd; |
|
|
|
my $thisread; |
|
my $rv = $socket->recv($thisread, 1, 0); |
|
Debug(8, "rcv: data length = ".length($thisread)." read =".$thisread); |
|
if (!defined($rv) || length($thisread) == 0) { |
|
# Likely eof on socket. |
|
Debug(5,"Client Socket closed on lonc for p_c_c"); |
|
close($socket); |
|
$watcher->cancel(); |
|
return; |
|
} |
|
|
|
my $data = $watcher->data().$thisread; |
|
$watcher->data($data); |
|
if($data =~ /\n$/) { # Request entirely read. |
|
chomp($data); |
|
} else { |
|
return; |
|
} |
|
|
&Debug(9,"Creating child for $host (parent_client_connection)"); |
&Debug(5,"Creating child for $data (parent_client_connection)"); |
&CreateChild($host, $socket); |
&CreateChild($data); |
|
|
# Clean up the listen since now the child takes over until it exits. |
# Clean up the listen since now the child takes over until it exits. |
|
|
$watcher->cancel(); # Nolonger listening to this event |
$watcher->cancel(); # Nolonger listening to this event |
delete($listening_to{$socket}); |
$socket->send("done\n"); |
delete($parent_dispatchers{$host}); |
|
$socket->close(); |
$socket->close(); |
} |
|
} |
} |
|
|
# parent_listen: |
# parent_listen: |
Line 1836 sub parent_listen {
|
Line 1890 sub parent_listen {
|
my ($loncapa_host) = @_; |
my ($loncapa_host) = @_; |
Debug(5, "parent_listen: $loncapa_host"); |
Debug(5, "parent_listen: $loncapa_host"); |
|
|
my $socket = &SetupLoncListener($loncapa_host); |
my $socket = &SetupLoncListener($loncapa_host); |
$listening_to{$socket} = $loncapa_host; |
$listening_to{$socket} = $loncapa_host; |
if (!$socket) { |
if (!$socket) { |
die "Unable to create a listen socket for $loncapa_host"; |
die "Unable to create a listen socket for $loncapa_host"; |
Line 1845 sub parent_listen {
|
Line 1899 sub parent_listen {
|
my $lock_file = &GetLoncSocketPath($loncapa_host).".lock"; |
my $lock_file = &GetLoncSocketPath($loncapa_host).".lock"; |
unlink($lock_file); # No problem if it doesn't exist yet [startup e.g.] |
unlink($lock_file); # No problem if it doesn't exist yet [startup e.g.] |
|
|
my $watcher = Event->io(cb => \&parent_client_connection, |
my $watcher = |
poll => 'r', |
Event->io(cb => \&parent_client_connection, |
desc => "Parent listener unix socket ($loncapa_host)", |
poll => 'r', |
fd => $socket); |
desc => "Parent listener unix socket ($loncapa_host)", |
|
data => "", |
|
fd => $socket); |
$parent_dispatchers{$loncapa_host} = $watcher; |
$parent_dispatchers{$loncapa_host} = $watcher; |
|
|
} |
} |
|
|
|
sub parent_clean_up { |
|
my ($loncapa_host) = @_; |
|
Debug(5, "parent_clean_up: $loncapa_host"); |
|
|
|
my $socket_file = &GetLoncSocketPath($loncapa_host); |
|
unlink($socket_file); # No problem if it doesn't exist yet [startup e.g.] |
|
my $lock_file = $socket_file.".lock"; |
|
unlink($lock_file); # No problem if it doesn't exist yet [startup e.g.] |
|
} |
|
|
|
|
# listen_on_all_unix_sockets: |
# listen_on_all_unix_sockets: |
# This sub initiates a listen on all unix domain lonc client sockets. |
# This sub initiates a listen on all unix domain lonc client sockets. |
Line 1875 sub listen_on_all_unix_sockets {
|
Line 1941 sub listen_on_all_unix_sockets {
|
my $host_iterator = &LondConnection::GetHostIterator(); |
my $host_iterator = &LondConnection::GetHostIterator(); |
while (!$host_iterator->end()) { |
while (!$host_iterator->end()) { |
my $host_entry_ref = $host_iterator->get(); |
my $host_entry_ref = $host_iterator->get(); |
my $host_name = $host_entry_ref->[0]; |
my $host_name = $host_entry_ref->[3]; |
Debug(9, "Listen for $host_name"); |
Debug(9, "Listen for $host_name"); |
&parent_listen($host_name); |
&parent_listen($host_name); |
$host_iterator->next(); |
$host_iterator->next(); |
} |
} |
} |
} |
|
|
|
sub listen_on_common_socket { |
|
Debug(5, "listen_on_common_socket"); |
|
&parent_listen('common'); |
|
} |
|
|
# server_died is called whenever a child process exits. |
# server_died is called whenever a child process exits. |
# Since this is dispatched via a signal, we must process all |
# Since this is dispatched via a signal, we must process all |
# dead children until there are no more left. The action |
# dead children until there are no more left. The action |
Line 1906 sub server_died {
|
Line 1977 sub server_died {
|
&Debug(9, "Caught sigchild for $host"); |
&Debug(9, "Caught sigchild for $host"); |
delete($ChildHash{$pid}); |
delete($ChildHash{$pid}); |
delete($HostToPid{$host}); |
delete($HostToPid{$host}); |
&parent_listen($host); |
if ($hosts_tab) { |
|
&parent_listen($host); |
|
} else { |
|
&parent_clean_up($host); |
|
} |
|
|
} else { |
} else { |
&Debug(5, "Caught sigchild for pid not in hosts hash: $pid"); |
&Debug(5, "Caught sigchild for pid not in hosts hash: $pid"); |
} |
} |
Line 1967 my $HostIterator = LondConnection::GetHo
|
Line 2042 my $HostIterator = LondConnection::GetHo
|
|
|
if ($DieWhenIdle) { |
if ($DieWhenIdle) { |
$RemoteHost = "[parent]"; |
$RemoteHost = "[parent]"; |
&listen_on_all_unix_sockets(); |
if ($hosts_tab) { |
|
&listen_on_all_unix_sockets(); |
|
} else { |
|
&listen_on_common_socket(); |
|
} |
} else { |
} else { |
|
|
while (! $HostIterator->end()) { |
while (! $HostIterator->end()) { |
Line 2005 if ($DieWhenIdle) {
|
Line 2084 if ($DieWhenIdle) {
|
$parent_handlers{TERM} = Event->signal(cb => \&Terminate, |
$parent_handlers{TERM} = Event->signal(cb => \&Terminate, |
desc => "Parent TERM handler", |
desc => "Parent TERM handler", |
signal => "TERM"); |
signal => "TERM"); |
$parent_handlers{HUP} = Event->signal(cb => \&Restart, |
if ($hosts_tab) { |
desc => "Parent HUP handler.", |
$parent_handlers{HUP} = Event->signal(cb => \&Restart, |
signal => "HUP"); |
desc => "Parent HUP handler.", |
|
signal => "HUP"); |
|
} else { |
|
$parent_handlers{HUP} = Event->signal(cb => \&KillThemAll, |
|
desc => "Parent HUP handler.", |
|
signal => "HUP"); |
|
} |
$parent_handlers{USR1} = Event->signal(cb => \&CheckKids, |
$parent_handlers{USR1} = Event->signal(cb => \&CheckKids, |
desc => "Parent USR1 handler", |
desc => "Parent USR1 handler", |
signal => "USR1"); |
signal => "USR1"); |
Line 2030 if ($DieWhenIdle) {
|
Line 2115 if ($DieWhenIdle) {
|
|
|
$SIG{INT} = \&Terminate; |
$SIG{INT} = \&Terminate; |
$SIG{TERM} = \&Terminate; |
$SIG{TERM} = \&Terminate; |
$SIG{HUP} = \&Restart; |
if ($hosts_tab) { |
|
$SIG{HUP} = \&Restart; |
|
} else { |
|
$SIG{HUP} = \&KillThemAll; |
|
} |
$SIG{USR1} = \&CheckKids; |
$SIG{USR1} = \&CheckKids; |
$SIG{USR2} = \&UpdateKids; # LonManage update request. |
$SIG{USR2} = \&UpdateKids; # LonManage update request. |
|
|
Line 2115 sub UpdateKids {
|
Line 2204 sub UpdateKids {
|
# The down side is transactions that are in flight will get timed out |
# The down side is transactions that are in flight will get timed out |
# (lost unless they are critical). |
# (lost unless they are critical). |
|
|
&Restart(); |
if ($hosts_tab) { |
|
&Restart(); |
|
} else { |
|
&KillThemAll(); |
|
} |
} |
} |
|
|
|
|
Line 2156 sub KillThemAll {
|
Line 2248 sub KillThemAll {
|
Log("CRITICAL", "Nicely Killing lonc for $serving pid = $pid"); |
Log("CRITICAL", "Nicely Killing lonc for $serving pid = $pid"); |
kill 'QUIT' => $pid; |
kill 'QUIT' => $pid; |
} |
} |
|
|
|
|
} |
} |
|
|
|
|