You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by ch...@apache.org on 2024/04/17 11:03:58 UTC
(kafka) branch trunk updated: KAFKA-16363 Storage tool crashes if dir is unavailable (#15733)
This is an automated email from the ASF dual-hosted git repository.
chia7712 pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git
The following commit(s) were added to refs/heads/trunk by this push:
new 44196984bd2 KAFKA-16363 Storage tool crashes if dir is unavailable (#15733)
44196984bd2 is described below
commit 44196984bd244b1e1cc1a3bcda85035d3dee2dc8
Author: Michael Westerby <mi...@apple.com>
AuthorDate: Wed Apr 17 12:03:51 2024 +0100
KAFKA-16363 Storage tool crashes if dir is unavailable (#15733)
Reviewers: Igor Soarez <so...@apple.com>, Federico Valeri <fe...@gmail.com>, Chia-Ping Tsai <ch...@gmail.com>
---
core/src/main/scala/kafka/tools/StorageTool.scala | 8 +++-
.../scala/unit/kafka/tools/StorageToolTest.scala | 53 ++++++++++++++++++++++
2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/core/src/main/scala/kafka/tools/StorageTool.scala b/core/src/main/scala/kafka/tools/StorageTool.scala
index 6f0fad731eb..148be404bf7 100644
--- a/core/src/main/scala/kafka/tools/StorageTool.scala
+++ b/core/src/main/scala/kafka/tools/StorageTool.scala
@@ -441,8 +441,12 @@ object StorageTool extends Logging {
"Use --ignore-formatted to ignore this directory and format the others.")
}
if (!copier.errorLogDirs().isEmpty) {
- val firstLogDir = copier.errorLogDirs().iterator().next()
- throw new TerseFailure(s"I/O error trying to read log directory $firstLogDir.")
+ copier.errorLogDirs().forEach(errorLogDir => {
+ stream.println(s"I/O error trying to read log directory $errorLogDir. Ignoring...")
+ })
+ if (metaPropertiesEnsemble.emptyLogDirs().isEmpty && copier.logDirProps().isEmpty) {
+ throw new TerseFailure("No available log directories to format.")
+ }
}
if (metaPropertiesEnsemble.emptyLogDirs().isEmpty) {
stream.println("All of the log directories are already formatted.")
diff --git a/core/src/test/scala/unit/kafka/tools/StorageToolTest.scala b/core/src/test/scala/unit/kafka/tools/StorageToolTest.scala
index 4470d877536..a44ac0c63ad 100644
--- a/core/src/test/scala/unit/kafka/tools/StorageToolTest.scala
+++ b/core/src/test/scala/unit/kafka/tools/StorageToolTest.scala
@@ -192,6 +192,59 @@ Found problem:
} finally Utils.delete(tempDir)
}
+ private def runFormatCommand(stream: ByteArrayOutputStream, directories: Seq[String], ignoreFormatted: Boolean = false): Int = {
+ val metaProperties = new MetaProperties.Builder().
+ setVersion(MetaPropertiesVersion.V1).
+ setClusterId("XcZZOzUqS4yHOjhMQB6JLQ").
+ setNodeId(2).
+ build()
+ val bootstrapMetadata = StorageTool.buildBootstrapMetadata(MetadataVersion.latestTesting(), None, "test format command")
+ StorageTool.formatCommand(new PrintStream(stream), directories, metaProperties, bootstrapMetadata, MetadataVersion.latestTesting(), ignoreFormatted)
+ }
+
+ @Test
+ def testFormatSucceedsIfAllDirectoriesAreAvailable(): Unit = {
+ val availableDir1 = TestUtils.tempDir()
+ val availableDir2 = TestUtils.tempDir()
+ val stream = new ByteArrayOutputStream()
+ assertEquals(0, runFormatCommand(stream, Seq(availableDir1.toString, availableDir2.toString)))
+ assertTrue(stream.toString().contains("Formatting %s".format(availableDir1)))
+ assertTrue(stream.toString().contains("Formatting %s".format(availableDir2)))
+ }
+
+ @Test
+ def testFormatSucceedsIfAtLeastOneDirectoryIsAvailable(): Unit = {
+ val availableDir1 = TestUtils.tempDir()
+ val unavailableDir1 = TestUtils.tempFile()
+ val stream = new ByteArrayOutputStream()
+ assertEquals(0, runFormatCommand(stream, Seq(availableDir1.toString, unavailableDir1.toString)))
+ assertTrue(stream.toString().contains("I/O error trying to read log directory %s. Ignoring...".format(unavailableDir1)))
+ assertTrue(stream.toString().contains("Formatting %s".format(availableDir1)))
+ assertFalse(stream.toString().contains("Formatting %s".format(unavailableDir1)))
+ }
+
+ @Test
+ def testFormatFailsIfAllDirectoriesAreUnavailable(): Unit = {
+ val unavailableDir1 = TestUtils.tempFile()
+ val unavailableDir2 = TestUtils.tempFile()
+ val stream = new ByteArrayOutputStream()
+ assertEquals("No available log directories to format.", assertThrows(classOf[TerseFailure],
+ () => runFormatCommand(stream, Seq(unavailableDir1.toString, unavailableDir2.toString))).getMessage)
+ assertTrue(stream.toString().contains("I/O error trying to read log directory %s. Ignoring...".format(unavailableDir1)))
+ assertTrue(stream.toString().contains("I/O error trying to read log directory %s. Ignoring...".format(unavailableDir2)))
+ }
+
+ @Test
+ def testFormatSucceedsIfAtLeastOneFormattedDirectoryIsAvailable(): Unit = {
+ val availableDir1 = TestUtils.tempDir()
+ val stream = new ByteArrayOutputStream()
+ assertEquals(0, runFormatCommand(stream, Seq(availableDir1.toString)))
+
+ val stream2 = new ByteArrayOutputStream()
+ val unavailableDir1 = TestUtils.tempFile()
+ assertEquals(0, runFormatCommand(stream2, Seq(availableDir1.toString, unavailableDir1.toString), ignoreFormatted = true))
+ }
+
@Test
def testFormatWithInvalidClusterId(): Unit = {
val config = new KafkaConfig(newSelfManagedProperties())