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

jetbrains.exodus.gc.BackgroundCleaner.kt Maven / Gradle / Ivy

There is a newer version: 9.8.0.76914
Show newest version
/**
 * Copyright 2010 - 2022 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jetbrains.exodus.gc

import jetbrains.exodus.ExodusException
import jetbrains.exodus.core.execution.*
import jetbrains.exodus.kotlin.synchronized
import mu.KLogging

internal class BackgroundCleaner(private val gc: GarbageCollector) {

    private val backgroundCleaningJob = BackgroundCleaningJob(gc)
    private var processor: JobProcessorAdapter
    internal var threadId: Long = 0

    @Volatile
    var isSuspended: Boolean = false
        private set

    @Volatile
    var isCleaning: Boolean = false

    init {
        processor = setJobProcessor(
            if (gc.environment.environmentConfig.isLogCacheShared) {
                DelegatingJobProcessor(ThreadJobProcessorPool.getOrCreateJobProcessor("Exodus shared background cleaner"))
            } else {
                ThreadJobProcessor("Exodus background cleaner for " + gc.environment.location)
            }
        )
    }

    fun setJobProcessor(processor: JobProcessorAdapter): JobProcessorAdapter {
        if (processor is ThreadJobProcessor) {
            threadId = processor.id
        } else if (processor is DelegatingJobProcessor<*>) {
            val delegate = processor.delegate
            if (delegate is ThreadJobProcessor) {
                threadId = delegate.id
            } else {
                throw ExodusException("Unexpected job processor: $processor")
            }
        }
        if (processor.exceptionHandler == null) {
            processor.exceptionHandler = JobProcessorExceptionHandler { _, _, t -> logger.error(t.message, t) }
        }
        processor.start()
        this.processor = processor
        return processor
    }

    fun getJobProcessor() = processor

    fun addBeforeGcAction(action: Runnable) = backgroundCleaningJob.addBeforeGcAction(action)

    val isFinished: Boolean get() = processor.isFinished

    val isCurrentThread: Boolean get() = threadId == Thread.currentThread().id

    fun finish() {
        (processor.currentJob as? GcJob)?.cancel()
        backgroundCleaningJob.cancel()
        processor.waitForLatchJob(object : LatchJob() {
            override fun execute() {
                try {
                    gc.deletePendingFiles()
                } finally {
                    release()
                }
            }
        }, 100)
        processor.finish()
    }

    fun suspend() = backgroundCleaningJob.synchronized {
        if (!isSuspended) {
            isSuspended = true
        }
    }

    fun resume() = backgroundCleaningJob.synchronized {
        isSuspended = false
        queueCleaningJob()
    }

    fun queueCleaningJob() {
        if (gc.environment.environmentConfig.isGcEnabled) {
            backgroundCleaningJob.renew(gc)
            processor.queue(backgroundCleaningJob)
        }
    }

    fun queueCleaningJobAt(millis: Long) {
        if (gc.environment.environmentConfig.isGcEnabled) {
            backgroundCleaningJob.renew(gc)
            processor.queueAt(backgroundCleaningJob, millis)
        }
    }

    fun cleanEntireLog() {
        processor.waitForLatchJob(CleanEntireLogJob(gc), 0)
    }

    fun checkThread() {
        if (!isCurrentThread) {
            throw ExodusException("Background cleaner thread expected as current one")
        }
    }

    companion object : KLogging()
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy