about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-02-03T15·34+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-02-03T15·34+0000
commitbc1e478db160059753c4bf4cb28dd50437a76b27 (patch)
treecb3f5cb95831cae721800cffd37bce5fde37cbbd
parent4d8a85b8f56625616c993d0bace0a4e856e7f2c5 (diff)
* nix-copy-closure: start only one SSH connection to the server, or
  recycle an already existing connection (using  OpenSSH's connection
  sharing feature).

-rw-r--r--scripts/Makefile.am2
-rw-r--r--scripts/nix-copy-closure.in16
-rw-r--r--scripts/ssh.pm36
3 files changed, 49 insertions, 5 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 0e8443e9c239..aa5d6f78c18a 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -15,6 +15,7 @@ install-exec-local: readmanifest.pm download-using-manifests.pl copy-from-other-
 	$(INSTALL) -d $(DESTDIR)$(libexecdir)/nix
 	$(INSTALL_DATA) readmanifest.pm $(DESTDIR)$(libexecdir)/nix 
 	$(INSTALL_DATA) readconfig.pm $(DESTDIR)$(libexecdir)/nix 
+	$(INSTALL_DATA) ssh.pm $(DESTDIR)$(libexecdir)/nix 
 	$(INSTALL_PROGRAM) find-runtime-roots.pl $(DESTDIR)$(libexecdir)/nix 
 	$(INSTALL_PROGRAM) generate-patches.pl $(DESTDIR)$(libexecdir)/nix 
 	$(INSTALL_PROGRAM) build-remote.pl $(DESTDIR)$(libexecdir)/nix 
@@ -31,6 +32,7 @@ EXTRA_DIST = nix-collect-garbage.in \
   nix-channel.in \
   readmanifest.pm.in \
   readconfig.pm.in \
+  ssh.pm \
   nix-build.in \
   download-using-manifests.pl.in \
   copy-from-other-stores.pl.in \
diff --git a/scripts/nix-copy-closure.in b/scripts/nix-copy-closure.in
index 4f31953b922a..313d6f0192e6 100644
--- a/scripts/nix-copy-closure.in
+++ b/scripts/nix-copy-closure.in
@@ -1,4 +1,6 @@
-#! @perl@ -w
+#! @perl@ -w -I@libexecdir@/nix
+
+use ssh;
 
 my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
 
@@ -14,7 +16,6 @@ EOF
 
 # Get the target host.
 my $sshHost;
-my @sshOpts = split ' ', ($ENV{"NIX_SSHOPTS"} or "");
 
 my $sign = 0;
 
@@ -52,6 +53,9 @@ while (@ARGV) {
 }
 
 
+openSSHConnection $sshHost;
+
+
 if ($toMode) { # Copy TO the remote machine.
 
     my @allStorePaths;
@@ -73,7 +77,6 @@ if ($toMode) { # Copy TO the remote machine.
     my @missing = ();
     while (<READ>) {
         chomp;
-        print STDERR "target machine needs $_\n";
         push @missing, $_;
     }
     close READ or die;
@@ -81,6 +84,8 @@ if ($toMode) { # Copy TO the remote machine.
 
     # Export the store paths and import them on the remote machine.
     if (scalar @missing > 0) {
+        print STDERR "copying these missing paths:\n";
+        print STDERR "  $_\n" foreach @missing;
         my $extraOpts = "";
         $extraOpts .= "--sign" if $sign == 1;
         system("nix-store --export $extraOpts @missing | $compressor | ssh @sshOpts $sshHost '$decompressor | nix-store --import'") == 0
@@ -114,7 +119,6 @@ else { # Copy FROM the remote machine.
     my @missing = ();
     while (<READ>) {
         chomp;
-        print STDERR "local machine needs $_\n";
         push @missing, $_;
     }
     close READ or die;
@@ -122,10 +126,12 @@ else { # Copy FROM the remote machine.
 
     # Export the store paths on the remote machine and import them on locally.
     if (scalar @missing > 0) {
+        print STDERR "copying these missing paths:\n";
+        print STDERR "  $_\n" foreach @missing;
         my $extraOpts = "";
         $extraOpts .= "--sign" if $sign == 1;
         system("ssh @sshOpts $sshHost 'nix-store --export $extraOpts @missing | $compressor' | $decompressor | @bindir@/nix-store --import") == 0
-            or die "copying store paths to remote machine `$sshHost' failed: $?";
+            or die "copying store paths from remote machine `$sshHost' failed: $?";
     }
 
 }
diff --git a/scripts/ssh.pm b/scripts/ssh.pm
new file mode 100644
index 000000000000..0295cef33b0a
--- /dev/null
+++ b/scripts/ssh.pm
@@ -0,0 +1,36 @@
+use strict;
+use File::Temp qw(tempdir);
+
+our @sshOpts = split ' ', ($ENV{"NIX_SSHOPTS"} or "");
+
+my $sshStarted = 0;
+my $sshHost;
+
+# Open a master SSH connection to `host', unless there already is a
+# running master connection (as determined by `-O check').
+sub openSSHConnection {
+    my ($host) = @_;
+    die if $sshStarted;
+    $sshHost = $host;
+    return if system("ssh $sshHost @sshOpts -O check 2> /dev/null") == 0;
+
+    my $tmpDir = tempdir("nix-ssh.XXXXXX", CLEANUP => 1, TMPDIR => 1)
+        or die "cannot create a temporary directory";
+    
+    push @sshOpts, "-S", "$tmpDir/control";
+    system("ssh $sshHost @sshOpts -M -N -f") == 0
+        or die "unable to start SSH: $?";
+    $sshStarted = 1;
+}
+
+# Tell the master SSH client to exit.
+sub closeSSHConnection {
+    if ($sshStarted) {
+        system("ssh $sshHost @sshOpts -O exit 2> /dev/null") == 0
+            or warn "unable to stop SSH master: $?";
+    }
+}
+
+END { closeSSHConnection; }
+
+return 1;