diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java index 6b0136abf664..b49e792348cc 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java @@ -18,7 +18,6 @@ package org.apache.hadoop.hdds.scm.block; import static org.apache.hadoop.hdds.scm.exceptions.SCMException.ResultCodes.INVALID_BLOCK_SIZE; -import static org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator.LOCAL_ID; import java.io.IOException; import java.util.ArrayList; @@ -39,6 +38,7 @@ import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList; import org.apache.hadoop.hdds.scm.exceptions.SCMException; import org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator; +import org.apache.hadoop.hdds.scm.ha.SequenceIdType; import org.apache.hadoop.hdds.scm.pipeline.Pipeline; import org.apache.hadoop.hdds.scm.pipeline.PipelineManager; import org.apache.hadoop.hdds.scm.pipeline.PipelineNotFoundException; @@ -185,7 +185,7 @@ private AllocatedBlock newBlock(ContainerInfo containerInfo) try { final Pipeline pipeline = pipelineManager .getPipeline(containerInfo.getPipelineID()); - long localID = sequenceIdGen.getNextId(LOCAL_ID); + long localID = sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID); long containerID = containerInfo.getContainerID(); AllocatedBlock.Builder abb = new AllocatedBlock.Builder() .setContainerBlockID(new ContainerBlockID(containerID, localID)) diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java index 652e59aead71..ef8ca6906a0d 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java @@ -20,7 +20,6 @@ import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_BLOCK_DELETION_PER_DN_DISTRIBUTION_FACTOR; import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_BLOCK_DELETION_PER_DN_DISTRIBUTION_FACTOR_DEFAULT; import static org.apache.hadoop.hdds.scm.block.SCMDeletedBlockTransactionStatusManager.SCMDeleteBlocksCommandStatusManager.CmdStatus; -import static org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator.DEL_TXN_ID; import com.google.common.annotations.VisibleForTesting; import com.google.protobuf.ByteString; @@ -53,6 +52,7 @@ import org.apache.hadoop.hdds.scm.ha.SCMContext; import org.apache.hadoop.hdds.scm.ha.SCMHADBTransactionBuffer; import org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator; +import org.apache.hadoop.hdds.scm.ha.SequenceIdType; import org.apache.hadoop.hdds.scm.server.StorageContainerManager; import org.apache.hadoop.hdds.server.events.EventHandler; import org.apache.hadoop.hdds.server.events.EventPublisher; @@ -240,7 +240,7 @@ public void addTransactions(Map> containerBlocksMap) long currentBatchSizeBytes = 0; for (Map.Entry> entry : containerBlocksMap.entrySet()) { - long nextTXID = sequenceIdGen.getNextId(DEL_TXN_ID); + long nextTXID = sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID); DeletedBlocksTransaction tx = constructNewTransaction(nextTXID, entry.getKey(), entry.getValue()); txsToBeAdded.add(tx); diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerManagerImpl.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerManagerImpl.java index 15a566f6421b..189b8ae20e90 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerManagerImpl.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerManagerImpl.java @@ -17,8 +17,6 @@ package org.apache.hadoop.hdds.scm.container; -import static org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator.CONTAINER_ID; - import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import java.io.IOException; @@ -42,6 +40,7 @@ import org.apache.hadoop.hdds.scm.container.replication.ContainerReplicaPendingOps; import org.apache.hadoop.hdds.scm.ha.SCMHAManager; import org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator; +import org.apache.hadoop.hdds.scm.ha.SequenceIdType; import org.apache.hadoop.hdds.scm.pipeline.Pipeline; import org.apache.hadoop.hdds.scm.pipeline.PipelineManager; import org.apache.hadoop.hdds.utils.db.Table; @@ -243,7 +242,7 @@ private ContainerInfo allocateContainer(final Pipeline pipeline, return null; } - final long uniqueId = sequenceIdGen.getNextId(CONTAINER_ID); + final long uniqueId = sequenceIdGen.getNextId(SequenceIdType.CONTAINER_ID); Preconditions.checkState(uniqueId > 0, "Cannot allocate container, negative container id" + " generated. %s.", uniqueId); diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdGenerator.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdGenerator.java index 6bef88f5ba3d..5c694d1b6b43 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdGenerator.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdGenerator.java @@ -26,7 +26,7 @@ import java.math.BigInteger; import java.security.cert.X509Certificate; import java.time.LocalDate; -import java.util.HashMap; +import java.util.EnumMap; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -64,19 +64,19 @@ public class SequenceIdGenerator { /** * Ids supported. */ - public static final String LOCAL_ID = "localId"; - public static final String DEL_TXN_ID = "delTxnId"; - public static final String CONTAINER_ID = "containerId"; + public static final String LOCAL_ID = SequenceIdType.LOCAL_ID.getDbKey(); + public static final String DEL_TXN_ID = SequenceIdType.DEL_TXN_ID.getDbKey(); + public static final String CONTAINER_ID = SequenceIdType.CONTAINER_ID.getDbKey(); // Certificate ID for all services, including root certificates, whose ID // were using "rootCertificateId" before. - public static final String CERTIFICATE_ID = "CertificateId"; + public static final String CERTIFICATE_ID = SequenceIdType.CERTIFICATE_ID.getDbKey(); @Deprecated - public static final String ROOT_CERTIFICATE_ID = "rootCertificateId"; + public static final String ROOT_CERTIFICATE_ID = SequenceIdType.ROOT_CERTIFICATE_ID.getDbKey(); private static final long INVALID_SEQUENCE_ID = 0; - private final Map sequenceIdToBatchMap; + private final Map sequenceIdToBatchMap; private final Lock lock; private final long batchSize; @@ -89,7 +89,7 @@ public class SequenceIdGenerator { */ public SequenceIdGenerator(ConfigurationSource conf, SCMHAManager scmhaManager, Table sequenceIdTable) { - this.sequenceIdToBatchMap = new HashMap<>(); + this.sequenceIdToBatchMap = new EnumMap<>(SequenceIdType.class); this.lock = new ReentrantLock(); this.batchSize = conf.getInt(OZONE_SCM_SEQUENCE_ID_BATCH_SIZE, OZONE_SCM_SEQUENCE_ID_BATCH_SIZE_DEFAULT); @@ -108,14 +108,14 @@ public StateManager createStateManager(SCMHAManager scmhaManager, } /** - * @param sequenceIdName : name of the sequenceId - * @return : next id of this sequenceId. + * @param idType : supported sequence ID type + * @return next id of this sequence ID. */ - public long getNextId(String sequenceIdName) throws SCMException { + public long getNextId(SequenceIdType idType) throws SCMException { lock.lock(); try { Batch batch = sequenceIdToBatchMap.computeIfAbsent( - sequenceIdName, key -> new Batch()); + idType, key -> new Batch()); if (batch.nextId <= batch.lastId) { return batch.nextId++; @@ -128,18 +128,18 @@ public long getNextId(String sequenceIdName) throws SCMException { Preconditions.checkArgument(Long.MAX_VALUE - batch.lastId >= batchSize); long nextLastId = batch.lastId + - ((sequenceIdName.equals(CERTIFICATE_ID)) ? 1 : batchSize); + (idType == SequenceIdType.CERTIFICATE_ID ? 1 : batchSize); - if (stateManager.allocateBatch(sequenceIdName, + if (stateManager.allocateBatch(idType.getDbKey(), prevLastId, nextLastId)) { batch.lastId = nextLastId; LOG.info("Allocate a batch for {}, change lastId from {} to {}.", - sequenceIdName, prevLastId, batch.lastId); + idType, prevLastId, batch.lastId); break; } // reload lastId from RocksDB. - batch.lastId = stateManager.getLastId(sequenceIdName); + batch.lastId = stateManager.getLastId(idType.getDbKey()); } Preconditions.checkArgument(batch.nextId <= batch.lastId); diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdType.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdType.java new file mode 100644 index 000000000000..9b882b245f07 --- /dev/null +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdType.java @@ -0,0 +1,84 @@ +/* + * 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.hdds.scm.ha; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Represents the sequence ID types managed by {@link SequenceIdGenerator} and their persisted RocksDB keys. + */ +public enum SequenceIdType { + + LOCAL_ID("localId"), + + DEL_TXN_ID("delTxnId"), + + CONTAINER_ID("containerId"), + + /** Certificate ID for all services, including root certificates. */ + CERTIFICATE_ID("CertificateId"), + + /** + * @deprecated Use {@link #CERTIFICATE_ID} instead. + */ + @Deprecated + ROOT_CERTIFICATE_ID("rootCertificateId"); + + /** + * The key string stored in the RocksDB sequenceId table. + */ + private final String dbKey; + + /** + * Reverse lookup map from db key string to enum constant. + */ + private static final Map DB_KEY_MAP; + + static { + Map map = new HashMap<>(); + for (SequenceIdType type : values()) { + map.put(type.dbKey, type); + } + DB_KEY_MAP = Collections.unmodifiableMap(map); + } + + SequenceIdType(String dbKey) { + this.dbKey = dbKey; + } + + /** + * Returns the key string used to persist this sequence ID in RocksDB. + * This value must not be changed to keep backward compatibility with + * existing databases. + */ + public String getDbKey() { + return dbKey; + } + + /** + * Returns the {@link SequenceIdType} corresponding to the provided RocksDB key string, or null if unmapped. + */ + public static SequenceIdType fromDbKey(String dbKey) { + if (dbKey == null) { + return null; + } + return DB_KEY_MAP.get(dbKey); + } +} diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationManager.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationManager.java index 1b0caadcfbe4..73c6d7a06e8b 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationManager.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationManager.java @@ -20,7 +20,6 @@ import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_NEW_KEY_CERT_DIR_NAME_PROGRESS_SUFFIX; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_NEW_KEY_CERT_DIR_NAME_SUFFIX; import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_X509_DIR_NAME_DEFAULT; -import static org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator.CERTIFICATE_ID; import static org.apache.hadoop.ozone.OzoneConsts.SCM_ROOT_CA_COMPONENT_NAME; import com.google.common.annotations.VisibleForTesting; @@ -55,6 +54,7 @@ import org.apache.hadoop.hdds.scm.ha.SCMContext; import org.apache.hadoop.hdds.scm.ha.SCMServiceException; import org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator; +import org.apache.hadoop.hdds.scm.ha.SequenceIdType; import org.apache.hadoop.hdds.scm.ha.StatefulService; import org.apache.hadoop.hdds.scm.server.SCMStorageConfig; import org.apache.hadoop.hdds.scm.server.StorageContainerManager; @@ -378,7 +378,7 @@ public void run() { CertificateServer newRootCAServer = null; BigInteger newId = BigInteger.ONE; try { - newId = BigInteger.valueOf(sequenceIdGen.getNextId(CERTIFICATE_ID)); + newId = BigInteger.valueOf(sequenceIdGen.getNextId(SequenceIdType.CERTIFICATE_ID)); newRootCAServer = HASecurityUtils.initializeRootCertificateServer(secConf, scm.getCertificateStore(), scmStorageConfig, newId, diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java index 00e67f63439c..c5f73f331e7d 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java @@ -18,7 +18,6 @@ package org.apache.hadoop.hdds.scm.server; import static org.apache.hadoop.hdds.scm.ScmUtils.checkIfCertSignRequestAllowed; -import static org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator.CERTIFICATE_ID; import static org.apache.hadoop.hdds.security.exception.SCMSecretKeyException.ErrorCode.SECRET_KEY_NOT_ENABLED; import static org.apache.hadoop.hdds.security.exception.SCMSecretKeyException.ErrorCode.SECRET_KEY_NOT_INITIALIZED; import static org.apache.hadoop.hdds.security.exception.SCMSecurityException.ErrorCode.CERTIFICATE_NOT_FOUND; @@ -63,6 +62,7 @@ import org.apache.hadoop.hdds.scm.ScmConfigKeys; import org.apache.hadoop.hdds.scm.exceptions.SCMException; import org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator; +import org.apache.hadoop.hdds.scm.ha.SequenceIdType; import org.apache.hadoop.hdds.scm.protocol.SCMSecurityProtocolServerSideTranslatorPB; import org.apache.hadoop.hdds.scm.protocol.SecretKeyProtocolServerSideTranslatorPB; import org.apache.hadoop.hdds.security.exception.SCMSecretKeyException; @@ -481,7 +481,7 @@ public List removeExpiredCertificates() throws IOException { } private String getNextCertificateId() throws IOException { - return String.valueOf(sequenceIdGen.getNextId(CERTIFICATE_ID)); + return String.valueOf(sequenceIdGen.getNextId(SequenceIdType.CERTIFICATE_ID)); } @VisibleForTesting diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIDGenerator.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIDGenerator.java index a42d660a5f39..1d2e3fe52749 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIDGenerator.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIDGenerator.java @@ -58,33 +58,33 @@ public void testSequenceIDGenUponNonRatis() throws Exception { conf, scmHAManager, scmMetadataStore.getSequenceIdTable()); // the first batch is [1, 1000] - assertEquals(1L, sequenceIdGen.getNextId("someKey")); - assertEquals(2L, sequenceIdGen.getNextId("someKey")); - assertEquals(3L, sequenceIdGen.getNextId("someKey")); + assertEquals(1L, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(2L, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(3L, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); - assertEquals(1L, sequenceIdGen.getNextId("otherKey")); - assertEquals(2L, sequenceIdGen.getNextId("otherKey")); - assertEquals(3L, sequenceIdGen.getNextId("otherKey")); + assertEquals(1L, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(2L, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(3L, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); // default batchSize is 1000, the next batch is [1001, 2000] sequenceIdGen.invalidateBatch(); - assertEquals(1001, sequenceIdGen.getNextId("someKey")); - assertEquals(1002, sequenceIdGen.getNextId("someKey")); - assertEquals(1003, sequenceIdGen.getNextId("someKey")); + assertEquals(1001, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(1002, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(1003, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); - assertEquals(1001, sequenceIdGen.getNextId("otherKey")); - assertEquals(1002, sequenceIdGen.getNextId("otherKey")); - assertEquals(1003, sequenceIdGen.getNextId("otherKey")); + assertEquals(1001, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(1002, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(1003, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); // default batchSize is 1000, the next batch is [2001, 3000] sequenceIdGen.invalidateBatch(); - assertEquals(2001, sequenceIdGen.getNextId("someKey")); - assertEquals(2002, sequenceIdGen.getNextId("someKey")); - assertEquals(2003, sequenceIdGen.getNextId("someKey")); + assertEquals(2001, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(2002, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(2003, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); - assertEquals(2001, sequenceIdGen.getNextId("otherKey")); - assertEquals(2002, sequenceIdGen.getNextId("otherKey")); - assertEquals(2003, sequenceIdGen.getNextId("otherKey")); + assertEquals(2001, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(2002, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(2003, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); } @Test @@ -103,33 +103,33 @@ public void testSequenceIDGenUponRatis() throws Exception { conf, scmHAManager, scmMetadataStore.getSequenceIdTable()); // the first batch is [1, 100] - assertEquals(1L, sequenceIdGen.getNextId("someKey")); - assertEquals(2L, sequenceIdGen.getNextId("someKey")); - assertEquals(3L, sequenceIdGen.getNextId("someKey")); + assertEquals(1L, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(2L, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(3L, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); - assertEquals(1L, sequenceIdGen.getNextId("otherKey")); - assertEquals(2L, sequenceIdGen.getNextId("otherKey")); - assertEquals(3L, sequenceIdGen.getNextId("otherKey")); + assertEquals(1L, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(2L, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(3L, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); // the next batch is [101, 200] sequenceIdGen.invalidateBatch(); - assertEquals(101, sequenceIdGen.getNextId("someKey")); - assertEquals(102, sequenceIdGen.getNextId("someKey")); - assertEquals(103, sequenceIdGen.getNextId("someKey")); + assertEquals(101, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(102, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(103, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); - assertEquals(101, sequenceIdGen.getNextId("otherKey")); - assertEquals(102, sequenceIdGen.getNextId("otherKey")); - assertEquals(103, sequenceIdGen.getNextId("otherKey")); + assertEquals(101, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(102, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(103, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); // the next batch is [201, 300] sequenceIdGen.invalidateBatch(); - assertEquals(201, sequenceIdGen.getNextId("someKey")); - assertEquals(202, sequenceIdGen.getNextId("someKey")); - assertEquals(203, sequenceIdGen.getNextId("someKey")); + assertEquals(201, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(202, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); + assertEquals(203, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); - assertEquals(201, sequenceIdGen.getNextId("otherKey")); - assertEquals(202, sequenceIdGen.getNextId("otherKey")); - assertEquals(203, sequenceIdGen.getNextId("otherKey")); + assertEquals(201, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(202, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); + assertEquals(203, sequenceIdGen.getNextId(SequenceIdType.DEL_TXN_ID)); } @Test @@ -159,7 +159,7 @@ public StateManager createStateManager( } }; - assertEquals(1L, sequenceIdGen.getNextId("someKey")); + assertEquals(1L, sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID)); // Simulation currently this SCM is not a leader node, // So this SCM can only allocate IDs within the current batch @@ -170,7 +170,7 @@ public StateManager createStateManager( for (int i = 0; i < batchSize * 3; i++) { try { - long nextID = sequenceIdGen.getNextId("someKey"); + long nextID = sequenceIdGen.getNextId(SequenceIdType.LOCAL_ID); if (nextID > batchSize) { fail("Should not allocate a blockID: " + nextID + " that exceeds the current Batch: " + batchSize); diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIdType.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIdType.java new file mode 100644 index 000000000000..5c1ef02dd96a --- /dev/null +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIdType.java @@ -0,0 +1,93 @@ +/* + * 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.hdds.scm.ha; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link SequenceIdType}. + */ +public class TestSequenceIdType { + + @Test + @SuppressWarnings("deprecation") + public void testStringSyncWithEnumConstants() { + // Even though we changed to an Enum, these underlying strings are + // persisted in RocksDB. Do not change them. + assertEquals("localId", SequenceIdType.LOCAL_ID.getDbKey()); + assertEquals("delTxnId", SequenceIdType.DEL_TXN_ID.getDbKey()); + assertEquals("containerId", SequenceIdType.CONTAINER_ID.getDbKey()); + assertEquals("CertificateId", SequenceIdType.CERTIFICATE_ID.getDbKey()); + assertEquals("rootCertificateId", SequenceIdType.ROOT_CERTIFICATE_ID.getDbKey()); + } + + @Test + @SuppressWarnings("deprecation") + public void testDeprecatedStringSyncWithEnumConstants() { + assertEquals(SequenceIdType.ROOT_CERTIFICATE_ID.getDbKey(), + SequenceIdGenerator.ROOT_CERTIFICATE_ID); + } + + @Test + public void testNumberOfEnumConstants() { + // If a new SequenceIdType is added, this test will fail. + // This serves as a reminder to the developer to verify RocksDB backward + // compatibility and update this test class accordingly. + assertEquals(5, SequenceIdType.values().length); + } + + @Test + public void testIfNewEnumConstantGetsAdded() { + Set expectedNames = new HashSet<>(Arrays.asList( + "LOCAL_ID", "DEL_TXN_ID", "CONTAINER_ID", + "CERTIFICATE_ID", "ROOT_CERTIFICATE_ID")); + + Set actualNames = new HashSet<>(); + for (SequenceIdType type : SequenceIdType.values()) { + actualNames.add(type.name()); + } + + // Filter exactly what changed to make the failure message extremely clear + Set added = new HashSet<>(actualNames); + added.removeAll(expectedNames); + + Set removed = new HashSet<>(expectedNames); + removed.removeAll(actualNames); + + assertTrue(added.isEmpty() && removed.isEmpty(), + () -> "SequenceIdType constants changed!\n" + + "Unexpectedly Added: " + added + "\n" + + "Unexpectedly Removed: " + removed + "\n" + + "ACTION REQUIRED: If this change is intentional, you MUST verify " + + "RocksDB backward compatibility and update this test's expectedNames."); + } + + @Test + public void testReturnsNullIfEnumConstantNotAvailable() { + assertNull(SequenceIdType.fromDbKey("unmapped-key-string")); + assertNull(SequenceIdType.fromDbKey(null)); + } + +} diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/security/TestRootCARotationManager.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/security/TestRootCARotationManager.java index d23bf0d06d27..6cb5ed60c7d8 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/security/TestRootCARotationManager.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/security/TestRootCARotationManager.java @@ -58,6 +58,7 @@ import org.apache.hadoop.hdds.scm.ha.SCMRatisServerImpl; import org.apache.hadoop.hdds.scm.ha.SCMServiceManager; import org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator; +import org.apache.hadoop.hdds.scm.ha.SequenceIdType; import org.apache.hadoop.hdds.scm.ha.StatefulServiceStateManager; import org.apache.hadoop.hdds.scm.server.SCMSecurityProtocolServer; import org.apache.hadoop.hdds.scm.server.SCMStorageConfig; @@ -125,7 +126,7 @@ public void init() throws IOException, TimeoutException, when(scm.getScmHAManager()).thenReturn(scmhaManager); when(scmhaManager.getRatisServer()).thenReturn(mock(SCMRatisServerImpl.class)); when(scm.getSequenceIdGen()).thenReturn(sequenceIdGenerator); - when(sequenceIdGenerator.getNextId(anyString())).thenReturn(2L); + when(sequenceIdGenerator.getNextId(any(SequenceIdType.class))).thenReturn(2L); when(scm.getScmStorageConfig()).thenReturn(scmStorageConfig); when(scm.getSecurityProtocolServer()).thenReturn(scmSecurityProtocolServer); doNothing().when(scmSecurityProtocolServer).setRootCertificateServer(any());