name.remal.gradle_plugins.dsl.utils.TempDirsWithCleanup.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-plugins-kotlin-dsl Show documentation
Show all versions of gradle-plugins-kotlin-dsl Show documentation
Remal Gradle plugins: gradle-plugins-kotlin-dsl
package name.remal.gradle_plugins.dsl.utils
import name.remal.createDirectories
import name.remal.newTempDir
import net.jcip.annotations.ThreadSafe
import org.gradle.wrapper.GradleUserHomeLookup.gradleUserHome
import java.io.File
import java.io.FileFilter
import java.io.RandomAccessFile
import java.lang.System.currentTimeMillis
import java.time.Duration
@ThreadSafe
class TempDirsWithCleanup(
private val tempDirPrefix: String,
private val baseTmpDir: File = gradleUserHome().resolve("tmp").absoluteFile,
private val cleanupDelayMilliseconds: Long = Duration.ofMinutes(30).toMillis(),
private val autoCleanupPeriodMilliseconds: Long = Duration.ofMinutes(5).toMillis()
) {
private var lastCleanupTimestamp: Long = Long.MIN_VALUE;
@Synchronized
fun cleanup() {
lastCleanupTimestamp = currentTimeMillis()
if (!baseTmpDir.exists()) return
val filteredFiles = baseTmpDir.listFiles(FileFilter { it.name.startsWith(tempDirPrefix) }) ?: emptyArray()
val now = currentTimeMillis()
filteredFiles.forEach { file ->
if (file.name.endsWith(".lock")) {
if (cleanupDelayMilliseconds <= 0 || file.lastModified() < now - cleanupDelayMilliseconds) {
file.delete()
}
}
}
filteredFiles.forEach { file ->
if (!file.name.endsWith(".lock")) {
val lockFile = file.resolveSibling(file.name + ".lock")
if (!lockFile.exists()) {
file.deleteRecursively()
}
}
}
}
@Synchronized
private fun runCleanupIfNeeded() {
if (lastCleanupTimestamp < currentTimeMillis() - autoCleanupPeriodMilliseconds) {
cleanup()
}
}
fun withTempDir(action: (tempDir: File) -> R): R {
runCleanupIfNeeded()
val tempDir = newTempDir(tempDirPrefix, false, baseTmpDir.createDirectories())
try {
val lockFile = tempDir.resolveSibling(tempDir.name + ".lock").also { it.createNewFile() }
try {
RandomAccessFile(lockFile, "rw").channel.use { lockFileChannel ->
lockFileChannel.lock(0, Long.MAX_VALUE, true).use { _ ->
return action(tempDir)
}
}
} finally {
lockFile.delete()
}
} finally {
tempDir.deleteRecursively()
}
}
/*
* Embedded Kotlin of Gradle 4.5 doesn't have this method.
* So let's copy-paste it here for compatibility reasons.
*/
private inline fun T.use(block: (T) -> R): R {
var closed = false
try {
return block(this)
} catch (e: Exception) {
closed = true
try {
this?.close()
} catch (closeException: Exception) {
e.addSuppressed(closeException)
}
throw e
} finally {
if (!closed) {
this?.close()
}
}
}
}