Fixed bug #50081: --keep-order --round-robin should give predictable results.

This commit is contained in:
Ole Tange 2017-02-05 00:27:10 +01:00
parent 09cc44e209
commit 1229288418
5 changed files with 56 additions and 9 deletions

View file

@ -597,24 +597,38 @@ sub nindex {
push @robin_queue, (sort { $a->seq() <=> $b->seq() } push @robin_queue, (sort { $a->seq() <=> $b->seq() }
values %Global::running); values %Global::running);
} }
do { if($opt::keeporder) {
$written = 0;
for my $job (@robin_queue) { for my $job (@robin_queue) {
if($job->block_length() > 0) { if($job->block_length() > 0) {
$written += $job->non_blocking_write(); $written += $job->non_blocking_write();
} else { } else {
$job->set_block($header_ref,$buffer_ref, $job->set_block($header_ref,$buffer_ref,$endpos,$recstart,$recend);
$endpos,$recstart,$recend);
$block_passed = 1; $block_passed = 1;
$job->set_virgin(0); $job->set_virgin(0);
$written += $job->non_blocking_write(); $written += $job->non_blocking_write();
last; last;
} }
} }
if($written) { } else {
$sleep = $sleep/1.5+0.001; do {
} $written = 0;
} while($written and not $block_passed); for my $job (@robin_queue) {
if($job->block_length() > 0) {
$written += $job->non_blocking_write();
} else {
$job->set_block($header_ref,$buffer_ref,
$endpos,$recstart,$recend);
$block_passed = 1;
$job->set_virgin(0);
$written += $job->non_blocking_write();
last;
}
}
if($written) {
$sleep = $sleep/1.5+0.001;
}
} while($written and not $block_passed);
}
$sleep = ::reap_usleep($sleep); $sleep = ::reap_usleep($sleep);
} }
return $written; return $written;
@ -961,6 +975,7 @@ sub options_hash {
"cat" => \$opt::cat, "cat" => \$opt::cat,
"fifo" => \$opt::fifo, "fifo" => \$opt::fifo,
"pipepart|pipe-part" => \$opt::pipepart, "pipepart|pipe-part" => \$opt::pipepart,
"tee" => \$opt::tee,
"hgrp|hostgrp|hostgroup|hostgroups" => \$opt::hostgroups, "hgrp|hostgrp|hostgroup|hostgroups" => \$opt::hostgroups,
); );
} }
@ -7876,7 +7891,8 @@ sub start {
if($opt::pipe) { if($opt::pipe) {
my ($stdin_fh) = ::gensym(); my ($stdin_fh) = ::gensym();
$pid = open3_setpgrp($stdin_fh,$stdout_fh,$stderr_fh,$command); $pid = open3_setpgrp($stdin_fh,$stdout_fh,$stderr_fh,$command);
if($opt::roundrobin) { if($opt::roundrobin and not $opt::keeporder) {
# --keep-order will make sure the order will be reproducible
::set_fh_non_blocking($stdin_fh); ::set_fh_non_blocking($stdin_fh);
} }
$job->set_fh(0,"w",$stdin_fh); $job->set_fh(0,"w",$stdin_fh);

View file

@ -988,6 +988,9 @@ to see the difference:
If used with B<--onall> or B<--nonall> the output will grouped by If used with B<--onall> or B<--nonall> the output will grouped by
sshlogin in sorted order. sshlogin in sorted order.
If used with B<--pipe --roundrobin> and the same input, the jobslots
will get the same blocks in the same order in every run.
=item B<-L> I<max-lines> =item B<-L> I<max-lines>

View file

@ -196,6 +196,7 @@ par_result_replace() {
rm -rf /tmp/par_*_49983-* rm -rf /tmp/par_*_49983-*
} }
export -f $(compgen -A function | grep par_) export -f $(compgen -A function | grep par_)
compgen -A function | grep par_ | sort | compgen -A function | grep par_ | sort |
parallel -j6 --tag -k --joblog +/tmp/jl-`basename $0` '{} 2>&1' parallel -j6 --tag -k --joblog +/tmp/jl-`basename $0` '{} 2>&1'

View file

@ -79,6 +79,31 @@ par_pipepart_block() {
rm /run/shm/parallel$$ rm /run/shm/parallel$$
} }
par_keeporder_roundrobin() {
echo 'bug #50081: --keep-order --round-robin should give predictable results'
export PARALLEL="-j13 --block 1m --pipe --roundrobin"
random500m() {
< /dev/zero openssl enc -aes-128-ctr -K 1234 -iv 1234 2>/dev/null |
head -c 500m;
}
a=$(random500m | parallel -k 'echo {#} $(md5sum)' | sort)
b=$(random500m | parallel -k 'echo {#} $(md5sum)' | sort)
c=$(random500m | parallel 'echo {#} $(md5sum)' | sort)
if [ "$a" == "$b" ] ; then
# Good: -k should be == -k
if [ "$a" == "$c" ] ; then
# Bad: without -k the command should give different output
echo 'Broken: a == c'
printf "$a\n$b\n$c\n"
else
echo OK
fi
else
echo 'Broken: a <> b'
printf "$a\n$b\n$c\n"
fi
}
export -f $(compgen -A function | grep par_) export -f $(compgen -A function | grep par_)
compgen -A function | grep par_ | sort | parallel -j6 --tag -k '{} 2>&1' compgen -A function | grep par_ | sort | parallel -j6 --tag -k '{} 2>&1'

View file

@ -4,6 +4,8 @@ par_children_receive_sig Got TERM
par_children_receive_sig Got TERM par_children_receive_sig Got TERM
par_children_receive_sig Got INT par_children_receive_sig Got INT
par_children_receive_sig Got TERM par_children_receive_sig Got TERM
par_keeporder_roundrobin bug #50081: --keep-order --round-robin should give predictable results
par_keeporder_roundrobin OK
par_kill_int_twice ### Are children killed if GNU Parallel receives INT twice? There should be no sleep at the end par_kill_int_twice ### Are children killed if GNU Parallel receives INT twice? There should be no sleep at the end
par_kill_int_twice bash-+-perl---bash---sleep par_kill_int_twice bash-+-perl---bash---sleep
par_kill_int_twice `-pstree par_kill_int_twice `-pstree