Home
BUGS
CHANGES.PLAINTEXT
CHANGES
CONFIG
HOWTO
INSTALL
IPCFile.pm
LICENSE
NEWAGENT
PROTOCOL
Q+A
README
README.rpm
README.win32
RELEASE_NOTES-0.30
RELEASE_NOTES-0.32
RELEASE_NOTES-0.33
RELEASE_NOTES-0.37
RELEASE_NOTES-0.38
RELEASE_NOTES-0.93
RELEASE_NOTES-0.94
RELEASE_NOTES-0.95
RELEASE_NOTES-0.98a
RELEASE_NOTES-0.98b4
RELEASE_NOTES-0.98b5
RELEASE_NOTES-0.98b6
RELEASE_NOTES-0.98c7
RELEASE_NOTES-0.98c8
RELEASE_NOTES-0.99b1
RELEASE_NOTES-0.99b1.win32
SNMP_AGENT
TODO
UPDATE


    
    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;