#!/usr/bin/perl -w #------------------------------------------------------------------------------ # Copyright (c) Perforce Software, Inc., 2007-2014. All rights reserved # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1 Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE # SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. #------------------------------------------------------------------------------ # For a summary of command line options, run: p4pcm.pl -h # This runs on Unix/Linux systems only. # Log file is p4pcm.log use strict; use File::Find; use File::Basename; use Getopt::Long; use POSIX; #------------------------------------------------------------------------------ # Initialization #------------------------------------------------------------------------------ BEGIN { $main::ThisScript = basename($0); } #------------------------------------------------------------------------------ # Prototypes for local functions. #------------------------------------------------------------------------------ sub usage(); sub getDriveSpace($;); #------------------------------------------------------------------------------ # Declarations #------------------------------------------------------------------------------ # $freespace is less than $threshhold1, then start deleting files. # $threshhold2 is the amount of diskspace we want available/free constantly. my $acctime; my $rmfile; my $topdir; my $threshold1 = 10737418240; # 10GB my $threshold2 = 21474836480; # 20GB my $totalsize; my $freespace; my $timestamp; my $datestamp; my @rmlist; my @date_sorted; my %oldest; #------------------------------------------------------------------------------ # Parse command line. #------------------------------------------------------------------------------ Getopt::Long::config "no_ignore_case"; Getopt::Long::config "auto_abbrev"; GetOptions(\%main::CmdLine, "help", "noop", "dir=s", "tlow=s", "thigh=s") or die "\nUsage Error: Unrecognized argument.\n"; # Validate command line arguments. usage() if $main::CmdLine{'help'}; # The '-d <topdir>' argument is required. usage() unless ($main::CmdLine{'dir'}); $topdir = $main::CmdLine{'dir'}; $datestamp = strftime("\%Y-\%m-\%d",localtime); $threshold1 = $main::CmdLine{'tlow'} if ($main::CmdLine{'tlow'}); $threshold2 = $main::CmdLine{'thigh'} if ($main::CmdLine{'thigh'}); #------------------------------------------------------------------------------ # Main Program. #------------------------------------------------------------------------------ $timestamp = strftime("\%H:\%M:\%S",localtime); my ($name, $dir, $ext) = fileparse($0, '\..*'); my $logfile = "$name.log"; open (LOG, ">>$logfile"); print "Log file is: $logfile\n"; print LOG "$datestamp ============= $timestamp ================\n"; # Check if $topdir exists and that it's a directory. if (-e $topdir && -d $topdir) { # Find the total amount of free space in $topdir. ($totalsize, $freespace) = getDriveSpace($topdir); print LOG "$datestamp Free Space = $freespace\n"; # compare $freespace to $threshold1 if ( $freespace < $threshold1 ) { # while $freespace is less than $threshold2 # Find oldest file based on "Date Modified" find (sub {$oldest{$File::Find::name} = -M if -f;}, $topdir); @date_sorted = sort {(stat($a))[9] <=> (stat($b))[9] } keys %oldest; while ( $freespace < $threshold2 ) { $rmfile = shift @date_sorted; last unless ($rmfile); $freespace += (stat($rmfile))[7]; push(@rmlist, $rmfile); } # if @rmlist exists, delete it + log if ( @rmlist ) { # record the files that will be deleted print LOG "$datestamp File \t Size \t Accessed\n"; foreach $rmfile ( @rmlist ) { $acctime = (stat($rmfile))[9]; print LOG "$datestamp $rmfile \t " . (stat($rmfile))[7] . "\t" . scalar(localtime($acctime)) . "\n"; } # Delete files to free space. if ($main::CmdLine{'noop'}) { print LOG "NO-OP: $datestamp @rmlist would have been deleted\n"; } else { print LOG "$datestamp Files deleted:\n@rmlist\n\n"; unlink @rmlist or print LOG "$datestamp ERROR: Files not deleted:\n@rmlist\n"; } } } else { # log: theres enough free space in $topdir until next time print LOG "$datestamp No files need to be deleted\n"; } } # Stop logging. $timestamp = strftime("\%H:\%M:\%S",localtime); print LOG "$datestamp ============= $timestamp ================\n"; close(LOG); #------------------------------------------------------------------------------ # Function: usage() # Displays usage message. #------------------------------------------------------------------------------ sub usage () { print "\nUsage:\n $main::ThisScript -d \"proxy cache dir\" [-tlow <low_threshold>] [-thigh <high_threshold>] [-n] or $main::ThisScript -h This utility removes files in the proxy cache if the amount of free disk space falls below the low threshold (default 10GB). It removes files (oldest first) until the high threshold is (default 20GB) is reached. The '-d \"proxy cache dir\"' argument is required. Use '-n' to show what files would be removed. "; exit 1;; } #------------------------------------------------------------------------------ # Function getDriveSpace($topdir) # Returns a 2-element array containing $totalspace and $freespace, i.e. # returns ($totalspace, $freespace). #------------------------------------------------------------------------------ sub getDriveSpace($;) { my ($topdir) = @_; my $totalSpace; my $freeSpace; my $dirInfo; my $junk; # Run 'df -k $topdir', and extract the total and available space values, # using $junk to ignore extranneous information. $dirInfo = `df -k $topdir`; $dirInfo =~ s/^.*?\n//; # Zap the header line. $dirInfo =~ s/\s+/,/gs; # Replace whitespace with comma as field delimiter. ($junk, $totalSpace, $junk, $freeSpace, $junk, $junk) = split (',',$dirInfo); return ($totalSpace, $freeSpace); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#16 | 30621 | Neal Firth |
Enhanced messaging to allow easier determination of operation in progress using a tail of the log file. Moved delete of the nomination file from before space recovery deletes until after space recovery deletes. Otherwise, a run overlapping the space recovery deletes could potentially include files nominated for delete resulting in a smaller than expected recovery of space. |
||
#15 | 30522 | Robert Cowham | Conver DOS line endings to Unix | ||
#14 | 30519 | Neal Firth |
Modified through swarm to change DOS line endings to Unix line endings. #review-30520 |
||
#13 | 30426 | Neal Firth |
Modified through swarm. #review Major changes. Effectively a new approach. Significant performance improvements. Specifically: * Change from time-last-modified to time-last-accessed. * Replace perl based find code with effectively equivalent shell code. Operates at least 7 times faster with smaller resource footprint than the perl code. * Threshold parameters can be specified as percentage of total disk space. * Enhanced parameter validation. * Enhanced log information for better performance tracking and debug support. * Added check so that a new run does not interrupt a run in progress. * Updated help information to reflect new technologies and capabilities. * Added internal algorithm related comments to aid future support/ enhancements. * Minor code consistency changes. Mostly adding support functions to standardize. |
||
#12 | 29585 | C. Thomas Tyler | Rollback of accidental submit of wrong file. | ||
#11 | 29584 | C. Thomas Tyler | Added '-v' (verbose) option and some debugging output. | ||
#10 | 29301 | C. Thomas Tyler |
p4pcm.pl v1.1.7: Adjusted shebang line. The prior shebang line forced usage of /p4/common/perl/bin/perl. At one point in history that was more reliably available, when building a self-contained Perl in the SDP was more common. But no longer. The shebang line now finds perl from PATH. The default SDP path still prefers /p4/common/perl/bin, so if a perl exists there it will be used. This change will have no functional impact to existing installations that have and user /p4/common/perl, but will not require new installstions to build a self-contained perl. #review-29302 |
||
#9 | 28215 | C. Thomas Tyler | Merge Down from main -> dev. | ||
#8 | 27722 | C. Thomas Tyler |
Refinements to @27712: * Resolved one out-of-date file (verify_sdp.sh). * Added missing adoc file for which HTML file had a change (WorkflowEnforcementTriggers.adoc). * Updated revdate/revnumber in *.adoc files. * Additional content updates in Server/Unix/p4/common/etc/cron.d/ReadMe.md. * Bumped version numbers on scripts with Version= def'n. * Generated HTML, PDF, and doc/gen files: - Most HTML and all PDF are generated using Makefiles that call an AsciiDoc utility. - HTML for Perl scripts is generated with pod2html. - doc/gen/*.man.txt files are generated with .../tools/gen_script_man_pages.sh. #review-27712 |
||
#7 | 26649 | Robert Cowham |
More SDP Doc tidy up. Removed some command summary files. |
||
#6 | 25552 | C. Thomas Tyler |
Fixed off-by-three-orders-of-magnitude error in Proxy cleanup script. The key change is to adjust the output of a stat() call, dividing the numeric value in bytes returned by 1024 to get the number of Kilobytes. This script makes use of the Perl stat() function, the details of which are helpful: https://perldoc.perl.org/functions/stat.html See also: SDP-191 and change @21751. This was an earlier change that detected the bytes/Kilobtyes confusion, and addressed it by adjusting the default threshhold values from the baseline version. This change change undoes that method of addressing the problem, rolling back to the original defaults for thresholds. Now with the calculation adjusted to use KB rather than bytes, the original change is no longer needed. #review @amorriss |
||
#5 | 21751 | C. Thomas Tyler | Merged Erik's change to dev. | ||
#4 | 19250 | C. Thomas Tyler |
SDP-ified: * Now puts the p4pcm.log file in $LOGS dir. * No longer requires '-d' flag if $P4PCACHE environment variable is defined. Also did some internal refactoring. To Do: The log just grows and is not rotated. |
||
#3 | 16029 | C. Thomas Tyler |
Routine merge to dev from main using: p4 merge -b perforce_software-sdp-dev |
||
#2 | 12169 | Russell C. Jackson (Rusty) |
Updated copyright date to 2015 Updated shell scripts to require an instance parameter to eliminate the need for calling p4master_run. Python and Perl still need it since you have to set the environment for them to run in. Incorporated comments from reviewers. Left the . instead of source as that seems more common in the field and has the same functionality. |
||
#1 | 10638 | C. Thomas Tyler | Populate perforce_software-sdp-dev. | ||
//guest/perforce_software/sdp/main/Server/Unix/p4/common/bin/p4pcm.pl | |||||
#1 | 10148 | C. Thomas Tyler | Promoted the Perforce Server Deployment Package to The Workshop. |