diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java index 46f8ec0..ae2fe5f 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java @@ -441,7 +441,7 @@ public class HTable implements HTableInterface { try { ClientProtos.GetResponse response = getStub().get(controller, request); if (response == null) return null; - return ProtobufUtil.toResult(response.getResult()); + return ProtobufUtil.toResult(response.getResult(), controller.cellScanner()); } catch (ServiceException se) { throw ProtobufUtil.getRemoteException(se); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.java index d610d8c..f4e2614 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.java @@ -161,7 +161,7 @@ public class RpcRetryingCallerWithReadReplicas { if (response == null) { return null; } - return ProtobufUtil.toResult(response.getResult()); + return ProtobufUtil.toResult(response.getResult(), controller.cellScanner()); } catch (ServiceException se) { throw ProtobufUtil.getRemoteException(se); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java index 1ffdfaf..3ed92be 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java @@ -3130,7 +3130,13 @@ public final class ProtobufUtil { */ public static RPCProtos.VersionInfo getVersionInfo() { RPCProtos.VersionInfo.Builder builder = RPCProtos.VersionInfo.newBuilder(); - builder.setVersion(VersionInfo.getVersion()); + String version = VersionInfo.getVersion(); + builder.setVersion(version); + String[] components = version.split("\\."); + if (components != null && components.length > 2) { + builder.setVersionMajor(Integer.parseInt(components[0])); + builder.setVersionMinor(Integer.parseInt(components[1])); + } builder.setUrl(VersionInfo.getUrl()); builder.setRevision(VersionInfo.getRevision()); builder.setUser(VersionInfo.getUser()); diff --git a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/RPCProtos.java b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/RPCProtos.java index 99ccf76..472b837 100644 --- a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/RPCProtos.java +++ b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/RPCProtos.java @@ -790,6 +790,26 @@ public final class RPCProtos { */ com.google.protobuf.ByteString getSrcChecksumBytes(); + + // optional uint32 version_major = 7; + /** + * optional uint32 version_major = 7; + */ + boolean hasVersionMajor(); + /** + * optional uint32 version_major = 7; + */ + int getVersionMajor(); + + // optional uint32 version_minor = 8; + /** + * optional uint32 version_minor = 8; + */ + boolean hasVersionMinor(); + /** + * optional uint32 version_minor = 8; + */ + int getVersionMinor(); } /** * Protobuf type {@code hbase.pb.VersionInfo} @@ -876,6 +896,16 @@ public final class RPCProtos { srcChecksum_ = input.readBytes(); break; } + case 56: { + bitField0_ |= 0x00000040; + versionMajor_ = input.readUInt32(); + break; + } + case 64: { + bitField0_ |= 0x00000080; + versionMinor_ = input.readUInt32(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -1174,6 +1204,38 @@ public final class RPCProtos { } } + // optional uint32 version_major = 7; + public static final int VERSION_MAJOR_FIELD_NUMBER = 7; + private int versionMajor_; + /** + * optional uint32 version_major = 7; + */ + public boolean hasVersionMajor() { + return ((bitField0_ & 0x00000040) == 0x00000040); + } + /** + * optional uint32 version_major = 7; + */ + public int getVersionMajor() { + return versionMajor_; + } + + // optional uint32 version_minor = 8; + public static final int VERSION_MINOR_FIELD_NUMBER = 8; + private int versionMinor_; + /** + * optional uint32 version_minor = 8; + */ + public boolean hasVersionMinor() { + return ((bitField0_ & 0x00000080) == 0x00000080); + } + /** + * optional uint32 version_minor = 8; + */ + public int getVersionMinor() { + return versionMinor_; + } + private void initFields() { version_ = ""; url_ = ""; @@ -1181,6 +1243,8 @@ public final class RPCProtos { user_ = ""; date_ = ""; srcChecksum_ = ""; + versionMajor_ = 0; + versionMinor_ = 0; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -1236,6 +1300,12 @@ public final class RPCProtos { if (((bitField0_ & 0x00000020) == 0x00000020)) { output.writeBytes(6, getSrcChecksumBytes()); } + if (((bitField0_ & 0x00000040) == 0x00000040)) { + output.writeUInt32(7, versionMajor_); + } + if (((bitField0_ & 0x00000080) == 0x00000080)) { + output.writeUInt32(8, versionMinor_); + } getUnknownFields().writeTo(output); } @@ -1269,6 +1339,14 @@ public final class RPCProtos { size += com.google.protobuf.CodedOutputStream .computeBytesSize(6, getSrcChecksumBytes()); } + if (((bitField0_ & 0x00000040) == 0x00000040)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(7, versionMajor_); + } + if (((bitField0_ & 0x00000080) == 0x00000080)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(8, versionMinor_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -1322,6 +1400,16 @@ public final class RPCProtos { result = result && getSrcChecksum() .equals(other.getSrcChecksum()); } + result = result && (hasVersionMajor() == other.hasVersionMajor()); + if (hasVersionMajor()) { + result = result && (getVersionMajor() + == other.getVersionMajor()); + } + result = result && (hasVersionMinor() == other.hasVersionMinor()); + if (hasVersionMinor()) { + result = result && (getVersionMinor() + == other.getVersionMinor()); + } result = result && getUnknownFields().equals(other.getUnknownFields()); return result; @@ -1359,6 +1447,14 @@ public final class RPCProtos { hash = (37 * hash) + SRC_CHECKSUM_FIELD_NUMBER; hash = (53 * hash) + getSrcChecksum().hashCode(); } + if (hasVersionMajor()) { + hash = (37 * hash) + VERSION_MAJOR_FIELD_NUMBER; + hash = (53 * hash) + getVersionMajor(); + } + if (hasVersionMinor()) { + hash = (37 * hash) + VERSION_MINOR_FIELD_NUMBER; + hash = (53 * hash) + getVersionMinor(); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -1484,6 +1580,10 @@ public final class RPCProtos { bitField0_ = (bitField0_ & ~0x00000010); srcChecksum_ = ""; bitField0_ = (bitField0_ & ~0x00000020); + versionMajor_ = 0; + bitField0_ = (bitField0_ & ~0x00000040); + versionMinor_ = 0; + bitField0_ = (bitField0_ & ~0x00000080); return this; } @@ -1536,6 +1636,14 @@ public final class RPCProtos { to_bitField0_ |= 0x00000020; } result.srcChecksum_ = srcChecksum_; + if (((from_bitField0_ & 0x00000040) == 0x00000040)) { + to_bitField0_ |= 0x00000040; + } + result.versionMajor_ = versionMajor_; + if (((from_bitField0_ & 0x00000080) == 0x00000080)) { + to_bitField0_ |= 0x00000080; + } + result.versionMinor_ = versionMinor_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -1582,6 +1690,12 @@ public final class RPCProtos { srcChecksum_ = other.srcChecksum_; onChanged(); } + if (other.hasVersionMajor()) { + setVersionMajor(other.getVersionMajor()); + } + if (other.hasVersionMinor()) { + setVersionMinor(other.getVersionMinor()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -2077,6 +2191,72 @@ public final class RPCProtos { return this; } + // optional uint32 version_major = 7; + private int versionMajor_ ; + /** + * optional uint32 version_major = 7; + */ + public boolean hasVersionMajor() { + return ((bitField0_ & 0x00000040) == 0x00000040); + } + /** + * optional uint32 version_major = 7; + */ + public int getVersionMajor() { + return versionMajor_; + } + /** + * optional uint32 version_major = 7; + */ + public Builder setVersionMajor(int value) { + bitField0_ |= 0x00000040; + versionMajor_ = value; + onChanged(); + return this; + } + /** + * optional uint32 version_major = 7; + */ + public Builder clearVersionMajor() { + bitField0_ = (bitField0_ & ~0x00000040); + versionMajor_ = 0; + onChanged(); + return this; + } + + // optional uint32 version_minor = 8; + private int versionMinor_ ; + /** + * optional uint32 version_minor = 8; + */ + public boolean hasVersionMinor() { + return ((bitField0_ & 0x00000080) == 0x00000080); + } + /** + * optional uint32 version_minor = 8; + */ + public int getVersionMinor() { + return versionMinor_; + } + /** + * optional uint32 version_minor = 8; + */ + public Builder setVersionMinor(int value) { + bitField0_ |= 0x00000080; + versionMinor_ = value; + onChanged(); + return this; + } + /** + * optional uint32 version_minor = 8; + */ + public Builder clearVersionMinor() { + bitField0_ = (bitField0_ & ~0x00000080); + versionMinor_ = 0; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:hbase.pb.VersionInfo) } @@ -7527,29 +7707,30 @@ public final class RPCProtos { java.lang.String[] descriptorData = { "\n\tRPC.proto\022\010hbase.pb\032\rTracing.proto\032\013HB" + "ase.proto\"<\n\017UserInformation\022\026\n\016effectiv" + - "e_user\030\001 \002(\t\022\021\n\treal_user\030\002 \001(\t\"o\n\013Versi" + - "onInfo\022\017\n\007version\030\001 \002(\t\022\013\n\003url\030\002 \002(\t\022\020\n\010" + - "revision\030\003 \002(\t\022\014\n\004user\030\004 \002(\t\022\014\n\004date\030\005 \002" + - "(\t\022\024\n\014src_checksum\030\006 \002(\t\"\310\001\n\020ConnectionH" + - "eader\022,\n\tuser_info\030\001 \001(\0132\031.hbase.pb.User" + - "Information\022\024\n\014service_name\030\002 \001(\t\022\036\n\026cel" + - "l_block_codec_class\030\003 \001(\t\022#\n\033cell_block_" + - "compressor_class\030\004 \001(\t\022+\n\014version_info\030\005", - " \001(\0132\025.hbase.pb.VersionInfo\"\037\n\rCellBlock" + - "Meta\022\016\n\006length\030\001 \001(\r\"|\n\021ExceptionRespons" + - "e\022\034\n\024exception_class_name\030\001 \001(\t\022\023\n\013stack" + - "_trace\030\002 \001(\t\022\020\n\010hostname\030\003 \001(\t\022\014\n\004port\030\004" + - " \001(\005\022\024\n\014do_not_retry\030\005 \001(\010\"\270\001\n\rRequestHe" + - "ader\022\017\n\007call_id\030\001 \001(\r\022&\n\ntrace_info\030\002 \001(" + - "\0132\022.hbase.pb.RPCTInfo\022\023\n\013method_name\030\003 \001" + - "(\t\022\025\n\rrequest_param\030\004 \001(\010\0220\n\017cell_block_" + - "meta\030\005 \001(\0132\027.hbase.pb.CellBlockMeta\022\020\n\010p" + - "riority\030\006 \001(\r\"\203\001\n\016ResponseHeader\022\017\n\007call", - "_id\030\001 \001(\r\022.\n\texception\030\002 \001(\0132\033.hbase.pb." + - "ExceptionResponse\0220\n\017cell_block_meta\030\003 \001" + - "(\0132\027.hbase.pb.CellBlockMetaB<\n*org.apach" + - "e.hadoop.hbase.protobuf.generatedB\tRPCPr" + - "otosH\001\240\001\001" + "e_user\030\001 \002(\t\022\021\n\treal_user\030\002 \001(\t\"\235\001\n\013Vers" + + "ionInfo\022\017\n\007version\030\001 \002(\t\022\013\n\003url\030\002 \002(\t\022\020\n" + + "\010revision\030\003 \002(\t\022\014\n\004user\030\004 \002(\t\022\014\n\004date\030\005 " + + "\002(\t\022\024\n\014src_checksum\030\006 \002(\t\022\025\n\rversion_maj" + + "or\030\007 \001(\r\022\025\n\rversion_minor\030\010 \001(\r\"\310\001\n\020Conn" + + "ectionHeader\022,\n\tuser_info\030\001 \001(\0132\031.hbase." + + "pb.UserInformation\022\024\n\014service_name\030\002 \001(\t" + + "\022\036\n\026cell_block_codec_class\030\003 \001(\t\022#\n\033cell", + "_block_compressor_class\030\004 \001(\t\022+\n\014version" + + "_info\030\005 \001(\0132\025.hbase.pb.VersionInfo\"\037\n\rCe" + + "llBlockMeta\022\016\n\006length\030\001 \001(\r\"|\n\021Exception" + + "Response\022\034\n\024exception_class_name\030\001 \001(\t\022\023" + + "\n\013stack_trace\030\002 \001(\t\022\020\n\010hostname\030\003 \001(\t\022\014\n" + + "\004port\030\004 \001(\005\022\024\n\014do_not_retry\030\005 \001(\010\"\270\001\n\rRe" + + "questHeader\022\017\n\007call_id\030\001 \001(\r\022&\n\ntrace_in" + + "fo\030\002 \001(\0132\022.hbase.pb.RPCTInfo\022\023\n\013method_n" + + "ame\030\003 \001(\t\022\025\n\rrequest_param\030\004 \001(\010\0220\n\017cell" + + "_block_meta\030\005 \001(\0132\027.hbase.pb.CellBlockMe", + "ta\022\020\n\010priority\030\006 \001(\r\"\203\001\n\016ResponseHeader\022" + + "\017\n\007call_id\030\001 \001(\r\022.\n\texception\030\002 \001(\0132\033.hb" + + "ase.pb.ExceptionResponse\0220\n\017cell_block_m" + + "eta\030\003 \001(\0132\027.hbase.pb.CellBlockMetaB<\n*or" + + "g.apache.hadoop.hbase.protobuf.generated" + + "B\tRPCProtosH\001\240\001\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -7567,7 +7748,7 @@ public final class RPCProtos { internal_static_hbase_pb_VersionInfo_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_hbase_pb_VersionInfo_descriptor, - new java.lang.String[] { "Version", "Url", "Revision", "User", "Date", "SrcChecksum", }); + new java.lang.String[] { "Version", "Url", "Revision", "User", "Date", "SrcChecksum", "VersionMajor", "VersionMinor", }); internal_static_hbase_pb_ConnectionHeader_descriptor = getDescriptor().getMessageTypes().get(2); internal_static_hbase_pb_ConnectionHeader_fieldAccessorTable = new diff --git a/hbase-protocol/src/main/protobuf/RPC.proto b/hbase-protocol/src/main/protobuf/RPC.proto index 5645c06..39b920b 100644 --- a/hbase-protocol/src/main/protobuf/RPC.proto +++ b/hbase-protocol/src/main/protobuf/RPC.proto @@ -86,6 +86,8 @@ message VersionInfo { required string user = 4; required string date = 5; required string src_checksum = 6; + optional uint32 version_major = 7; + optional uint32 version_minor = 8; } // This is sent on connection setup after the connection preamble is sent. diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedurePrepareLatch.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedurePrepareLatch.java index 2a1abca..6da4dc0 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedurePrepareLatch.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/ProcedurePrepareLatch.java @@ -24,10 +24,8 @@ import java.util.concurrent.CountDownLatch; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; -import org.apache.hadoop.hbase.ipc.RpcServer; -import org.apache.hadoop.hbase.ipc.RpcCallContext; import org.apache.hadoop.hbase.procedure2.Procedure; -import org.apache.hadoop.hbase.protobuf.generated.RPCProtos.VersionInfo; +import org.apache.hadoop.hbase.util.VersionUtil; /** * Latch used by the Master to have the prepare() sync behaviour for old @@ -44,24 +42,7 @@ public abstract class ProcedurePrepareLatch { } public static boolean hasProcedureSupport() { - return currentClientHasMinimumVersion(1, 1); - } - - private static boolean currentClientHasMinimumVersion(int major, int minor) { - RpcCallContext call = RpcServer.getCurrentCall(); - VersionInfo versionInfo = call != null ? call.getClientVersionInfo() : null; - if (versionInfo != null) { - String[] components = versionInfo.getVersion().split("\\."); - - int clientMajor = components.length > 0 ? Integer.parseInt(components[0]) : 0; - if (clientMajor != major) { - return clientMajor > major; - } - - int clientMinor = components.length > 1 ? Integer.parseInt(components[1]) : 0; - return clientMinor >= minor; - } - return false; + return VersionUtil.currentClientHasMinimumVersion(1, 1); } protected abstract void countDown(final Procedure proc); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java index 65cedee..5592660 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java @@ -171,6 +171,7 @@ import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; import org.apache.hadoop.hbase.util.Pair; import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil; import org.apache.hadoop.hbase.util.Strings; +import org.apache.hadoop.hbase.util.VersionUtil; import org.apache.hadoop.hbase.wal.WAL; import org.apache.hadoop.hbase.wal.WALKey; import org.apache.hadoop.hbase.wal.WALSplitter; @@ -1987,7 +1988,17 @@ public class RSRpcServices implements HBaseRPCErrorHandler, ProtobufUtil.toResult(existence, region.getRegionInfo().getReplicaId() != 0); builder.setResult(pbr); } else if (r != null) { - ClientProtos.Result pbr = ProtobufUtil.toResult(r); + ClientProtos.Result pbr; + RpcCallContext call = RpcServer.getCurrentCall(); + if (call != null && call.isClientCellBlockSupport() + && controller instanceof PayloadCarryingRpcController + && VersionUtil.currentClientHasMinimumVersion(1, 2, call.getClientVersionInfo())) { + pbr = ProtobufUtil.toResultNoData(r); + ((PayloadCarryingRpcController) controller).setCellScanner(CellUtil.createCellScanner(r + .rawCells())); + } else { + pbr = ProtobufUtil.toResult(r); + } builder.setResult(pbr); } if (r != null) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/VersionUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/VersionUtil.java new file mode 100644 index 0000000..9317241 --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/VersionUtil.java @@ -0,0 +1,75 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.util; + +import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.ipc.RpcCallContext; +import org.apache.hadoop.hbase.ipc.RpcServer; +import org.apache.hadoop.hbase.protobuf.generated.RPCProtos.VersionInfo; + +@InterfaceAudience.Private +public final class VersionUtil { + + /** + * Private constructor to keep this class from being instantiated. + */ + private VersionUtil() { + } + + /** + * Checks whether the current calling client has a specified minimum version or not. + * @param major + * @param minor + * @return true when current client has minimum version as specified + */ + public static boolean currentClientHasMinimumVersion(int major, int minor) { + RpcCallContext call = RpcServer.getCurrentCall(); + VersionInfo versionInfo = call != null ? call.getClientVersionInfo() : null; + return currentClientHasMinimumVersion(major, minor, versionInfo); + } + + /** + * Checks whether the current calling client has a specified minimum version or not. + * @param major + * @param minor + * @param clientVersionInfo Version info as got from client + * @return true when current client has minimum version as specified + */ + public static boolean currentClientHasMinimumVersion(int major, int minor, + VersionInfo clientVersionInfo) { + if (clientVersionInfo != null) { + if (clientVersionInfo.hasVersionMajor() && clientVersionInfo.hasVersionMinor()) { + int clientMajor = clientVersionInfo.getVersionMajor(); + if (clientMajor != major) { + return clientMajor > major; + } + int clientMinor = clientVersionInfo.getVersionMinor(); + return clientMinor >= minor; + } + // We have to parse the version string to get client's major and minor versions + String[] components = clientVersionInfo.getVersion().split("\\."); + int clientMajor = components.length > 0 ? Integer.parseInt(components[0]) : 0; + if (clientMajor != major) { + return clientMajor > major; + } + int clientMinor = components.length > 1 ? Integer.parseInt(components[1]) : 0; + return clientMinor >= minor; + } + return false; + } +} \ No newline at end of file