This is an automated email from the ASF dual-hosted git repository.
devesh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new dd22dbef89 HDDS-11615. Add Upgrade Action for Initial Schema
Constraints for Unhealthy Container Table in Recon. (#7372)
dd22dbef89 is described below
commit dd22dbef8958311c2ec5e99822269405d59f8eba
Author: Arafat2198 <[email protected]>
AuthorDate: Fri Nov 15 17:33:43 2024 +0530
HDDS-11615. Add Upgrade Action for Initial Schema Constraints for Unhealthy
Container Table in Recon. (#7372)
---
.../recon/schema/ContainerSchemaDefinition.java | 35 +---
.../org/apache/hadoop/ozone/recon/ReconServer.java | 4 +-
.../scm/ReconStorageContainerManagerFacade.java | 12 +-
.../upgrade/InitialConstraintUpgradeAction.java | 114 ++++++++++++
.../recon/upgrade/ReconLayoutVersionManager.java | 5 +-
.../ozone/recon/upgrade/ReconUpgradeAction.java | 4 +-
.../TestInitialConstraintUpgradeAction.java | 192 +++++++++++++++++++++
.../upgrade/TestReconLayoutVersionManager.java | 41 +++--
8 files changed, 358 insertions(+), 49 deletions(-)
diff --git
a/hadoop-ozone/recon-codegen/src/main/java/org/hadoop/ozone/recon/schema/ContainerSchemaDefinition.java
b/hadoop-ozone/recon-codegen/src/main/java/org/hadoop/ozone/recon/schema/ContainerSchemaDefinition.java
index 0882de3bf4..0c778aead5 100644
---
a/hadoop-ozone/recon-codegen/src/main/java/org/hadoop/ozone/recon/schema/ContainerSchemaDefinition.java
+++
b/hadoop-ozone/recon-codegen/src/main/java/org/hadoop/ozone/recon/schema/ContainerSchemaDefinition.java
@@ -31,7 +31,6 @@ import org.jooq.impl.SQLDataType;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
-import java.util.Arrays;
/**
* Class used to create tables that are required for tracking containers.
@@ -70,39 +69,11 @@ public class ContainerSchemaDefinition implements
ReconSchemaDefinition {
public void initializeSchema() throws SQLException {
Connection conn = dataSource.getConnection();
dslContext = DSL.using(conn);
-
- if (TABLE_EXISTS_CHECK.test(conn, UNHEALTHY_CONTAINERS_TABLE_NAME)) {
- // Drop the existing constraint if it exists
- String constraintName = UNHEALTHY_CONTAINERS_TABLE_NAME + "ck1";
- dslContext.alterTable(UNHEALTHY_CONTAINERS_TABLE_NAME)
- .dropConstraint(constraintName)
- .execute();
-
- // Add the updated constraint with all enum states
- addUpdatedConstraint();
- } else {
- // Create the table if it does not exist
+ if (!TABLE_EXISTS_CHECK.test(conn, UNHEALTHY_CONTAINERS_TABLE_NAME)) {
createUnhealthyContainersTable();
}
}
- /**
- * Add the updated constraint to the table.
- */
- private void addUpdatedConstraint() {
- // Get all enum values as a list of strings
- String[] enumStates = Arrays.stream(UnHealthyContainerStates.values())
- .map(Enum::name)
- .toArray(String[]::new);
-
- // Alter the table to add the updated constraint
- dslContext.alterTable(UNHEALTHY_CONTAINERS_TABLE_NAME)
- .add(DSL.constraint(UNHEALTHY_CONTAINERS_TABLE_NAME + "ck1")
- .check(field(name("container_state"))
- .in(enumStates)))
- .execute();
- }
-
/**
* Create the Missing Containers table.
*/
@@ -126,4 +97,8 @@ public class ContainerSchemaDefinition implements
ReconSchemaDefinition {
public DSLContext getDSLContext() {
return dslContext;
}
+
+ public DataSource getDataSource() {
+ return dataSource;
+ }
}
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconServer.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconServer.java
index 7c9564c23b..24b5c10952 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconServer.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconServer.java
@@ -165,7 +165,9 @@ public class ReconServer extends GenericCli {
ReconLayoutVersionManager layoutVersionManager =
new ReconLayoutVersionManager(versionTableManager, reconContext);
// Run the upgrade framework to finalize layout features if needed
- layoutVersionManager.finalizeLayoutFeatures();
+ ReconStorageContainerManagerFacade reconStorageContainerManagerFacade =
+ (ReconStorageContainerManagerFacade)
this.getReconStorageContainerManager();
+
layoutVersionManager.finalizeLayoutFeatures(reconStorageContainerManagerFacade);
LOG.info("Initializing support of Recon Features...");
FeatureProvider.initFeatureSupport(configuration);
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconStorageContainerManagerFacade.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconStorageContainerManagerFacade.java
index ea1a344016..eff68848a2 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconStorageContainerManagerFacade.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/scm/ReconStorageContainerManagerFacade.java
@@ -131,6 +131,8 @@ import
org.hadoop.ozone.recon.schema.tables.daos.ReconTaskStatusDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.sql.DataSource;
+
/**
* Recon's 'lite' version of SCM.
*/
@@ -156,6 +158,7 @@ public class ReconStorageContainerManagerFacade
private final SCMHAManager scmhaManager;
private final SequenceIdGenerator sequenceIdGen;
private final ContainerHealthTask containerHealthTask;
+ private final DataSource dataSource;
private DBStore dbStore;
private ReconNodeManager nodeManager;
@@ -188,7 +191,8 @@ public class ReconStorageContainerManagerFacade
ReconContainerMetadataManager
reconContainerMetadataManager,
ReconUtils reconUtils,
ReconSafeModeManager
safeModeManager,
- ReconContext reconContext) throws
IOException {
+ ReconContext reconContext,
+ DataSource dataSource) throws
IOException {
reconNodeDetails = reconUtils.getReconNodeDetails(conf);
this.threadNamePrefix = reconNodeDetails.threadNamePrefix();
this.eventQueue = new EventQueue(threadNamePrefix);
@@ -285,6 +289,8 @@ public class ReconStorageContainerManagerFacade
containerCountBySizeDao,
utilizationSchemaDefinition);
+ this.dataSource = dataSource;
+
StaleNodeHandler staleNodeHandler =
new ReconStaleNodeHandler(nodeManager, pipelineManager, conf,
pipelineSyncTask);
@@ -754,4 +760,8 @@ public class ReconStorageContainerManagerFacade
public ReconContext getReconContext() {
return reconContext;
}
+
+ public DataSource getDataSource() {
+ return dataSource;
+ }
}
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/InitialConstraintUpgradeAction.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/InitialConstraintUpgradeAction.java
new file mode 100644
index 0000000000..e75efd2116
--- /dev/null
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/InitialConstraintUpgradeAction.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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 org.apache.hadoop.ozone.recon.upgrade;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.hadoop.ozone.recon.scm.ReconStorageContainerManagerFacade;
+import org.hadoop.ozone.recon.schema.ContainerSchemaDefinition;
+import org.jooq.DSLContext;
+import org.jooq.impl.DSL;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Arrays;
+
+import static
org.apache.hadoop.ozone.recon.upgrade.ReconLayoutFeature.INITIAL_VERSION;
+import static
org.apache.hadoop.ozone.recon.upgrade.ReconUpgradeAction.UpgradeActionType.FINALIZE;
+import static org.hadoop.ozone.recon.codegen.SqlDbUtils.TABLE_EXISTS_CHECK;
+import static
org.hadoop.ozone.recon.schema.ContainerSchemaDefinition.UNHEALTHY_CONTAINERS_TABLE_NAME;
+import static org.jooq.impl.DSL.field;
+import static org.jooq.impl.DSL.name;
+
+/**
+ * Upgrade action for the INITIAL schema version, which manages constraints
+ * for the UNHEALTHY_CONTAINERS table.
+ */
+@UpgradeActionRecon(feature = INITIAL_VERSION, type = FINALIZE)
+public class InitialConstraintUpgradeAction implements ReconUpgradeAction {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(InitialConstraintUpgradeAction.class);
+ private DataSource dataSource;
+ private DSLContext dslContext;
+
+ @Override
+ public void execute(ReconStorageContainerManagerFacade scmFacade) throws
SQLException {
+ this.dataSource = scmFacade.getDataSource();
+ try (Connection conn = dataSource.getConnection()) {
+ if (!TABLE_EXISTS_CHECK.test(conn, UNHEALTHY_CONTAINERS_TABLE_NAME)) {
+ return;
+ }
+ dslContext = DSL.using(conn);
+ // Drop the existing constraint
+ dropConstraint();
+ // Add the updated constraint with all enum states
+ addUpdatedConstraint();
+ } catch (SQLException e) {
+ throw new SQLException("Failed to execute
InitialConstraintUpgradeAction", e);
+ }
+ }
+
+ /**
+ * Drops the existing constraint from the UNHEALTHY_CONTAINERS table.
+ */
+ private void dropConstraint() {
+ String constraintName = UNHEALTHY_CONTAINERS_TABLE_NAME + "ck1";
+ dslContext.alterTable(UNHEALTHY_CONTAINERS_TABLE_NAME)
+ .dropConstraint(constraintName)
+ .execute();
+ LOG.debug("Dropped the existing constraint: {}", constraintName);
+ }
+
+ /**
+ * Adds the updated constraint directly within this class.
+ */
+ private void addUpdatedConstraint() {
+ String[] enumStates = Arrays
+ .stream(ContainerSchemaDefinition.UnHealthyContainerStates.values())
+ .map(Enum::name)
+ .toArray(String[]::new);
+
+
dslContext.alterTable(ContainerSchemaDefinition.UNHEALTHY_CONTAINERS_TABLE_NAME)
+
.add(DSL.constraint(ContainerSchemaDefinition.UNHEALTHY_CONTAINERS_TABLE_NAME +
"ck1")
+ .check(field(name("container_state"))
+ .in(enumStates)))
+ .execute();
+
+ LOG.info("Added the updated constraint to the UNHEALTHY_CONTAINERS table
for enum state values: {}",
+ Arrays.toString(enumStates));
+ }
+
+ @Override
+ public UpgradeActionType getType() {
+ return FINALIZE;
+ }
+
+ @VisibleForTesting
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ @VisibleForTesting
+ public void setDslContext(DSLContext dslContext) {
+ this.dslContext = dslContext;
+ }
+}
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconLayoutVersionManager.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconLayoutVersionManager.java
index b646f6d9a8..e9f7fc9650 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconLayoutVersionManager.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconLayoutVersionManager.java
@@ -21,6 +21,7 @@ package org.apache.hadoop.ozone.recon.upgrade;
import org.apache.hadoop.ozone.recon.ReconContext;
import org.apache.hadoop.ozone.recon.ReconSchemaVersionTableManager;
+import org.apache.hadoop.ozone.recon.scm.ReconStorageContainerManagerFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -78,7 +79,7 @@ public class ReconLayoutVersionManager {
* Finalizes the layout features that need to be upgraded, by executing the
upgrade action for each
* feature that is registered for finalization.
*/
- public void finalizeLayoutFeatures() {
+ public void finalizeLayoutFeatures(ReconStorageContainerManagerFacade
scmFacade) {
// Get features that need finalization, sorted by version
List<ReconLayoutFeature> featuresToFinalize = getRegisteredFeatures();
@@ -88,7 +89,7 @@ public class ReconLayoutVersionManager {
Optional<ReconUpgradeAction> action =
feature.getAction(ReconUpgradeAction.UpgradeActionType.FINALIZE);
if (action.isPresent()) {
// Execute the upgrade action & update the schema version in the DB
- action.get().execute();
+ action.get().execute(scmFacade);
updateSchemaVersion(feature.getVersion());
LOG.info("Feature versioned {} finalized successfully.",
feature.getVersion());
}
diff --git
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconUpgradeAction.java
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconUpgradeAction.java
index f09cdf8e1f..d5fdbdacb7 100644
---
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconUpgradeAction.java
+++
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/upgrade/ReconUpgradeAction.java
@@ -19,6 +19,8 @@
package org.apache.hadoop.ozone.recon.upgrade;
+import org.apache.hadoop.ozone.recon.scm.ReconStorageContainerManagerFacade;
+
/**
* ReconUpgradeAction is an interface for executing upgrade actions in Recon.
*/
@@ -40,7 +42,7 @@ public interface ReconUpgradeAction {
/**
* Execute the upgrade action.
*/
- void execute() throws Exception;
+ void execute(ReconStorageContainerManagerFacade scmFacade) throws Exception;
/**
* Provides the type of upgrade phase (e.g., FINALIZE).
diff --git
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestInitialConstraintUpgradeAction.java
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestInitialConstraintUpgradeAction.java
new file mode 100644
index 0000000000..b2399f4236
--- /dev/null
+++
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestInitialConstraintUpgradeAction.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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 org.apache.hadoop.ozone.recon.upgrade;
+
+import org.apache.hadoop.ozone.recon.persistence.AbstractReconSqlDBTest;
+import org.apache.hadoop.ozone.recon.scm.ReconStorageContainerManagerFacade;
+import org.hadoop.ozone.recon.schema.ContainerSchemaDefinition;
+import org.jooq.DSLContext;
+import org.jooq.impl.DSL;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import static
org.hadoop.ozone.recon.schema.ContainerSchemaDefinition.UNHEALTHY_CONTAINERS_TABLE_NAME;
+import static org.jooq.impl.DSL.field;
+import static org.jooq.impl.DSL.name;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test class for InitialConstraintUpgradeAction.
+ */
+public class TestInitialConstraintUpgradeAction extends AbstractReconSqlDBTest
{
+
+ private InitialConstraintUpgradeAction upgradeAction;
+ private DSLContext dslContext;
+ private ReconStorageContainerManagerFacade mockScmFacade;
+
+ @BeforeEach
+ public void setUp() throws SQLException {
+ // Initialize the DSLContext
+ dslContext = getDslContext();
+
+ // Initialize the upgrade action
+ upgradeAction = new InitialConstraintUpgradeAction();
+
+ // Mock the SCM facade to provide the DataSource
+ mockScmFacade = mock(ReconStorageContainerManagerFacade.class);
+ DataSource dataSource = getInjector().getInstance(DataSource.class);
+ when(mockScmFacade.getDataSource()).thenReturn(dataSource);
+
+ // Set the DataSource and DSLContext directly
+ upgradeAction.setDataSource(dataSource);
+ upgradeAction.setDslContext(dslContext);
+
+ // Check if the table already exists
+ try (Connection conn = dataSource.getConnection()) {
+ DatabaseMetaData dbMetaData = conn.getMetaData();
+ ResultSet tables = dbMetaData.getTables(null, null,
UNHEALTHY_CONTAINERS_TABLE_NAME, null);
+ if (!tables.next()) {
+ // Create the initial table if it does not exist
+ dslContext.createTable(UNHEALTHY_CONTAINERS_TABLE_NAME)
+ .column("container_id", org.jooq.impl.SQLDataType.BIGINT
+ .nullable(false))
+ .column("container_state", org.jooq.impl.SQLDataType.VARCHAR(16)
+ .nullable(false))
+ .constraint(DSL.constraint("pk_container_id")
+ .primaryKey("container_id", "container_state"))
+ .execute();
+ }
+ }
+ }
+
+ @Test
+ public void testUpgradeAppliesConstraintModificationForAllStates() throws
SQLException {
+ // Run the upgrade action
+ upgradeAction.execute(mockScmFacade);
+
+ // Iterate over all valid states and insert records
+ for (ContainerSchemaDefinition.UnHealthyContainerStates state :
+ ContainerSchemaDefinition.UnHealthyContainerStates.values()) {
+ dslContext.insertInto(DSL.table(UNHEALTHY_CONTAINERS_TABLE_NAME))
+ .columns(
+ field(name("container_id")),
+ field(name("container_state")),
+ field(name("in_state_since")),
+ field(name("expected_replica_count")),
+ field(name("actual_replica_count")),
+ field(name("replica_delta")),
+ field(name("reason"))
+ )
+ .values(
+ System.currentTimeMillis(), // Unique container_id for each
record
+ state.name(), System.currentTimeMillis(), 3, 2, 1, "Replica
count mismatch"
+ )
+ .execute();
+ }
+
+ // Verify that the number of inserted records matches the number of enum
values
+ int count =
dslContext.fetchCount(DSL.table(UNHEALTHY_CONTAINERS_TABLE_NAME));
+
assertEquals(ContainerSchemaDefinition.UnHealthyContainerStates.values().length,
+ count, "Expected one record for each valid state");
+
+ // Try inserting an invalid state (should fail due to constraint)
+ assertThrows(org.jooq.exception.DataAccessException.class, () ->
+ dslContext.insertInto(DSL.table(UNHEALTHY_CONTAINERS_TABLE_NAME))
+ .columns(
+ field(name("container_id")),
+ field(name("container_state")),
+ field(name("in_state_since")),
+ field(name("expected_replica_count")),
+ field(name("actual_replica_count")),
+ field(name("replica_delta")),
+ field(name("reason"))
+ )
+ .values(999L, "INVALID_STATE", System.currentTimeMillis(), 3, 2, 1,
+ "Invalid state test").execute(),
+ "Inserting an invalid container_state should fail due to the
constraint");
+ }
+
+ @Test
+ public void testInsertionWithNullContainerState() {
+ assertThrows(org.jooq.exception.DataAccessException.class, () -> {
+ dslContext.insertInto(DSL.table(UNHEALTHY_CONTAINERS_TABLE_NAME))
+ .columns(
+ field(name("container_id")),
+ field(name("container_state")),
+ field(name("in_state_since")),
+ field(name("expected_replica_count")),
+ field(name("actual_replica_count")),
+ field(name("replica_delta")),
+ field(name("reason"))
+ )
+ .values(
+ 100L, // container_id
+ null, // container_state is NULL
+ System.currentTimeMillis(), 3, 2, 1, "Testing NULL state"
+ )
+ .execute();
+ }, "Inserting a NULL container_state should fail due to the NOT NULL
constraint");
+ }
+
+ @Test
+ public void testDuplicatePrimaryKeyInsertion() throws SQLException {
+ // Insert the first record
+ dslContext.insertInto(DSL.table(UNHEALTHY_CONTAINERS_TABLE_NAME))
+ .columns(
+ field(name("container_id")),
+ field(name("container_state")),
+ field(name("in_state_since")),
+ field(name("expected_replica_count")),
+ field(name("actual_replica_count")),
+ field(name("replica_delta")),
+ field(name("reason"))
+ )
+ .values(200L, "MISSING", System.currentTimeMillis(), 3, 2, 1, "First
insertion"
+ )
+ .execute();
+
+ // Try inserting a duplicate record with the same primary key
+ assertThrows(org.jooq.exception.DataAccessException.class, () -> {
+ dslContext.insertInto(DSL.table(UNHEALTHY_CONTAINERS_TABLE_NAME))
+ .columns(
+ field(name("container_id")),
+ field(name("container_state")),
+ field(name("in_state_since")),
+ field(name("expected_replica_count")),
+ field(name("actual_replica_count")),
+ field(name("replica_delta")),
+ field(name("reason"))
+ )
+ .values(200L, "MISSING", System.currentTimeMillis(), 3, 2, 1,
"Duplicate insertion"
+ )
+ .execute();
+ }, "Inserting a duplicate primary key should fail due to the primary key
constraint");
+ }
+
+}
diff --git
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestReconLayoutVersionManager.java
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestReconLayoutVersionManager.java
index 1da4c48a94..e1a949b6d1 100644
---
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestReconLayoutVersionManager.java
+++
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/upgrade/TestReconLayoutVersionManager.java
@@ -21,6 +21,7 @@ package org.apache.hadoop.ozone.recon.upgrade;
import org.apache.hadoop.ozone.recon.ReconContext;
import org.apache.hadoop.ozone.recon.ReconSchemaVersionTableManager;
+import org.apache.hadoop.ozone.recon.scm.ReconStorageContainerManagerFacade;
import org.mockito.InOrder;
import org.mockito.MockedStatic;
import org.junit.jupiter.api.BeforeEach;
@@ -107,7 +108,8 @@ public class TestReconLayoutVersionManager {
*/
@Test
public void testFinalizeLayoutFeaturesWithMockedValues() throws SQLException
{
- layoutVersionManager.finalizeLayoutFeatures();
+ layoutVersionManager.finalizeLayoutFeatures(mock(
+ ReconStorageContainerManagerFacade.class));
// Verify that schema versions are updated for our custom features
verify(schemaVersionTableManager, times(1)).updateSchemaVersion(1);
@@ -137,7 +139,8 @@ public class TestReconLayoutVersionManager {
@Test
public void testNoLayoutFeatures() throws SQLException {
mockedEnum.when(ReconLayoutFeature::values).thenReturn(new
ReconLayoutFeature[]{});
- layoutVersionManager.finalizeLayoutFeatures();
+ layoutVersionManager.finalizeLayoutFeatures(mock(
+ ReconStorageContainerManagerFacade.class));
verify(schemaVersionTableManager, never()).updateSchemaVersion(anyInt());
}
@@ -155,8 +158,11 @@ public class TestReconLayoutVersionManager {
when(feature1.getVersion()).thenReturn(1);
ReconUpgradeAction action1 = mock(ReconUpgradeAction.class);
+ // Create a consistent mock instance for the SCM facade
+ ReconStorageContainerManagerFacade scmFacadeMock =
mock(ReconStorageContainerManagerFacade.class);
+
// Simulate an exception being thrown during the upgrade action execution
- doThrow(new RuntimeException("Upgrade failed")).when(action1).execute();
+ doThrow(new RuntimeException("Upgrade
failed")).when(action1).execute(scmFacadeMock);
when(feature1.getAction(ReconUpgradeAction.UpgradeActionType.FINALIZE))
.thenReturn(Optional.of(action1));
@@ -165,9 +171,11 @@ public class TestReconLayoutVersionManager {
// Execute the layout feature finalization
try {
- layoutVersionManager.finalizeLayoutFeatures();
+ layoutVersionManager.finalizeLayoutFeatures(scmFacadeMock);
} catch (Exception e) {
+ // Exception is expected, so it's fine to catch and ignore it here
}
+
// Verify that schema version update was never called due to the exception
verify(schemaVersionTableManager, never()).updateSchemaVersion(anyInt());
}
@@ -203,14 +211,17 @@ public class TestReconLayoutVersionManager {
// Mock the static values method to return custom features in a jumbled
order
mockedEnum.when(ReconLayoutFeature::values).thenReturn(new
ReconLayoutFeature[]{feature2, feature3, feature1});
+ // Create a consistent mock instance for SCM facade
+ ReconStorageContainerManagerFacade scmFacadeMock =
mock(ReconStorageContainerManagerFacade.class);
+
// Execute the layout feature finalization
- layoutVersionManager.finalizeLayoutFeatures();
+ layoutVersionManager.finalizeLayoutFeatures(scmFacadeMock);
// Verify that the actions were executed in the correct order using InOrder
InOrder inOrder = inOrder(action1, action2, action3);
- inOrder.verify(action1).execute(); // Should be executed first
- inOrder.verify(action2).execute(); // Should be executed second
- inOrder.verify(action3).execute(); // Should be executed third
+ inOrder.verify(action1).execute(scmFacadeMock); // Should be executed first
+ inOrder.verify(action2).execute(scmFacadeMock); // Should be executed
second
+ inOrder.verify(action3).execute(scmFacadeMock); // Should be executed third
}
/**
@@ -221,7 +232,8 @@ public class TestReconLayoutVersionManager {
public void testNoUpgradeActionsNeeded() throws SQLException {
when(schemaVersionTableManager.getCurrentSchemaVersion()).thenReturn(2);
layoutVersionManager = new
ReconLayoutVersionManager(schemaVersionTableManager, mock(ReconContext.class));
- layoutVersionManager.finalizeLayoutFeatures();
+ layoutVersionManager.finalizeLayoutFeatures(mock(
+ ReconStorageContainerManagerFacade.class));
verify(schemaVersionTableManager, never()).updateSchemaVersion(anyInt());
}
@@ -252,8 +264,9 @@ public class TestReconLayoutVersionManager {
mockedEnum.when(ReconLayoutFeature::values).thenReturn(new
ReconLayoutFeature[]{feature1, feature2});
+ ReconStorageContainerManagerFacade scmFacadeMock =
mock(ReconStorageContainerManagerFacade.class);
// Finalize the first two features.
- layoutVersionManager.finalizeLayoutFeatures();
+ layoutVersionManager.finalizeLayoutFeatures(scmFacadeMock);
// Verify that the schema versions for the first two features were updated.
verify(schemaVersionTableManager, times(1)).updateSchemaVersion(1);
@@ -272,17 +285,17 @@ public class TestReconLayoutVersionManager {
when(schemaVersionTableManager.getCurrentSchemaVersion()).thenReturn(2);
// Finalize again, but only feature 3 should be finalized.
- layoutVersionManager.finalizeLayoutFeatures();
+ layoutVersionManager.finalizeLayoutFeatures(scmFacadeMock);
// Verify that the schema version for feature 3 was updated.
verify(schemaVersionTableManager, times(1)).updateSchemaVersion(3);
// Verify that action1 and action2 were not executed again.
- verify(action1, times(1)).execute(); // Still should have been executed
only once
- verify(action2, times(1)).execute(); // Still should have been executed
only once
+ verify(action1, times(1)).execute(scmFacadeMock);
+ verify(action2, times(1)).execute(scmFacadeMock);
// Verify that the upgrade action for feature 3 was executed.
- verify(action3, times(1)).execute();
+ verify(action3, times(1)).execute(scmFacadeMock);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]