diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java index 363ee7c..5b04a1d 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java @@ -1108,8 +1108,9 @@ public interface Admin extends Abortable, Closeable { * @param instance The instance name of the procedure. For some procedures, this parameter is * optional. * @param props Property/Value pairs of properties passing to the procedure + * @return data returned after procedure execution. null if no return data. */ - void execProcedure(String signature, String instance, Map props) + byte[] execProcedure(String signature, String instance, Map props) throws IOException; /** diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java index 95b5c07..e614122 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java @@ -3062,8 +3062,10 @@ public class HBaseAdmin implements Admin { * @param instance The instance name of the procedure. For some procedures, this parameter is * optional. * @param props Property/Value pairs of properties passing to the procedure + * @return data returned after procedure execution. null if no return data. + * @throws IOException */ - public void execProcedure(String signature, String instance, + public byte[] execProcedure(String signature, String instance, Map props) throws IOException { ProcedureDescription.Builder builder = ProcedureDescription.newBuilder(); builder.setSignature(signature).setInstance(instance); @@ -3084,6 +3086,11 @@ public class HBaseAdmin implements Admin { } }); + byte[] returnData = response.hasReturnData() ? response.getReturnData().toByteArray() + : null; + + // We probably can mandate the above execProcedure synchronous + // to return any data. long start = EnvironmentEdgeManager.currentTimeMillis(); long max = response.getExpectedTimeout(); long maxPauseTime = max / this.numRetries; @@ -3110,6 +3117,8 @@ public class HBaseAdmin implements Admin { throw new IOException("Procedure '" + signature + " : " + instance + "' wasn't completed in expectedTime:" + max + " ms"); } + + return returnData; } /** diff --git a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java index 47af425..f677dc3 100644 --- a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java +++ b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java @@ -38907,6 +38907,16 @@ public final class MasterProtos { * required int64 expected_timeout = 1; */ long getExpectedTimeout(); + + // optional bytes return_data = 2; + /** + * optional bytes return_data = 2; + */ + boolean hasReturnData(); + /** + * optional bytes return_data = 2; + */ + com.google.protobuf.ByteString getReturnData(); } /** * Protobuf type {@code ExecProcedureResponse} @@ -38964,6 +38974,11 @@ public final class MasterProtos { expectedTimeout_ = input.readInt64(); break; } + case 18: { + bitField0_ |= 0x00000002; + returnData_ = input.readBytes(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -39020,8 +39035,25 @@ public final class MasterProtos { return expectedTimeout_; } + // optional bytes return_data = 2; + public static final int RETURN_DATA_FIELD_NUMBER = 2; + private com.google.protobuf.ByteString returnData_; + /** + * optional bytes return_data = 2; + */ + public boolean hasReturnData() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional bytes return_data = 2; + */ + public com.google.protobuf.ByteString getReturnData() { + return returnData_; + } + private void initFields() { expectedTimeout_ = 0L; + returnData_ = com.google.protobuf.ByteString.EMPTY; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -39042,6 +39074,9 @@ public final class MasterProtos { if (((bitField0_ & 0x00000001) == 0x00000001)) { output.writeInt64(1, expectedTimeout_); } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, returnData_); + } getUnknownFields().writeTo(output); } @@ -39055,6 +39090,10 @@ public final class MasterProtos { size += com.google.protobuf.CodedOutputStream .computeInt64Size(1, expectedTimeout_); } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(2, returnData_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -39083,6 +39122,11 @@ public final class MasterProtos { result = result && (getExpectedTimeout() == other.getExpectedTimeout()); } + result = result && (hasReturnData() == other.hasReturnData()); + if (hasReturnData()) { + result = result && getReturnData() + .equals(other.getReturnData()); + } result = result && getUnknownFields().equals(other.getUnknownFields()); return result; @@ -39100,6 +39144,10 @@ public final class MasterProtos { hash = (37 * hash) + EXPECTED_TIMEOUT_FIELD_NUMBER; hash = (53 * hash) + hashLong(getExpectedTimeout()); } + if (hasReturnData()) { + hash = (37 * hash) + RETURN_DATA_FIELD_NUMBER; + hash = (53 * hash) + getReturnData().hashCode(); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -39211,6 +39259,8 @@ public final class MasterProtos { super.clear(); expectedTimeout_ = 0L; bitField0_ = (bitField0_ & ~0x00000001); + returnData_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000002); return this; } @@ -39243,6 +39293,10 @@ public final class MasterProtos { to_bitField0_ |= 0x00000001; } result.expectedTimeout_ = expectedTimeout_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.returnData_ = returnData_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -39262,6 +39316,9 @@ public final class MasterProtos { if (other.hasExpectedTimeout()) { setExpectedTimeout(other.getExpectedTimeout()); } + if (other.hasReturnData()) { + setReturnData(other.getReturnData()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -39326,6 +39383,42 @@ public final class MasterProtos { return this; } + // optional bytes return_data = 2; + private com.google.protobuf.ByteString returnData_ = com.google.protobuf.ByteString.EMPTY; + /** + * optional bytes return_data = 2; + */ + public boolean hasReturnData() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional bytes return_data = 2; + */ + public com.google.protobuf.ByteString getReturnData() { + return returnData_; + } + /** + * optional bytes return_data = 2; + */ + public Builder setReturnData(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + returnData_ = value; + onChanged(); + return this; + } + /** + * optional bytes return_data = 2; + */ + public Builder clearReturnData() { + bitField0_ = (bitField0_ & ~0x00000002); + returnData_ = getDefaultInstance().getReturnData(); + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:ExecProcedureResponse) } @@ -44592,88 +44685,89 @@ public final class MasterProtos { "uest\"4\n\027IsMasterRunningResponse\022\031\n\021is_ma" + "ster_running\030\001 \002(\010\"@\n\024ExecProcedureReque" + "st\022(\n\tprocedure\030\001 \002(\0132\025.ProcedureDescrip" + - "tion\"1\n\025ExecProcedureResponse\022\030\n\020expecte" + - "d_timeout\030\001 \002(\003\"B\n\026IsProcedureDoneReques" + - "t\022(\n\tprocedure\030\001 \001(\0132\025.ProcedureDescript" + - "ion\"W\n\027IsProcedureDoneResponse\022\023\n\004done\030\001" + - " \001(\010:\005false\022\'\n\010snapshot\030\002 \001(\0132\025.Procedur" + - "eDescription2\256\027\n\rMasterService\022S\n\024GetSch" + - "emaAlterStatus\022\034.GetSchemaAlterStatusReq", - "uest\032\035.GetSchemaAlterStatusResponse\022P\n\023G" + - "etTableDescriptors\022\033.GetTableDescriptors" + - "Request\032\034.GetTableDescriptorsResponse\022>\n" + - "\rGetTableNames\022\025.GetTableNamesRequest\032\026." + - "GetTableNamesResponse\022G\n\020GetClusterStatu" + - "s\022\030.GetClusterStatusRequest\032\031.GetCluster" + - "StatusResponse\022D\n\017IsMasterRunning\022\027.IsMa" + - "sterRunningRequest\032\030.IsMasterRunningResp" + - "onse\0222\n\tAddColumn\022\021.AddColumnRequest\032\022.A" + - "ddColumnResponse\022;\n\014DeleteColumn\022\024.Delet", - "eColumnRequest\032\025.DeleteColumnResponse\022;\n" + - "\014ModifyColumn\022\024.ModifyColumnRequest\032\025.Mo" + - "difyColumnResponse\0225\n\nMoveRegion\022\022.MoveR" + - "egionRequest\032\023.MoveRegionResponse\022Y\n\026Dis" + - "patchMergingRegions\022\036.DispatchMergingReg" + - "ionsRequest\032\037.DispatchMergingRegionsResp" + - "onse\022;\n\014AssignRegion\022\024.AssignRegionReque" + - "st\032\025.AssignRegionResponse\022A\n\016UnassignReg" + - "ion\022\026.UnassignRegionRequest\032\027.UnassignRe" + - "gionResponse\022>\n\rOfflineRegion\022\025.OfflineR", - "egionRequest\032\026.OfflineRegionResponse\0228\n\013" + - "DeleteTable\022\023.DeleteTableRequest\032\024.Delet" + - "eTableResponse\022>\n\rtruncateTable\022\025.Trunca" + - "teTableRequest\032\026.TruncateTableResponse\0228" + - "\n\013EnableTable\022\023.EnableTableRequest\032\024.Ena" + - "bleTableResponse\022;\n\014DisableTable\022\024.Disab" + - "leTableRequest\032\025.DisableTableResponse\0228\n" + - "\013ModifyTable\022\023.ModifyTableRequest\032\024.Modi" + - "fyTableResponse\0228\n\013CreateTable\022\023.CreateT" + - "ableRequest\032\024.CreateTableResponse\022/\n\010Shu", - "tdown\022\020.ShutdownRequest\032\021.ShutdownRespon" + - "se\0225\n\nStopMaster\022\022.StopMasterRequest\032\023.S" + - "topMasterResponse\022,\n\007Balance\022\017.BalanceRe" + - "quest\032\020.BalanceResponse\022M\n\022SetBalancerRu" + - "nning\022\032.SetBalancerRunningRequest\032\033.SetB" + - "alancerRunningResponse\022A\n\016RunCatalogScan" + - "\022\026.RunCatalogScanRequest\032\027.RunCatalogSca" + - "nResponse\022S\n\024EnableCatalogJanitor\022\034.Enab" + - "leCatalogJanitorRequest\032\035.EnableCatalogJ" + - "anitorResponse\022\\\n\027IsCatalogJanitorEnable", - "d\022\037.IsCatalogJanitorEnabledRequest\032 .IsC" + - "atalogJanitorEnabledResponse\022L\n\021ExecMast" + - "erService\022\032.CoprocessorServiceRequest\032\033." + - "CoprocessorServiceResponse\022/\n\010Snapshot\022\020" + - ".SnapshotRequest\032\021.SnapshotResponse\022V\n\025G" + - "etCompletedSnapshots\022\035.GetCompletedSnaps" + - "hotsRequest\032\036.GetCompletedSnapshotsRespo" + - "nse\022A\n\016DeleteSnapshot\022\026.DeleteSnapshotRe" + - "quest\032\027.DeleteSnapshotResponse\022A\n\016IsSnap" + - "shotDone\022\026.IsSnapshotDoneRequest\032\027.IsSna", - "pshotDoneResponse\022D\n\017RestoreSnapshot\022\027.R" + - "estoreSnapshotRequest\032\030.RestoreSnapshotR" + - "esponse\022V\n\025IsRestoreSnapshotDone\022\035.IsRes" + - "toreSnapshotDoneRequest\032\036.IsRestoreSnaps" + - "hotDoneResponse\022>\n\rExecProcedure\022\025.ExecP" + - "rocedureRequest\032\026.ExecProcedureResponse\022" + - "D\n\017IsProcedureDone\022\027.IsProcedureDoneRequ" + - "est\032\030.IsProcedureDoneResponse\022D\n\017ModifyN" + - "amespace\022\027.ModifyNamespaceRequest\032\030.Modi" + - "fyNamespaceResponse\022D\n\017CreateNamespace\022\027", - ".CreateNamespaceRequest\032\030.CreateNamespac" + - "eResponse\022D\n\017DeleteNamespace\022\027.DeleteNam" + - "espaceRequest\032\030.DeleteNamespaceResponse\022" + - "Y\n\026GetNamespaceDescriptor\022\036.GetNamespace" + - "DescriptorRequest\032\037.GetNamespaceDescript" + - "orResponse\022_\n\030ListNamespaceDescriptors\022 " + - ".ListNamespaceDescriptorsRequest\032!.ListN" + - "amespaceDescriptorsResponse\022t\n\037ListTable" + - "DescriptorsByNamespace\022\'.ListTableDescri" + - "ptorsByNamespaceRequest\032(.ListTableDescr", - "iptorsByNamespaceResponse\022b\n\031ListTableNa" + - "mesByNamespace\022!.ListTableNamesByNamespa" + - "ceRequest\032\".ListTableNamesByNamespaceRes" + - "ponseBB\n*org.apache.hadoop.hbase.protobu" + - "f.generatedB\014MasterProtosH\001\210\001\001\240\001\001" + "tion\"F\n\025ExecProcedureResponse\022\030\n\020expecte" + + "d_timeout\030\001 \002(\003\022\023\n\013return_data\030\002 \001(\014\"B\n\026" + + "IsProcedureDoneRequest\022(\n\tprocedure\030\001 \001(" + + "\0132\025.ProcedureDescription\"W\n\027IsProcedureD" + + "oneResponse\022\023\n\004done\030\001 \001(\010:\005false\022\'\n\010snap" + + "shot\030\002 \001(\0132\025.ProcedureDescription2\256\027\n\rMa" + + "sterService\022S\n\024GetSchemaAlterStatus\022\034.Ge", + "tSchemaAlterStatusRequest\032\035.GetSchemaAlt" + + "erStatusResponse\022P\n\023GetTableDescriptors\022" + + "\033.GetTableDescriptorsRequest\032\034.GetTableD" + + "escriptorsResponse\022>\n\rGetTableNames\022\025.Ge" + + "tTableNamesRequest\032\026.GetTableNamesRespon" + + "se\022G\n\020GetClusterStatus\022\030.GetClusterStatu" + + "sRequest\032\031.GetClusterStatusResponse\022D\n\017I" + + "sMasterRunning\022\027.IsMasterRunningRequest\032" + + "\030.IsMasterRunningResponse\0222\n\tAddColumn\022\021" + + ".AddColumnRequest\032\022.AddColumnResponse\022;\n", + "\014DeleteColumn\022\024.DeleteColumnRequest\032\025.De" + + "leteColumnResponse\022;\n\014ModifyColumn\022\024.Mod" + + "ifyColumnRequest\032\025.ModifyColumnResponse\022" + + "5\n\nMoveRegion\022\022.MoveRegionRequest\032\023.Move" + + "RegionResponse\022Y\n\026DispatchMergingRegions" + + "\022\036.DispatchMergingRegionsRequest\032\037.Dispa" + + "tchMergingRegionsResponse\022;\n\014AssignRegio" + + "n\022\024.AssignRegionRequest\032\025.AssignRegionRe" + + "sponse\022A\n\016UnassignRegion\022\026.UnassignRegio" + + "nRequest\032\027.UnassignRegionResponse\022>\n\rOff", + "lineRegion\022\025.OfflineRegionRequest\032\026.Offl" + + "ineRegionResponse\0228\n\013DeleteTable\022\023.Delet" + + "eTableRequest\032\024.DeleteTableResponse\022>\n\rt" + + "runcateTable\022\025.TruncateTableRequest\032\026.Tr" + + "uncateTableResponse\0228\n\013EnableTable\022\023.Ena" + + "bleTableRequest\032\024.EnableTableResponse\022;\n" + + "\014DisableTable\022\024.DisableTableRequest\032\025.Di" + + "sableTableResponse\0228\n\013ModifyTable\022\023.Modi" + + "fyTableRequest\032\024.ModifyTableResponse\0228\n\013" + + "CreateTable\022\023.CreateTableRequest\032\024.Creat", + "eTableResponse\022/\n\010Shutdown\022\020.ShutdownReq" + + "uest\032\021.ShutdownResponse\0225\n\nStopMaster\022\022." + + "StopMasterRequest\032\023.StopMasterResponse\022," + + "\n\007Balance\022\017.BalanceRequest\032\020.BalanceResp" + + "onse\022M\n\022SetBalancerRunning\022\032.SetBalancer" + + "RunningRequest\032\033.SetBalancerRunningRespo" + + "nse\022A\n\016RunCatalogScan\022\026.RunCatalogScanRe" + + "quest\032\027.RunCatalogScanResponse\022S\n\024Enable" + + "CatalogJanitor\022\034.EnableCatalogJanitorReq" + + "uest\032\035.EnableCatalogJanitorResponse\022\\\n\027I", + "sCatalogJanitorEnabled\022\037.IsCatalogJanito" + + "rEnabledRequest\032 .IsCatalogJanitorEnable" + + "dResponse\022L\n\021ExecMasterService\022\032.Coproce" + + "ssorServiceRequest\032\033.CoprocessorServiceR" + + "esponse\022/\n\010Snapshot\022\020.SnapshotRequest\032\021." + + "SnapshotResponse\022V\n\025GetCompletedSnapshot" + + "s\022\035.GetCompletedSnapshotsRequest\032\036.GetCo" + + "mpletedSnapshotsResponse\022A\n\016DeleteSnapsh" + + "ot\022\026.DeleteSnapshotRequest\032\027.DeleteSnaps" + + "hotResponse\022A\n\016IsSnapshotDone\022\026.IsSnapsh", + "otDoneRequest\032\027.IsSnapshotDoneResponse\022D" + + "\n\017RestoreSnapshot\022\027.RestoreSnapshotReque" + + "st\032\030.RestoreSnapshotResponse\022V\n\025IsRestor" + + "eSnapshotDone\022\035.IsRestoreSnapshotDoneReq" + + "uest\032\036.IsRestoreSnapshotDoneResponse\022>\n\r" + + "ExecProcedure\022\025.ExecProcedureRequest\032\026.E" + + "xecProcedureResponse\022D\n\017IsProcedureDone\022" + + "\027.IsProcedureDoneRequest\032\030.IsProcedureDo" + + "neResponse\022D\n\017ModifyNamespace\022\027.ModifyNa" + + "mespaceRequest\032\030.ModifyNamespaceResponse", + "\022D\n\017CreateNamespace\022\027.CreateNamespaceReq" + + "uest\032\030.CreateNamespaceResponse\022D\n\017Delete" + + "Namespace\022\027.DeleteNamespaceRequest\032\030.Del" + + "eteNamespaceResponse\022Y\n\026GetNamespaceDesc" + + "riptor\022\036.GetNamespaceDescriptorRequest\032\037" + + ".GetNamespaceDescriptorResponse\022_\n\030ListN" + + "amespaceDescriptors\022 .ListNamespaceDescr" + + "iptorsRequest\032!.ListNamespaceDescriptors" + + "Response\022t\n\037ListTableDescriptorsByNamesp" + + "ace\022\'.ListTableDescriptorsByNamespaceReq", + "uest\032(.ListTableDescriptorsByNamespaceRe" + + "sponse\022b\n\031ListTableNamesByNamespace\022!.Li" + + "stTableNamesByNamespaceRequest\032\".ListTab" + + "leNamesByNamespaceResponseBB\n*org.apache" + + ".hadoop.hbase.protobuf.generatedB\014Master" + + "ProtosH\001\210\001\001\240\001\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -45159,7 +45253,7 @@ public final class MasterProtos { internal_static_ExecProcedureResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_ExecProcedureResponse_descriptor, - new java.lang.String[] { "ExpectedTimeout", }); + new java.lang.String[] { "ExpectedTimeout", "ReturnData", }); internal_static_IsProcedureDoneRequest_descriptor = getDescriptor().getMessageTypes().get(80); internal_static_IsProcedureDoneRequest_fieldAccessorTable = new diff --git a/hbase-protocol/src/main/protobuf/Master.proto b/hbase-protocol/src/main/protobuf/Master.proto index d6b7278..3e9497d 100644 --- a/hbase-protocol/src/main/protobuf/Master.proto +++ b/hbase-protocol/src/main/protobuf/Master.proto @@ -346,6 +346,7 @@ message ExecProcedureRequest { message ExecProcedureResponse { required int64 expected_timeout = 1; + optional bytes return_data = 2; } message IsProcedureDoneRequest { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index 7ab9bd4..3393297 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -152,6 +152,7 @@ import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; import org.apache.zookeeper.KeeperException; +import com.google.protobuf.ByteString; import com.google.protobuf.Descriptors; import com.google.protobuf.Message; import com.google.protobuf.RpcCallback; @@ -615,7 +616,10 @@ public class MasterRpcServices extends RSRpcServices } /** - * Triggers an asynchronous attempt to run a distributed procedure. + * Triggers an attempt to run a distributed procedure. + * This call can be synchronous or asynchronous. + * The underlying global procedure is always synchronous + * because we wait for its completion. * {@inheritDoc} */ @Override @@ -634,13 +638,19 @@ public class MasterRpcServices extends RSRpcServices LOG.info(master.getClientIdAuditPrefix() + " procedure request for: " + desc.getSignature()); - mpm.execProcedure(desc); + byte[] data = mpm.execProcedure(desc); + + ExecProcedureResponse.Builder builder = ExecProcedureResponse.newBuilder(); + // set return data if available + if (data != null) { + builder.setReturnData(ByteString.copyFrom(data)); + } // send back the max amount of time the client should wait for the procedure // to complete long waitTime = SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME; - return ExecProcedureResponse.newBuilder().setExpectedTimeout( - waitTime).build(); + builder.setExpectedTimeout(waitTime); + return builder.build(); } catch (IOException e) { throw new ServiceException(e); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/SnapshotManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/SnapshotManager.java index ddedf9f..d271253 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/SnapshotManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/SnapshotManager.java @@ -1037,8 +1037,9 @@ public class SnapshotManager extends MasterProcedureManager implements Stoppable } @Override - public void execProcedure(ProcedureDescription desc) throws IOException { + public byte[] execProcedure(ProcedureDescription desc) throws IOException { takeSnapshot(toSnapshotDescription(desc)); + return null; } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/procedure/MasterProcedureManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/procedure/MasterProcedureManager.java index 35e31c6..a19ef41 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/procedure/MasterProcedureManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/procedure/MasterProcedureManager.java @@ -70,11 +70,14 @@ public abstract class MasterProcedureManager extends ProcedureManager implements /** * Execute a distributed procedure on cluster - * + * An implementation of this method can return data from the procedure + * execution, preferably in a synchronous execution after the procedure + * has completed successfully. * @param desc Procedure description + * @return data returned from the procedure execution, null if no data * @throws IOException */ - public abstract void execProcedure(ProcedureDescription desc) throws IOException; + public abstract byte[] execProcedure(ProcedureDescription desc) throws IOException; /** * Check if the procedure is finished successfully diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/procedure/flush/MasterFlushTableProcedureManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/procedure/flush/MasterFlushTableProcedureManager.java index 16456c3..62d393a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/procedure/flush/MasterFlushTableProcedureManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/procedure/flush/MasterFlushTableProcedureManager.java @@ -106,7 +106,7 @@ public class MasterFlushTableProcedureManager extends MasterProcedureManager { } @Override - public void execProcedure(ProcedureDescription desc) throws IOException { + public byte[] execProcedure(ProcedureDescription desc) throws IOException { TableName tableName = TableName.valueOf(desc.getInstance()); @@ -176,6 +176,7 @@ public class MasterFlushTableProcedureManager extends MasterProcedureManager { monitor.receive(ee); } monitor.rethrowException(); + return null; } @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/SimpleMasterProcedureManager.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/SimpleMasterProcedureManager.java index 06e9d7c..182dd7b 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/SimpleMasterProcedureManager.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/SimpleMasterProcedureManager.java @@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.procedure; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.concurrent.ThreadPoolExecutor; @@ -27,22 +28,20 @@ import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.errorhandling.ForeignException; import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher; -import org.apache.hadoop.hbase.executor.ExecutorService; import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.MetricsMaster; import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ProcedureDescription; -import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException; import org.apache.zookeeper.KeeperException; public class SimpleMasterProcedureManager extends MasterProcedureManager { public static final String SIMPLE_SIGNATURE = "simle_test"; + public static final String SIMPLE_DATA = "simple_test_data"; private static final Log LOG = LogFactory.getLog(SimpleMasterProcedureManager.class); private MasterServices master; private ProcedureCoordinator coordinator; - private ExecutorService executorService; private boolean done; @@ -69,7 +68,6 @@ public class SimpleMasterProcedureManager extends MasterProcedureManager { master.getZooKeeper(), getProcedureSignature(), name); this.coordinator = new ProcedureCoordinator(comms, tpool); - this.executorService = master.getExecutorService(); } @Override @@ -78,7 +76,7 @@ public class SimpleMasterProcedureManager extends MasterProcedureManager { } @Override - public void execProcedure(ProcedureDescription desc) throws IOException { + public byte[] execProcedure(ProcedureDescription desc) throws IOException { this.done = false; // start the process on the RS ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(desc.getInstance()); @@ -93,13 +91,14 @@ public class SimpleMasterProcedureManager extends MasterProcedureManager { String msg = "Failed to submit distributed procedure for '" + getProcedureSignature() + "'"; LOG.error(msg); - throw new HBaseSnapshotException(msg); + throw new IOException(msg); } + HashMap returnData = null; try { // wait for the procedure to complete. A timer thread is kicked off that should cancel this // if it takes too long. - proc.waitForCompleted(); + returnData = proc.waitForCompletedWithRet(); LOG.info("Done waiting - exec procedure for " + desc.getInstance()); this.done = true; } catch (InterruptedException e) { @@ -110,6 +109,8 @@ public class SimpleMasterProcedureManager extends MasterProcedureManager { } catch (ForeignException e) { monitor.receive(e); } + // return the first value for testing + return returnData.values().iterator().next(); } @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/SimpleRSProcedureManager.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/SimpleRSProcedureManager.java index d277c3a..7620bbb 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/SimpleRSProcedureManager.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/SimpleRSProcedureManager.java @@ -249,7 +249,7 @@ public class SimpleRSProcedureManager extends RegionServerProcedureManager { @Override public byte[] insideBarrier() throws ForeignException { execute(); - return new byte[0]; + return SimpleMasterProcedureManager.SIMPLE_DATA.getBytes(); } /** diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/TestProcedureManager.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/TestProcedureManager.java index 8d9ec24..a5d934a 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/TestProcedureManager.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/procedure/TestProcedureManager.java @@ -27,6 +27,7 @@ import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.SmallTests; import org.apache.hadoop.hbase.client.HBaseAdmin; import org.junit.AfterClass; +import static org.junit.Assert.assertArrayEquals; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -60,7 +61,9 @@ public class TestProcedureManager { public void testSimpleProcedureManager() throws IOException { HBaseAdmin admin = util.getHBaseAdmin(); - admin.execProcedure(SimpleMasterProcedureManager.SIMPLE_SIGNATURE, + byte[] result = admin.execProcedure(SimpleMasterProcedureManager.SIMPLE_SIGNATURE, "mytest", new HashMap()); + assertArrayEquals("Incorrect return data from execProcedure", + SimpleMasterProcedureManager.SIMPLE_DATA.getBytes(), result); } }