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 886dd588e92 HDDS-14850. Implement StatefulService without reflection.. 
(#9940)
886dd588e92 is described below

commit 886dd588e92728b944590233fffaf1cdafc7d995
Author: Tsz-Wo Nicholas Sze <[email protected]>
AuthorDate: Wed Mar 18 00:11:18 2026 -0700

    HDDS-14850. Implement StatefulService without reflection.. (#9940)
---
 .../scm/container/balancer/ContainerBalancer.java  | 20 +++------
 .../apache/hadoop/hdds/scm/ha/ReflectionUtil.java  | 19 ---------
 .../apache/hadoop/hdds/scm/ha/StatefulService.java | 48 +++++++++-------------
 .../hdds/scm/security/RootCARotationManager.java   | 14 ++-----
 4 files changed, 29 insertions(+), 72 deletions(-)

diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java
index 2d3d7a3bc4b..03df1ff2087 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java
@@ -40,7 +40,7 @@
  * Container balancer is a service in SCM to move containers between over- and
  * under-utilized datanodes.
  */
-public class ContainerBalancer extends StatefulService {
+public class ContainerBalancer extends 
StatefulService<ContainerBalancerConfigurationProto> {
 
   private static final AtomicInteger ID = new AtomicInteger();
 
@@ -65,7 +65,8 @@ public class ContainerBalancer extends StatefulService {
    * @param scm the storage container manager
    */
   public ContainerBalancer(StorageContainerManager scm) {
-    super(scm.getStatefulServiceStateManager());
+    super(scm.getStatefulServiceStateManager(),
+        
ContainerBalancerConfigurationProto.getDefaultInstance().getParserForType());
     this.scm = scm;
     this.ozoneConfiguration = scm.getConfiguration();
     this.config = ozoneConfiguration.getObject(
@@ -131,8 +132,7 @@ public void notifyStatusChanged() {
   @Override
   public boolean shouldRun() {
     try {
-      ContainerBalancerConfigurationProto proto =
-          readConfiguration(ContainerBalancerConfigurationProto.class);
+      final ContainerBalancerConfigurationProto proto = readConfiguration();
       if (proto == null) {
         LOG.warn("Could not find persisted configuration for {} when checking" 
+
             " if ContainerBalancer should run. ContainerBalancer should not " +
@@ -208,14 +208,6 @@ private boolean canBalancerStop() {
     return isBalancerRunning();
   }
 
-  /**
-   * @return Name of this service.
-   */
-  @Override
-  public String getServiceName() {
-    return ContainerBalancer.class.getSimpleName();
-  }
-
   /**
    * Starts ContainerBalancer as an SCMService. Validates state, reads and
    * validates persisted configuration, and then starts the balancing
@@ -233,9 +225,9 @@ public void start() throws 
IllegalContainerBalancerStateException,
     try {
       // should be leader-ready, out of safe mode, and not running already
       validateState(false);
-      ContainerBalancerConfigurationProto proto;
+      final ContainerBalancerConfigurationProto proto;
       try {
-        proto = readConfiguration(ContainerBalancerConfigurationProto.class);
+        proto = readConfiguration();
       } catch (IOException e) {
         throw new InvalidContainerBalancerConfigurationException("Could not " +
             "retrieve persisted configuration while starting " +
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/ReflectionUtil.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/ReflectionUtil.java
index ba62d9ccbfc..e927166f2b2 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/ReflectionUtil.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/ReflectionUtil.java
@@ -17,7 +17,6 @@
 
 package org.apache.hadoop.hdds.scm.ha;
 
-import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -46,22 +45,4 @@ public static Class<?> getClass(String className)
     }
     return classCache.get(className);
   }
-
-  /**
-   * Returns a {@code Method} object that reflects the specified public
-   * member method of the given {@code Class} object.
-   *
-   * @param clazz the class object which has the method
-   * @param methodName the name of the method
-   * @param arg the list of parameters
-   * @return the {@code Method} object that matches the specified
-   *         {@code name} and {@code parameterTypes}
-   * @throws NoSuchMethodException if a matching method is not found
-   *         or if the name is "&lt;init&gt;"or "&lt;clinit&gt;".
-   */
-  public static Method getMethod(
-      final Class<?> clazz, final String methodName, final Class<?>... arg)
-      throws NoSuchMethodException {
-    return clazz.getMethod(methodName, arg);
-  }
 }
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/StatefulService.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/StatefulService.java
index e60bc5826e1..3343afe175e 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/StatefulService.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/StatefulService.java
@@ -19,66 +19,58 @@
 
 import com.google.protobuf.ByteString;
 import com.google.protobuf.Message;
+import com.google.protobuf.Parser;
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
 
 /**
  * A StatefulService is an SCMService that persists configuration to RocksDB.
- * The service must define this configuration as a Protobuf message.
+ *
+ * @param <CONF> The configuration type, which is a protobuf {@link Message}.
  */
-public abstract class StatefulService implements SCMService {
+public abstract class StatefulService<CONF extends Message> implements 
SCMService {
+  private final String name;
   private final StatefulServiceStateManager stateManager;
+  private final Parser<CONF> parser;
 
   /**
    * Initialize a StatefulService from an extending class.
    * @param stateManager a reference to the
    * {@link StatefulServiceStateManager} from SCM.
    */
-  protected StatefulService(StatefulServiceStateManager stateManager) {
+  protected StatefulService(StatefulServiceStateManager stateManager, 
Parser<CONF> parser) {
+    this.name = getClass().getSimpleName();
     this.stateManager = stateManager;
+    this.parser = parser;
+  }
+
+  @Override
+  public final String getServiceName() {
+    return name;
   }
 
   /**
-   * Persists the specified {@link Message} configurationMessage
-   * to RocksDB with this service's {@link SCMService#getServiceName()} as the
-   * key.
-   * @param configurationMessage configuration Message to persist
+   * Persists the given configuration to RocksDB with {@link 
SCMService#getServiceName()} as the key.
+   * @param configuration configuration to persist
    * @throws IOException on failure to persist configuration
    */
-  protected final void saveConfiguration(Message configurationMessage)
-      throws IOException {
-    stateManager.saveConfiguration(getServiceName(),
-        configurationMessage.toByteString());
+  protected final void saveConfiguration(CONF configuration) throws 
IOException {
+    stateManager.saveConfiguration(getServiceName(), 
configuration.toByteString());
   }
 
   /**
    * Reads persisted configuration mapped to this service's
    * {@link SCMService#getServiceName()} name.
    *
-   * @param configType the Class object of the protobuf message type
-   * @param <T>        the Type of the protobuf message
    * @return persisted protobuf message or null if the entry is not found
    * @throws IOException on failure to fetch the message from DB or when
    *                     parsing it. ensure the specified configType is correct
    */
-  protected final <T extends Message> T readConfiguration(
-      Class<T> configType) throws IOException {
+  protected final CONF readConfiguration() throws IOException {
     ByteString byteString = stateManager.readConfiguration(getServiceName());
     if (byteString == null) {
       return null;
     }
-    try {
-      return configType.cast(ReflectionUtil.getMethod(configType,
-              "parseFrom", ByteString.class)
-          .invoke(null, byteString));
-    } catch (NoSuchMethodException | IllegalAccessException
-        | InvocationTargetException e) {
-      e.printStackTrace();
-      throw new IOException("Message cannot be parsed. Ensure that "
-          + configType + " is the correct expected message type for " +
-          this.getServiceName(), e);
-    }
-
+    return parser.parseFrom(byteString);
   }
 
   /**
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 e20cf22cb18..10017d970fe 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
@@ -73,7 +73,7 @@
 /**
  * Root CA Rotation Service is a service in SCM to control the CA rotation.
  */
-public class RootCARotationManager extends StatefulService {
+public class RootCARotationManager extends StatefulService<CertInfoProto> {
 
   private static final Logger LOG =
       LoggerFactory.getLogger(RootCARotationManager.class);
@@ -137,7 +137,7 @@ public class RootCARotationManager extends StatefulService {
    *   (4) Rotation Committed
    */
   public RootCARotationManager(StorageContainerManager scm) {
-    super(scm.getStatefulServiceStateManager());
+    super(scm.getStatefulServiceStateManager(), 
CertInfoProto.getDefaultInstance().getParserForType());
     this.scm = scm;
     this.ozoneConf = scm.getConfiguration();
     this.secConf = new SecurityConfig(ozoneConf);
@@ -220,14 +220,6 @@ public boolean shouldRun() {
     return true;
   }
 
-  /**
-   * @return Name of this service.
-   */
-  @Override
-  public String getServiceName() {
-    return RootCARotationManager.class.getSimpleName();
-  }
-
   /**
    * Schedule monitor task.
    */
@@ -778,7 +770,7 @@ public boolean shouldSkipRootCert(String newRootCertId) 
throws IOException {
 
   private void checkAndHandlePostProcessing() throws IOException,
       CertificateException {
-    CertInfoProto proto = readConfiguration(CertInfoProto.class);
+    final CertInfoProto proto = readConfiguration();
     if (proto == null) {
       LOG.info("No {} configuration found in stateful storage",
           getServiceName());


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

Reply via email to