#! /usr/bin/perl

use Foomatic::Defaults;
use Foomatic::DB;

my ($db) = new Foomatic::DB;

use Getopt::Std;
getopts('fj:h');
my $force = ($opt_f ? 1 : 0);

# Do the whole world

chdir $libdir or die "Can't change to $libdir";

if ($opt_h) {
    print <<EOF;
compile_db [ -f ] [ -j n ] [driver1] [driver2] ...
 -f     recompile everything regardless of cache states
 -j n   n==number of work processes to run (150MB each!)
 driver1 driver2 ...  
        only compile the database for these drivers
EOF

    exit 0;
}

if ($opt_f) {
    system "rm -rf $cachedir/compiled";
    system "rm -rf $cachedir/pcache";
}

# Compute the overview in a subprocess
if ($force) {
    if (!fork()) {
	$db->get_overview(1);
	exit(0);
    } else {
	wait;
    }
}

# Which drivers should be processed?
my @driverlist;
if (@ARGV) {
    @driverlist = @ARGV;
} else {
    @driverlist = $db->get_driverlist();
}

# Subprocess to compute all p/d combinations
my @combos;
if (open COMB, '-|') {
    while(<COMB>) {
	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
if ($opt_j > 1) {
    while ($opt_j-- > 1) {
	if (!fork()) {
	    # Child, go on immediately
	    last;
	}
    }
}

# Reorder combos randomly:
my $ct = scalar(@combos);
my @rcombos;
while ($ct) {
    my $idx = int(rand($ct--));
    my $next = splice(@combos, $idx, 1);
    push (@rcombos, $next);
}

# Now, the processing loop:
my $combo;
my $pcount=0;
my $fileh=spawn_child();
while($combo=pop(@rcombos)) {
    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;

	    # Skip entirely if we can
	    next if (-f "$cachedir/compiled/combo/$driver/$printer.xml");
	    
	    print STDERR "  ...printer $printer, driver $driver\n";
	    
	    # Get and store the compiled XML for the combo.
	    # gcdx will also save the data in the compiled xml cache...
	    my $grove = $db->get_combo_data_grove($driver,$printer);
	}

	# No more input!
	exit (0);
    }    
}
