Skip to content

Conversation

@Jaehui-Lee
Copy link
Contributor

@Apache-HBase
Copy link

💔 -1 overall

Vote Subsystem Runtime Logfile Comment
+0 🆗 reexec 0m 0s Docker mode activated.
-1 ❌ docker 0m 2s Docker failed to build run-specific yetus/hbase:tp-16052}.
Subsystem Report/Notes
GITHUB PR #7544
Console output https://ci-hbase.apache.org/job/HBase-PreCommit-GitHub-PR/job/PR-7544/1/console
versions git=2.17.1
Powered by Apache Yetus 0.15.0 https://yetus.apache.org

This message was automatically generated.

@Apache-HBase
Copy link

🎊 +1 overall

Vote Subsystem Runtime Logfile Comment
+0 🆗 reexec 0m 33s Docker mode activated.
-0 ⚠️ yetus 0m 3s Unprocessed flag(s): --brief-report-file --spotbugs-strict-precheck --author-ignore-list --blanks-eol-ignore-file --blanks-tabs-ignore-file --quick-hadoopcheck
_ Prechecks _
_ branch-3 Compile Tests _
+1 💚 mvninstall 4m 28s branch-3 passed
+1 💚 compile 1m 17s branch-3 passed
+1 💚 javadoc 0m 36s branch-3 passed
+1 💚 shadedjars 7m 22s branch has no errors when building our shaded downstream artifacts.
_ Patch Compile Tests _
+1 💚 mvninstall 3m 48s the patch passed
+1 💚 compile 1m 9s the patch passed
+1 💚 javac 1m 9s the patch passed
+1 💚 javadoc 0m 33s the patch passed
+1 💚 shadedjars 6m 43s patch has no errors when building our shaded downstream artifacts.
_ Other Tests _
+1 💚 unit 248m 40s hbase-server in the patch passed.
280m 39s
Subsystem Report/Notes
Docker ClientAPI=1.43 ServerAPI=1.43 base: https://ci-hbase.apache.org/job/HBase-PreCommit-GitHub-PR/job/PR-7544/1/artifact/yetus-jdk17-hadoop3-check/output/Dockerfile
GITHUB PR #7544
Optional Tests javac javadoc unit compile shadedjars
uname Linux 520aae85814b 5.4.0-1103-aws #111~18.04.1-Ubuntu SMP Tue May 23 20:04:10 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
Build tool maven
Personality dev-support/hbase-personality.sh
git revision branch-3 / 63912c2
Default Java Eclipse Adoptium-17.0.11+9
Test Results https://ci-hbase.apache.org/job/HBase-PreCommit-GitHub-PR/job/PR-7544/1/testReport/
Max. process+thread count 3817 (vs. ulimit of 30000)
modules C: hbase-server U: hbase-server
Console output https://ci-hbase.apache.org/job/HBase-PreCommit-GitHub-PR/job/PR-7544/1/console
versions git=2.34.1 maven=3.9.8
Powered by Apache Yetus 0.15.0 https://yetus.apache.org

This message was automatically generated.

Copy link
Contributor

@taklwu taklwu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docker yetus failure is unrelated as reported in https://issues.apache.org/jira/browse/INFRA-27492, I will keep the PR open for another day and see if they can come back and look at the logs

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where dynamic configuration changes for coprocessors were not being properly detected and applied. The root cause was that the configuration change detection was comparing two Configuration objects instead of comparing the currently loaded coprocessors with the new configuration values.

Key Changes:

  • Refactored CoprocessorConfigurationUtil.checkConfigurationChange() to compare current loaded coprocessors against new configuration instead of comparing two configuration objects
  • Added getCoprocessorClassNames() method to CoprocessorHost to retrieve currently loaded coprocessor class names
  • Updated all call sites to pass the CoprocessorHost instance instead of the old Configuration object

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
hbase-server/src/main/java/org/apache/hadoop/hbase/util/CoprocessorConfigurationUtil.java Rewrote checkConfigurationChange() to compare current state vs new config; added hasCoprocessorsConfigured() helper method
hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java Added getCoprocessorClassNames() method to expose currently loaded coprocessor class names
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java Updated to pass rsHost instance instead of old configuration to checkConfigurationChange()
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java Updated to pass coprocessorHost instance instead of old configuration to checkConfigurationChange()
hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java Updated to pass cpHost instance instead of old configuration; inlined initializeCoprocessorHost() method
hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java Updated to pass cpHost instance instead of old configuration to checkConfigurationChange()
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionServerOnlineConfigChange.java Updated tests to modify the actual server configuration object to properly test dynamic configuration reload

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +96 to 104
private static boolean hasCoprocessorsConfigured(Configuration conf, String... configurationKey) {
for (String key : configurationKey) {
String oldValue = oldConfig.get(key);
String newValue = newConfig.get(key);
// check if the coprocessor key has any difference
if (!StringUtils.equalsIgnoreCase(oldValue, newValue)) {
isConfigurationChange = true;
break;
String[] coprocessors = conf.getStrings(key);
if (coprocessors != null && coprocessors.length > 0) {
return true;
}
}
return isConfigurationChange;
return false;
}
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hasCoprocessorsConfigured method should validate that the coprocessor strings contain actual class names, not just check if the array is non-empty. If the configuration contains empty strings or only whitespace, this method will incorrectly return true even though no valid coprocessors are configured. This is inconsistent with the logic in checkConfigurationChange (lines 78-84) which properly filters empty class names. The method should parse the className|priority|path format and check if the actual class name is non-empty after trimming.

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +71
if (
!conf.getBoolean(CoprocessorHost.COPROCESSORS_ENABLED_CONF_KEY,
CoprocessorHost.DEFAULT_COPROCESSORS_ENABLED)
) {
return false;
}

if (coprocessorHost == null) {
// If no coprocessor host exists, check if any coprocessors are now configured
return hasCoprocessorsConfigured(conf, configurationKey);
}

// Get currently loaded coprocessor class names
Set<String> currentlyLoaded = coprocessorHost.getCoprocessorClassNames();

Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When coprocessors are disabled in the new configuration (COPROCESSORS_ENABLED_CONF_KEY is false), this method returns false indicating no configuration change. However, if coprocessors were previously enabled and loaded, this prevents the coprocessor host from being recreated to unload those coprocessors. The method should return true if there's a mismatch between the current loaded state and the desired state, even when coprocessors are being disabled. Consider checking if currentlyLoaded is non-empty when coprocessors are disabled - that would indicate a change requiring coprocessor unloading.

Suggested change
if (
!conf.getBoolean(CoprocessorHost.COPROCESSORS_ENABLED_CONF_KEY,
CoprocessorHost.DEFAULT_COPROCESSORS_ENABLED)
) {
return false;
}
if (coprocessorHost == null) {
// If no coprocessor host exists, check if any coprocessors are now configured
return hasCoprocessorsConfigured(conf, configurationKey);
}
// Get currently loaded coprocessor class names
Set<String> currentlyLoaded = coprocessorHost.getCoprocessorClassNames();
if (coprocessorHost == null) {
// If no coprocessor host exists, check if any coprocessors are now configured
if (!conf.getBoolean(CoprocessorHost.COPROCESSORS_ENABLED_CONF_KEY,
CoprocessorHost.DEFAULT_COPROCESSORS_ENABLED)) {
// Coprocessors are disabled and none are loaded, so no change
return false;
}
return hasCoprocessorsConfigured(conf, configurationKey);
}
// Get currently loaded coprocessor class names
Set<String> currentlyLoaded = coprocessorHost.getCoprocessorClassNames();
if (!conf.getBoolean(CoprocessorHost.COPROCESSORS_ENABLED_CONF_KEY,
CoprocessorHost.DEFAULT_COPROCESSORS_ENABLED)) {
// Coprocessors are now disabled, but if any are currently loaded, we need to unload them
return !currentlyLoaded.isEmpty();
}

Copilot uses AI. Check for mistakes.
*/
public static boolean checkConfigurationChange(CoprocessorHost<?, ?> coprocessorHost,
Configuration conf, String... configurationKey) {
Preconditions.checkArgument(configurationKey != null, "Configuration Key(s) must be provided");
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The precondition check verifies that configurationKey is not null, but doesn't check if the array is empty. If an empty array is passed, the method will always return false (no change) even if coprocessors are currently loaded and should be unloaded. Consider adding a check for array length or documenting that an empty array is allowed and means "no configuration keys to check".

Suggested change
Preconditions.checkArgument(configurationKey != null, "Configuration Key(s) must be provided");
Preconditions.checkArgument(configurationKey != null, "Configuration Key(s) must be provided");
Preconditions.checkArgument(configurationKey.length > 0, "At least one configuration key must be provided");

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +91
public static boolean checkConfigurationChange(CoprocessorHost<?, ?> coprocessorHost,
Configuration conf, String... configurationKey) {
Preconditions.checkArgument(configurationKey != null, "Configuration Key(s) must be provided");
boolean isConfigurationChange = false;
Preconditions.checkArgument(conf != null, "Configuration must be provided");

if (
!conf.getBoolean(CoprocessorHost.COPROCESSORS_ENABLED_CONF_KEY,
CoprocessorHost.DEFAULT_COPROCESSORS_ENABLED)
) {
return false;
}

if (coprocessorHost == null) {
// If no coprocessor host exists, check if any coprocessors are now configured
return hasCoprocessorsConfigured(conf, configurationKey);
}

// Get currently loaded coprocessor class names
Set<String> currentlyLoaded = coprocessorHost.getCoprocessorClassNames();

// Get coprocessor class names from configuration
// Only class names are compared; priority and path changes are not detected
Set<String> configuredClasses = new HashSet<>();
for (String key : configurationKey) {
String[] classes = conf.getStrings(key);
if (classes != null) {
for (String className : classes) {
// Handle the className|priority|path format
String[] classNameToken = className.split("\\|");
String actualClassName = classNameToken[0].trim();
if (!Strings.isNullOrEmpty(actualClassName)) {
configuredClasses.add(actualClassName);
}
}
}
}

// Compare the two sets
return !currentlyLoaded.equals(configuredClasses);
}
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new checkConfigurationChange method lacks unit test coverage. While integration tests exist in TestRegionServerOnlineConfigChange, they don't cover important edge cases such as: (1) disabling coprocessors when some are loaded, (2) the null coprocessorHost path that calls hasCoprocessorsConfigured, (3) parsing of className|priority|path format, (4) removing coprocessors from configuration, and (5) empty or whitespace-only class names. Consider adding unit tests for CoprocessorConfigurationUtil to ensure these scenarios are properly handled.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants