@@ -169,6 +169,90 @@ buildscript {
169169 }
170170}
171171
172+ private static int freePort (String minioAddress ) {
173+ int minioPort
174+ ServerSocket serverSocket = new ServerSocket (0 , 1 , InetAddress . getByName(minioAddress))
175+ try {
176+ minioPort = serverSocket. localPort
177+ } finally {
178+ serverSocket. close()
179+ }
180+ if (minioPort == 0 ) {
181+ throw new GradleException (" Could not find a free port for Minio" )
182+ }
183+ return minioPort
184+ }
185+
186+ private int getMinioPid (Process minioProcess ) {
187+ int minioPid
188+ if (JavaVersion . current() <= JavaVersion . VERSION_1_8 ) {
189+ try {
190+ Class<?> cProcessImpl = minioProcess. getClass()
191+ Field fPid = cProcessImpl. getDeclaredField(" pid" )
192+ if (! fPid. isAccessible()) {
193+ fPid. setAccessible(true )
194+ }
195+ minioPid = fPid. getInt(minioProcess)
196+ } catch (Exception e) {
197+ logger. error(" failed to read pid from minio process" , e)
198+ minioProcess. destroyForcibly()
199+ throw e
200+ }
201+ } else {
202+ minioPid = minioProcess. pid()
203+ }
204+ return minioPid
205+ }
206+
207+ private static Process setupMinio (String minioAddress , int minioPort , String minioDataDir , String accessKey , String secretKey ,
208+ String minioBinDir , String minioFileName ) {
209+ // we skip these tests on Windows so we do no need to worry about compatibility here
210+ final ProcessBuilder minio = new ProcessBuilder (
211+ " ${ minioBinDir} /${ minioFileName} " ,
212+ " server" ,
213+ " --address" ,
214+ minioAddress + " :" + minioPort,
215+ minioDataDir)
216+ minio. environment(). put(' MINIO_ACCESS_KEY' , accessKey)
217+ minio. environment(). put(' MINIO_SECRET_KEY' , secretKey)
218+ return minio. start()
219+ }
220+
221+ private void addShutdownHook (Process minioProcess , int minioPort , int minioPid ) {
222+ new BufferedReader (new InputStreamReader (minioProcess. inputStream)). withReader { br ->
223+ String line
224+ int httpPort = 0
225+ while ((line = br. readLine()) != null ) {
226+ logger. info(line)
227+ if (line. matches(' .*Endpoint.*:\\ d+$' )) {
228+ assert httpPort == 0
229+ final int index = line. lastIndexOf(" :" )
230+ assert index >= 0
231+ httpPort = Integer . parseInt(line. substring(index + 1 ))
232+ if (httpPort != minioPort) {
233+ throw new IllegalStateException (" Port mismatch, expected ${ minioPort} but was ${ httpPort} " )
234+ }
235+
236+ final File script = new File (project. buildDir, " minio/minio.killer.sh" )
237+ script. setText(
238+ [" function shutdown {" ,
239+ " kill ${ minioPid} " ,
240+ " }" ,
241+ " trap shutdown EXIT" ,
242+ // will wait indefinitely for input, but we never pass input, and the pipe is only closed when the build dies
243+ " read line\n " ]. join(' \n ' ), ' UTF-8' )
244+ final ProcessBuilder killer = new ProcessBuilder (" bash" , script. absolutePath)
245+ killer. start()
246+ break
247+ }
248+ }
249+
250+ if (httpPort <= 0 ) {
251+ throw new IllegalStateException (" httpPort must be > 0" )
252+ }
253+ }
254+ }
255+
172256if (useFixture && minioDistribution) {
173257 apply plugin : ' de.undercouch.download'
174258
@@ -201,72 +285,28 @@ if (useFixture && minioDistribution) {
201285 ext. minioPort = 0
202286
203287 doLast {
204- // get free port
205- ServerSocket serverSocket = new ServerSocket (0 , 1 , InetAddress . getByName(minioAddress))
206- try {
207- minioPort = serverSocket. localPort
208- } finally {
209- serverSocket. close()
210- }
211- if (minioPort == 0 ) {
212- throw new GradleException (" Could not find a free port for Minio" )
213- }
214-
215288 new File (" ${ minioDataDir} /${ s3PermanentBucket} " ). mkdirs()
216- // we skip these tests on Windows so we do no need to worry about compatibility here
217- final ProcessBuilder minio = new ProcessBuilder (
218- " ${ minioBinDir} /${ minioFileName} " ,
219- " server" ,
220- " --address" ,
221- minioAddress + " :" + minioPort,
222- minioDataDir)
223- minio. environment(). put(' MINIO_ACCESS_KEY' , s3PermanentAccessKey)
224- minio. environment(). put(' MINIO_SECRET_KEY' , s3PermanentSecretKey)
225- final Process process = minio. start()
226- if (JavaVersion . current() <= JavaVersion . VERSION_1_8 ) {
289+
290+ Exception accumulatedException = null
291+ for (int i = 0 ; i < 5 ; ++ i) {
227292 try {
228- Class<?> cProcessImpl = process . getClass( )
229- Field fPid = cProcessImpl . getDeclaredField( " pid " )
230- if ( ! fPid . isAccessible()) {
231- fPid . setAccessible( true )
232- }
233- minioPid = fPid . getInt(process)
293+ minioPort = freePort(minioAddress )
294+ final Process process =
295+ setupMinio(minioAddress, minioPort, minioDataDir, s3PermanentAccessKey, s3PermanentSecretKey, minioBinDir, minioFileName)
296+ minioPid = getMinioPid(process )
297+ addShutdownHook(process, minioPort, minioPid)
298+ break
234299 } catch (Exception e) {
235- logger. error(" failed to read pid from minio process" , e)
236- process. destroyForcibly()
237- throw e
238- }
239- } else {
240- minioPid = process. pid()
241- }
242-
243- new BufferedReader (new InputStreamReader (process. getInputStream())). withReader { br ->
244- String line
245- int httpPort = 0
246- while ((line = br. readLine()) != null ) {
247- logger. info(line)
248- if (line. matches(' .*Endpoint.*:\\ d+$' )) {
249- assert httpPort == 0
250- final int index = line. lastIndexOf(" :" )
251- assert index >= 0
252- httpPort = Integer . parseInt(line. substring(index + 1 ))
253- assert httpPort == minioPort : " Port mismatch, expected ${ minioPort} but was ${ httpPort} "
254-
255- final File script = new File (project. buildDir, " minio/minio.killer.sh" )
256- script. setText(
257- [" function shutdown {" ,
258- " kill ${ minioPid} " ,
259- " }" ,
260- " trap shutdown EXIT" ,
261- // will wait indefinitely for input, but we never pass input, and the pipe is only closed when the build dies
262- " read line\n " ]. join(' \n ' ), ' UTF-8' )
263- final ProcessBuilder killer = new ProcessBuilder (" bash" , script. absolutePath)
264- killer. start()
265- break
300+ logger. error(" Exception while trying to start Minio {}" , e)
301+ if (accumulatedException == null ) {
302+ accumulated = e
303+ } else {
304+ accumulatedException. addSuppressed(e)
266305 }
267306 }
268-
269- assert httpPort > 0
307+ }
308+ if (accumulatedException != null ) {
309+ throw new GradleException (" Failed to start Minio" , accumulatedException)
270310 }
271311 }
272312 }
0 commit comments