#!/usr/bin/perl # -*- perl -*- use Foomatic::Defaults; use Foomatic::DB; use Cwd; my ($db) = new Foomatic::DB; use Getopt::Std; getopts('ft:j:hd:') || help(); my $force = ($opt_f ? 1 : 0); my $debug = 0; # Do the whole world sub help { print STDERR <get_overview(); # Which drivers should be processed? my @driverlist; if (@ARGV) { @driverlist = grep {isdrivervalid($_)} @ARGV; } else { @driverlist = grep {isdrivervalid($_)} $db->get_driverlist(); } # Subprocess to compute all p/d combinations my @combos; if (open COMB, '-|') { while() { push (@combos, $_); } close COMB; # wait for child end } else { my $driver; for $driver (@driverlist) { my $printer; for $printer ($db->get_printers_for_driver($driver)) { # Note this combo... print STDOUT "$printer,$driver\n"; } } exit 0; # end of subprocessing } # OK, spawn n manager processes # create lists to process $opt_j = 0 if( not defined $opt_j ); $opt_j += 0; $opt_j = 1 if( not $opt_j or $opt_j < 0 ); my $n = 0; my $rcombos = []; my @rcombos; for( $n = 0; $n < $opt_j; ++$n ){ $rcombos->[$n] = []; } $n = 0; while( @combos ){ my $pos = int(rand(scalar(@combos))); my $j = $n % $opt_j; print "$n: combos " . scalar(@combos) . ", pos $pos, id $j\n" if $debug; push( @{$rcombos->[$n % $opt_j]}, splice( @combos, $pos, 1 ) ); ++$n; } my (@pids, $pid ); for( $n = 0; $n < $opt_j; ++$n ){ $pid = fork(); if( ! defined( $pid ) ){ warn( "cannot fork child process" ); break; } elsif( ! $pid ){ # Child, go on immediately @rcombos = @{$rcombos->[$n]}; last; } print "process $pid\n" if $debug; } if( $pid ){ # we wait for the processes while( ($pid = wait()) > 0 ){ print "DONE $pid\n" if $debug }; print "ALL DONE" if $debug; } print "Monitor process $$\n"; # Now, the processing loop: my $combo; my $pcount=0; my $fileh=spawn_child(); while($combo=pop(@rcombos)) { print "PROCESS $n - $$, $combo" if $debug;; print $fileh $combo; if ($pcount++ > 25) { close $fileh or die "\nError in child...\n"; $fileh = spawn_child(); $pcount=0; } } close $fileh; print STDERR "Done.\n"; exit (0); # Form a combo-computing child process to handle a flock of combos sub spawn_child { if (open CHILD, '|-') { return \*CHILD; } else { while ($line=) { my ($printer,$driver) = split(',',$line); chomp $driver; # Determine file name for the output file my $printer = Foomatic::DB::translate_printer_id($printer); my $filename = "$destdir/$printer-$driver$suffix"; # Skip on bad file name if ($filename =~ /^\-/) { print STDERR "WARNING: $printer with $driver gives a bad PPD file name: $filename\n\n"; next; } # Skip on non-existing printer XML file (happens if in the # list of supported printers of a driver is a printer # which does not exist in the Foomatic database) next if !defined($db->get_printer($printer)); ## Skip entirely if we can #next if (-f $filename); print STDERR " Worker $$ ...printer $printer, driver $driver\n"; # Generate the file ... if ($filetype eq 'xml') { @data = $db->get_combo_data_xml($driver, $printer); } else { my $possible = $db->getdat($driver, $printer); # Do not create a PPD file if the printer/driver combo # is not possible or if the renderer command line is # empty and no custom PPD file is available next if ((!$possible) or ((!$db->{'dat'}{'cmd'}) and (!$db->{'dat'}{'ppdfile'}))); @data = $db->getppd(); } open OUTPUT, "> $filename" || die "Cannot write $filename!"; print OUTPUT join('', @data); close OUTPUT; } # No more input! exit (0); } } sub isdrivervalid { my ($driver) = @_; # Check whether the driver has a valid command line if ($filetype ne 'xml') { my $driverentry = $db->get_driver($driver); if ($driverentry->{'cmd'}) {return 1;} return 0; } else { return 1; } }