This is an automated email from the ASF dual-hosted git repository.

szetszwo 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 57405007a2b HDDS-15370. Change sequenceIdTable to use SequenceIdType 
(#10381)
57405007a2b is described below

commit 57405007a2b235abfc69c53e123192ce3ddc4cba
Author: Navink <[email protected]>
AuthorDate: Sat May 30 20:22:15 2026 +0530

    HDDS-15370. Change sequenceIdTable to use SequenceIdType (#10381)
---
 .../apache/hadoop/hdds/scm/ha/SequenceIdType.java  | 143 +++++++++++++++++++++
 .../hadoop/hdds/scm/metadata/SCMMetadataStore.java |   3 +-
 .../hadoop/hdds/scm/ha/TestSequenceIdType.java     |   0
 .../hadoop/hdds/scm/ha/SequenceIdGenerator.java    |  66 +++++-----
 .../apache/hadoop/hdds/scm/ha/SequenceIdType.java  |  41 ------
 .../hadoop/hdds/scm/metadata/SCMDBDefinition.java  |   5 +-
 .../hdds/scm/metadata/SCMMetadataStoreImpl.java    |   5 +-
 .../hdds/scm/ha/TestSequenceIDGenerator.java       |   4 +-
 .../hdds/scm/metadata/TestSequenceIdTypeCodec.java |  78 +++++++++++
 9 files changed, 264 insertions(+), 81 deletions(-)

diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdType.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdType.java
new file mode 100644
index 00000000000..13e4255e24d
--- /dev/null
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdType.java
@@ -0,0 +1,143 @@
+/*
+ * 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 jakarta.annotation.Nonnull;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.hadoop.hdds.StringUtils;
+import org.apache.hadoop.hdds.utils.db.Codec;
+import org.apache.hadoop.hdds.utils.db.CodecBuffer;
+import org.apache.hadoop.hdds.utils.db.CodecException;
+import org.apache.hadoop.hdds.utils.db.StringCodec;
+
+/**
+ * Represents the sequence ID types managed by
+ * {@code org.apache.hadoop.hdds.scm.ha.SequenceIdGenerator}
+ * The enum constant names are kept exactly as their persisted RocksDB keys.
+ */
+public enum SequenceIdType {
+
+  localId,
+  delTxnId,
+  containerId,
+
+  /**
+   * Certificate ID for all services, including root certificates.
+   */
+  CertificateId,
+
+  /**
+   * @deprecated Use {@link #CertificateId} instead.
+   */
+  @Deprecated
+  rootCertificateId;
+
+  private static final Codec<SequenceIdType> INSTANCE = new 
Codec<SequenceIdType>() {
+    @Override
+    public Class<SequenceIdType> getTypeClass() {
+      return SequenceIdType.class;
+    }
+
+    @Override
+    public boolean supportCodecBuffer() {
+      return true;
+    }
+
+    @Override
+    public byte[] toPersistedFormat(SequenceIdType type) {
+      return type.getByteArray();
+    }
+
+    @Override
+    public SequenceIdType fromPersistedFormat(byte[] bytes) throws 
CodecException {
+      final SequenceIdType type = SEQUENCE_ID_TYPES.get(bytes[0]);
+      if (type != null && Arrays.equals(type.getByteArray(), bytes)) {
+        return type;
+      }
+      throw new CodecException("Failed to decode " + 
StringUtils.bytes2Hex(ByteBuffer.wrap(bytes), 20));
+    }
+
+    @Override
+    public CodecBuffer toCodecBuffer(@Nonnull SequenceIdType object, 
CodecBuffer.Allocator allocator) {
+      final ByteBuffer buffer = object.getByteBuffer();
+      final CodecBuffer cb = allocator.apply(buffer.remaining());
+      cb.put(buffer);
+      return cb;
+    }
+
+    @Override
+    public SequenceIdType fromCodecBuffer(@Nonnull CodecBuffer bytes) throws 
CodecException {
+      final ByteBuffer buffer = bytes.asReadOnlyByteBuffer();
+      final SequenceIdType type = 
SEQUENCE_ID_TYPES.get(buffer.get(buffer.position()));
+      if (type != null && type.getByteBuffer().equals(buffer)) {
+        return type;
+      }
+      throw new CodecException("Failed to decode " + 
StringUtils.bytes2Hex(buffer, 20));
+
+    }
+
+    @Override
+    public SequenceIdType copyObject(SequenceIdType object) {
+      return object;
+    }
+  };
+
+  /** Only use the first byte in the name since they are all distinct. */
+  private static final Map<Byte, SequenceIdType> SEQUENCE_ID_TYPES;
+
+  private final byte[] byteArray;
+  private final ByteBuffer byteBuffer;
+
+  SequenceIdType() {
+    try {
+      this.byteArray = 
StringCodec.getCodecNoFallback().toPersistedFormat(name());
+    } catch (CodecException e) {
+      throw new IllegalStateException("Failed to construct " + this, e);
+    }
+
+    this.byteBuffer = ByteBuffer.wrap(byteArray).asReadOnlyBuffer();
+  }
+
+  public byte[] getByteArray() {
+    return byteArray.clone();
+  }
+
+  public ByteBuffer getByteBuffer() {
+    return byteBuffer.duplicate();
+  }
+
+  static {
+    final Map<Byte, SequenceIdType> map = new HashMap<>();
+    for (SequenceIdType type : SequenceIdType.values()) {
+      final byte first =  type.getByteArray()[0];
+      final SequenceIdType previous = map.put(first, type);
+      if (previous != null) {
+        throw new IllegalStateException("Duplicated first byte: " + type + " 
and " + previous);
+      }
+    }
+    SEQUENCE_ID_TYPES = Collections.unmodifiableMap(map);
+  }
+
+  public static Codec<SequenceIdType> getCodec() {
+    return INSTANCE;
+  }
+}
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStore.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStore.java
index 9d109c32b0b..37322ee2c13 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStore.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStore.java
@@ -27,6 +27,7 @@
 import org.apache.hadoop.hdds.scm.container.ContainerID;
 import org.apache.hadoop.hdds.scm.container.ContainerInfo;
 import org.apache.hadoop.hdds.scm.container.common.helpers.MoveDataNodePair;
+import org.apache.hadoop.hdds.scm.ha.SequenceIdType;
 import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
 import org.apache.hadoop.hdds.scm.pipeline.PipelineID;
 import org.apache.hadoop.hdds.utils.DBStoreHAManager;
@@ -102,7 +103,7 @@ public interface SCMMetadataStore extends DBStoreHAManager {
   /**
    * Table that maintains sequence id information.
    */
-  Table<String, Long> getSequenceIdTable();
+  Table<SequenceIdType, Long> getSequenceIdTable();
 
   /**
    * Table that maintains move information.
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIdType.java
 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIdType.java
similarity index 100%
rename from 
hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIdType.java
rename to 
hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/scm/ha/TestSequenceIdType.java
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 92659d2f3a0..08916b65dc5 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
@@ -77,7 +77,7 @@ public class SequenceIdGenerator {
    * @param sequenceIdTable : sequenceIdTable
    */
   public SequenceIdGenerator(ConfigurationSource conf,
-      SCMHAManager scmhaManager, Table<String, Long> sequenceIdTable) {
+      SCMHAManager scmhaManager, Table<SequenceIdType, Long> sequenceIdTable) {
     this.sequenceIdToBatchMap = newSequenceIdToBatchMap();
     this.lock = new ReentrantLock();
     this.batchSize = conf.getInt(OZONE_SCM_SEQUENCE_ID_BATCH_SIZE,
@@ -96,7 +96,7 @@ static Map<SequenceIdType, Batch> newSequenceIdToBatchMap() {
   }
 
   public StateManager createStateManager(SCMHAManager scmhaManager,
-      Table<String, Long> sequenceIdTable) {
+      Table<SequenceIdType, Long> sequenceIdTable) {
     Objects.requireNonNull(scmhaManager, "scmhaManager == null");
     return new StateManagerImpl.Builder()
         .setRatisServer(scmhaManager.getRatisServer())
@@ -168,7 +168,7 @@ private void invalidateBatchInternal() {
    * Reinitialize the SequenceIdGenerator with the latest sequenceIdTable
    * during SCM reload.
    */
-  public void reinitialize(Table<String, Long> sequenceIdTable)
+  public void reinitialize(Table<SequenceIdType, Long> sequenceIdTable)
       throws IOException {
     LOG.info("reinitialize SequenceIdGenerator.");
     lock.lock();
@@ -208,7 +208,7 @@ Boolean allocateBatch(String sequenceIdName,
      * Reinitialize the SequenceIdGenerator with the latest sequenceIdTable
      * during SCM reload.
      */
-    void reinitialize(Table<String, Long> sequenceIdTable) throws IOException;
+    void reinitialize(Table<SequenceIdType, Long> sequenceIdTable) throws 
IOException;
 
     @Override
     default RequestType getType() {
@@ -221,11 +221,11 @@ default RequestType getType() {
    * DBTransactionBuffer until a snapshot is taken.
    */
   static final class StateManagerImpl implements StateManager {
-    private Table<String, Long> sequenceIdTable;
+    private Table<SequenceIdType, Long> sequenceIdTable;
     private final DBTransactionBuffer transactionBuffer;
     private final Map<SequenceIdType, Long> sequenceIdToLastIdMap;
 
-    private StateManagerImpl(Table<String, Long> sequenceIdTable,
+    private StateManagerImpl(Table<SequenceIdType, Long> sequenceIdTable,
                                DBTransactionBuffer trxBuffer) {
       this.sequenceIdTable = sequenceIdTable;
       this.transactionBuffer = trxBuffer;
@@ -240,7 +240,7 @@ public Boolean allocateBatch(String sequenceIdName,
       Long lastId = sequenceIdToLastIdMap.computeIfAbsent(idType,
           key -> {
             try {
-              Long idInDb = this.sequenceIdTable.get(key.name());
+              Long idInDb = this.sequenceIdTable.get(key);
               return idInDb != null ? idInDb : INVALID_SEQUENCE_ID;
             } catch (IOException ioe) {
               throw new RuntimeException("Failed to get lastId from db", ioe);
@@ -255,7 +255,7 @@ public Boolean allocateBatch(String sequenceIdName,
 
       try {
         transactionBuffer
-            .addToBuffer(sequenceIdTable, idType.name(), newLastId);
+            .addToBuffer(sequenceIdTable, idType, newLastId);
       } catch (IOException ioe) {
         throw new RuntimeException("Failed to put lastId to Batch", ioe);
       }
@@ -270,7 +270,7 @@ public Long getLastId(SequenceIdType idType) {
     }
 
     @Override
-    public void reinitialize(Table<String, Long> seqIdTable)
+    public void reinitialize(Table<SequenceIdType, Long> seqIdTable)
         throws IOException {
       this.sequenceIdTable = seqIdTable;
       this.sequenceIdToLastIdMap.clear();
@@ -278,17 +278,17 @@ public void reinitialize(Table<String, Long> seqIdTable)
     }
 
     private void initialize() throws IOException {
-      try (Table.KeyValueIterator<String, Long> iterator = 
sequenceIdTable.iterator()) {
+      try (Table.KeyValueIterator<SequenceIdType, Long> iterator = 
sequenceIdTable.iterator()) {
 
         while (iterator.hasNext()) {
-          Table.KeyValue<String, Long> kv = iterator.next();
-          final String sequenceIdName = kv.getKey();
+          Table.KeyValue<SequenceIdType, Long> kv = iterator.next();
+          final SequenceIdType idType = kv.getKey();
           final Long lastId = kv.getValue();
-          Objects.requireNonNull(sequenceIdName,
-              "sequenceIdName should not be null");
+          Objects.requireNonNull(idType,
+              "idType should not be null");
           Objects.requireNonNull(lastId,
               "lastId should not be null");
-          sequenceIdToLastIdMap.put(SequenceIdType.valueOf(sequenceIdName), 
lastId);
+          sequenceIdToLastIdMap.put(idType, lastId);
         }
       }
     }
@@ -297,7 +297,7 @@ private void initialize() throws IOException {
      * Builder for Ratis based StateManager.
      */
     public static class Builder {
-      private Table<String, Long> table;
+      private Table<SequenceIdType, Long> table;
       private DBTransactionBuffer buffer;
       private SCMRatisServer ratisServer;
 
@@ -307,7 +307,7 @@ public Builder setRatisServer(final SCMRatisServer 
scmRatisServer) {
       }
 
       public Builder setSequenceIdTable(
-          final Table<String, Long> sequenceIdTable) {
+          final Table<SequenceIdType, Long> sequenceIdTable) {
         table = sequenceIdTable;
         return this;
       }
@@ -337,7 +337,7 @@ public StateManager build() {
    */
   public static void upgradeToSequenceId(SCMMetadataStore scmMetadataStore)
       throws IOException {
-    Table<String, Long> sequenceIdTable = 
scmMetadataStore.getSequenceIdTable();
+    Table<SequenceIdType, Long> sequenceIdTable = 
scmMetadataStore.getSequenceIdTable();
 
     // upgrade localId
     // Short-term solution: when setup multi SCM from scratch, they need
@@ -345,29 +345,29 @@ public static void upgradeToSequenceId(SCMMetadataStore 
scmMetadataStore)
     // Long-term solution: the bootstrapped SCM will explicitly download
     // scm.db from leader SCM, and drop its own scm.db. Thus the upgrade
     // operations can take effect exactly once in a SCM HA cluster.
-    if (sequenceIdTable.get(SequenceIdType.localId.name()) == null) {
+    if (sequenceIdTable.get(SequenceIdType.localId) == null) {
       long millisSinceEpoch = TimeUnit.DAYS.toMillis(
           LocalDate.of(LocalDate.now().getYear() + 1, 1, 1).toEpochDay());
 
       long localId = millisSinceEpoch << Short.SIZE;
       Preconditions.checkArgument(localId > UniqueId.next());
 
-      sequenceIdTable.put(SequenceIdType.localId.name(), localId);
-      LOG.info("upgrade {} to {}", SequenceIdType.localId, 
sequenceIdTable.get(SequenceIdType.localId.name()));
+      sequenceIdTable.put(SequenceIdType.localId, localId);
+      LOG.info("upgrade {} to {}", SequenceIdType.localId, 
sequenceIdTable.get(SequenceIdType.localId));
     }
 
     // upgrade delTxnId
-    if (sequenceIdTable.get(SequenceIdType.delTxnId.name()) == null) {
+    if (sequenceIdTable.get(SequenceIdType.delTxnId) == null) {
       // fetch delTxnId from DeletedBlocksTXTable
       // check HDDS-4477 for details.
       DeletedBlocksTransaction txn
           = scmMetadataStore.getDeletedBlocksTXTable().get(0L);
-      sequenceIdTable.put(SequenceIdType.delTxnId.name(), txn != null ? 
txn.getTxID() : 0L);
-      LOG.info("upgrade {} to {}", SequenceIdType.delTxnId, 
sequenceIdTable.get(SequenceIdType.delTxnId.name()));
+      sequenceIdTable.put(SequenceIdType.delTxnId, txn != null ? txn.getTxID() 
: 0L);
+      LOG.info("upgrade {} to {}", SequenceIdType.delTxnId, 
sequenceIdTable.get(SequenceIdType.delTxnId));
     }
 
     // upgrade containerId
-    if (sequenceIdTable.get(SequenceIdType.containerId.name()) == null) {
+    if (sequenceIdTable.get(SequenceIdType.containerId) == null) {
       long largestContainerId = 0;
       try (TableIterator<ContainerID, ContainerInfo> iterator
           = scmMetadataStore.getContainerTable().valueIterator()) {
@@ -378,9 +378,9 @@ public static void upgradeToSequenceId(SCMMetadataStore 
scmMetadataStore)
         }
       }
 
-      sequenceIdTable.put(SequenceIdType.containerId.name(), 
largestContainerId);
+      sequenceIdTable.put(SequenceIdType.containerId, largestContainerId);
       LOG.info("upgrade {} to {}",
-          SequenceIdType.containerId, 
sequenceIdTable.get(SequenceIdType.containerId.name()));
+          SequenceIdType.containerId, 
sequenceIdTable.get(SequenceIdType.containerId));
     }
 
     upgradeToCertificateSequenceId(scmMetadataStore, false);
@@ -388,10 +388,10 @@ public static void upgradeToSequenceId(SCMMetadataStore 
scmMetadataStore)
 
   public static void upgradeToCertificateSequenceId(
       SCMMetadataStore scmMetadataStore, boolean force) throws IOException {
-    Table<String, Long> sequenceIdTable = 
scmMetadataStore.getSequenceIdTable();
+    Table<SequenceIdType, Long> sequenceIdTable = 
scmMetadataStore.getSequenceIdTable();
 
     // upgrade certificate ID table
-    if (sequenceIdTable.get(SequenceIdType.CertificateId.name()) == null || 
force) {
+    if (sequenceIdTable.get(SequenceIdType.CertificateId) == null || force) {
       // Start from ID 2.
       // ID 1 - root certificate, ID 2 - first SCM certificate.
       long largestCertId = BigInteger.ONE.add(BigInteger.ONE).longValueExact();
@@ -413,15 +413,15 @@ public static void upgradeToCertificateSequenceId(
         }
       }
 
-      sequenceIdTable.put(SequenceIdType.CertificateId.name(), largestCertId);
+      sequenceIdTable.put(SequenceIdType.CertificateId, largestCertId);
       LOG.info("upgrade {} to {}", SequenceIdType.CertificateId,
-          sequenceIdTable.get(SequenceIdType.CertificateId.name()));
+          sequenceIdTable.get(SequenceIdType.CertificateId));
     }
 
     // delete the ROOT_CERTIFICATE_ID record if exists
     // ROOT_CERTIFICATE_ID is replaced with CERTIFICATE_ID now
-    if (sequenceIdTable.get(SequenceIdType.rootCertificateId.name()) != null) {
-      sequenceIdTable.delete(SequenceIdType.rootCertificateId.name());
+    if (sequenceIdTable.get(SequenceIdType.rootCertificateId) != null) {
+      sequenceIdTable.delete(SequenceIdType.rootCertificateId);
     }
   }
 
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
deleted file mode 100644
index 4b80e3feef4..00000000000
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdType.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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;
-
-/**
- * Represents the sequence ID types managed by {@link SequenceIdGenerator}
- * The enum constant names are kept exactly as their persisted RocksDB keys.
- */
-public enum SequenceIdType {
-
-  localId,
-  delTxnId,
-  containerId,
-
-  /**
-   * Certificate ID for all services, including root certificates.
-   */
-  CertificateId,
-
-  /**
-   * @deprecated Use {@link #CertificateId} instead.
-   */
-  @Deprecated
-  rootCertificateId;
-
-}
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMDBDefinition.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMDBDefinition.java
index 4aae413c0c2..3b22a9f528e 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMDBDefinition.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMDBDefinition.java
@@ -26,6 +26,7 @@
 import org.apache.hadoop.hdds.scm.container.ContainerID;
 import org.apache.hadoop.hdds.scm.container.ContainerInfo;
 import org.apache.hadoop.hdds.scm.container.common.helpers.MoveDataNodePair;
+import org.apache.hadoop.hdds.scm.ha.SequenceIdType;
 import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
 import org.apache.hadoop.hdds.scm.pipeline.PipelineID;
 import org.apache.hadoop.hdds.utils.TransactionInfo;
@@ -82,11 +83,11 @@ public class SCMDBDefinition extends DBDefinition.WithMap {
           StringCodec.get(),
           TransactionInfo.getCodec());
 
-  public static final DBColumnFamilyDefinition<String, Long>
+  public static final DBColumnFamilyDefinition<SequenceIdType, Long>
       SEQUENCE_ID =
       new DBColumnFamilyDefinition<>(
           "sequenceId",
-          StringCodec.get(),
+          SequenceIdType.getCodec(),
           LongCodec.get());
 
   public static final DBColumnFamilyDefinition<ContainerID,
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreImpl.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreImpl.java
index 254ce10edbe..f6f8a40ad5b 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreImpl.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreImpl.java
@@ -41,6 +41,7 @@
 import org.apache.hadoop.hdds.scm.container.ContainerID;
 import org.apache.hadoop.hdds.scm.container.ContainerInfo;
 import org.apache.hadoop.hdds.scm.container.common.helpers.MoveDataNodePair;
+import org.apache.hadoop.hdds.scm.ha.SequenceIdType;
 import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
 import org.apache.hadoop.hdds.scm.pipeline.PipelineID;
 import org.apache.hadoop.hdds.utils.HAUtils;
@@ -71,7 +72,7 @@ public class SCMMetadataStoreImpl implements SCMMetadataStore 
{
 
   private Table<String, TransactionInfo> transactionInfoTable;
 
-  private Table<String, Long> sequenceIdTable;
+  private Table<SequenceIdType, Long> sequenceIdTable;
 
   private Table<ContainerID, MoveDataNodePair> moveTable;
 
@@ -214,7 +215,7 @@ public Table<ContainerID, ContainerInfo> 
getContainerTable() {
   }
 
   @Override
-  public Table<String, Long> getSequenceIdTable() {
+  public Table<SequenceIdType, Long> getSequenceIdTable() {
     return sequenceIdTable;
   }
 
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 f7d8b1c499a..1f07927a49d 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
@@ -156,7 +156,7 @@ public void 
testSequenceIDGenUponRatisWhenCurrentScmIsNotALeader()
         conf, scmHAManager, scmMetadataStore.getSequenceIdTable()) {
       @Override
       public StateManager createStateManager(
-          SCMHAManager scmhaManager, Table<String, Long> sequenceIdTable) {
+          SCMHAManager scmhaManager, Table<SequenceIdType, Long> 
sequenceIdTable) {
         Objects.requireNonNull(scmhaManager, "scmhaManager == null");
         return stateManager;
       }
@@ -227,7 +227,7 @@ public void testReinitializePopulatesSequenceIdMapFromDB() 
throws Exception {
 
     SequenceIdType idType = SequenceIdType.containerId;
     // Simulate an SCM restart by writing a raw String directly to the 
database.
-    scmMetadataStore.getSequenceIdTable().put(idType.name(), 100L);
+    scmMetadataStore.getSequenceIdTable().put(idType, 100L);
 
     // Create the StateManager directly using its Builder
     SequenceIdGenerator.StateManager stateManager =
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/metadata/TestSequenceIdTypeCodec.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/metadata/TestSequenceIdTypeCodec.java
new file mode 100644
index 00000000000..846c4e3a431
--- /dev/null
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/metadata/TestSequenceIdTypeCodec.java
@@ -0,0 +1,78 @@
+/*
+ * 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.metadata;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.hadoop.hdds.scm.ha.SequenceIdType;
+import org.apache.hadoop.hdds.utils.db.Codec;
+import org.apache.hadoop.hdds.utils.db.CodecTestUtil;
+import org.apache.hadoop.hdds.utils.db.StringCodec;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Testing serialization and deserialization of SequenceIdType objects to/from 
RocksDB.
+ */
+public class TestSequenceIdTypeCodec {
+
+  private final Codec<SequenceIdType> enumCodec = SequenceIdType.getCodec();
+  private final Codec<String> stringCodec = StringCodec.get();
+
+  @Test
+  public void testCodecBuffersWithOzoneTestUtil() throws Exception {
+    for (SequenceIdType type : SequenceIdType.values()) {
+      // Verify codec compatibility with heap and direct byte buffers.
+      CodecTestUtil.runTest(enumCodec, type, type.getByteArray().length, null);
+    }
+  }
+
+  @Test
+  public void testSerializedBytesMatchStringCodec() throws Exception {
+    for (SequenceIdType type : SequenceIdType.values()) {
+      byte[] expectedStringBytes = stringCodec.toPersistedFormat(type.name());
+      byte[] computedEnumBytes = enumCodec.toPersistedFormat(type);
+
+      // Verify exact match for on-disk binary format representation.
+      assertArrayEquals(expectedStringBytes, computedEnumBytes,
+          "Serialized bytes must match the StringCodec exactly");
+    }
+  }
+
+  @Test
+  public void testSequenceIdTypeCodecCanReadStringCodecBytes() throws 
Exception {
+    for (SequenceIdType type : SequenceIdType.values()) {
+      byte[] legacyBytes = stringCodec.toPersistedFormat(type.name());
+
+      // Verify deserialization compatibility for cluster upgrade path.
+      SequenceIdType decodedEnum = enumCodec.fromPersistedFormat(legacyBytes);
+      assertEquals(type, decodedEnum, "SequenceIdTypeCodec failed to read 
legacy string bytes");
+    }
+  }
+
+  @Test
+  public void testStringCodecCanReadSequenceIdTypeCodecBytes() throws 
Exception {
+    for (SequenceIdType type : SequenceIdType.values()) {
+      byte[] newBytes = enumCodec.toPersistedFormat(type);
+
+      // Verify deserialization compatibility for cluster downgrade path.
+      String decodedString = stringCodec.fromPersistedFormat(newBytes);
+      assertEquals(type.name(), decodedString, "StringCodec failed to read new 
enum bytes");
+    }
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to