All Downloads are FREE. Search and download functionalities are using the official Maven repository.

name.remal.gradle_plugins.dsl.utils.TempDirsWithCleanup.kt Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
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()
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy