Skip to content

Comments

HBASE-29756: Programmatically register related co-processor during initialization#7743

Open
sharmaar12 wants to merge 3 commits intoapache:HBASE-29081from
sharmaar12:prog_reg_cop
Open

HBASE-29756: Programmatically register related co-processor during initialization#7743
sharmaar12 wants to merge 3 commits intoapache:HBASE-29081from
sharmaar12:prog_reg_cop

Conversation

@sharmaar12
Copy link

No description provided.

@sharmaar12 sharmaar12 marked this pull request as ready for review February 12, 2026 15:15
Copy link
Contributor

@anmolnar anmolnar left a comment

Choose a reason for hiding this comment

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

Please see my comment.

LOG.info("Updated {} readOnlyEnabled={}", this.getClass().getName(),
readOnlyEnabledFromConfig);
if (this.masterServices != null) {
manageActiveClusterIdFile(readOnlyEnabledFromConfig);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there's an issue with this approach.

  1. We talked about briefly that the local globalReadOnlyEnabled is not needed anymore, because coprocs will be loaded only when R/O mode is enabled. So, I think you should remove the field in this patch.
  2. As a consequence this method will always be called with readOnlyEnabledFromConfig == true and the active cluster id file will never be removed.

I suggest to make this method static and call it from HMaster at line 4440. You don't need to resolve the coproc, just call the static method directly with the new configuration and do the management of cluster id file.

Copy link
Author

Choose a reason for hiding this comment

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

Noted and Done.

Copy link
Contributor

@kgeisz kgeisz left a comment

Choose a reason for hiding this comment

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

LGTM aside from @anmolnar's comment

@sharmaar12 sharmaar12 requested a review from anmolnar February 20, 2026 19:09
addReadOnlyCoprocessors(this.baseConf);
addReadOnlyCoprocessors(this.conf);
} else {
removeReadOnlyCoprocessors(this.baseConf);
Copy link
Author

Choose a reason for hiding this comment

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

We need to add this to introduce the REGION_COPROCESSOR_CONF_KEY property in the conf object, which is instance of CompoundConfiguration. This is needed because if the property is not present as a local copy in CompoundConfiguration then updating it using setStrings does not work so though Coprocessors are not needed still the property must be set to empty collection.

this.conf.setBoolean(HConstants.HBASE_GLOBAL_READONLY_ENABLED_KEY, readOnlyMode);
// If readonly is true then add the coprocessor of master
if (readOnlyMode) {
addReadOnlyCoprocessors(this.baseConf);
Copy link
Author

@sharmaar12 sharmaar12 Feb 20, 2026

Choose a reason for hiding this comment

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

We must sync both conf as well as baseConf object because baseConf is used when new table/region is created and synching just conf will make the new table to use initial value with which the cluster started. This is also important when region split happens as in the split baseConf gets used instead of conf object.

// remove the coprocessors
// Also conf.unset will not have any effect on CompoundConfiguration, unlike with Hmaster and
// HRegionServer
conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, new String[0]);
Copy link
Author

Choose a reason for hiding this comment

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

We have to explicitly use setStrings instead of conf.unset() because unset does not work with CompoundConfiguration (shallow copy), as setting it to null or using unset has no effect on CompoundConfiguration.

Copy link
Contributor

@anmolnar anmolnar left a comment

Choose a reason for hiding this comment

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

See my initial review feedback.

Comment on lines +1092 to +1093
conf.getBoolean(HConstants.HBASE_GLOBAL_READONLY_ENABLED_KEY,
HConstants.HBASE_GLOBAL_READONLY_ENABLED_DEFAULT)
Copy link
Contributor

Choose a reason for hiding this comment

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

You might want to extract this to separate method:

public boolean isGlobalReadonlyEnabled(Configuration conf) {
  return conf.getBoolean(HConstants.HBASE_GLOBAL_READONLY_ENABLED_KEY,
          HConstants.HBASE_GLOBAL_READONLY_ENABLED_DEFAULT);
}

Comment on lines +4439 to +4440
// Needed as safety measure in case the coprocessors are added in hbase-site.xml manually and
// the user toggles the read only mode on and off.
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes me a bit concerned. Since we deliver this feature, adding read-only coprocessors to hbase-site.xml will be invalid configuration. Why would like to implement this workaround for it?

Comment on lines +4436 to +4438
if (readOnlyMode) {
addReadOnlyCoprocessors(newConf);
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

You've repeated the same logic that you already implemented in syncReadOnlyConfigurations() method. Call it here instead.

Comment on lines +4565 to +4570
final int length = null == masterCoprocs ? 0 : masterCoprocs.length;
String[] updatedCoprocs = new String[length + 1];
if (length > 0) {
System.arraycopy(masterCoprocs, 0, updatedCoprocs, 0, masterCoprocs.length);
}
updatedCoprocs[length] = MasterReadOnlyController.class.getName();
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of juggling with arrays here, you can just use generic type ArrayList and call toArray() method at the end.

Comment on lines +1309 to +1314
private String[] append(String[] original, String value) {
String[] updated = new String[original.length + 1];
System.arraycopy(original, 0, updated, 0, original.length);
updated[original.length] = value;
return updated;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Again. Generic type ArrayList has been invented to provide higher level convenience methods over low level arrays. Feel free to use it and convert it back to array[] once you finished the processing.

StringBuilder could be another useful high level abstraction for the logic here.

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