|
|
package IPCFile;
use strict;
use FileHandle;
sub new
{
my ($this, $file, $maxlog, $logno) = @_;
my $class = ref($this) || $this;
my $self = {};
bless($self, $class);
$self->{"file"} = $file;
($maxlog=1024*1024) unless( $maxlog );
($logno=7) unless( $logno );
$self->{"maxlog"} = $maxlog;
$self->{"logno"} = $logno;
$self->{"mintime"} = 30 * 60;
$self->{"nexttime"} = time + ($self->{"mintime"});
return $self;
}
sub set_rotate_hook {
my( $self, $callback ) = @_;
$self->{"rotatehook"} = $callback;
}
sub log {
my( $self, $text ) = @_;
return unless( $text );
unless( $self->{"outfh"} ) {
$self->_nextoutfile();
}
return unless( $self->{"outfh"} );
$text = (time)." ".$text."\n";
my $fh = $self->{"outfh"};
print $fh $text;
$self->{"size"} += length( $text );
if( ($self->{"size"} > $self->{"maxlog"})
&& (time -$self->{"createtime"} > $self->{"mintime"} )) {
$self->_nextoutfile();
}
}
sub _nextoutfile {
my( $self ) = @_;
if( $self->{"outfh"} ) {
close $self->{"outfh"};
$self->{"outfh"} = undef;
}
my $nextname = ($self->{"file"}).(time).".";
for( my $index=0; ($index<100) && (-f $nextname.$index); $index++ ) {;}
my $fh = new FileHandle();
unless( open( $fh, ">$nextname" ) ) {
BigSister::common::log( "err", "could not create interprocess communication file $nextname" );
Platform::poll_sleep(10);
}
$self->{"size"} = 0;
$self->{"createtime"} = time;
$self->{"outfh"} = $fh;
my $oldfh = select $fh; select $fh; $| = 1; select $oldfh;
my $i=0;
while( 1 ) {
last if( open( _STAMP, ">".($self->{"file"}) )
&& (print _STAMP ":$nextname:\n")
&& close( _STAMP ) );
select( undef,undef,undef, 0.5 );
if( $i++ == 10 ) {
BigSister::common::log( "warning", "cannot create file $self->{'file'} - trying again but this is probably an error" );
}
}
my $dir = $self->{"file"};
my $file = $self->{"file"};
$file =~ s#.*/##;
$dir =~ s#\Q$file\E$##;
opendir( _DIR, $dir );
foreach my $name (readdir( _DIR )) {
if( $name =~ /^\Q$file\E[\d\.]+$/ ) {
my $candidate = $dir.$name;
next if( $candidate eq $nextname );
my $mtime = ((stat($candidate))[9]);
next if( time-$mtime < 1800 );
unlink( $candidate );
}
}
}
sub read {
my( $self ) = @_;
unless( $self->{"readfh"} ) {
$self->_nextinputfile();
}
my $fh = $self->{"readfh"};
return( undef ) unless( $fh );
seek( $fh, $self->{"readpos"}, 0 ) || return undef;
my $text = <$fh>
if( $text ) {
$text = $self->{"readbuffer"}.$text;
$self->{"readbuffer"} = "";
$self->{"readpos"} = tell( $fh );
unless( $text =~ /[\r\n]$/ ) {
$self->{"readbuffer"} = $text;
return undef;
}
chomp $text;
$text =~ /^(\d+) (.*)$/;
return( $1, $2 );
}
$self->_checkreadnext();
}
sub skipread {
my( $self ) = @_;
return unless( $self->{"readfh"} );
seek( $self->{"readfh"}, 0, 2 );
$self->{"readpos"} = tell( $self->{"readfh"} );
}
sub _nextinputfile {
my( $self ) = @_;
if( $self->{"readfh"} ) {
close( $self->{"readfh"} );
$self->{"readfh"} = undef;
}
my $newfile;
my $mtime = ((stat($self->{"file"}))[9]);
unless( open( _FILEN, "<$self->{'file'}" )
&& ($newfile=<_FILEN>)
&& ($newfile =~ /^:(.*):[\r\n]*$/) ) {
close _FILEN;
return;
}
close _FILEN;
$newfile = $1;
my $fh = new FileHandle();
unless( open( $fh, "<$newfile" ) ) {
$self->{"readwarned"} || BigSister::common::log( "err", "cannot open interprocess communication file $newfile" );
$self->{"readwarned"} = 1;
return;
}
$self->{"readwarned"} = 0;
$self->{"readfh"} = $fh;
$self->{"readstamp"} = $mtime;
$self->{"readpos"} = 0;
}
sub _checkreadnext {
my( $self ) = @_;
if( $self->{"readfh"} ) {
my $mtime = ((stat($self->{"file"}))[9]);
return if( $mtime == $self->{"readstamp"} );
}
$self->_nextinputfile();
}
1;
|