43
43
import java .util .ArrayList ;
44
44
import java .util .Arrays ;
45
45
import java .util .HashMap ;
46
+ import java .util .HashSet ;
46
47
import java .util .List ;
47
48
import java .util .Map ;
48
49
import java .util .Map .Entry ;
49
50
import java .util .Objects ;
50
51
import java .util .Optional ;
52
+ import java .util .Set ;
51
53
import java .util .UUID ;
52
54
import java .util .concurrent .Phaser ;
53
55
import java .util .concurrent .TimeUnit ;
54
56
import java .util .concurrent .atomic .AtomicBoolean ;
55
57
import java .util .concurrent .locks .Lock ;
56
58
import java .util .concurrent .locks .ReentrantLock ;
59
+ import java .util .stream .Stream ;
57
60
58
61
import javax .sql .DataSource ;
59
62
@@ -681,19 +684,31 @@ private static String getArchitecture()
681
684
* @param stream A stream with the postgres binaries.
682
685
* @param targetDir The directory to extract the content to.
683
686
*/
684
- private static void extractTxz (InputStream stream , String targetDir ) throws IOException {
687
+ private static void extractTxz (InputStream stream , File targetDir ) throws IOException {
685
688
try (
686
689
XZInputStream xzIn = new XZInputStream (stream );
687
690
TarArchiveInputStream tarIn = new TarArchiveInputStream (xzIn )
688
691
) {
692
+ final Set <File > dirsToUpdate = new HashSet <>();
689
693
final Phaser phaser = new Phaser (1 );
690
694
TarArchiveEntry entry ;
691
695
692
696
while ((entry = tarIn .getNextTarEntry ()) != null ) {
693
697
final String individualFile = entry .getName ();
694
698
final File fsObject = new File (targetDir , individualFile );
695
699
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 ()) {
697
712
Path target = FileSystems .getDefault ().getPath (entry .getLinkName ());
698
713
Files .createSymbolicLink (fsObject .toPath (), target );
699
714
} else if (entry .isFile ()) {
@@ -743,6 +758,10 @@ private void closeChannel(Channel channel) {
743
758
}
744
759
}
745
760
761
+ for (File updatedDir : dirsToUpdate ) {
762
+ updatedDir .setLastModified (System .currentTimeMillis ());
763
+ }
764
+
746
765
phaser .arriveAndAwaitAdvance ();
747
766
}
748
767
}
@@ -786,31 +805,28 @@ private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File over
786
805
final File unpackLockFile = new File (pgDir , LOCK_FILE_NAME );
787
806
final File pgDirExists = new File (pgDir , ".exists" );
788
807
789
- if (!pgDirExists . exists ( )) {
808
+ if (!isPgBinReady ( pgDirExists )) {
790
809
try (FileOutputStream lockStream = new FileOutputStream (unpackLockFile );
791
810
FileLock unpackLock = lockStream .getChannel ().tryLock ()) {
792
811
if (unpackLock != null ) {
793
812
try {
794
- if (pgDirExists .exists ()) {
795
- throw new IllegalStateException ("unpack lock acquired but .exists file is present " + pgDirExists );
796
- }
797
813
LOG .info ("Extracting Postgres..." );
798
814
try (ByteArrayInputStream bais = new ByteArrayInputStream (baos .toByteArray ())) {
799
- extractTxz (bais , pgDir . getPath () );
815
+ extractTxz (bais , pgDir );
800
816
}
801
817
if (!pgDirExists .createNewFile ()) {
802
- throw new IllegalStateException ( "couldn't make .exists file " + pgDirExists );
818
+ pgDirExists . setLastModified ( System . currentTimeMillis () );
803
819
}
804
820
} catch (Exception e ) {
805
821
LOG .error ("while unpacking Postgres" , e );
806
822
}
807
823
} else {
808
824
// the other guy is unpacking for us.
809
825
int maxAttempts = 60 ;
810
- while (!pgDirExists . exists ( ) && --maxAttempts > 0 ) {
826
+ while (!isPgBinReady ( pgDirExists ) && --maxAttempts > 0 ) {
811
827
Thread .sleep (1000L );
812
828
}
813
- if (!pgDirExists . exists ( )) {
829
+ if (!isPgBinReady ( pgDirExists )) {
814
830
throw new IllegalStateException ("Waited 60 seconds for postgres to be unpacked but it never finished!" );
815
831
}
816
832
}
@@ -834,6 +850,18 @@ private static File prepareBinaries(PgBinaryResolver pgBinaryResolver, File over
834
850
}
835
851
}
836
852
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
+
837
865
@ Override
838
866
public String toString ()
839
867
{
0 commit comments