Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

This seems to go into an endless loop, and I'm not sure why. Every file needs to go through the process cp -> dbv -> gzip -> mv. The logic is supposed to get the cp part finished as quickly as possible, so we can restart the database.
#!/usr/local/bin/perl -w # This does all of the copying, verifying, zipping, and moving # of backup files. # # ToDo: # 1. use @ARGV to hand in list of data file paths, dop, blocksize, etc +. # use POSIX ":sys_wait_h"; use DBSystemUtils; use File::Basename; ##################################################### # Most of this will be passed in from the main program # if I can - much of what's here is just to make this # program run on its own while developing it $children = 0; $dop = 3; # degree of parallelism $blocksize = 8192; %pidCommands = (); %pidStatus = (); @kidFiles = (); @dbFilePaths = ("/export/home/oracle/ORIG/file01.dbf", "/export/home/oracle/ORIG/file02.dbf", "/export/home/oracle/ORIG/system01.dbf", "/export/home/oracle/ORIG/file03.dbf", "/export/home/oracle/ORIG/file04.dbf", "/export/home/oracle/ORIG/file05.dbf"); @dbFileNames = basename(@dbFilePaths); #$origDir = dirname($dbFilePaths[0]); $localDir = "/export/home/oracle/LOCAL"; $destDir = "/export/home/oracle/DEST"; %fileSizes = ("/export/home/oracle/ORIG/file01.dbf"=>83894272, "/export/home/oracle/ORIG/system01.dbf"=>83894272, "/export/home/oracle/ORIG/file03.dbf"=>83894272, "/export/home/oracle/ORIG/file04.dbf"=>83894272, "/export/home/oracle/ORIG/file05.dbf"=>83894272, "/export/home/oracle/ORIG/file02.dbf"=>83894272); #$totalSize = 0; %fileStatus = map {$_, "0"} @dbFilePaths; #%statusCodes = (0=>"orig", # 1=>"copying", # 2=>"copied", # 3=>"verifying", # 4=>"verified", # 5=>"zipping", # 6=>"zipped", # 7=>"moving", # 8=>"moved", # 999=>"error"); $availSpace = DBSystemUtils->spaceAvailable($localDir); # make space tight for testing purposes $availSpace = $availSpace - 6081900; ###################################################### print "STARTSTARTSTARTSTART\n"; "coldBUfileOps.pl" 237 lines, 5849 characters print "STARTSTARTSTARTSTART\n"; while (@dbFilePaths) { $file = shift(@dbFilePaths); print "1. Looping on: [$file]\n"; print "2. Top of loop status.\n"; foreach $key (keys %fileStatus) { print "3. name: [$key] status: [$fileStatus{$key}]\n"; } print "\n"; # if there's room for the file in localDir, copy it there if ( ($fileStatus{$file} == 0) && ($fileSizes{$file} < $availSpace) +) { print "4. There's room for $file\n"; print "5. file: [$file] status: [$fileStatus{$file}]\n"; ++$fileStatus{$file}; print "6. file: [$file] status: [$fileStatus{$file}]\n"; $command = "cp $file $localDir"; $availSpace = $availSpace - $fileSizes{$file}; } else { # no room so work on files already in localDir to try to make some spa +ce print "7. No room for file: [$file] status: [$fileStatus{$file}]\n"; # put the file back on the todo list unshift (@dbFilePaths, $file); $zippedFile = smallestOfStatus(6,\%fileSizes,\%fileStatus); $verifiedFile = smallestOfStatus(4,\%fileSizes,\%fileStatus); $copiedFile = smallestOfStatus(2,\%fileSizes,\%fileStatus); if (defined $zippedFile) { print "8. zippedFile: [$zippedFile]\n"; } if (defined $verifiedFile) { print "9. verifiedFile: [$verifiedFile]\n"; } if (defined $copiedFile) { print "10. copiedFile: [$copiedFile]\n"; } if ($zippedFile) { print "11. Have zipped files.\n"; $zippedFile = $zippedFile . ".gz"; $command = "mv $zippedFile $destDir"; } elsif ($verifiedFile) { print "12. Have verified files.\n"; $command = "gzip $verifiedFile"; $command = "gzip $verifiedFile"; } elsif ($copiedFile) { print "13. Have copied files.\n"; $command = "dbv file=$copiedFile blocksize=$blocksize"; } else { print "14. Problem\n"; exit 0; } } forkIt(\%pidStatus,\%pidCommands,$command,$file); } sub smallestOfStatus { my $desiredStatus = shift; my $fileSizesRef = shift; my $fileStatusRef = shift; my %oneStatSize = (); foreach $key (keys %$fileStatusRef) { next unless $$fileStatusRef{$key} == $desiredStatus; $oneStatSize{$key} = $$fileSizesRef{$key}; } %reverseOneStatSize = reverse %oneStatSize; $smallestSize = (sort (values %oneStatSize))[0]; $smallestFile = $reverseOneStatSize{$smallestSize}; return $smallestFile; } sub forkIt { print "15. In the fork\n"; my $pidStatusRef = shift; my $pidCommandsRef = shift; my $command = shift; my $fileName = shift; my $pid; print "16. command: [$command]\n\n"; foreach $key (keys %$pidStatusRef) { print "17. pid: [$key] status: [$$pidStatusRef]\n"; } foreach $key (keys %$pidCommandsRef) { print "18. pid: [$key] status: [$$pidCommandsRef]\n"; } if ($children < $dop) { print "19. Not too many children.\n"; $children++; $children++; ++$fileStatus{$file}; if ($pid = fork) { # If a child has alredy worked on this file, don't give it # to another child foreach $value (values %$pidCommands) { print "19.25 command: [$value]\n"; $name = (split /\s/, $value)[1]; print "19.5 name: [$name]\n"; exit 0 if $name eq $fileName; } $$pidCommands{$pid} = $command; $$pidStatus{$pid} = "alive"; next; } else { $error = system($command); if ($error) { print "20. error on $command: $?\n"; } exit 0; } } else { #reaper print "21. Too many children. In the reaper.\n"; foreach $key (keys %pidStatus) { next if $key eq "dead"; if (WIFEXITED($?)) { print "22. Child $key exited.\n"; $$pidStatus{$key } = "dead"; $fileOperatedOn = (split /\s+/,$$pidCommands{$key})[1]; print "23. fileOperatedOn: [$fileOperatedOn]\n"; $children--; next; } #end operating on ready-to-reap children } #end walking live children } #end reaper }

Replies are listed 'Best First'.
Re: More fork and reap
by slayven (Pilgrim) on Mar 17, 2001 at 06:46 UTC
    it's a hashref, remember? :)
    foreach $key (keys %{ $pidStatus }) {
    i guess
    $children++ $children++
    is a copy and paste mistake...

    slay
      Doh! Ref ref ref ref ref (she says pounding herself on the head).

      At least now it dies somewhere else. Even painful progress is better than none. :->

      Many thanx,

      ltg