From 44662aad098c1dea4b120ce3eaa4637125380709 Mon Sep 17 00:00:00 2001
From: Paul Wolneykien <manowar@altlinux.org>
Date: Tue, 20 Oct 2020 15:42:53 +0300
Subject: [PATCH] Count local slot numbers for each sshlogin

Signed-off-by: Paul Wolneykien <manowar@altlinux.org>
---
 parallel/src/parallel     | 40 ++++++++++++++++++++++++++++++++++++++-
 parallel/src/parallel.pod | 11 +++++++++++
 2 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/parallel/src/parallel b/parallel/src/parallel
index f1f061a..3136230 100755
--- a/parallel/src/parallel
+++ b/parallel/src/parallel
@@ -2234,6 +2234,8 @@ sub init_globals() {
 	 '{sshlogin}' => '1 $_="\${PARALLEL_SSHLOGIN}";uq()',
 	 # {localargs} = localargs
 	 '{localargs}' => '1 $_="\${PARALLEL_LOCALARGS}";uq()',
+	 # {localslot} = $PARALLEL_LOCALSLOT
+	 '{localslot}' => '1 $_="\${PARALLEL_LOCALSLOT}";uq()',
 	);
     # Modifiable copy of %Global::replace
     %Global::rpl = %Global::replace;
@@ -3434,6 +3436,7 @@ sub init_run_jobs() {
 			 ($opt::results and $opt::resume and $job->is_already_in_results()));
 		debug("start", "Command to run on '", $job->sshlogin()->string(), "': '",
 		      $job->replaced(),"'\n");
+        $job->set_localslot($sshlogin->next_localslot());
 		if($job->start()) {
 		    if($opt::pipe) {
 			if($job->virgin()) {
@@ -3455,6 +3458,7 @@ sub init_run_jobs() {
 			  " pid:", $job->pid(), "\n");
 		    return 1;
 		} else {
+            $job->free_localslot();
 		    # Not enough processes to run the job.
 		    # Put it back on the queue.
 		    $Global::JobQueue->unget($job);
@@ -4760,6 +4764,7 @@ sub reaper() {
 
     debug("run", "seq ",$job->seq()," died (", $job->exitstatus(), ")");
     $job->set_endtime(::now());
+    $job->free_localslot();
     my $sshlogin = $job->sshlogin();
     $sshlogin->dec_jobs_running();
     if($job->should_be_retried()) {
@@ -6176,6 +6181,21 @@ sub jobs_running($) {
     return ($self->{'jobs_running'} || "0");
 }
 
+sub next_localslot($) {
+    my $self = shift;
+    my $localslot = shift @{$self->{'localslots'}};
+    if (not $localslot) {
+        $localslot = $self->jobs_running() + 1;
+    }
+    return $localslot;
+}
+
+sub free_localslot($$) {
+    my $self = shift;
+    my $localslot = shift;
+    push @{$self->{'localslots'}}, $localslot;
+}
+
 sub inc_jobs_running($) {
     my $self = shift;
     $self->{'jobs_running'}++;
@@ -8958,6 +8978,23 @@ sub sshlogin($) {
     return $self->{'sshlogin'};
 }
 
+sub localslot($) {
+    my $self = shift;
+    return $self->{'localslot'};
+}
+
+sub set_localslot($$) {
+    my $self = shift;
+    $self->{'localslot'} = shift;
+}
+
+sub free_localslot($) {
+    my $self = shift;
+    my $localslot = $self->{'localslot'};
+    $self->{'localslot'} = undef;
+    $self->sshlogin()->free_localslot($localslot);
+}
+
 sub string_base64($) {
     # Base64 encode strings into 1000 byte blocks.
     # 1000 bytes is the largest word size csh supports
@@ -9175,7 +9212,7 @@ sub sshlogin_wrap($) {
 
 	push(@vars, "PARALLEL_PID", "PARALLEL_SEQ",
 	     "PARALLEL_SSHLOGIN", "PARALLEL_LOCALARGS", "PARALLEL_SSHHOST",
-         "PARALLEL_JOBSLOT",
+         "PARALLEL_JOBSLOT", "PARALLEL_LOCALSLOT",
 	     map { ("BASH_FUNC_$_()", "BASH_FUNC_$_%%") } @vars);
 	# Keep only defined variables
 	return grep { defined($ENV{$_}) } @vars;
@@ -9238,6 +9275,7 @@ sub sshlogin_wrap($) {
 	$ENV{'PARALLEL_SSHLOGIN'} = $sshlogin->string();
 	$ENV{'PARALLEL_LOCALARGS'} = $sshlogin->localargs();
 	$ENV{'PARALLEL_SSHHOST'} = $sshlogin->serverlogin();
+	$ENV{'PARALLEL_LOCALSLOT'} = $self->localslot();
 	$ENV{'PARALLEL_PID'} = $$;
 	if($serverlogin eq ":") {
 	    if($opt::workdir) {
diff --git a/parallel/src/parallel.pod b/parallel/src/parallel.pod
index b9eab2a..68127e8 100644
--- a/parallel/src/parallel.pod
+++ b/parallel/src/parallel.pod
@@ -1576,6 +1576,7 @@ Shorthands for variables:
   {sshlogin}    $PARALLEL_SSHLOGIN
   {host}        $PARALLEL_SSHHOST
   {localargs}   $PARALLEL_LOCALARGS
+  {localslot}   $PARALLEL_LOCALSLOT
 
 The following dynamic replacement strings are also activated. They are
 inspired by bash's parameter expansion:
@@ -4954,6 +4955,16 @@ results in "PARALLEL_LOCALARGS = -b 32" on host1 and
 "PARALLEL_LOCALARGS = -b 64" on host2.
 
 
+=item $PARALLEL_LOCALSLOT
+
+Set by GNU B<parallel> and can be used in jobs run by GNU B<parallel>.
+Remember to quote the $, so it gets evaluated by the correct shell. Or
+use B<--plus> and {localslot}.
+
+The value is the host-local slot number occupied by the job: a number
+from 1 to I<ncpus> value passed to --B<sshlogin>.
+
+
 =item $PARALLEL_SEQ
 
 Set by GNU B<parallel> and can be used in jobs run by GNU B<parallel>.
-- 
2.21.0

