liblog-agent-rotate-perl-0.1.4.orig/0042755000175000017500000000000007534205170016030 5ustar tonytonyliblog-agent-rotate-perl-0.1.4.orig/ChangeLog0100444000175000017500000000267707470116703017611 0ustar tonytonyTue May 14 01:00:12 EDT 2002 Mark Rogaski . Description: Version 0.1.4. Allow restriction of file permissions with -file_perm argument to Log::Agent::Rotate->make(). Wed Apr 11 18:01:46 MEST 2001 Raphael Manfredi . Description: Mark rotation in the logfile before rotating it, so that any pending "tail -f" gets to know about it. Added a regression test for it. Now depends on Getargs::Long for argument parsing. Sun Nov 12 15:56:22 MET 2000 Raphael Manfredi . Description: Version 0.1.2. Untaint data read or rename() complains under -T. Changed pre-req on Log::Agent: must now use 0.2.1. Changed DLSI description to match CPAN's New -single_host parameter is used to optimize LockFile::Simple: we don't supply -nfs when -single_host is true, for faster locking procedure. Mon Nov 6 21:06:22 MET 2000 Raphael Manfredi . Description: Version 0.1.1. Moved to an array representation for the config object. Removed reference to driver and the ability to specify -max_time in other units than seconds (e.g. "2d"). Added is_same() to compare rotation policies. Added build_pm_hash() to compute PM value from MANIFEST. Updated t/badconf.t to new detection logic within Log::Agent. Sun Mar 5 22:53:51 MET 2000 Raphael Manfredi . Description Initial revision 0.1. liblog-agent-rotate-perl-0.1.4.orig/README0100444000175000017500000000546107470116703016711 0ustar tonytony Log::Agent::Rotate 0.1 Copyright (c) 2000, Raphael Manfredi ------------------------------------------------------------------------ This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License, a copy of which can be found with perl. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Artistic License for more details. ------------------------------------------------------------------------ *** This is alpha software -- use at your own risks *** Name DSLI Description Info ----------- ---- -------------------------------------------- ----- Log::Agent ---- A general logging framework RAM ::Rotate adpO Logfile rotation config and support RAM The Log::Agent::Rotate module is an extension of Log::Agent that brings file-rotating features to the File logging driver. It is separated from Log::Agent itself because it has dependencies on LockFile::Simple and Compress::Zlib that Log::Agent cannot have: everyone with a plain stock Perl distribution must be able to simply install Log::Agent and start using it. This is NOT a generic all-purpose logfile rotation package. It is meant to be used only within the Log::Agent framework. SYNOPSIS use Log::Agent; require Log::Agent::Driver::File; require Log::Agent::Rotate; (my $me = $0) =~ s|.*/(.*)|$1|; my $rotate = Log::Agent::Rotate->make( -backlog => 7, # keep last seven logs + current -unzipped => 2, # don't compress last archived 2 logs -is_alone => 1, # programmer says only ONE process will run -max_size => 100_000, # file will rotate when bigger than 100K ); my $driver = Log::Agent::Driver::File->make( -prefix => $me, -showpid => 1, -rotate => $rotate, # default rotation policy -channels => { 'error' => '/tmp/output.err', 'output' => ['log.out', $rotate], # could have special policy 'debug' => '../appli.debug', }, ); logconfig(-driver => $driver, -level => 'notice'); DESCRIPTION Log::Agent::Rotate lets you specify the logfile rotation policy that will be used on the logfiles managed via a Log::Agent::Driver::File driver. It can be useful for daemon process to periodically rotate the logfiles whilst keeping some fair amount of backlog. But it can also be used by programs that run a short period of time and generate systematic logging, that would end-up eating all the disk space if not monitored. Please read the Log::Agent::Rotate(3) manpage and the related pages for more information. -- Raphael Manfredi liblog-agent-rotate-perl-0.1.4.orig/t/0042755000175000017500000000000007470116731016276 5ustar tonytonyliblog-agent-rotate-perl-0.1.4.orig/t/code.pl0100444000175000017500000000136207470116703017537 0ustar tonytony# # $Id: code.pl,v 1.1 2002/05/12 17:33:43 wendigo Exp $ # # Copyright (c) 2000, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # # HISTORY # $Log: code.pl,v $ # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1 2000/03/05 22:15:40 ram # Baseline for first alpha release. # # $EndLog$ # sub ok { my ($num, $ok) = @_; print "not " unless $ok; print "ok $num\n"; } sub contains { my ($file, $pattern) = @_; local *FILE; local $_; open(FILE, $file) || die "can't open $file: $!\n"; my $found = 0; while () { if (/$pattern/) { $found = 1; last; } } close FILE; return $found; } 1; liblog-agent-rotate-perl-0.1.4.orig/t/perm.t0100444000175000017500000000416507470116703017424 0ustar tonytony#!perl ########################################################################### # $Id: perm.t,v 1.1 2002/05/14 04:46:34 wendigo Exp $ ########################################################################### # # perm.t # # RCS Revision: $Revision: 1.1 $ # Date: $Date: 2002/05/14 04:46:34 $ # # Copyright (c) 2002 Mark Rogaski, mrogaski@cpan.org; all rights reserved. # # See the README file included with the # distribution for license information. # # $Log: perm.t,v $ # Revision 1.1 2002/05/14 04:46:34 wendigo # Initial revision # # ########################################################################### use Test; BEGIN { plan tests => 4 } use Log::Agent; require Log::Agent::Driver::File; require Log::Agent::Rotate; sub clear_log () { unlink ; } sub perm_ok ($$) { # # Given a fileame and target permissions, checks if the file # was created with the correct permissions. # my($file, $target) = @_; $target &= ~ umask; # account for user mask my $mode = (stat $file)[2]; # find the current mode $mode &= 0777; # we only care about UGO return $mode == $target; } my $rotate = Log::Agent::Rotate->make( -backlog => 2, -unzipped => 2, -is_alone => 1, -single_host => 1, -max_size => 100, -file_perm => 0600 ); my $driver = Log::Agent::Driver::File->make( -rotate => $rotate, -channels => { 'error' => 't/logfile', 'output' => 't/logfile', }, ); my $msg = '!' x 55; logconfig(-driver => $driver); clear_log; logsay $msg; ok(perm_ok("t/logfile", 0600)); logsay $msg; ok(perm_ok("t/logfile.0", 0600)); $rotate = Log::Agent::Rotate->make( -backlog => 2, -unzipped => 2, -is_alone => 1, -single_host => 1, -max_size => 100, -file_perm => 0644 ); $driver = Log::Agent::Driver::File->make( -rotate => $rotate, -channels => { 'error' => 't/logfile', 'output' => 't/logfile', }, ); logconfig(-driver => $driver); clear_log; logsay $msg; ok(perm_ok("t/logfile", 0644)); logsay $msg; ok(perm_ok("t/logfile.0", 0644)); clear_log; liblog-agent-rotate-perl-0.1.4.orig/t/hole.t0100444000175000017500000000370107470116703017403 0ustar tonytony#!./perl # # $Id: hole.t,v 1.1 2002/05/12 17:33:43 wendigo Exp $ # # Copyright (c) 2000, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # # HISTORY # $Log: hole.t,v $ # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1 2000/03/05 22:15:40 ram # Baseline for first alpha release. # # $EndLog$ # # # Check behaviour when archived logfiles are externally removed # print "1..21\n"; require 't/code.pl'; sub ok; sub cleanlog() { unlink ; } use Log::Agent; require Log::Agent::Driver::File; require Log::Agent::Rotate; cleanlog; my $rotate_dflt = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 2, -is_alone => 0, -max_size => 100, ); my $driver = Log::Agent::Driver::File->make( -channels => { 'error' => 't/logfile_err', 'output' => ['t/logfile', $rotate_dflt], }, ); logconfig(-driver => $driver); my $message = "this is a message whose size is exactly 53 characters"; logsay $message; logsay $message; # rotates logsay $message; logsay $message; # rotates again logsay $message; logsay $message; # rotates again logsay $message; logsay $message; # rotates again ok 1, -e("t/logfile.0"); ok 2, -e("t/logfile.1"); ok 3, -e("t/logfile.2.gz"); ok 4, -e("t/logfile.3.gz"); ok 5, !-e("t/logfile.4.gz"); ok 6, unlink "t/logfile.0"; ok 7, unlink "t/logfile.2.gz"; logsay $message; logsay $message; # rotates again ok 8, -e("t/logfile.0"); ok 9, !-e("t/logfile.1"); ok 10, -e("t/logfile.2.gz"); ok 11, !-e("t/logfile.3.gz"); ok 12, -e("t/logfile.4.gz"); ok 13, !-e("t/logfile.5.gz"); ok 14, unlink "t/logfile.2.gz"; logsay $message; logsay $message; # rotates again ok 15, -e("t/logfile.0"); ok 16, -e("t/logfile.1"); ok 17, !-e("t/logfile.2.gz"); ok 18, !-e("t/logfile.3.gz"); ok 19, !-e("t/logfile.4.gz"); ok 20, -e("t/logfile.5.gz"); ok 21, !-e("t/logfile.6.gz"); cleanlog; liblog-agent-rotate-perl-0.1.4.orig/t/rename.t0100444000175000017500000000311207470116703017717 0ustar tonytony#!./perl # # $Id: rename.t,v 1.1 2002/05/12 17:33:43 wendigo Exp $ # # Copyright (c) 2000, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # # HISTORY # $Log: rename.t,v $ # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1 2000/03/05 22:15:41 ram # Baseline for first alpha release. # # $EndLog$ # # # Check normal behaviour, with 2 non-compressed files # print "1..10\n"; require 't/code.pl'; sub ok; sub cleanlog() { unlink ; } use Log::Agent; require Log::Agent::Driver::File; require Log::Agent::Rotate; cleanlog; my $rotate_dflt = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 2, -is_alone => 0, -max_size => 100, ); my $driver = Log::Agent::Driver::File->make( -rotate => $rotate_dflt, -channels => { 'error' => 't/logfile', 'output' => 't/logfile', }, ); logconfig(-driver => $driver); my $message = "this is a message whose size is exactly 53 characters"; logsay $message; logwarn $message; # will bring logsize size > 100 chars logerr "new $message"; # not enough to rotate again ok 1, -e("t/logfile"); ok 2, -e("t/logfile.0"); ok 3, !-e("t/logfile.1"); ok 4, rename("t/logfile", "t/logfile.0"); logsay $message; # does not rotate, since we renamed above ok 5, -e("t/logfile"); ok 6, -e("t/logfile.0"); ok 7, !-e("t/logfile.1"); ok 8, rename("t/logfile", "t/logfile.0"); logsay $message; ok 9, !-e("t/logfile.1"); logsay $message; # finally rotates ok 10, -e("t/logfile.1"); cleanlog; liblog-agent-rotate-perl-0.1.4.orig/t/normal.t0100444000175000017500000000506307470116703017747 0ustar tonytony#!./perl # # $Id: normal.t,v 1.1 2002/05/12 17:33:43 wendigo Exp $ # # Copyright (c) 2000, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # # HISTORY # $Log: normal.t,v $ # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1.1.2 2001/04/11 16:00:55 ram # patch3: ensure logfile rotation indication is left properly # # Revision 0.1.1.1 2000/11/12 14:54:26 ram # patch2: use new -single_host parameter # # Revision 0.1 2000/03/05 22:15:41 ram # Baseline for first alpha release. # # $EndLog$ # # # Check normal behaviour, with 2 non-compressed files # print "1..21\n"; require 't/code.pl'; sub ok; sub cleanlog() { unlink ; } use Log::Agent; require Log::Agent::Driver::File; require Log::Agent::Rotate; cleanlog; my $rotate_dflt = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 2, -is_alone => 1, -single_host => 1, -max_size => 100, ); my $driver = Log::Agent::Driver::File->make( -rotate => $rotate_dflt, -channels => { 'error' => 't/logfile', 'output' => 't/logfile', }, ); logconfig(-driver => $driver); my $message = "this is a message whose size is exactly 53 characters"; logsay $message; logwarn $message; # will bring logsize size > 100 chars logerr "new $message"; # not enough to rotate again ok 1, -e("t/logfile"); ok 2, -e("t/logfile.0"); ok 3, !-e("t/logfile.1"); logsay $message; # rotates, creates logfile.1 logsay $message; logsay $message; # rotates again, now has logfile.2.gz, no logfile ok 4, !-e("t/logfile"); ok 5, -e("t/logfile.0"); ok 6, -e("t/logfile.1"); ok 7, -e("t/logfile.2.gz"); ok 8, !-e("t/logfile.3.gz"); logsay $message; # creates a logfile ok 9, -e("t/logfile"); logsay $message; # rotates again, now has logfile.3.gz logsay $message; logsay $message; # rotates again, now has logfile.4.gz logsay $message; logsay $message; # rotates again, now has logfile.5.gz logsay $message; logsay $message; # rotates again, now has logfile.6.gz logsay $message; logsay $message; # rotates again, no logfile.7.gz ok 10, !-e("t/logfile"); ok 11, -e("t/logfile.0"); ok 12, -e("t/logfile.1"); ok 13, -e("t/logfile.2.gz"); ok 14, -e("t/logfile.3.gz"); ok 15, -e("t/logfile.4.gz"); ok 16, -e("t/logfile.5.gz"); ok 17, -e("t/logfile.6.gz"); ok 18, !-e("t/logfile.7.gz"); logsay $message; logsay $message; # rotates again, sill no logfile.7.gz ok 19, -e("t/logfile.6.gz"); ok 20, !-e("t/logfile.7.gz"); ok 21, contains("t/logfile.0", "LOGFILE ROTATED ON"); cleanlog; liblog-agent-rotate-perl-0.1.4.orig/t/badconf.t0100444000175000017500000000366207470116703020056 0ustar tonytony#!./perl # # $Id: badconf.t,v 1.1 2002/05/12 17:33:43 wendigo Exp $ # # Copyright (c) 2000, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # # HISTORY # $Log: badconf.t,v $ # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1.1.1 2000/11/06 20:04:10 ram # patch1: updated test to new logic # # Revision 0.1 2000/03/05 22:15:40 ram # Baseline for first alpha release. # # $EndLog$ # # # Ensure possible incorrect rotation is detected whith bad Log::Agent config # print "1..6\n"; require 't/code.pl'; sub ok; sub cleanlog() { unlink ; } use Log::Agent; require Log::Agent::Driver::File; require Log::Agent::Rotate; cleanlog; my $rotate_dflt = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 2, -is_alone => 1, -max_size => 100, ); my $rotate_other = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 1, -is_alone => 1, -max_size => 100, ); my $driver = Log::Agent::Driver::File->make( -rotate => $rotate_dflt, -channels => { 'error' => ['t/logfile', $rotate_other], 'output' => 't/logfile', }, ); logconfig(-driver => $driver); my $message = "this is a message whose size is exactly 53 characters"; logsay $message; logwarn $message; # will bring logsize size > 100 chars ok 1, -e("t/logfile"); ok 2, -e("t/logfile.0"); ok 3, contains("t/logfile.0", "Rotation for 't/logfile' may be wrong"); cleanlog; undef $Log::Agent::Driver; # Cheat $driver = Log::Agent::Driver::File->make( -rotate => $rotate_dflt, -channels => { 'error' => ['t/logfile', $rotate_dflt], 'output' => 't/logfile', }, ); logconfig(-driver => $driver); logsay $message; logwarn $message; # will bring logsize size > 100 chars ok 4, !-e("t/logfile"); ok 5, -e("t/logfile.0"); ok 6, !contains("t/logfile.0", "Rotation for 'error' may be wrong"); cleanlog; liblog-agent-rotate-perl-0.1.4.orig/t/mixed.t0100444000175000017500000001067107470116703017566 0ustar tonytony#!./perl # # $Id: mixed.t,v 1.1 2002/05/12 17:33:43 wendigo Exp $ # # Copyright (c) 2000, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # # HISTORY # $Log: mixed.t,v $ # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1 2000/03/05 22:15:41 ram # Baseline for first alpha release. # # $EndLog$ # # # Check behaviour when mixed compressing policies are used in sequence # print "1..50\n"; require 't/code.pl'; sub ok; sub cleanlog() { unlink ; } use Log::Agent; require Log::Agent::Driver::File; require Log::Agent::Rotate; cleanlog; my $rotate_dflt = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 2, -is_alone => 1, -max_size => 100, ); my $driver = Log::Agent::Driver::File->make( -channels => { 'error' => 't/logfile_err', 'output' => ['t/logfile', $rotate_dflt], }, ); logconfig(-driver => $driver); my $message = "this is a message whose size is exactly 53 characters"; logsay $message; logsay $message; # will bring logsize size > 100 chars logsay $message; logsay $message; # rotates again, creates logfile.1 logsay $message; logsay $message; # rotates again, now has logfile.2.gz ok 1, !-e("t/logfile"); ok 2, -e("t/logfile.0"); ok 3, -e("t/logfile.1"); ok 4, -e("t/logfile.2.gz"); ok 5, !-e("t/logfile.3.gz"); undef $Log::Agent::Driver; # Cheat $rotate_dflt = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 4, -is_alone => 1, -max_size => 100, ); $driver = Log::Agent::Driver::File->make( -channels => { 'error' => 't/logfile_err', 'output' => ['t/logfile', $rotate_dflt], }, ); logconfig(-driver => $driver); logsay $message; logsay $message; # rotate, logfile.2.gz not uncompresed ok 6, !-e("t/logfile"); ok 7, -e("t/logfile.0"); ok 8, -e("t/logfile.1"); ok 9, -e("t/logfile.2"); ok 10, -e("t/logfile.3.gz"); ok 11, !-e("t/logfile.4.gz"); logsay $message; logsay $message; # rotate, logfile.3.gz not uncompresed ok 12, !-e("t/logfile"); ok 13, -e("t/logfile.0"); ok 14, -e("t/logfile.1"); ok 15, -e("t/logfile.2"); ok 16, -e("t/logfile.3"); ok 17, -e("t/logfile.4.gz"); ok 18, !-e("t/logfile.5.gz"); undef $Log::Agent::Driver; # Cheat $rotate_dflt = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 1, -is_alone => 1, -max_size => 100, ); $driver = Log::Agent::Driver::File->make( -channels => { 'error' => 't/logfile_err', 'output' => ['t/logfile', $rotate_dflt], }, ); logconfig(-driver => $driver); logsay $message; logsay $message; # rotate, re-compresses up to logfile.1.gz ok 19, !-e("t/logfile"); ok 20, -e("t/logfile.0"); ok 21, -e("t/logfile.1.gz"); ok 22, -e("t/logfile.2.gz"); ok 23, -e("t/logfile.3.gz"); ok 24, -e("t/logfile.4.gz"); ok 25, -e("t/logfile.5.gz"); ok 26, !-e("t/logfile.6.gz"); undef $Log::Agent::Driver; # Cheat $rotate_dflt = Log::Agent::Rotate->make( -backlog => 4, -unzipped => 1, -is_alone => 1, -max_size => 100, ); $driver = Log::Agent::Driver::File->make( -channels => { 'error' => 't/logfile_err', 'output' => ['t/logfile', $rotate_dflt], }, ); logconfig(-driver => $driver); logsay $message; logsay $message; # rotate, keeps only from .0 to .3.gz ok 27, !-e("t/logfile"); ok 28, -e("t/logfile.0"); ok 29, -e("t/logfile.1.gz"); ok 30, -e("t/logfile.2.gz"); ok 31, -e("t/logfile.3.gz"); ok 32, !-e("t/logfile.4.gz"); ok 33, !-e("t/logfile.5.gz"); ok 34, !-e("t/logfile.6.gz"); undef $Log::Agent::Driver; # Cheat $rotate_dflt = Log::Agent::Rotate->make( -backlog => 4, -unzipped => 4, -is_alone => 1, -max_size => 100, ); $driver = Log::Agent::Driver::File->make( -channels => { 'error' => 't/logfile_err', 'output' => ['t/logfile', $rotate_dflt], }, ); logconfig(-driver => $driver); logsay $message; logsay $message; # rotate, no compression at all ok 35, !-e("t/logfile"); ok 36, -e("t/logfile.0"); ok 37, -e("t/logfile.1"); ok 38, -e("t/logfile.2.gz"); ok 39, -e("t/logfile.3.gz"); ok 40, !-e("t/logfile.4.gz"); logsay $message; logsay $message; # rotate, no compression at all logsay $message; logsay $message; # rotate, no compression at all ok 41, !-e("t/logfile"); ok 42, -e("t/logfile.0"); ok 43, -e("t/logfile.1"); ok 44, -e("t/logfile.2"); ok 45, -e("t/logfile.3"); ok 46, !-e("t/logfile.4"); ok 47, !-e("t/logfile.3.gz"); ok 48, !-e("t/logfile.2.gz"); ok 49, !-e("t/logfile.1.gz"); ok 50, !-e("t/logfile.0.gz"); cleanlog; liblog-agent-rotate-perl-0.1.4.orig/MANIFEST0100444000175000017500000000151207470116703017153 0ustar tonytonyREADME The main README file MANIFEST This list ChangeLog List of changes File/Rotate.pm A logfile capable of rotating itself Makefile.PL Generic Makefile template Rotate.pm File rotation parameters patchlevel.h Records the current patchlevel t/badconf.t Test error when bad rotation config t/code.pl Library for tests t/hole.t Test holes in logfile sequence t/mixed.t Test mixed rotation policy t/normal.t Test normal configuration t/perm.t Test file permission behavior t/rename.t Test behaviour with external logfile renaming liblog-agent-rotate-perl-0.1.4.orig/Rotate.pm0100444000175000017500000002251107470116703017620 0ustar tonytony########################################################################### # $Id: Rotate.pm,v 1.5 2002/05/14 05:15:30 wendigo Exp $ ########################################################################### # # Log::Agent::Rotate # # RCS Revision: $Revision: 1.5 $ # Date: $Date: 2002/05/14 05:15:30 $ # # Copyright (c) 2000 Raphael Manfredi. # Copyright (c) 2002 Mark Rogaski, mrogaski@cpan.org; all rights reserved. # # See the README file included with the # distribution for license information. # # $Log: Rotate.pm,v $ # Revision 1.5 2002/05/14 05:15:30 wendigo # updated POD # # Revision 1.4 2002/05/14 04:58:28 wendigo # corrected $VERSION # # Revision 1.3 2002/05/14 04:49:49 wendigo # modified version control # # Revision 1.2 2002/05/14 04:47:21 wendigo # added file_perm argument # # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1.1.3 2001/04/11 16:00:29 ram # patch3: switched to Getargs::Long for argument parsing # patch3: updated version number # # Revision 0.1.1.2 2000/11/12 14:54:10 ram # patch2: new -single_host parameter # # Revision 0.1.1.1 2000/11/06 20:03:35 ram # patch1: moved to an array representation for the object # patch1: added ability to specify -max_time in other units than seconds # patch1: added is_same() to compare configurations # # Revision 0.1 2000/03/05 22:15:40 ram # Baseline for first alpha release. # ########################################################################### use strict; ########################################################################### package Log::Agent::Rotate; use Getargs::Long qw(ignorecase); # # File rotating policy # use vars qw($VERSION); $VERSION = sprintf "%d.%01d%02d%s", '$Name: rel0_1_4 $' =~ /(p?\d+)/g; BEGIN { sub BACKLOG () {0} sub UNZIPPED () {1} sub MAX_SIZE () {2} sub MAX_WRITE () {3} sub MAX_TIME () {4} sub IS_ALONE () {5} sub SINGLE_HOST () {6} sub FILE_PERM () {7} } # # ->make # # Creation routine. # # Attributes: # backlog amount of old files to keep (0 for none) # unzipped amount of old files to NOT compress (defaults to 1) # max_size maximum amount of bytes in file # max_write maximum amount of bytes to write in file # max_time maximum amount of time to keep open # is_alone hint: only one instance is busy manipulating the logfiles # single_host hint: access to logfiles always made via one host # sub make { my $self = bless [], shift; ( $self->[BACKLOG], $self->[UNZIPPED], $self->[MAX_SIZE], $self->[MAX_WRITE], $self->[MAX_TIME], $self->[IS_ALONE], $self->[SINGLE_HOST], $self->[FILE_PERM] ) = xgetargs(@_, -backlog => ['i', 7], -unzipped => ['i', 1], -max_size => ['i', 1_048_576], -max_write => ['i', 0], -max_time => ['s', "0"], -is_alone => ['i', 0], -single_host => ['i', 0], -file_perm => ['i', 0666] ); $self->[MAX_TIME] = seconds_in_period($self->[MAX_TIME]) if $self->[MAX_TIME]; return $self; } # # seconds_in_period # # Converts a period into a number of seconds. # sub seconds_in_period { my ($p) = @_; $p =~ s|^(\d+)||; my $base = int($1); # Number of elementary periods my $u = "s"; # Default Unit $u = substr($1, 0, 1) if $p =~ /^\s*(\w+)$/; my $sec; if ($u eq 'm') { $sec = 60; # One minute = 60 seconds } elsif ($u eq 'h') { $sec = 3600; # One hour = 3600 seconds } elsif ($u eq 'd') { $sec = 86400; # One day = 24 hours } elsif ($u eq 'w') { $sec = 604800; # One week = 7 days } elsif ($u eq 'M') { $sec = 2592000; # One month = 30 days } elsif ($u eq 'y') { $sec = 31536000; # One year = 365 days } else { $sec = 1; # Unrecognized: defaults to seconds } return $base * $sec; } # # Attribute access # sub backlog { $_[0]->[BACKLOG] } sub unzipped { $_[0]->[UNZIPPED] } sub max_size { $_[0]->[MAX_SIZE] } sub max_write { $_[0]->[MAX_WRITE] } sub max_time { $_[0]->[MAX_TIME] } sub is_alone { $_[0]->[IS_ALONE] } sub single_host { $_[0]->[SINGLE_HOST] } sub file_perm { $_[0]->[FILE_PERM] } # # There's no set_xxx() routines: those objects are passed by reference and # never "expanded", i.e. passed by copy. Modifying any of the attributes # would then lead to strange effects. # # # ->is_same # # Compare settings of $self with that of $other # sub is_same { my $self = shift; my ($other) = @_; for (my $i = 0; $i < @$self; $i++) { return 0 if $self->[$i] != $other->[$i]; } return 1; } 1; # for require __END__ =head1 NAME Log::Agent::Rotate - parameters for logfile rotation =head1 SYNOPSIS require Log::Agent::Rotate; my $policy = Log::Agent::Rotate->make( -backlog => 7, -unzipped => 2, -is_alone => 0, -max_size => 100_000, -max_time => "1w", -file_perm => 0666 ); =head1 DESCRIPTION The C class holds the parameters describing the logfile rotation policy, and is meant to be supplied to instances of C via arguments in the creation routine, such as C<-rotate>, or by using array references as values in the C<-channels> hashref: See complementary information in L. As rotation cycles are performed, the current logfile is renamed, and possibly compressed, until the maximum backlog is reached, at which time files are deleted. Assuming a backlog of 5 and that the latest 2 files are not compressed, the following files can be present on the filesystem: logfile # the current logfile logfile.0 # most recently renamed logfile logfile.1 logfile.2.gz logfile.3.gz logfile.4.gz # oldest logfile, unlinked next cycle The following I are available to the creation routine make(), listed in alphabetical order, all taking a single integer value as argument: =over 4 =item I The total amount of old logfiles to keep, besides the current logfile. Defaults to 7. =item I The file permissions, given as an octal integer value, to supply to sysopen() during file creation. This value is modified during execution by the umask of the process. In most cases, it is good practice to leave this set to the default and let the user process controll the file permissions. Defaults to 0666. =item I The argument is a boolean stating whether the program writing to the logfile will be the only one or not. This is a hint that drives some optimizations, but it is up to the program to B that noone else will be able to write to or unlink the current logfile when set to I. Defaults to I. =item I The maximum logfile size. This is a threshold, which will cause a logfile rotation cycle to be performed, when crossed after a write to the file. If set to C<0>, this threshold is not checked. Defaults to 1 megabyte. =item I The maximum time in seconds between the moment we opened the file and the next rotation cycle occurs. This threshold is only checked after a write to the file. The value can also be given as a string, postfixed by one of the following letters to specify the period unit (e.g. "3w"): Letter Unit ------ ------- m minutes h hours d days d days w weeks M months (30 days of 24 hours) y years Defaults to C<0>, meaning it is not checked. =item I The maximum amount of data we can write to the logfile. Like C, this is a threshold, which is only checked after a write to the logfile. This is not the total logfile size: if several programs write to the same logfile and C is not used, then the logfiles may never be rotated at all if none of the programs write at least C bytes to the logfile before exiting. Defaults to C<0>, meaning it is not checked. =item I The argument is a boolean stating whether the access to the logfiles will be made from one single host or not. This is a hint that drives some optimizations, but it is up to the program to B that it is accurately set. Defaults to I, which is always a safe value. =item I The amount of old logfiles, amongst the most recent ones, that should not be compressed but be kept as plain files. Defaults to 1. =back To test whether two configurations are strictly identical, use is_same(), as in: print "identical\n" if $x->is_same($y); where both $x and $y are C objects. All the aforementioned switches also have a corresponding querying routine that can be issued on instances of the class to get their value. It is not possible to modify those attributes. For instance: my $x = Log::Agent::Rotate->make(...); my $mwrite = $x->max_write(); would get the configured I threshold. =head1 AUTHORS Originally written by Raphael Manfredi ERaphael_Manfredi@pobox.comE, currently maintained by Mark Rogaski Emrogaski@cpan.orgE. Thanks to Chris Meshkin for his suggestions on file permissions. =head1 SEE ALSO Log::Agent(3), Log::Agent::Driver::File(3), Log::Agent::Rotate::File(3). =cut liblog-agent-rotate-perl-0.1.4.orig/Makefile.PL0100444000175000017500000000325507470116703020002 0ustar tonytony# $Id: Makefile.PL,v 1.1 2002/05/12 17:33:43 wendigo Exp $ # # Copyright (c) 2000, Raphael Manfredi # # You may redistribute only under the terms of the Artistic License, # as specified in the README file that comes with the distribution. # # HISTORY # $Log: Makefile.PL,v $ # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1.1.3 2001/04/11 15:58:55 ram # patch3: now depends on Getargs::Long # # Revision 0.1.1.2 2000/11/12 14:53:38 ram # patch2: changed pre-req on Log::Agent # # Revision 0.1.1.1 2000/11/06 19:57:50 ram # patch1: added build_pm_hash() to compute PM value from MANIFEST # # Revision 0.1 2000/03/05 22:15:40 ram # Baseline for first alpha release. # # $EndLog$ # use ExtUtils::MakeMaker; use Log::Agent; WriteMakefile( 'NAME' => 'Log::Agent::Rotate', 'VERSION_FROM' => 'Rotate.pm', # finds $VERSION 'PREREQ_PM' => { 'Compress::Zlib' => '0.4', 'Getargs::Long' => '0.103', 'LockFile::Simple' => '0.202', 'Log::Agent' => '0.201', }, 'PM' => build_pm_hash(), 'LIBS' => [''], # e.g., '-lm' 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING' 'INC' => '', # e.g., '-I/usr/include/other' # 'PREFIX' => '/home/ram/usr/lib/site_perl', ); # # build_pm_hash # # Find out all the *.pm files in the MANIFEST, and build a hash ref # containing entries like: # # 'file.pm' => '$(INST_LIBDIR)/file.pm' # # for each file. # sub build_pm_hash { local *MANI; open(MANI, "MANIFEST") || logdie "can't open MANIFEST: $!"; local $_; my @pm; while () { my ($file, $comment) = split; next unless $file =~ /\.pm$/; push @pm, $file; } my %pm = map { $_ => '$(INST_LIBDIR)/' . $_ } @pm; return \%pm; } liblog-agent-rotate-perl-0.1.4.orig/File/0042755000175000017500000000000007470116731016712 5ustar tonytonyliblog-agent-rotate-perl-0.1.4.orig/File/Rotate.pm0100444000175000017500000003713007470116703020502 0ustar tonytony########################################################################### # $Id: Rotate.pm,v 1.2 2002/05/14 04:47:50 wendigo Exp $ ########################################################################### # # Log::Agent::File::Rotate # # RCS Revision: $Revision: 1.2 $ # Date: $Date: 2002/05/14 04:47:50 $ # # Copyright (c) 2000 Raphael Manfredi. # Copyright (c) 2002 Mark Rogaski, mrogaski@cpan.org; all rights reserved. # # See the README file included with the # distribution for license information. # # $Log: Rotate.pm,v $ # Revision 1.2 2002/05/14 04:47:50 wendigo # added support for file_perm # # Revision 1.1 2002/05/12 17:33:43 wendigo # Initial revision # # Revision 0.1.1.3 2001/04/11 15:58:34 ram # patch3: mark rotation in the logfile before rotating it # # Revision 0.1.1.2 2000/11/12 14:53:27 ram # patch2: untaint data read or rename() complains under -T # patch2: use new -single_host parameter to configure LockFile::Simple # # Revision 0.1.1.1 2000/11/06 19:57:24 ram # patch1: removed reference on driver # # Revision 0.1 2000/03/05 22:15:40 ram # Baseline for first alpha release. # ########################################################################### use strict; ########################################################################### package Log::Agent::File::Rotate; # # A rotating logfile set # use File::stat; use Fcntl; use Symbol; use Compress::Zlib; require LockFile::Simple; use Log::Agent; # We're using logerr() ourselves when safe to do so my $DEBUG = 0; # # ->make # # Creation routine. # # Attributes initialized by parameters: # path file path # config rotating configuration (a Log::Agent::Rotate object) # # Other attributes: # fd currently opened file descriptor # handle symbol used for Perl handle # warned records calls made to hardwired warn() to only do them once # written total amount written since opening # size logfile size # opened time when opening occurred # dev device holding logfile # ino inode number of logfile # lockmgr lockfile manager # rotating within the rotate() routine # sub make { my $self = bless {}, shift; my ($path, $config) = @_; $self->{'path'} = $path; $self->{'config'} = $config; $self->{'fd'} = undef; $self->{'handle'} = gensym; $self->{'warned'} = {}; $self->{'rotating'} = 0; $self->{'lockmgr'} = LockFile::Simple->make( -autoclean => 1, -delay => 1, # until sleep(.25) is supported -efunc => undef, -hold => 60, -max => 5, -nfs => !$config->single_host, -stale => 1, -warn => 0, -wfunc => undef ); return $self; } # # Attribute access # sub path { $_[0]->{'path'} } sub config { $_[0]->{'config'} } sub fd { $_[0]->{'fd'} } sub handle { $_[0]->{'handle'} } sub warned { $_[0]->{'warned'} } sub written { $_[0]->{'written'} } sub opened { $_[0]->{'opened'} } sub size { $_[0]->{'size'} } sub dev { $_[0]->{'dev'} } sub ino { $_[0]->{'ino'} } sub lockmgr { $_[0]->{'lockmgr'} } sub rotating { $_[0]->{'rotating'} } # # ->print # # Print to file. # This is where all the monitoring is performed: # # . If the file was renamed underneath us, re-open it. # This costs a stat() system call each time a log is to be emitted # and can be avoided by setting config->is_alone. # sub print { my $self = shift; my $str = join('', @_); my $fd = $self->fd; my $cf = $self->config; # # If the file was renamed underneath us, re-open it. # This costs a stat() system call each time a log is to be emitted # and can be avoided by setting config->is_alone when appropriate. # if (defined $fd && !$cf->is_alone) { my $st = stat($self->path); if (!$st || $st->dev != $self->dev || $st->ino != $self->ino) { $self->close; undef $fd; # Will be re-opened below } } # # Open file if not already done. # unless (defined $fd) { $fd = $self->open; return unless defined $fd; } # # Write to logfile # return unless syswrite($fd, $str, length $str); # # If the overall logfile size is monitored, update it. # Unless we're alone, we have to fstat() the file descriptor. # if ($cf->max_size) { if ($cf->is_alone) { $self->{'size'} += length $str; } else { my $st = stat($fd); if ($st) { $self->{'size'} = $st->size; # Paranoid test } else { $self->{'size'} += length $str; } } if ($self->size > $cf->max_size) { $self->rotate; return; } } # # If the amount of bytes written exceeds the threshold, # rotate the files. # if ($cf->max_write) { $self->{'written'} += length $str; if ($self->written > $cf->max_write) { $self->rotate; return; } } # # If the opening time is exceeded, rotate the files. # if ($cf->max_time) { if (time - $self->opened > $cf->max_time) { $self->rotate; return; } } # Did not rotate anything return; } # # ->open # # Open current logfile. # Returns opened handle, or nothing if error. # sub open { my $self = shift; my $fd = $self->handle; my $path = $self->path; my $mode = O_CREAT|O_APPEND|O_WRONLY; my $perm = ($self->config)->file_perm; warn "opening $path\n" if $DEBUG; unless (sysopen($fd, $path, $mode, $perm)) { # # Can't log errors via Log::Agent since we might recurse down here. # Therefore, use warn(), but only once, and clear condition when # opening is successful. # warn "$0: can't open logfile \"$path\": $!\n" unless $self->warned->{$path}++; return; } my $st = stat($fd); # An fstat(), really $self->warned->{$path} = 0; # Clear warning condition $self->{'fd'} = $fd; # Records: file opened $self->{'written'} = 0; # Amount written $self->{'opened'} = time; # Opening time $self->{'size'} = $st ? $st->size : 0; # Current size $self->{'dev'} = $st->dev; $self->{'ino'} = $st->ino; return $fd; } # # ->close # # Close current logfile. # sub close { my $self = shift; my $fd = $self->fd; return unless defined $fd; # Already closed warn "closing logfile\n" if $DEBUG; close($fd); $self->{'fd'} = undef; # Mark as closed } # # ->rotate # # Perform logfile rotation, as configured, and log any returned error # to the error channel. # sub rotate { my $self = shift; return if $self->rotating; # no recusion if error & limits too small $self->{'rotating'} = 1; my @errors = $self->do_rotate; unless (@errors) { $self->{'rotating'} = 0; return; } # # Errors are logged using logerr(). There's no danger we could # recurse down here since we're protected by the `rotating' flag. # my $error = @errors == 1 ? "error" : sprintf("%d errors", scalar @errors); logerr "the following $error occurred while rotating logfiles:"; foreach my $err (@errors) { logerr $err; warn "ERROR: $err\n" if $DEBUG; } $self->{'rotating'} = 0; } # # ->do_rotate # # Perform logfile rotation, as configured. # Returns nothing if OK, an array of error messages otherwise. # sub do_rotate { my $self = shift; my $path = $self->path; my $cf = $self->config; my $lock = $self->lockmgr->lock($path); # # Emission of errors has to be delayed, since we're in the middle of # logfile rotation, which could be the error channel. # my @errors = (); push(@errors, "proceeded with rotation of $path without lock") unless defined $lock; # # We're unix-centric in the following code fragment, but I don't know # how to do the same thing on non-unix operating systems. Sorry. # my ($dir, $file) = ($path =~ m|^(.*)/(.*)|); ($dir, $file) = (".", $path) unless $dir; local *DIR; unless (opendir(DIR, $dir)) { my $error = "can't open directory \"$dir\" to rotate $path: $!"; $lock->release if defined $lock; return ($error); } my @files = readdir DIR; closedir DIR; # # Identify the logfiles already present. # # We use the common convention of renaming un-compressed logfiles # as "path.0", "path.1", etc... the .0 being the more recent file, # and use "path.0.gz", "path.1.gz", etc... for compressed logfiles. # my @logfiles = (); # Logfiles to rotate my @unlink = (); # Logfiles to unlink my $lookfor = "$file."; my $unlink_at = $cf->backlog - 1; warn "unlink_at=$unlink_at\n" if $DEBUG; foreach my $f (@files) { next unless substr($f, 0, length $lookfor) eq $lookfor; my ($idx) = ($f =~ /\.(\d+)(?:\.gz)?$/); warn "f=$f, idx=$idx\n" if $DEBUG; next unless defined $idx; $f = $1 if $f =~ /^(.*)$/; # untaint if ($idx >= $unlink_at) { push(@unlink, $f); } else { $logfiles[$idx] = $f; } } if ($DEBUG) { warn "unlink=@unlink\n"; warn "logfiles=@logfiles\n"; } # # Delete old files, if any. # foreach my $f (@unlink) { unlink("$dir/$f") or push(@errors, "can't unlink $dir/$f: $!"); } # # File rotation section... # # If backlog=5 and unzipped=2, then, when things have stabilized, # we have the following logfiles: # # path.4.gz was unlinked above # path.3.gz renamed as path.4.gz # path.2.gz renamed as path.3.gz # path.1 compressed as path.2.gz # path.0 renamed as path.1 # path current logfile, closed and renamed path.0 # # The code below is prepared to deal with missing files, or policy # changes. Compressed file are not uncompressed though. # my $last = $cf->backlog - 2; # Oldest logfile already deleted my $gz_limit = $cf->unzipped; # Files up to that index are .gz warn "last=$last, gz_limit=$gz_limit\n" if $DEBUG; # # Handle renaming of compressed files # for (my $i = $last; $i >= $gz_limit; $i--) { next unless defined $logfiles[$i]; # Not that much backlog yet? my $old = "$dir/$logfiles[$i]"; my $new = "$path." . ($i+1) . ".gz"; warn "compressing old=$old, new=$new\n" if $DEBUG; if ($old =~ /\.gz$/) { rename($old, $new) or push(@errors, "can't rename $old to $new: $!"); } else { # Compression policy changed? my $err = $self->mv_gzip($old, $new); push(@errors, $err) if defined $err; } } # # Handle compression and renaming of the oldest uncompressed file # if ($gz_limit > 0 && defined $logfiles[$gz_limit-1]) { my $old = "$dir/$logfiles[$gz_limit-1]"; my $new = "$path.$gz_limit.gz"; warn "rename and compress old=$old, new=$new\n" if $DEBUG; if ($old !~ /\.gz$/) { my $err = $self->mv_gzip($old, $new); push(@errors, $err) if defined $err; } else { # Compression policy changed? rename($old, $new) or push(@errors, "can't rename $old to $new: $!"); } } # # Handle renaming of uncompressed files # for (my $i = $gz_limit - 2; $i >= 0; $i--) { next unless defined $logfiles[$i]; # Not that much backlog yet? my $old = "$dir/$logfiles[$i]"; my $new = "$path." . ($i+1); warn "rename old=$old, new=$new\n" if $DEBUG; $new .= ".gz" if $old =~ /\.gz$/; # Compression policy changed? rename($old, $new) or push(@errors, "can't rename $old to $new: $!"); } # # Mark rotation, in case they "tail -f" on it. # my $fd = $self->fd; syswrite($fd, "*** LOGFILE ROTATED ON " . scalar(localtime) . "\n"); # # Finally, close current logfile and rename it. # $self->close; if ($gz_limit) { rename($path, "$path.0") or push(@errors, "can't rename $path to $path.0: $!"); } else { my $err = $self->mv_gzip($path, "$path.0.gz"); push(@errors, $err) if defined $err; } # # Unlock logfile and propagate errors to be logged in new current file. # $lock->release if defined $lock; return @errors if @errors; return; } # # ->mv_gzip # # Compress old file into new file and unlink old file, propagating mtime. # Returns error string, nothing if OK. # sub mv_gzip { my $self = shift; my ($old, $new) = @_; local *FILE; my $st = stat($old); unless (defined $st && CORE::open(FILE, $old)) { return "can't open $old to compress into $new: $!"; } my $gz = gzopen($new, "wb9"); unless (defined $gz) { CORE::close FILE; return "can't write into $new: $gzerrno"; } local $_; my $error; while () { unless ($gz->gzwrite($_)) { $error = "error while compressing $old in $new: $gzerrno"; last; } } CORE::close FILE; $gz->gzclose(); utime $st->atime, $st->mtime, $new; # don't care if it fails unlink $old or do { $error = "can't unlink $old: $!" }; return $error if defined $error; return; } 1; # for require __END__ =head1 NAME Log::Agent::File::Rotate - a rotating logfile set =head1 SYNOPSIS # # This class is not user-visible. # # It is documented only for programmers wishing to inherit # from it to further extend its behaviour. # require Log::Agent::Driver::File; require Log::Agent::Rotate; require Log::Agent::File::Rotate; my $config = Log::Agent::Rotate->make(...); my $driver = Log::Agent::Driver::File->make(...); my $fh = Log::Agent::File::Rotate->make("file", $config, $driver); =head1 DESCRIPTION This class represents a rotating logfile and is used drivers wishing to rotate their logfiles periodically. From the outside, it exports a single C routine, just like C. Internally, it uses the parameters given by a C object to transparently close the current logfile and cycle the older logs. Before rotating the current logfile, the string: *** LOGFILE ROTATED ON is emitted, so that people monitoring the file via "tail -f" know about it and are not surprised by the sudden stop of messages. Its exported interface is: =over 4 =item make I, I This is the creation routine. The I object is an instance of C. =item print I Prints I to the file. After having printed the data, monitor the file against the thresholds defined in the configuration, and possibly rotate the logfiles according to the parameters held in the same configuration object. When the C flag is not set in the configuration, the logfile is checked everytime a C is issued to see if its inode changed. Indeed, when several instances of the same program using rotating logfiles are running, each of them may decide to cycle the logs at some point in time, and therefore our opened handle could point to an already renamed or unlinked file. =back =head1 AUTHORS Originally written by Raphael Manfredi ERaphael_Manfredi@pobox.comE, currently maintained by Mark Rogaski Emrogaski@pobox.comE. =head1 SEE ALSO Log::Agent::Rotate(3), Log::Agent::Driver::File(3). =cut liblog-agent-rotate-perl-0.1.4.orig/patchlevel.h0100444000175000017500000000002507470116703020320 0ustar tonytony#define PATCHLEVEL 3