@@ -21,11 +21,11 @@ import java.io.{File, IOException}
21
21
import java .lang .{Long => JLong }
22
22
import java .nio ._
23
23
import java .util
24
- import java .util .Date
24
+ import java .util .{ Date , Optional }
25
25
import java .util .concurrent .TimeUnit
26
26
import kafka .log .LogCleaner .{CleanerRecopyPercentMetricName , DeadThreadCountMetricName , MaxBufferUtilizationPercentMetricName , MaxCleanTimeMetricName , MaxCompactionDelayMetricsName }
27
27
import kafka .server .{BrokerReconfigurable , KafkaConfig }
28
- import kafka .utils .{ Logging , Pool }
28
+ import kafka .utils .Logging
29
29
import org .apache .kafka .common .{KafkaException , TopicPartition }
30
30
import org .apache .kafka .common .config .ConfigException
31
31
import org .apache .kafka .common .errors .{CorruptRecordException , KafkaStorageException }
@@ -36,12 +36,13 @@ import org.apache.kafka.common.utils.{BufferSupplier, Time}
36
36
import org .apache .kafka .server .config .ServerConfigs
37
37
import org .apache .kafka .server .metrics .KafkaMetricsGroup
38
38
import org .apache .kafka .server .util .ShutdownableThread
39
- import org .apache .kafka .storage .internals .log .{AbortedTxn , CleanerConfig , LastRecord , LogCleaningAbortedException , LogDirFailureChannel , LogSegment , LogSegmentOffsetOverflowException , OffsetMap , SkimpyOffsetMap , ThreadShutdownException , TransactionIndex , UnifiedLog }
39
+ import org .apache .kafka .storage .internals .log .{AbortedTxn , CleanerConfig , LastRecord , LogCleanerManager , LogCleaningAbortedException , LogCleaningException , LogDirFailureChannel , LogSegment , LogSegmentOffsetOverflowException , LogToClean , OffsetMap , PreCleanStats , SkimpyOffsetMap , ThreadShutdownException , TransactionIndex , UnifiedLog }
40
40
import org .apache .kafka .storage .internals .utils .Throttler
41
41
42
42
import scala .jdk .CollectionConverters ._
43
43
import scala .collection .mutable .ListBuffer
44
44
import scala .collection .{Iterable , Seq , Set , mutable }
45
+ import scala .jdk .OptionConverters .{RichOption , RichOptional }
45
46
import scala .util .control .ControlThrowable
46
47
47
48
/**
@@ -93,13 +94,13 @@ import scala.util.control.ControlThrowable
93
94
*
94
95
* @param initialConfig Initial configuration parameters for the cleaner. Actual config may be dynamically updated.
95
96
* @param logDirs The directories where offset checkpoints reside
96
- * @param logs The pool of logs
97
+ * @param logs The map of logs
97
98
* @param logDirFailureChannel The channel used to add offline log dirs that may be encountered when cleaning the log
98
99
* @param time A way to control the passage of time
99
100
*/
100
101
class LogCleaner (initialConfig : CleanerConfig ,
101
102
val logDirs : Seq [File ],
102
- val logs : Pool [TopicPartition , UnifiedLog ],
103
+ val logs : util.concurrent. ConcurrentMap [TopicPartition , UnifiedLog ],
103
104
val logDirFailureChannel : LogDirFailureChannel ,
104
105
time : Time = Time .SYSTEM ) extends Logging with BrokerReconfigurable {
105
106
// Visible for test.
@@ -109,7 +110,7 @@ class LogCleaner(initialConfig: CleanerConfig,
109
110
@ volatile private var config = initialConfig
110
111
111
112
/* for managing the state of partitions being cleaned. package-private to allow access in tests */
112
- private [log] val cleanerManager = new LogCleanerManager (logDirs, logs, logDirFailureChannel)
113
+ private [log] val cleanerManager = new LogCleanerManager (logDirs.asJava , logs, logDirFailureChannel)
113
114
114
115
/* a throttle used to limit the I/O of all the cleaner threads to a user-specified maximum rate */
115
116
private [log] val throttler = new Throttler (config.maxIoBytesPerSecond, 300 , " cleaner-io" , " bytes" , time)
@@ -249,7 +250,7 @@ class LogCleaner(initialConfig: CleanerConfig,
249
250
* @param partitionToRemove The topicPartition to be removed, default none
250
251
*/
251
252
def updateCheckpoints (dataDir : File , partitionToRemove : Option [TopicPartition ] = None ): Unit = {
252
- cleanerManager.updateCheckpoints(dataDir, partitionToRemove = partitionToRemove)
253
+ cleanerManager.updateCheckpoints(dataDir, Optional .empty(), partitionToRemove.toJava )
253
254
}
254
255
255
256
/**
@@ -300,7 +301,7 @@ class LogCleaner(initialConfig: CleanerConfig,
300
301
* @param topicPartitions The collection of topicPartitions to be resumed cleaning
301
302
*/
302
303
def resumeCleaning (topicPartitions : Iterable [TopicPartition ]): Unit = {
303
- cleanerManager.resumeCleaning(topicPartitions)
304
+ cleanerManager.resumeCleaning(topicPartitions.toList.asJava )
304
305
}
305
306
306
307
/**
@@ -314,7 +315,7 @@ class LogCleaner(initialConfig: CleanerConfig,
314
315
* @return A boolean indicating whether the work has completed before timeout
315
316
*/
316
317
def awaitCleaned (topicPartition : TopicPartition , offset : Long , maxWaitMs : Long = 60000L ): Boolean = {
317
- def isCleaned = cleanerManager.allCleanerCheckpoints.get(topicPartition).fold(false )(_ >= offset)
318
+ def isCleaned = Option ( cleanerManager.allCleanerCheckpoints.get(topicPartition) ).fold(false )(_ >= offset)
318
319
var remainingWaitMs = maxWaitMs
319
320
while (! isCleaned && remainingWaitMs > 0 ) {
320
321
val sleepTime = math.min(100 , remainingWaitMs)
@@ -331,7 +332,7 @@ class LogCleaner(initialConfig: CleanerConfig,
331
332
* @return A list of log partitions that retention threads can safely work on
332
333
*/
333
334
def pauseCleaningForNonCompactedPartitions (): Iterable [(TopicPartition , UnifiedLog )] = {
334
- cleanerManager.pauseCleaningForNonCompactedPartitions()
335
+ cleanerManager.pauseCleaningForNonCompactedPartitions().asScala.map(entry => (entry.getKey, entry.getValue))
335
336
}
336
337
337
338
// Only for testing
@@ -409,7 +410,7 @@ class LogCleaner(initialConfig: CleanerConfig,
409
410
@ throws(classOf [LogCleaningException ])
410
411
private def cleanFilthiestLog (): Boolean = {
411
412
val preCleanStats = new PreCleanStats ()
412
- val ltc = cleanerManager.grabFilthiestCompactedLog(time, preCleanStats)
413
+ val ltc = cleanerManager.grabFilthiestCompactedLog(time, preCleanStats).toScala
413
414
val cleaned = ltc match {
414
415
case None =>
415
416
false
@@ -424,7 +425,7 @@ class LogCleaner(initialConfig: CleanerConfig,
424
425
case e : Exception => throw new LogCleaningException (cleanable.log, e.getMessage, e)
425
426
}
426
427
}
427
- val deletable : Iterable [( TopicPartition , UnifiedLog )] = cleanerManager.deletableLogs()
428
+ val deletable = cleanerManager.deletableLogs().asScala
428
429
try {
429
430
deletable.foreach { case (_, log) =>
430
431
try {
@@ -435,7 +436,7 @@ class LogCleaner(initialConfig: CleanerConfig,
435
436
}
436
437
}
437
438
} finally {
438
- cleanerManager.doneDeleting(deletable.map(_._1) )
439
+ cleanerManager.doneDeleting(deletable.keys.toList.asJava )
439
440
}
440
441
441
442
cleaned
@@ -1150,25 +1151,6 @@ private[log] class Cleaner(val id: Int,
1150
1151
}
1151
1152
}
1152
1153
1153
- /**
1154
- * A simple struct for collecting pre-clean stats
1155
- */
1156
- private class PreCleanStats {
1157
- var maxCompactionDelayMs = 0L
1158
- var delayedPartitions = 0
1159
- var cleanablePartitions = 0
1160
-
1161
- def updateMaxCompactionDelay (delayMs : Long ): Unit = {
1162
- maxCompactionDelayMs = Math .max(maxCompactionDelayMs, delayMs)
1163
- if (delayMs > 0 ) {
1164
- delayedPartitions += 1
1165
- }
1166
- }
1167
- def recordCleanablePartitions (numOfCleanables : Int ): Unit = {
1168
- cleanablePartitions = numOfCleanables
1169
- }
1170
- }
1171
-
1172
1154
/**
1173
1155
* A simple struct for collecting stats about log cleaning
1174
1156
*/
@@ -1221,22 +1203,6 @@ private class CleanerStats(time: Time = Time.SYSTEM) {
1221
1203
1222
1204
}
1223
1205
1224
- /**
1225
- * Helper class for a log, its topic/partition, the first cleanable position, the first uncleanable dirty position,
1226
- * and whether it needs compaction immediately.
1227
- */
1228
- private case class LogToClean (topicPartition : TopicPartition ,
1229
- log : UnifiedLog ,
1230
- firstDirtyOffset : Long ,
1231
- uncleanableOffset : Long ,
1232
- needCompactionNow : Boolean = false ) extends Ordered [LogToClean ] {
1233
- val cleanBytes : Long = log.logSegments(- 1 , firstDirtyOffset).asScala.map(_.size.toLong).sum
1234
- val (firstUncleanableOffset, cleanableBytes) = LogCleanerManager .calculateCleanableBytes(log, firstDirtyOffset, uncleanableOffset)
1235
- val totalBytes : Long = cleanBytes + cleanableBytes
1236
- val cleanableRatio : Double = cleanableBytes / totalBytes.toDouble
1237
- override def compare (that : LogToClean ): Int = math.signum(this .cleanableRatio - that.cleanableRatio).toInt
1238
- }
1239
-
1240
1206
/**
1241
1207
* This is a helper class to facilitate tracking transaction state while cleaning the log. It maintains a set
1242
1208
* of the ongoing aborted and committed transactions as the cleaner is working its way through the log. This
0 commit comments