2752: Avoid hiccup on arv-put with short stdin.
authorBrett Smith <brett@curoverse.com>
Tue, 27 May 2014 14:49:13 +0000 (10:49 -0400)
committerBrett Smith <brett@curoverse.com>
Fri, 30 May 2014 14:40:10 +0000 (10:40 -0400)
Trying to call os.stat(os.path.realpath('/dev/stdin')) usually fails
in this case.  Since we're never going to be able to resume from stdin
anyway, don't bother with that check in this case.

sdk/python/arvados/collection.py
sdk/python/tests/test_arv-put.py

index 32c45289c2e85c8f3000a95b3e85188af94926c6..41adc88db17f119489c9b3b6e86ec6917553f545 100644 (file)
@@ -443,15 +443,22 @@ class ResumableCollectionWriter(CollectionWriter):
             raise errors.AssertionError("{} not a file path".format(source))
         try:
             path_stat = os.stat(src_path)
-        except OSError as error:
-            raise errors.AssertionError(
-                "could not stat {}: {}".format(source, error))
+        except OSError as stat_error:
+            path_stat = None
         super(ResumableCollectionWriter, self)._queue_file(source, filename)
         fd_stat = os.fstat(self._queued_file.fileno())
-        if path_stat.st_ino != fd_stat.st_ino:
+        if not S_ISREG(fd_stat.st_mode):
+            # We won't be able to resume from this cache anyway, so don't
+            # worry about further checks.
+            self._dependencies[source] = tuple(fd_stat)
+        elif path_stat is None:
+            raise errors.AssertionError(
+                "could not stat {}: {}".format(source, stat_error))
+        elif path_stat.st_ino != fd_stat.st_ino:
             raise errors.AssertionError(
                 "{} changed between open and stat calls".format(source))
-        self._dependencies[src_path] = tuple(fd_stat)
+        else:
+            self._dependencies[src_path] = tuple(fd_stat)
 
     def write(self, data):
         if self._queued_file is None:
index cd0e9658eb4030b592899dd49cd6702a32251191..2e572854f5af35c974a900a4ea2a3337a3139010 100644 (file)
@@ -4,7 +4,10 @@
 import os
 import re
 import shutil
+import subprocess
+import sys
 import tempfile
+import time
 import unittest
 
 import arvados
@@ -319,6 +322,25 @@ class ArvadosPutTest(ArvadosKeepLocalStoreTestCase):
                                         '098f6bcd4621d373cade4e832627b4f6')),
             "did not find file stream in Keep store")
 
+    def test_short_put_from_stdin(self):
+        # Have to run this separately since arv-put can't read from the
+        # tests' stdin.
+        # arv-put usually can't stat(os.path.realpath('/dev/stdin')) in this
+        # case, because the /proc entry is already gone by the time it tries.
+        pipe = subprocess.Popen(
+            [sys.executable, arv_put.__file__, '--stream'],
+            stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+        pipe.stdin.write('stdin test\n')
+        pipe.stdin.close()
+        deadline = time.time() + 5
+        while (pipe.poll() is None) and (time.time() < deadline):
+            time.sleep(.1)
+        if pipe.returncode is None:
+            pipe.terminate()
+            self.fail("arv-put did not PUT from stdin within 5 seconds")
+        self.assertEquals(pipe.returncode, 0)
+        self.assertIn('4a9c8b735dce4b5fa3acf221a0b13628+11', pipe.stdout.read())
+
 
 if __name__ == '__main__':
     unittest.main()