use DXLog;
use IO::File;
use Fcntl;
-use Carp;
use strict;
use vars qw(%work @msg $msgdir %valid %busy $maxage $last_clean
@badmsg @swop $swopfn $badmsgfn $forwardfn @forward $timeout $waittime
- $queueinterval $lastq $importfn);
+ $queueinterval $lastq $importfn $minchunk $maxchunk);
%work = (); # outstanding jobs
@msg = (); # messages we have
$queueinterval = 1*60; # run the queue every 1 minute
$lastq = 0;
+$minchunk = 4800; # minimum chunk size for a split message
+$maxchunk = 6000; # maximum chunk size
$badmsgfn = "$msgdir/badmsg.pl"; # list of TO address we wont store
$forwardfn = "$msgdir/forward.pl"; # the forwarding table
# this is periodic processing
if (!$self || !$line) {
- if ($main::systime > $lastq + $queueinterval) {
+ if ($main::systime >= $lastq + $queueinterval) {
# wander down the work queue stopping any messages that have timed out
for (keys %busy) {
$ref->{stream} = $stream;
$ref->{count} = 0; # no of lines between PC31s
dbg('msg', "new message from $f[4] to $f[3] '$f[8]' stream $stream\n");
+ Log('msg', "Incoming message $f[4] to $f[3] '$f[8]'" );
$work{"$f[2]$stream"} = $ref; # store in work
$busy{$f[2]} = $ref; # set interlock
$self->send(DXProt::pc30($f[2], $f[1], $stream)); # send ack
if ($ref->{subject} eq $m->{subject} && $ref->{t} == $m->{t} && $ref->{from} eq $m->{from} && $ref->{to} eq $m->{to}) {
$ref->stop_msg($self->call);
my $msgno = $m->{msgno};
- dbg('msg', "duplicate message to $msgno\n");
- Log('msg', "duplicate message to $msgno");
+ dbg('msg', "duplicate message from $ref->{from} -> $ref->{to} to $msgno");
+ Log('msg', "duplicate message from $ref->{from} -> $ref->{to} to $msgno");
return;
}
}
my @f;
my $size;
- $file = new IO::File;
- if (!open($file, $fn)) {
- print "Error reading $fn $!\n";
+ $file = new IO::File "$fn";
+ if (!$file) {
+ dbg('err', "Error reading $fn $!");
+ Log('err', "Error reading $fn $!");
return undef;
}
$size = -s $fn;
chomp $line;
$size -= length $line;
if (! $line =~ /^===/o) {
- print "corrupt first line in $fn ($line)\n";
+ dbg('err', "corrupt first line in $fn ($line)");
+ Log('err', "corrupt first line in $fn ($line)");
return undef;
}
$line =~ s/^=== //o;
chomp $line;
$size -= length $line;
if (! $line =~ /^===/o) {
- print "corrupt second line in $fn ($line)\n";
+ dbg('err', "corrupt second line in $fn ($line)");
+ Log('err', "corrupt second line in $fn ($line)");
return undef;
}
$line =~ s/^=== //o;
$file = new IO::File;
if (!open($file, $fn)) {
- print "Error reading $fn $!\n";
+ dbg('err' ,"Error reading $fn $!");
+ Log('err' ,"Error reading $fn $!");
return undef;
}
- chomp (@out = <$file>);
+ @out = map {chomp; $_} <$file>;
close($file);
shift @out if $out[0] =~ /^=== /;
next if $ref->{'read'}; # if it is read, it is stuck here
$clref = DXCluster->get_exact($ref->{to});
unless ($clref) { # otherwise look for a homenode
- my $uref = DXUser->get($ref->{to});
+ my $uref = DXUser->get_current($ref->{to});
my $hnode = $uref->homenode if $uref;
$clref = DXCluster->get_exact($hnode) if $hnode;
}
- if ($clref && !grep { $clref->{dxchan} == $_ } DXCommandmode::get_all) {
+ if ($clref && !grep { $clref->{dxchan} == $_ } DXCommandmode::get_all()) {
next if $clref->call eq $main::mycall; # i.e. it lives here
$noderef = $clref->{dxchan};
$ref->start_msg($noderef) if !get_busy($noderef->call) && $noderef->state eq 'normal';
my $ref;
# load various control files
- print "load badmsg: ", (load_badmsg() or "Ok"), "\n";
- print "load forward: ", (load_forward() or "Ok"), "\n";
- print "load swop: ", (load_swop() or "Ok"), "\n";
+ dbg('err', "load badmsg: " . (load_badmsg() or "Ok"));
+ dbg('err', "load forward: " . (load_forward() or "Ok"));
+ dbg('err', "load swop: " . (load_swop() or "Ok"));
# read in the directory
opendir($dir, $msgdir) or confess "can't open $msgdir $!";
# are there any to do in this directory?
return unless -d $importfn;
unless (opendir(DIR, $importfn)) {
- dbg('msg', "can't open $importfn $!");
- Log('msg', "can't open $importfn $!");
+ dbg('msg', "can\'t open $importfn $!");
+ Log('msg', "can\'t open $importfn $!");
return;
}
my $name;
foreach $name (@names) {
next if $name =~ /^\./;
+ my $splitit = $name =~ /^split/;
my $fn = "$importfn/$name";
next unless -f $fn;
unless (open(MSG, $fn)) {
- dbg('msg', "can't open import file $fn $!");
- Log('msg', "can't open import file $fn $!");
+ dbg('msg', "can\'t open import file $fn $!");
+ Log('msg', "can\'t open import file $fn $!");
unlink($fn);
next;
}
my @msg = map { chomp; $_ } <MSG>;
close(MSG);
unlink($fn);
- my @out = import_one($DXProt::me, \@msg);
+ my @out = import_one($DXProt::me, \@msg, $splitit);
Log('msg', @out);
}
}
{
my $dxchan = shift;
my $ref = shift;
+ my $splitit = shift;
my $private = '1';
my $rr = '0';
my $notincalls = 1;
# first line;
my $line = shift @$ref;
my @f = split /\s+/, $line;
- unless ($f[0] =~ /^(:?S|SP|SB|SEND)$/ ) {
+ unless (@f && $f[0] =~ /^(:?S|SP|SB|SEND)$/ ) {
my $m = "invalid first line in import '$line'";
dbg('MSG', $m );
return (1, $m);
}
}
}
-
+
if (grep $_ eq $f, @DXMsg::badmsg) {
push @out, $dxchan->msg('m3', $f);
} else {
- push @to, $f;
+ push @to, $f;
}
}
}
-
+
# subject is the next line
my $subject = shift @$ref;
# strip off trailing lines
- pop @$ref while (@$ref && ($$ref[-1] eq '' || $$ref[-1] =~ /^\s+$/));
-
+ pop @$ref while (@$ref && $$ref[-1] =~ /^\s*$/);
+
# strip off /EX or /ABORT
- return ("aborted") if (@$ref && $$ref[-1] =~ m{^/ABORT$}i);
+ return ("aborted") if @$ref && $$ref[-1] =~ m{^/ABORT$}i;
pop @$ref if (@$ref && $$ref[-1] =~ m{^/EX$}i);
+ # sort out any splitting that needs to be done
+ my @chunk;
+ if ($splitit) {
+ my $lth = 0;
+ my $lines = [];
+ for (@$ref) {
+ if ($lth >= $maxchunk || ($lth > $minchunk && /^\s*$/)) {
+ push @chunk, $lines;
+ $lines = [];
+ $lth = 0;
+ }
+ push @$lines, $_;
+ $lth += length;
+ }
+ push @chunk, $lines if @$lines;
+ } else {
+ push @chunk, $ref;
+ }
+
# write all the messages away
- my $to;
- foreach $to (@to) {
- my $systime = $main::systime;
- my $mycall = $main::mycall;
- my $mref = DXMsg->alloc(DXMsg::next_transno('Msgno'),
- $to,
- $from,
- $systime,
- $private,
- $subject,
- $origin,
- '0',
- $rr);
- $mref->swop_it($main::mycall);
- $mref->store($ref);
- $mref->add_dir();
- push @out, $dxchan->msg('m11', $mref->{msgno}, $to);
- #push @out, "msgno $ref->{msgno} sent to $to";
- my $todxchan = DXChannel->get(uc $to);
- if ($todxchan) {
- if ($todxchan->is_user()) {
- $todxchan->send($todxchan->msg('m9'));
+ my $i;
+ for ( $i = 0; $i < @chunk; $i++) {
+ my $chunk = $chunk[$i];
+ my $ch_subject;
+ if (@chunk > 1) {
+ my $num = " [" . ($i+1) . "/" . scalar @chunk . "]";
+ $ch_subject = substr($subject, 0, 27 - length $num) . $num;
+ } else {
+ $ch_subject = $subject;
+ }
+ my $to;
+ foreach $to (@to) {
+ my $systime = $main::systime;
+ my $mycall = $main::mycall;
+ my $mref = DXMsg->alloc(DXMsg::next_transno('Msgno'),
+ $to,
+ $from,
+ $systime,
+ $private,
+ $ch_subject,
+ $origin,
+ '0',
+ $rr);
+ $mref->swop_it($main::mycall);
+ $mref->store($chunk);
+ $mref->add_dir();
+ push @out, $dxchan->msg('m11', $mref->{msgno}, $to);
+ #push @out, "msgno $ref->{msgno} sent to $to";
+ my $todxchan = DXChannel->get(uc $to);
+ if ($todxchan) {
+ if ($todxchan->is_user()) {
+ $todxchan->send($todxchan->msg('m9'));
+ }
}
}
}
-
return @out;
}