#!@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 <<EOF;
compile_db [ -f ] [ -t type ] [ -d destdir] [ -j n ] [driver1] [driver2] ...
-f force: proceed even if the destination directory exists
-t type output file type: ppd or xml
-j n n==number of work processes to run at the same time
-d destdir put PPD files in this directory
driver1 driver2 ...
only compile the database for these drivers
EOF
exit 1;
}
help() if ($opt_h);
# Default file type are PPD files
if (!$opt_t) {
$opt_t = "ppd";
}
my $destdir;
if( $opt_d ){
$destdir = $opt_d;
}
print STDERR "\n";
# Destination directory
my $pwd = cwd;
if (($opt_t eq "ppd") || ($opt_t eq "cups") || ($opt_t eq "ppr")) {
# Generic PPDs
$filetype = "ppd";
$destdir = "$pwd/ppd" if not defined( $destdir );
$suffix = ".ppd";
print STDERR "Generating Foomatic PPD files ...\n";
} elsif ($opt_t eq "xml") {
$filetype = "xml";
$destdir = "$pwd/combo-xml" if not defined( $destdir );
$suffix = ".xml";
print STDERR "Generating Foomatic printer/driver combo XML files ...\n";
} else {
die "Unknown file type: $opt_t!\n";
}
print STDERR "\nStoring files in directory $destdir.\n";
mkdir $destdir, 0777 or $force or die "\nCannot make destination directory (If the directory already exists and you\nwant to proceed anyway, use the \"-f\" option)!\n";
# Compute the overview (only printer/driver combos which give a PPD)
$db->get_overview(1, ($filetype eq "ppd" ? 2 : 0));
# Find all printer/driver combinations
my @combos;
for my $printer (@{$db->{"overview"}}) {
my $poid = $printer->{'id'};
for my $driver (@{$printer->{'drivers'}}) {
if (!@ARGV || Foomatic::DB::member($driver, @ARGV)) {
push (@combos, "$poid,$driver\n");
}
}
}
# 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=<STDIN>) {
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 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);
}
}