try a different strategy
[spider.git] / perl / cluster.pl
index aa44006786c5d382925d10e45cb324f0ca162766..1e850c90f8b9c74a030a1cab913f770d4d86f218 100755 (executable)
@@ -61,9 +61,12 @@ use Filter;
 use DXDb;
 use AnnTalk;
 use WCY;
+use DXDupe;
+use BadWords;
 
 use Data::Dumper;
 use Fcntl ':flock'; 
+use POSIX ":sys_wait_h";
 
 use Local;
 
@@ -71,7 +74,7 @@ package main;
 
 @inqueue = ();                                 # the main input queue, an array of hashes
 $systime = 0;                                  # the time now (in seconds)
-$version = "1.41";                             # the version no of the software
+$version = "1.45";                             # the version no of the software
 $starttime = 0;                 # the starting time of the cluster   
 $lockfn = "cluster.lock";       # lock file name
 @outstanding_connects = ();     # list of outstanding connects
@@ -106,6 +109,11 @@ sub rec
        
        if (!defined $msg || (defined $err && $err)) {
                if ($dxchan) {
+                       if (defined $err) {
+                               $conn->disconnect;
+                               undef $conn;
+                               $dxchan->conn(undef);
+                       }
                        $dxchan->disconnect;
                } elsif ($conn) {
                        $conn->disconnect;
@@ -115,7 +123,8 @@ sub rec
        
        # set up the basic channel info - this needs a bit more thought - there is duplication here
        if (!defined $dxchan) {
-               my ($sort, $call, $line) = $msg =~ /^(\w)(\S+)\|(.*)$/;
+               my ($sort, $call, $line) = DXChannel::decode_input(0, $msg);
+               return unless defined $sort;
  
                # is there one already connected to me - locally? 
                my $user = DXUser->get($call);
@@ -182,6 +191,8 @@ sub cease
        $SIG{'TERM'} = 'IGNORE';
        $SIG{'INT'} = 'IGNORE';
        
+       DXUser::sync;
+
        eval {
                Local::finish();   # end local processing
        };
@@ -211,6 +222,7 @@ sub cease
        Msg->event_loop(1, 0.05);
        Msg->event_loop(1, 0.05);
        DXUser::finish();
+       DXDupe::finish();
 
        # close all databases
        DXDb::closeall;
@@ -227,9 +239,12 @@ sub cease
 # the reaper of children
 sub reap
 {
-       $SIG{'CHLD'} = \&reap;
-       my $cpid = wait;
-       @outstanding_connects = grep {$_->{pid} != $cpid} @outstanding_connects;
+       my $cpid;
+       while (($cpid = waitpid(1, &WNOHANG)) != -1) {
+               dbg('reap', "cpid: $cpid");
+               @outstanding_connects = grep {$_->{pid} != $cpid} @outstanding_connects;
+       }
+       dbg('reap', "cpid: $cpid");
 }
 
 # this is where the input queue is dealt with and things are dispatched off to other parts of
@@ -241,16 +256,9 @@ sub process_inqueue
        
        my $data = $self->{data};
        my $dxchan = $self->{dxchan};
-       my ($sort, $call, $line) = $data =~ /^(\w)([^\|]+)\|(.*)$/;
        my $error;
-       
-       # the above regexp must work
-       return unless ($sort && $call && $line);
-       
-       # translate any crappy characters into hex characters 
-       if ($line =~ /[\x00-\x06\x08\x0a-\x1f\x7f-\xff]/o) {
-               $line =~ s/([\x00-\x1f\x7f-\xff])/uc sprintf("%%%02x",ord($1))/eg;
-       }
+       my ($sort, $call, $line) = DXChannel::decode_input($dxchan, $data);
+       return unless defined $sort;
        
        # do the really sexy console interface bit! (Who is going to do the TK interface then?)
        dbg('chan', "<- $sort $call $line\n") unless $sort eq 'D';
@@ -320,11 +328,30 @@ DXUser->init($userfn, 1);
 dbg('err', "starting listener ...");
 Msg->new_server("$clusteraddr", $clusterport, \&login);
 
+# load bad words
+dbg('err', "load badwords: " . (BadWords::load or "Ok"));
+
 # prime some signals
-$SIG{'INT'} = \&cease;
-$SIG{'TERM'} = \&cease;
-$SIG{'HUP'} = 'IGNORE';
-$SIG{'CHLD'} = \&reap;
+$SIG{INT} = \&cease;
+$SIG{TERM} = \&cease;
+$SIG{HUP} = 'IGNORE';
+$SIG{CHLD} = \&reap;
+
+$SIG{PIPE} = sub {     dbg('err', "Broken PIPE signal received"); };
+$SIG{IO} = sub {       dbg('err', "SIGIO received"); };
+$SIG{WINCH} = $SIG{STOP} = $SIG{CONT} = 'IGNORE';
+$SIG{KILL} = 'DEFAULT';     # as if it matters....
+
+# catch the rest with a hopeful message
+for (keys %SIG) {
+       if (!$SIG{$_}) {
+#              dbg('chan', "Catching SIG $_");
+               $SIG{$_} = sub { my $sig = shift;       DXDebug::confess("Caught signal $sig");  }; 
+       }
+}
+
+# start dupe system
+DXDupe::init();
 
 # read in system messages
 DXM->init();
@@ -345,7 +372,7 @@ DXProt->init();
 
 
 # put in a DXCluster node for us here so we can add users and take them away
-DXNode->new(0, $mycall, 0, 1, $DXProt::myprot_version); 
+DXNode->new($DXProt::me, $mycall, 0, 1, $DXProt::myprot_version); 
 
 # read in any existing message headers and clean out old crap
 dbg('err', "reading existing message headers ...");
@@ -395,6 +422,9 @@ for (;;) {
                DXConnect::process();
                DXMsg::process();
                DXDb::process();
+               DXUser::process();
+               DXDupe::process();
+               
                eval { 
                        Local::process();       # do any localised processing
                };