4343import java .util .ArrayList ;
4444import java .util .Arrays ;
4545import java .util .HashMap ;
46+ import java .util .HashSet ;
4647import java .util .List ;
4748import java .util .Map ;
4849import java .util .Map .Entry ;
4950import java .util .Objects ;
5051import java .util .Optional ;
52+ import java .util .Set ;
5153import java .util .UUID ;
5254import java .util .concurrent .Phaser ;
5355import java .util .concurrent .TimeUnit ;
5456import java .util .concurrent .atomic .AtomicBoolean ;
5557import java .util .concurrent .locks .Lock ;
5658import java .util .concurrent .locks .ReentrantLock ;
59+ import java .util .stream .Stream ;
5760
5861import javax .sql .DataSource ;
5962
@@ -681,19 +684,31 @@ private static String getArchitecture()
681684 * @param stream A stream with the postgres binaries.
682685 * @param targetDir The directory to extract the content to.
683686 */
684- private static void extractTxz (InputStream stream , String targetDir ) throws IOException {
687+ private static void extractTxz (InputStream stream , File targetDir ) throws IOException {
685688 try (
686689 XZInputStream xzIn = new XZInputStream (stream );
687690 TarArchiveInputStream tarIn = new TarArchiveInputStream (xzIn )
688691 ) {
692+ final Set <File > dirsToUpdate = new HashSet <>();
689693 final Phaser phaser = new Phaser (1 );
690694 TarArchiveEntry entry ;
691695
692696 while ((entry = tarIn .getNextTarEntry ()) != null ) {
693697 final String individualFile = entry .getName ();
694698 final File fsObject = new File (targetDir , individualFile );
695699
696- if (entry .isSymbolicLink () || entry .isLink ()) {
700+ if (fsObject .exists ()) {
701+ fsObject .setLastModified (System .currentTimeMillis ());
702+
703+ File parentDir = fsObject .getParentFile ();
704+ while (parentDir != null ) {
705+ dirsToUpdate .add (parentDir );
706+ if (targetDir .equals (parentDir )) {
707+ break ;
708+ }
709+ parentDir = parentDir .getParentFile ();
710+ }
711+ } else if (entry .isSymbolicLink () || entry .isLink ()) {
697712 Path target = FileSystems .getDefault ().getPath (entry .getLinkName ());
698713 Files .createSymbolicLink (fsObject .toPath (), target );
699714 } else if (entry .isFile ()) {
@@ -743,6 +758,10 @@ private void closeChannel(Channel channel) {
743758 }
744759 }
745760
761+ for (File updatedDir : dirsToUpdate ) {
762+ updatedDir .setLastModified (System .currentTimeMillis ());
763+ }
764+
746765 phaser .arriveAndAwaitAdvance ();
747766 }
748767 }
@@ -786,31 +805,28 @@ private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File over
786805 final File unpackLockFile = new File (pgDir , LOCK_FILE_NAME );
787806 final File pgDirExists = new File (pgDir , ".exists" );
788807
789- if (!pgDirExists . exists ( )) {
808+ if (!isPgBinReady ( pgDirExists )) {
790809 try (FileOutputStream lockStream = new FileOutputStream (unpackLockFile );
791810 FileLock unpackLock = lockStream .getChannel ().tryLock ()) {
792811 if (unpackLock != null ) {
793812 try {
794- if (pgDirExists .exists ()) {
795- throw new IllegalStateException ("unpack lock acquired but .exists file is present " + pgDirExists );
796- }
797813 LOG .info ("Extracting Postgres..." );
798814 try (ByteArrayInputStream bais = new ByteArrayInputStream (baos .toByteArray ())) {
799- extractTxz (bais , pgDir . getPath () );
815+ extractTxz (bais , pgDir );
800816 }
801817 if (!pgDirExists .createNewFile ()) {
802- throw new IllegalStateException ( "couldn't make .exists file " + pgDirExists );
818+ pgDirExists . setLastModified ( System . currentTimeMillis () );
803819 }
804820 } catch (Exception e ) {
805821 LOG .error ("while unpacking Postgres" , e );
806822 }
807823 } else {
808824 // the other guy is unpacking for us.
809825 int maxAttempts = 60 ;
810- while (!pgDirExists . exists ( ) && --maxAttempts > 0 ) {
826+ while (!isPgBinReady ( pgDirExists ) && --maxAttempts > 0 ) {
811827 Thread .sleep (1000L );
812828 }
813- if (!pgDirExists . exists ( )) {
829+ if (!isPgBinReady ( pgDirExists )) {
814830 throw new IllegalStateException ("Waited 60 seconds for postgres to be unpacked but it never finished!" );
815831 }
816832 }
@@ -834,6 +850,18 @@ private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File over
834850 }
835851 }
836852
853+ public static boolean isPgBinReady (File pgDirExists ) {
854+ if (!pgDirExists .exists ()) {
855+ return false ;
856+ }
857+
858+ File parentDir = pgDirExists .getParentFile ();
859+ File [] otherFiles = Optional .ofNullable (parentDir .listFiles (file -> !file .equals (pgDirExists ))).orElseGet (() -> new File [0 ]);
860+
861+ long contentLastModified = Stream .of (otherFiles ).mapToLong (File ::lastModified ).max ().orElse (Long .MAX_VALUE );
862+ return parentDir .lastModified () <= pgDirExists .lastModified () && contentLastModified <= pgDirExists .lastModified ();
863+ }
864+
837865 @ Override
838866 public String toString ()
839867 {
0 commit comments