version 1.68, 2005/03/15 01:12:20
|
version 1.77, 2007/03/27 19:38:36
|
Line 106 my $ConnectionCount = 0;
|
Line 106 my $ConnectionCount = 0;
|
my $IdleSeconds = 0; # Number of seconds idle. |
my $IdleSeconds = 0; # Number of seconds idle. |
my $Status = ""; # Current status string. |
my $Status = ""; # Current status string. |
my $RecentLogEntry = ""; |
my $RecentLogEntry = ""; |
my $ConnectionRetries=2; # Number of connection retries allowed. |
my $ConnectionRetries=5; # Number of connection retries allowed. |
my $ConnectionRetriesLeft=2; # Number of connection retries remaining. |
my $ConnectionRetriesLeft=5; # Number of connection retries remaining. |
my $LondVersion = "unknown"; # Version of lond we talk with. |
my $LondVersion = "unknown"; # Version of lond we talk with. |
my $KeyMode = ""; # e.g. ssl, local, insecure from last connect. |
my $KeyMode = ""; # e.g. ssl, local, insecure from last connect. |
my $LondConnecting = 0; # True when a connection is being built. |
my $LondConnecting = 0; # True when a connection is being built. |
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 152 sub UpdateStatus {
|
Line 153 sub UpdateStatus {
|
Makes an entry into the permanent log file. |
Makes an entry into the permanent log file. |
|
|
=cut |
=cut |
|
|
sub LogPerm { |
sub LogPerm { |
my $message=shift; |
my $message=shift; |
my $execdir=$perlvar{'lonDaemons'}; |
my $execdir=$perlvar{'lonDaemons'}; |
Line 197 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 271 sub SocketDump {
|
Line 273 sub SocketDump {
|
and as what we return in a SIGUSR1 |
and as what we return in a SIGUSR1 |
|
|
=cut |
=cut |
|
|
sub ShowStatus { |
sub ShowStatus { |
my $state = shift; |
my $state = shift; |
my $now = time; |
my $now = time; |
Line 281 sub ShowStatus {
|
Line 284 sub ShowStatus {
|
|
|
=pod |
=pod |
|
|
=head 2 SocketTimeout |
=head2 SocketTimeout |
|
|
Called when an action on the socket times out. The socket is |
Called when an action on the socket times out. The socket is |
destroyed and any active transaction is failed. |
destroyed and any active transaction is failed. |
|
|
|
|
=cut |
=cut |
|
|
sub SocketTimeout { |
sub SocketTimeout { |
my $Socket = shift; |
my $Socket = shift; |
Log("WARNING", "A socket timeout was detected"); |
Log("WARNING", "A socket timeout was detected"); |
Line 328 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 674 sub FailTransaction {
|
Line 680 sub FailTransaction {
|
|
|
if ($ConnectionRetriesLeft > 0) { |
if ($ConnectionRetriesLeft > 0) { |
Log("WARNING", "Failing transaction " |
Log("WARNING", "Failing transaction " |
.$transaction->getRequest()); |
.$transaction->getLoggableRequest()); |
} |
} |
Debug(1, "Failing transaction: ".$transaction->getRequest()); |
Debug(1, "Failing transaction: ".$transaction->getLoggableRequest()); |
if (!$transaction->isDeferred()) { # If the transaction is deferred we'll get to it. |
if (!$transaction->isDeferred()) { # If the transaction is deferred we'll get to it. |
my $client = $transaction->getClient(); |
my $client = $transaction->getClient(); |
Debug(1," Replying con_lost to ".$transaction->getRequest()); |
Debug(1," Replying con_lost to ".$transaction->getRequest()); |
Line 686 sub FailTransaction {
|
Line 692 sub FailTransaction {
|
} |
} |
|
|
=pod |
=pod |
|
|
=head1 EmptyQueue |
=head1 EmptyQueue |
|
|
Fails all items in the work queue with con_lost. |
Fails all items in the work queue with con_lost. |
Note that each item in the work queue is a transaction. |
Note that each item in the work queue is a transaction. |
|
|
=cut |
=cut |
|
|
sub EmptyQueue { |
sub EmptyQueue { |
$ConnectionRetriesLeft--; # Counts as connection failure too. |
$ConnectionRetriesLeft--; # Counts as connection failure too. |
while($WorkQueue->Count()) { |
while($WorkQueue->Count()) { |
Line 707 sub EmptyQueue {
|
Line 715 sub EmptyQueue {
|
Close all connections open on lond prior to exit e.g. |
Close all connections open on lond prior to exit e.g. |
|
|
=cut |
=cut |
|
|
sub CloseAllLondConnections { |
sub CloseAllLondConnections { |
foreach my $Socket (keys %ActiveConnections) { |
foreach my $Socket (keys %ActiveConnections) { |
if(exists($ActiveTransactions{$Socket})) { |
if(exists($ActiveTransactions{$Socket})) { |
Line 715 sub CloseAllLondConnections {
|
Line 724 sub CloseAllLondConnections {
|
KillSocket($Socket); |
KillSocket($Socket); |
} |
} |
} |
} |
=cut |
|
|
|
=pod |
=pod |
|
|
Line 737 Parameters:
|
Line 745 Parameters:
|
|
|
nonzero if we are allowed to create a new connection. |
nonzero if we are allowed to create a new connection. |
|
|
|
|
=cut |
=cut |
|
|
sub KillSocket { |
sub KillSocket { |
my $Socket = shift; |
my $Socket = shift; |
|
|
Line 950 sub LondReadable {
|
Line 958 sub LondReadable {
|
# We need to be writable for this and probably don't belong |
# We need to be writable for this and probably don't belong |
# here inthe first place. |
# here inthe first place. |
|
|
Deubg(6, "SendingRequest state encountered in readable"); |
Debug(6, "SendingRequest state encountered in readable"); |
$Watcher->poll("w"); |
$Watcher->poll("w"); |
$Watcher->cb(\&LondWritable); |
$Watcher->cb(\&LondWritable); |
|
|
Line 1151 sub LondWritable {
|
Line 1159 sub LondWritable {
|
=pod |
=pod |
|
|
=cut |
=cut |
|
|
sub QueueDelayed { |
sub QueueDelayed { |
Debug(3,"QueueDelayed called"); |
Debug(3,"QueueDelayed called"); |
|
|
Line 1158 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 1559 into the status file.
|
Line 1577 into the status file.
|
|
|
We also use this to reset the retries count in order to allow the |
We also use this to reset the retries count in order to allow the |
client to retry connections with a previously dead server. |
client to retry connections with a previously dead server. |
|
|
=cut |
=cut |
|
|
sub ChildStatus { |
sub ChildStatus { |
Line 1591 sub ChildStatus {
|
Line 1610 sub ChildStatus {
|
flock(LOG,LOCK_UN); |
flock(LOG,LOCK_UN); |
close(LOG); |
close(LOG); |
$ConnectionRetriesLeft = $ConnectionRetries; |
$ConnectionRetriesLeft = $ConnectionRetries; |
|
UpdateStatus(); |
} |
} |
|
|
=pod |
=pod |
Line 1617 sub SignalledToDeath {
|
Line 1637 sub SignalledToDeath {
|
|
|
} |
} |
|
|
|
=pod |
|
|
=head2 ToggleDebug |
=head2 ToggleDebug |
|
|
This sub toggles trace debugging on and off. |
This sub toggles trace debugging on and off. |
Line 1632 sub ToggleDebug {
|
Line 1654 sub ToggleDebug {
|
|
|
} |
} |
|
|
|
=pod |
|
|
=head2 ChildProcess |
=head2 ChildProcess |
|
|
This sub implements a child process for a single lonc daemon. |
This sub implements a child process for a single lonc daemon. |
Line 1710 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 1784 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 1824 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 1833 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 1863 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 1894 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 1955 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 1993 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 2018 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 2103 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 2144 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; |
} |
} |
|
|
|
|
} |
} |
|
|
|
|
Line 2167 sub really_kill_them_all_dammit
|
Line 2269 sub really_kill_them_all_dammit
|
unlink("$execdir/logs/lonc.pid"); |
unlink("$execdir/logs/lonc.pid"); |
} |
} |
} |
} |
|
|
=pod |
=pod |
|
|
=head1 Terminate |
=head1 Terminate |