HBASE-29756: Programmatically register related co-processor during initialization#7743
HBASE-29756: Programmatically register related co-processor during initialization#7743sharmaar12 wants to merge 3 commits intoapache:HBASE-29081from
Conversation
b61c399 to
2909891
Compare
| LOG.info("Updated {} readOnlyEnabled={}", this.getClass().getName(), | ||
| readOnlyEnabledFromConfig); | ||
| if (this.masterServices != null) { | ||
| manageActiveClusterIdFile(readOnlyEnabledFromConfig); |
There was a problem hiding this comment.
I think there's an issue with this approach.
- We talked about briefly that the local
globalReadOnlyEnabledis 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. - As a consequence this method will always be called with
readOnlyEnabledFromConfig == trueand 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.
b04b6cb to
f3889b3
Compare
| addReadOnlyCoprocessors(this.baseConf); | ||
| addReadOnlyCoprocessors(this.conf); | ||
| } else { | ||
| removeReadOnlyCoprocessors(this.baseConf); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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]); |
There was a problem hiding this comment.
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.
anmolnar
left a comment
There was a problem hiding this comment.
See my initial review feedback.
| conf.getBoolean(HConstants.HBASE_GLOBAL_READONLY_ENABLED_KEY, | ||
| HConstants.HBASE_GLOBAL_READONLY_ENABLED_DEFAULT) |
There was a problem hiding this comment.
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);
}| // 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. |
There was a problem hiding this comment.
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?
| if (readOnlyMode) { | ||
| addReadOnlyCoprocessors(newConf); | ||
| } else { |
There was a problem hiding this comment.
You've repeated the same logic that you already implemented in syncReadOnlyConfigurations() method. Call it here instead.
| 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(); |
There was a problem hiding this comment.
Instead of juggling with arrays here, you can just use generic type ArrayList and call toArray() method at the end.
| 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; | ||
| } |
There was a problem hiding this comment.
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.
No description provided.