Skip to content

Commit

Permalink
GC is paused in case of data corruption.
Browse files Browse the repository at this point in the history
Debug code was removed.
  • Loading branch information
andrii0lomakin committed Jan 22, 2024
1 parent 7db84bb commit 2639b3c
Showing 1 changed file with 38 additions and 37 deletions.
75 changes: 38 additions & 37 deletions environment/src/main/kotlin/jetbrains/exodus/gc/GarbageCollector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ import jetbrains.exodus.tree.ExpiredLoggableCollection
import jetbrains.exodus.util.DeferredIO
import mu.KLogging
import java.io.File
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.io.PrintWriter
import java.io.StringWriter
import java.util.TreeSet
import java.util.concurrent.ConcurrentLinkedQueue


class GarbageCollector(internal val environment: EnvironmentImpl) {

// the last time when background cleaning job was invoked
Expand All @@ -50,7 +52,9 @@ class GarbageCollector(internal val environment: EnvironmentImpl) {
private val deletionQueue = ConcurrentLinkedQueue<Long>()
internal val cleaner = BackgroundCleaner(this)
private val openStoresCache = IntHashMap<StoreImpl>()
private val brokenFiles = Collections.newSetFromMap(ConcurrentHashMap<Long, Boolean>())

@Volatile
private var logExceptionMessage: String? = null
private var lastBrokenMessage = 0L

init {
Expand Down Expand Up @@ -228,13 +232,34 @@ class GarbageCollector(internal val environment: EnvironmentImpl) {
}

private fun doCleanFiles(fragmentedFiles: Iterator<Long>): Boolean {
if (logExceptionMessage != null) {
val ts = System.currentTimeMillis()

val printBrokenMessage = lastBrokenMessage + 15 * 60 * 1000 < ts
if (printBrokenMessage) {
lastBrokenMessage = ts
logger.error {
"GC is disabled on database ${log.location} because of error:\n $logExceptionMessage \n please contact support to fix broken database."
}
}

return false
}

// if there are no more files then even don't start a txn
if (!fragmentedFiles.hasNext()) {
return true
}


val guard = OOMGuard(softRef = false)

val sortedFiles = TreeSet<Long>()
for(fileId in fragmentedFiles) {
sortedFiles.add(fileId)
}

val sortedFilesIterator = sortedFiles.iterator()
val txn: ReadWriteTransaction = try {
environment.beginGCTransaction()
} catch (_: ReadonlyTransactionException) {
Expand All @@ -247,33 +272,10 @@ class GarbageCollector(internal val environment: EnvironmentImpl) {
val isTxnExclusive = txn.isExclusive
try {
val started = System.currentTimeMillis()
val printBrokenMessage = lastBrokenMessage + 15 * 60 * 1000 < started

while (fragmentedFiles.hasNext()) {
val file = fragmentedFiles.next()

if (brokenFiles.contains(file)) {
if (printBrokenMessage) {
logger.error {
"File ${LogUtil.getLogFilename(file)} " +
"is skipped by GC because it was processed with exception during previous " +
"iteration of cleaning cycle. " +
"To avoid given problems in future: please check the log, " +
"find the log entry which contains the file name and the exception" +
" and create the issue for the developers."
}
lastBrokenMessage = started
}

continue
}

try {
cleanSingleFile(file, txn)
} catch (e: Exception) {
brokenFiles.add(file)
throw e
}
while (sortedFilesIterator.hasNext()) {
val file = sortedFilesIterator.next()
cleanSingleFile(file, txn)

cleanedFiles.add(file)

Expand All @@ -297,10 +299,17 @@ class GarbageCollector(internal val environment: EnvironmentImpl) {
} catch (_: ReadonlyTransactionException) {
return false
} catch (e: Throwable) {
val sw = StringWriter()
val pw = PrintWriter(sw)

e.printStackTrace(pw)

logExceptionMessage = sw.toString()
throw ExodusException.toExodusException(e)
} finally {
txn.abort()
}

if (cleanedFiles.isNotEmpty()) {
for (file in cleanedFiles) {
if (isTxnExclusive) {
Expand Down Expand Up @@ -338,10 +347,6 @@ class GarbageCollector(internal val environment: EnvironmentImpl) {
* @param txn transaction
*/
private fun cleanSingleFile(fileAddress: Long, txn: ReadWriteTransaction) {
if (fileAddress == 520806727680L) {
return
}

// the file can be already cleaned
if (isFileCleaned(fileAddress)) {
throw ExodusException("Attempt to clean already cleaned file")
Expand Down Expand Up @@ -381,10 +386,6 @@ class GarbageCollector(internal val environment: EnvironmentImpl) {
openStoresCache[structureId] = store
}

if(loggable.address == 520806663897L) {
println("Caught it !")
}

store.reclaim(txn, loggable, loggables)
}
}
Expand Down

0 comments on commit 2639b3c

Please sign in to comment.