diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneManagerVersion.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneManagerVersion.java index 982b559c7a58..1943d84817fa 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneManagerVersion.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneManagerVersion.java @@ -55,10 +55,26 @@ public enum OzoneManagerVersion implements ComponentVersion { private static final Map BY_PROTO_VALUE = Arrays.stream(values()) .collect(toMap(OzoneManagerVersion::toProtoValue, identity())); - + private static final long SUPPORTED_FEATURE_BITMAP = calculateVersionBitmap(); private final int version; private final String description; + /** + * This is limited to 63 because the version bitmap is stored in a `long` type, + * which has 64 bits. One bit is reserved for each version number, starting from 0. + * Therefore, the highest representable version number is 63. + */ + public static final int MAX_SUPPORTED_VERSION = 63; + + static { + for (OzoneManagerVersion version : OzoneManagerVersion.values()) { + if (version.toProtoValue() > MAX_SUPPORTED_VERSION) { + throw new IllegalStateException( + "Version " + version + " exceeds the maximum supported version: " + MAX_SUPPORTED_VERSION); + } + } + } + OzoneManagerVersion(int version, String description) { this.version = version; this.description = description; @@ -82,4 +98,44 @@ private static OzoneManagerVersion latest() { OzoneManagerVersion[] versions = OzoneManagerVersion.values(); return versions[versions.length - 2]; } + + /** + * Checks if the given feature version is supported by the OM Service. + * + * @param omFeatureBitmap The feature bitmap from the remote OM. + * @param checkedFeature The feature to check. + * @return true if the feature is supported, false otherwise. + */ + public static boolean isOmFeatureSupported(long omFeatureBitmap, OzoneManagerVersion checkedFeature) { + if (checkedFeature.toProtoValue() < 0) { + return false; + } + return (omFeatureBitmap & (1L << checkedFeature .toProtoValue())) != 0; + } + + /** + * Get the current bitmap representing supported features. + * + * @return The bitmap of supported features. + */ + public static long getSupportedFeatureBitmap() { + return SUPPORTED_FEATURE_BITMAP; + } + + /** + * Calculate the version bitmap. Each bit position corresponds to a version. + * Example: Version 0 -> bit 0, Version 1 -> bit 1, etc. + * Note: + * - Uses a 64-bit `long`, supporting versions 0 to 63. + * - Versions beyond 63 are not supported. + */ + private static long calculateVersionBitmap() { + long bitmap = 0L; + for (OzoneManagerVersion version : values()) { + if (version.version >= 0) { // Ignore FUTURE_VERSION (-1) + bitmap |= (1L << version.version); + } + } + return bitmap; + } } diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/TestComponentVersionInvariants.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/TestComponentVersionInvariants.java index d5524688a64f..aef7e869f4ed 100644 --- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/TestComponentVersionInvariants.java +++ b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/TestComponentVersionInvariants.java @@ -26,6 +26,8 @@ import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.params.provider.Arguments.arguments; /** @@ -93,4 +95,26 @@ public void testAssignedProtoRepresentations( } assertEquals(values.length, ++startValue); } + + @ParameterizedTest + @MethodSource("values") + public void testSupportedFeatureBitmapIncludesAllVersions( + ComponentVersion[] values) { + if (values[0] instanceof OzoneManagerVersion) { + long expectedBitmap = 0L; + for (ComponentVersion version : values) { + int versionValue = version.toProtoValue(); + if (versionValue >= 0) { // Ignore FUTURE_VERSION (-1) + assertTrue(OzoneManagerVersion.isOmFeatureSupported( + OzoneManagerVersion.getSupportedFeatureBitmap(), (OzoneManagerVersion) version)); + expectedBitmap |= (1L << versionValue); + } else { + assertFalse(OzoneManagerVersion.isOmFeatureSupported( + OzoneManagerVersion.getSupportedFeatureBitmap(), (OzoneManagerVersion) version)); + } + } + assertEquals(expectedBitmap, OzoneManagerVersion.getSupportedFeatureBitmap(), + "The SUPPORTED_FEATURE_BITMAP should correctly represent all supported features."); + } + } } diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/KeyOutputStream.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/KeyOutputStream.java index 4f9e5db49a92..73993fb72874 100644 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/KeyOutputStream.java +++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/KeyOutputStream.java @@ -50,6 +50,7 @@ import org.apache.hadoop.io.retry.RetryPolicies; import org.apache.hadoop.io.retry.RetryPolicy; import org.apache.hadoop.ozone.OzoneManagerVersion; +import org.apache.hadoop.ozone.client.rpc.RpcClient; import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo; import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfoGroup; import org.apache.hadoop.ozone.om.helpers.OmMultipartCommitUploadPartInfo; @@ -113,6 +114,7 @@ enum StreamAction { private boolean atomicKeyCreation; private ContainerClientMetrics clientMetrics; private OzoneManagerVersion ozoneManagerVersion; + private long omSupportedFeatureBitmap; private final Lock writeLock = new ReentrantLock(); private final Condition retryHandlingCondition = writeLock.newCondition(); @@ -191,6 +193,7 @@ public KeyOutputStream(Builder b) { this.streamBufferArgs = b.getStreamBufferArgs(); this.clientMetrics = b.getClientMetrics(); this.ozoneManagerVersion = b.ozoneManagerVersion; + this.omSupportedFeatureBitmap = b.omSupportedFeatureBitmap; } /** @@ -540,10 +543,11 @@ public void hsync() throws IOException { throw new UnsupportedOperationException("The replication factor = " + replication.getRequiredNodes() + " <= 1"); } - if (ozoneManagerVersion.compareTo(OzoneManagerVersion.HBASE_SUPPORT) < 0) { - throw new UnsupportedOperationException("Hsync API requires OM version " - + OzoneManagerVersion.HBASE_SUPPORT + " or later. Current OM version " - + ozoneManagerVersion); + if (RpcClient.isOmFeatureSupported( + omSupportedFeatureBitmap, ozoneManagerVersion, OzoneManagerVersion.HBASE_SUPPORT)) { + throw new UnsupportedOperationException("Hsync API requires OM feature " + + OzoneManagerVersion.HBASE_SUPPORT + ". Current OM feature " + + omSupportedFeatureBitmap); } checkNotClosed(); final long hsyncPos = writeOffset; @@ -707,6 +711,7 @@ public static class Builder { private StreamBufferArgs streamBufferArgs; private Supplier executorServiceSupplier; private OzoneManagerVersion ozoneManagerVersion; + private long omSupportedFeatureBitmap; public String getMultipartUploadID() { return multipartUploadID; @@ -834,6 +839,11 @@ public Builder setOmVersion(OzoneManagerVersion omVersion) { return this; } + public Builder setOmSupportedFeatureBitmap(long featureBitmap) { + omSupportedFeatureBitmap = featureBitmap; + return this; + } + public OzoneManagerVersion getOmVersion() { return ozoneManagerVersion; } diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java index fe9866401765..aaeebdd53f4c 100644 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java +++ b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java @@ -224,6 +224,7 @@ public class RpcClient implements ClientProtocol { private final ByteBufferPool byteBufferPool; private final BlockInputStreamFactory blockInputStreamFactory; private final OzoneManagerVersion omVersion; + private final long omSupportedFeatureBitmap; private final MemoizedSupplier ecReconstructExecutor; private final ContainerClientMetrics clientMetrics; private final MemoizedSupplier writeExecutor; @@ -272,6 +273,7 @@ public RpcClient(ConfigurationSource conf, String omServiceId) dtService = omTransport.getDelegationTokenService(); ServiceInfoEx serviceInfoEx = ozoneManagerClient.getServiceInfo(); omVersion = getOmVersion(serviceInfoEx); + omSupportedFeatureBitmap = getOMSupportedFeatureBitmap(serviceInfoEx); if (OzoneSecurityUtil.isSecurityEnabled(conf)) { // If the client is authenticating using S3 style auth, all future // requests serviced by this client will need S3 Auth set. @@ -364,6 +366,20 @@ public static OzoneManagerVersion getOmVersion(ServiceInfoEx info) { return version; } + public static long getOMSupportedFeatureBitmap(ServiceInfoEx info) { + long omSupportedFeatureBitmap = 0; + for (ServiceInfo si : info.getServiceInfoList()) { + if (si.getNodeType() == HddsProtos.NodeType.OM) { + long current = si.getProtobuf().getSupportedFeatureBitmap(); + if (current > 0) { + omSupportedFeatureBitmap = current; + } + } + } + LOG.trace("Ozone Manager Supported Feature Bitmap is {}", omSupportedFeatureBitmap); + return omSupportedFeatureBitmap; + } + static boolean validateOmVersion(OzoneManagerVersion minimumVersion, List serviceInfoList) { if (minimumVersion == OzoneManagerVersion.FUTURE_VERSION) { @@ -625,6 +641,21 @@ public void createBucket(String volumeName, String bucketName) BucketArgs.newBuilder().build()); } + public static boolean isOmFeatureSupported(long omSupportedFeatureBitmap, OzoneManagerVersion omVersion, + OzoneManagerVersion checkedFeature) { + if (omSupportedFeatureBitmap > 0) { + // For the OM which support the "FeatureBitmap" + return OzoneManagerVersion.isOmFeatureSupported(omSupportedFeatureBitmap, checkedFeature); + } else { + // For the old OM which not support "FeatureBitmap~", fallback to use omVersion + return omVersion.compareTo(checkedFeature) >= 0; + } + } + + private boolean isOmFeatureSupported(OzoneManagerVersion checkedFeature) { + return isOmFeatureSupported(omSupportedFeatureBitmap, omVersion, checkedFeature); + } + @Override public void createBucket( String volumeName, String bucketName, BucketArgs bucketArgs) @@ -634,8 +665,7 @@ public void createBucket( Preconditions.checkNotNull(bucketArgs); verifyCountsQuota(bucketArgs.getQuotaInNamespace()); verifySpaceQuota(bucketArgs.getQuotaInBytes()); - if (omVersion - .compareTo(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT)) { if (bucketArgs.getDefaultReplicationConfig() != null && bucketArgs.getDefaultReplicationConfig().getType() == ReplicationType.EC) { @@ -1291,8 +1321,7 @@ public void setReplicationConfig( verifyVolumeName(volumeName); verifyBucketName(bucketName); Preconditions.checkNotNull(replicationConfig); - if (omVersion - .compareTo(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT)) { if (replicationConfig.getReplicationType() == HddsProtos.ReplicationType.EC) { throw new IOException("Can not set the default replication of the" @@ -1411,7 +1440,7 @@ public OzoneOutputStream createKey( Map metadata, Map tags) throws IOException { createKeyPreChecks(volumeName, bucketName, keyName, replicationConfig); - if (omVersion.compareTo(OzoneManagerVersion.OBJECT_TAG) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.OBJECT_TAG)) { if (tags != null && !tags.isEmpty()) { throw new IOException("OzoneManager does not support object tags"); } @@ -1446,7 +1475,7 @@ public OzoneOutputStream createKey( public OzoneOutputStream rewriteKey(String volumeName, String bucketName, String keyName, long size, long existingKeyGeneration, ReplicationConfig replicationConfig, Map metadata) throws IOException { - if (omVersion.compareTo(OzoneManagerVersion.ATOMIC_REWRITE_KEY) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.ATOMIC_REWRITE_KEY)) { throw new IOException("OzoneManager does not support atomic key rewrite."); } @@ -1481,8 +1510,7 @@ private void createKeyPreChecks(String volumeName, String bucketName, String key HddsClientUtils.verifyKeyName(keyName); } HddsClientUtils.checkNotNull(keyName); - if (omVersion - .compareTo(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT)) { if (replicationConfig != null && replicationConfig.getReplicationType() == HddsProtos.ReplicationType.EC) { @@ -1519,7 +1547,7 @@ public OzoneDataStreamOutput createStreamKey( } HddsClientUtils.checkNotNull(keyName); - if (omVersion.compareTo(OzoneManagerVersion.OBJECT_TAG) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.OBJECT_TAG)) { if (tags != null && !tags.isEmpty()) { throw new IOException("OzoneManager does not support object tags"); } @@ -1740,7 +1768,7 @@ public List listKeys(String volumeName, String bucketName, int maxListResult) throws IOException { - if (omVersion.compareTo(OzoneManagerVersion.LIGHTWEIGHT_LIST_KEYS) >= 0) { + if (isOmFeatureSupported(OzoneManagerVersion.LIGHTWEIGHT_LIST_KEYS)) { List keys = ozoneManagerClient.listKeysLight( volumeName, bucketName, prevKey, keyPrefix, maxListResult).getKeys(); @@ -1869,7 +1897,7 @@ private OmKeyInfo getKeyInfo( private OmKeyInfo getKeyInfo(OmKeyArgs keyArgs) throws IOException { final OmKeyInfo keyInfo; - if (omVersion.compareTo(OzoneManagerVersion.OPTIMIZED_GET_KEY_INFO) >= 0) { + if (isOmFeatureSupported(OzoneManagerVersion.OPTIMIZED_GET_KEY_INFO)) { keyInfo = ozoneManagerClient.getKeyInfo(keyArgs, false) .getKeyInfo(); } else { @@ -1934,8 +1962,7 @@ public OmMultipartInfo initiateMultipartUpload(String volumeName, verifyBucketName(bucketName); HddsClientUtils.checkNotNull(keyName); String ownerName = getRealUserInfo().getShortUserName(); - if (omVersion - .compareTo(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT)) { if (replicationConfig != null && replicationConfig.getReplicationType() == HddsProtos.ReplicationType.EC) { throw new IOException("Can not set the replication of the file to" @@ -1944,7 +1971,7 @@ public OmMultipartInfo initiateMultipartUpload(String volumeName, } } - if (omVersion.compareTo(OzoneManagerVersion.OBJECT_TAG) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.OBJECT_TAG)) { if (tags != null && !tags.isEmpty()) { throw new IOException("OzoneManager does not support object tags"); } @@ -2186,7 +2213,7 @@ public OzoneInputStream readFile(String volumeName, String bucketName, .setLatestVersionLocation(getLatestVersionLocation) .build(); final OmKeyInfo keyInfo; - if (omVersion.compareTo(OzoneManagerVersion.OPTIMIZED_GET_KEY_INFO) >= 0) { + if (isOmFeatureSupported(OzoneManagerVersion.OPTIMIZED_GET_KEY_INFO)) { keyInfo = ozoneManagerClient.getKeyInfo(keyArgs, false) .getKeyInfo(); if (!keyInfo.isFile()) { @@ -2234,8 +2261,7 @@ private OzoneInputStream getInputStreamWithRetryFunction( public OzoneOutputStream createFile(String volumeName, String bucketName, String keyName, long size, ReplicationConfig replicationConfig, boolean overWrite, boolean recursive) throws IOException { - if (omVersion - .compareTo(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT) < 0) { + if (!isOmFeatureSupported(OzoneManagerVersion.ERASURE_CODED_STORAGE_SUPPORT)) { if (replicationConfig.getReplicationType() == HddsProtos.ReplicationType.EC) { throw new IOException("Can not set the replication of the file to" @@ -2316,7 +2342,7 @@ public List listStatusLight(String volumeName, String bucketName, String keyName, boolean recursive, String startKey, long numEntries, boolean allowPartialPrefixes) throws IOException { OmKeyArgs keyArgs = prepareOmKeyArgs(volumeName, bucketName, keyName); - if (omVersion.compareTo(OzoneManagerVersion.LIGHTWEIGHT_LIST_STATUS) >= 0) { + if (isOmFeatureSupported(OzoneManagerVersion.LIGHTWEIGHT_LIST_STATUS)) { return ozoneManagerClient.listStatusLight(keyArgs, recursive, startKey, numEntries, allowPartialPrefixes); } else { @@ -2562,7 +2588,8 @@ private KeyOutputStream.Builder createKeyOutputStream( .setClientMetrics(clientMetrics) .setExecutorServiceSupplier(writeExecutor) .setStreamBufferArgs(streamBufferArgs) - .setOmVersion(omVersion); + .setOmVersion(omVersion) + .setOmSupportedFeatureBitmap(omSupportedFeatureBitmap); } @Override @@ -2709,20 +2736,20 @@ public void setTimes(OzoneObj obj, String keyName, long mtime, long atime) public LeaseKeyInfo recoverLease(String volumeName, String bucketName, String keyName, boolean force) throws IOException { - if (omVersion.compareTo(OzoneManagerVersion.HBASE_SUPPORT) < 0) { - throw new UnsupportedOperationException("Lease recovery API requires OM version " - + OzoneManagerVersion.HBASE_SUPPORT + " or later. Current OM version " - + omVersion); + if (!isOmFeatureSupported(OzoneManagerVersion.HBASE_SUPPORT)) { + throw new UnsupportedOperationException("Lease recovery API requires OM feature " + + OzoneManagerVersion.HBASE_SUPPORT + ". Current OM support feature " + + omSupportedFeatureBitmap); } return ozoneManagerClient.recoverLease(volumeName, bucketName, keyName, force); } @Override public void recoverKey(OmKeyArgs args, long clientID) throws IOException { - if (omVersion.compareTo(OzoneManagerVersion.HBASE_SUPPORT) < 0) { - throw new UnsupportedOperationException("Lease recovery API requires OM version " - + OzoneManagerVersion.HBASE_SUPPORT + " or later. Current OM version " - + omVersion); + if (!isOmFeatureSupported(OzoneManagerVersion.HBASE_SUPPORT)) { + throw new UnsupportedOperationException("Lease recovery API requires OM feature " + + OzoneManagerVersion.HBASE_SUPPORT + ". Current OM support feature " + + omSupportedFeatureBitmap); } ozoneManagerClient.recoverKey(args, clientID); } diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java index 5dbe3487e19c..992db5d1abd3 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/ServiceInfo.java @@ -54,6 +54,11 @@ public final class ServiceInfo { */ private OzoneManagerVersion omVersion; + /** + * Bitmap for supported versions. + */ + private long supportedFeatureBitmap; + /** * List of ports the service listens to. */ @@ -67,20 +72,6 @@ public final class ServiceInfo { */ public ServiceInfo() { } - /** - * Constructs the ServiceInfo for the {@code nodeType}. - * @param nodeType type of node/service - * @param hostname hostname of the service - * @param portList list of ports the service listens to - */ - private ServiceInfo(NodeType nodeType, - String hostname, - List portList, - OzoneManagerVersion omVersion, - OMRoleInfo omRole) { - this(nodeType, hostname, portList, omVersion, omRole, null); - } - /** * Constructs the ServiceInfo for the {@code nodeType}. * @param nodeType type of node/service @@ -88,14 +79,15 @@ private ServiceInfo(NodeType nodeType, * @param portList list of ports the service listens to * @param omVersion Om Version * @param omRole OM role Ino - * @param keyProviderUri KMS provider URI + * @param serverDefaults server defaults + * @param supportedFeatureBitmap bitmap of supported feature */ private ServiceInfo(NodeType nodeType, String hostname, List portList, OzoneManagerVersion omVersion, OMRoleInfo omRole, - OzoneFsServerDefaults serverDefaults) { + OzoneFsServerDefaults serverDefaults, long supportedFeatureBitmap) { Preconditions.checkNotNull(nodeType); Preconditions.checkNotNull(hostname); this.nodeType = nodeType; @@ -107,6 +99,7 @@ private ServiceInfo(NodeType nodeType, } this.omRoleInfo = omRole; this.serverDefaults = serverDefaults; + this.supportedFeatureBitmap = supportedFeatureBitmap; } /** @@ -203,6 +196,7 @@ public OzoneManagerProtocolProtos.ServiceInfo getProtobuf() { if (serverDefaults != null) { builder.setServerDefaults(serverDefaults.getProtobuf()); } + builder.setSupportedFeatureBitmap(supportedFeatureBitmap); return builder.build(); } @@ -220,7 +214,8 @@ public static ServiceInfo getFromProtobuf( OzoneManagerVersion.fromProtoValue(serviceInfo.getOMVersion()), serviceInfo.hasOmRole() ? serviceInfo.getOmRole() : null, serviceInfo.hasServerDefaults() ? OzoneFsServerDefaults.getFromProtobuf( - serviceInfo.getServerDefaults()) : null); + serviceInfo.getServerDefaults()) : null, + serviceInfo.getSupportedFeatureBitmap()); } /** @@ -241,6 +236,7 @@ public static class Builder { private List portList = new ArrayList<>(); private OMRoleInfo omRoleInfo; private OzoneManagerVersion omVersion; + private long supportedFeatureBitmap; private OzoneFsServerDefaults serverDefaults; /** @@ -300,6 +296,11 @@ public Builder setServerDefaults(OzoneFsServerDefaults defaults) { return this; } + public Builder setSupportedFeatureBitmap(long featureBitmap) { + supportedFeatureBitmap = featureBitmap; + return this; + } + /** * Builds and returns {@link ServiceInfo} with the set values. * @return {@link ServiceInfo} @@ -310,7 +311,8 @@ public ServiceInfo build() { portList, omVersion, omRoleInfo, - serverDefaults); + serverDefaults, + supportedFeatureBitmap); } } diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index f71dc44fec51..c5e34c893681 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -1638,6 +1638,7 @@ message ServiceInfo { optional OMRoleInfo omRole = 4; optional int32 OMVersion = 5 [default = 0]; optional FsServerDefaultsProto serverDefaults = 6; + optional uint64 supportedFeatureBitmap = 7; } message MultipartInfoInitiateRequest { diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index e2acafdd2427..c8f73b3ae6c7 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -3133,6 +3133,7 @@ public List getServiceList() throws IOException { .setNodeType(HddsProtos.NodeType.OM) .setHostname(omRpcAddress.getHostName()) .setOmVersion(OzoneManagerVersion.CURRENT) + .setSupportedFeatureBitmap(OzoneManagerVersion.getSupportedFeatureBitmap()) .addServicePort(ServicePort.newBuilder() .setType(ServicePort.Type.RPC) .setValue(omRpcAddress.getPort()) @@ -3182,10 +3183,11 @@ public List getServiceList() throws IOException { ServiceInfo.Builder peerOmServiceInfoBuilder = ServiceInfo.newBuilder() .setNodeType(HddsProtos.NodeType.OM) .setHostname(peerNode.getHostName()) - // For now assume peer is at the same version. + // For now assume peer is at the same version and Features // This field needs to be fetched from peer when rolling upgrades // are implemented. .setOmVersion(OzoneManagerVersion.CURRENT) + .setSupportedFeatureBitmap(OzoneManagerVersion.getSupportedFeatureBitmap()) .addServicePort(ServicePort.newBuilder() .setType(ServicePort.Type.RPC) .setValue(peerNode.getRpcPort()) diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/ListOpenFilesSubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/ListOpenFilesSubCommand.java index 221f9f9a1c48..7cdaa3d137da 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/ListOpenFilesSubCommand.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/ListOpenFilesSubCommand.java @@ -117,7 +117,8 @@ public Void call() throws Exception { parent.createOmClient(omServiceId, omHost, false); ServiceInfoEx serviceInfoEx = ozoneManagerClient.getServiceInfo(); final OzoneManagerVersion omVersion = RpcClient.getOmVersion(serviceInfoEx); - if (omVersion.compareTo(OzoneManagerVersion.HBASE_SUPPORT) < 0) { + final long omSupportedFeatureBitmap = RpcClient.getOMSupportedFeatureBitmap(serviceInfoEx); + if (RpcClient.isOmFeatureSupported(omSupportedFeatureBitmap, omVersion, OzoneManagerVersion.HBASE_SUPPORT)) { System.err.println("Error: This command requires OzoneManager version " + OzoneManagerVersion.HBASE_SUPPORT.name() + " or later."); return null;