001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.master;
020
021import java.io.IOException;
022import java.net.BindException;
023import java.net.InetAddress;
024import java.net.InetSocketAddress;
025import java.util.ArrayList;
026import java.util.HashMap;
027import java.util.HashSet;
028import java.util.List;
029import java.util.Map;
030import java.util.Map.Entry;
031import java.util.Set;
032import java.util.stream.Collectors;
033import org.apache.hadoop.conf.Configuration;
034import org.apache.hadoop.hbase.ClusterMetricsBuilder;
035import org.apache.hadoop.hbase.DoNotRetryIOException;
036import org.apache.hadoop.hbase.HConstants;
037import org.apache.hadoop.hbase.MetaTableAccessor;
038import org.apache.hadoop.hbase.NamespaceDescriptor;
039import org.apache.hadoop.hbase.Server;
040import org.apache.hadoop.hbase.ServerMetrics;
041import org.apache.hadoop.hbase.ServerMetricsBuilder;
042import org.apache.hadoop.hbase.ServerName;
043import org.apache.hadoop.hbase.TableName;
044import org.apache.hadoop.hbase.UnknownRegionException;
045import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
046import org.apache.hadoop.hbase.client.Connection;
047import org.apache.hadoop.hbase.client.MasterSwitchType;
048import org.apache.hadoop.hbase.client.RegionInfo;
049import org.apache.hadoop.hbase.client.RegionInfoBuilder;
050import org.apache.hadoop.hbase.client.TableDescriptor;
051import org.apache.hadoop.hbase.client.TableState;
052import org.apache.hadoop.hbase.client.VersionInfoUtil;
053import org.apache.hadoop.hbase.client.replication.ReplicationPeerConfigUtil;
054import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
055import org.apache.hadoop.hbase.errorhandling.ForeignException;
056import org.apache.hadoop.hbase.exceptions.UnknownProtocolException;
057import org.apache.hadoop.hbase.io.hfile.HFile;
058import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
059import org.apache.hadoop.hbase.ipc.PriorityFunction;
060import org.apache.hadoop.hbase.ipc.QosPriority;
061import org.apache.hadoop.hbase.ipc.RpcServer;
062import org.apache.hadoop.hbase.ipc.RpcServer.BlockingServiceAndInterface;
063import org.apache.hadoop.hbase.ipc.RpcServerFactory;
064import org.apache.hadoop.hbase.ipc.RpcServerInterface;
065import org.apache.hadoop.hbase.ipc.ServerRpcController;
066import org.apache.hadoop.hbase.master.assignment.RegionStates;
067import org.apache.hadoop.hbase.master.locking.LockProcedure;
068import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil;
069import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil.NonceProcedureRunnable;
070import org.apache.hadoop.hbase.mob.MobUtils;
071import org.apache.hadoop.hbase.procedure.MasterProcedureManager;
072import org.apache.hadoop.hbase.procedure2.LockType;
073import org.apache.hadoop.hbase.procedure2.LockedResource;
074import org.apache.hadoop.hbase.procedure2.Procedure;
075import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
076import org.apache.hadoop.hbase.procedure2.ProcedureUtil;
077import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
078import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService;
079import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
080import org.apache.hadoop.hbase.quotas.QuotaObserverChore;
081import org.apache.hadoop.hbase.quotas.QuotaUtil;
082import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
083import org.apache.hadoop.hbase.regionserver.RSRpcServices;
084import org.apache.hadoop.hbase.regionserver.RpcSchedulerFactory;
085import org.apache.hadoop.hbase.replication.ReplicationException;
086import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
087import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
088import org.apache.hadoop.hbase.security.User;
089import org.apache.hadoop.hbase.security.access.AccessChecker;
090import org.apache.hadoop.hbase.security.access.AccessController;
091import org.apache.hadoop.hbase.security.access.Permission;
092import org.apache.hadoop.hbase.security.visibility.VisibilityController;
093import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
094import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
095import org.apache.hadoop.hbase.util.Bytes;
096import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
097import org.apache.hadoop.hbase.util.ForeignExceptionUtil;
098import org.apache.hadoop.hbase.util.Pair;
099import org.apache.yetus.audience.InterfaceAudience;
100import org.apache.zookeeper.KeeperException;
101import org.slf4j.Logger;
102import org.slf4j.LoggerFactory;
103
104import org.apache.hbase.thirdparty.com.google.protobuf.RpcController;
105import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
106import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;
107
108import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
109import org.apache.hadoop.hbase.shaded.protobuf.ResponseConverter;
110import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactRegionRequest;
111import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactRegionResponse;
112import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest;
113import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse;
114import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos;
115import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos;
116import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;
117import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
118import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameStringPair;
119import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ProcedureDescription;
120import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
121import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockHeartbeatRequest;
122import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockHeartbeatResponse;
123import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockRequest;
124import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockResponse;
125import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockService;
126import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos;
127import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureRequest;
128import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureResponse;
129import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AddColumnRequest;
130import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AddColumnResponse;
131import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AssignRegionRequest;
132import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AssignRegionResponse;
133import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BalanceRequest;
134import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BalanceResponse;
135import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ClearDeadServersRequest;
136import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ClearDeadServersResponse;
137import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateNamespaceRequest;
138import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateNamespaceResponse;
139import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableRequest;
140import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableResponse;
141import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DecommissionRegionServersRequest;
142import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DecommissionRegionServersResponse;
143import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteColumnRequest;
144import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteColumnResponse;
145import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteNamespaceRequest;
146import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteNamespaceResponse;
147import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteSnapshotRequest;
148import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteSnapshotResponse;
149import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTableRequest;
150import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTableResponse;
151import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableRequest;
152import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableResponse;
153import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest;
154import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableCatalogJanitorResponse;
155import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableRequest;
156import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableResponse;
157import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ExecProcedureRequest;
158import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ExecProcedureResponse;
159import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetClusterStatusRequest;
160import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetClusterStatusResponse;
161import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetCompletedSnapshotsRequest;
162import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetCompletedSnapshotsResponse;
163import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetLocksRequest;
164import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetLocksResponse;
165import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest;
166import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorResponse;
167import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultRequest;
168import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultResponse;
169import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProceduresRequest;
170import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProceduresResponse;
171import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
172import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusResponse;
173import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
174import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
175import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesRequest;
176import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesResponse;
177import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateRequest;
178import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateResponse;
179import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.HbckService;
180import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsBalancerEnabledRequest;
181import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsBalancerEnabledResponse;
182import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
183import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledResponse;
184import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCleanerChoreEnabledRequest;
185import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCleanerChoreEnabledResponse;
186import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsInMaintenanceModeRequest;
187import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsInMaintenanceModeResponse;
188import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsMasterRunningRequest;
189import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsMasterRunningResponse;
190import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsNormalizerEnabledRequest;
191import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsNormalizerEnabledResponse;
192import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedureDoneRequest;
193import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedureDoneResponse;
194import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
195import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
196import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSplitOrMergeEnabledRequest;
197import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSplitOrMergeEnabledResponse;
198import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListDecommissionedRegionServersRequest;
199import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListDecommissionedRegionServersResponse;
200import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest;
201import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsResponse;
202import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceRequest;
203import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceResponse;
204import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableNamesByNamespaceRequest;
205import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableNamesByNamespaceResponse;
206import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MajorCompactionTimestampForRegionRequest;
207import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MajorCompactionTimestampRequest;
208import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MajorCompactionTimestampResponse;
209import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MasterService;
210import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MergeTableRegionsRequest;
211import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MergeTableRegionsResponse;
212import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyColumnRequest;
213import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyColumnResponse;
214import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyNamespaceRequest;
215import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyNamespaceResponse;
216import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyTableRequest;
217import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyTableResponse;
218import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MoveRegionRequest;
219import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MoveRegionResponse;
220import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.NormalizeRequest;
221import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.NormalizeResponse;
222import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.OfflineRegionRequest;
223import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.OfflineRegionResponse;
224import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RecommissionRegionServerRequest;
225import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RecommissionRegionServerResponse;
226import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
227import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
228import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanRequest;
229import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanResponse;
230import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreRequest;
231import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreResponse;
232import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
233import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse;
234import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
235import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
236import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest;
237import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningResponse;
238import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningRequest;
239import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningResponse;
240import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest;
241import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaResponse;
242import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledRequest;
243import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledResponse;
244import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetTableStateInMetaRequest;
245import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownRequest;
246import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownResponse;
247import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SnapshotRequest;
248import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SnapshotResponse;
249import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SplitTableRegionRequest;
250import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SplitTableRegionResponse;
251import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.StopMasterRequest;
252import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.StopMasterResponse;
253import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.TruncateTableRequest;
254import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.TruncateTableResponse;
255import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignRegionRequest;
256import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignRegionResponse;
257import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetQuotaStatesRequest;
258import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetQuotaStatesResponse;
259import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetQuotaStatesResponse.NamespaceQuotaSnapshot;
260import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetQuotaStatesResponse.TableQuotaSnapshot;
261import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaRegionSizesRequest;
262import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaRegionSizesResponse;
263import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaRegionSizesResponse.RegionSizes;
264import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdRequest;
265import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdResponse;
266import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest;
267import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerReportResponse;
268import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;
269import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupResponse;
270import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStatusService;
271import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionSpaceUse;
272import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionSpaceUseReportRequest;
273import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionSpaceUseReportResponse;
274import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRSFatalErrorRequest;
275import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRSFatalErrorResponse;
276import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionRequest;
277import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionResponse;
278import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.AddReplicationPeerRequest;
279import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.AddReplicationPeerResponse;
280import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.DisableReplicationPeerRequest;
281import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.DisableReplicationPeerResponse;
282import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.EnableReplicationPeerRequest;
283import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.EnableReplicationPeerResponse;
284import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerConfigRequest;
285import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerConfigResponse;
286import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.ListReplicationPeersRequest;
287import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.ListReplicationPeersResponse;
288import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.RemoveReplicationPeerRequest;
289import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.RemoveReplicationPeerResponse;
290import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.ReplicationState;
291import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigRequest;
292import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigResponse;
293import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;
294
295/**
296 * Implements the master RPC services.
297 */
298@InterfaceAudience.Private
299@SuppressWarnings("deprecation")
300public class MasterRpcServices extends RSRpcServices
301      implements MasterService.BlockingInterface, RegionServerStatusService.BlockingInterface,
302        LockService.BlockingInterface, HbckService.BlockingInterface {
303  private static final Logger LOG = LoggerFactory.getLogger(MasterRpcServices.class.getName());
304
305  private final HMaster master;
306
307  /**
308   * @return Subset of configuration to pass initializing regionservers: e.g.
309   * the filesystem to use and root directory to use.
310   */
311  private RegionServerStartupResponse.Builder createConfigurationSubset() {
312    RegionServerStartupResponse.Builder resp = addConfig(
313      RegionServerStartupResponse.newBuilder(), HConstants.HBASE_DIR);
314    resp = addConfig(resp, "fs.defaultFS");
315    return addConfig(resp, "hbase.master.info.port");
316  }
317
318  private RegionServerStartupResponse.Builder addConfig(
319      final RegionServerStartupResponse.Builder resp, final String key) {
320    NameStringPair.Builder entry = NameStringPair.newBuilder()
321      .setName(key)
322      .setValue(master.getConfiguration().get(key));
323    resp.addMapEntries(entry.build());
324    return resp;
325  }
326
327  public MasterRpcServices(HMaster m) throws IOException {
328    super(m);
329    master = m;
330  }
331
332  @Override
333  protected RpcServerInterface createRpcServer(Server server, Configuration conf,
334      RpcSchedulerFactory rpcSchedulerFactory, InetSocketAddress bindAddress, String name)
335      throws IOException {
336    // RpcServer at HM by default enable ByteBufferPool iff HM having user table region in it
337    boolean reservoirEnabled = conf.getBoolean(RESERVOIR_ENABLED_KEY,
338        (LoadBalancer.isTablesOnMaster(conf) && !LoadBalancer.isSystemTablesOnlyOnMaster(conf)));
339    try {
340      return RpcServerFactory.createRpcServer(server, name, getServices(),
341          bindAddress, // use final bindAddress for this server.
342          conf, rpcSchedulerFactory.create(conf, this, server), reservoirEnabled);
343    } catch (BindException be) {
344      throw new IOException(be.getMessage() + ". To switch ports use the '"
345          + HConstants.MASTER_PORT + "' configuration property.",
346          be.getCause() != null ? be.getCause() : be);
347    }
348  }
349
350  @Override
351  protected PriorityFunction createPriority() {
352    return new MasterAnnotationReadingPriorityFunction(this);
353  }
354
355  /**
356   * Checks for the following pre-checks in order:
357   * <ol>
358   *   <li>Master is initialized</li>
359   *   <li>Rpc caller has admin permissions</li>
360   * </ol>
361   * @param requestName name of rpc request. Used in reporting failures to provide context.
362   * @throws ServiceException If any of the above listed pre-check fails.
363   */
364  private void rpcPreCheck(String requestName) throws ServiceException {
365    try {
366      master.checkInitialized();
367      requirePermission(requestName, Permission.Action.ADMIN);
368    } catch (IOException ioe) {
369      throw new ServiceException(ioe);
370    }
371  }
372
373  enum BalanceSwitchMode {
374    SYNC,
375    ASYNC
376  }
377
378  /**
379   * Assigns balancer switch according to BalanceSwitchMode
380   * @param b new balancer switch
381   * @param mode BalanceSwitchMode
382   * @return old balancer switch
383   */
384  boolean switchBalancer(final boolean b, BalanceSwitchMode mode) throws IOException {
385    boolean oldValue = master.loadBalancerTracker.isBalancerOn();
386    boolean newValue = b;
387    try {
388      if (master.cpHost != null) {
389        master.cpHost.preBalanceSwitch(newValue);
390      }
391      try {
392        if (mode == BalanceSwitchMode.SYNC) {
393          synchronized (master.getLoadBalancer()) {
394            master.loadBalancerTracker.setBalancerOn(newValue);
395          }
396        } else {
397          master.loadBalancerTracker.setBalancerOn(newValue);
398        }
399      } catch (KeeperException ke) {
400        throw new IOException(ke);
401      }
402      LOG.info(master.getClientIdAuditPrefix() + " set balanceSwitch=" + newValue);
403      if (master.cpHost != null) {
404        master.cpHost.postBalanceSwitch(oldValue, newValue);
405      }
406    } catch (IOException ioe) {
407      LOG.warn("Error flipping balance switch", ioe);
408    }
409    return oldValue;
410  }
411
412  boolean synchronousBalanceSwitch(final boolean b) throws IOException {
413    return switchBalancer(b, BalanceSwitchMode.SYNC);
414  }
415
416  /**
417   * @return list of blocking services and their security info classes that this server supports
418   */
419  @Override
420  protected List<BlockingServiceAndInterface> getServices() {
421    List<BlockingServiceAndInterface> bssi = new ArrayList<>(5);
422    bssi.add(new BlockingServiceAndInterface(
423      MasterService.newReflectiveBlockingService(this),
424      MasterService.BlockingInterface.class));
425    bssi.add(new BlockingServiceAndInterface(
426      RegionServerStatusService.newReflectiveBlockingService(this),
427      RegionServerStatusService.BlockingInterface.class));
428    bssi.add(new BlockingServiceAndInterface(LockService.newReflectiveBlockingService(this),
429        LockService.BlockingInterface.class));
430    bssi.add(new BlockingServiceAndInterface(HbckService.newReflectiveBlockingService(this),
431        HbckService.BlockingInterface.class));
432    bssi.addAll(super.getServices());
433    return bssi;
434  }
435
436  @Override
437  @QosPriority(priority = HConstants.ADMIN_QOS)
438  public GetLastFlushedSequenceIdResponse getLastFlushedSequenceId(RpcController controller,
439      GetLastFlushedSequenceIdRequest request) throws ServiceException {
440    try {
441      master.checkServiceStarted();
442    } catch (IOException ioe) {
443      throw new ServiceException(ioe);
444    }
445    byte[] encodedRegionName = request.getRegionName().toByteArray();
446    RegionStoreSequenceIds ids = master.getServerManager()
447      .getLastFlushedSequenceId(encodedRegionName);
448    return ResponseConverter.buildGetLastFlushedSequenceIdResponse(ids);
449  }
450
451  @Override
452  public RegionServerReportResponse regionServerReport(
453      RpcController controller, RegionServerReportRequest request) throws ServiceException {
454    try {
455      master.checkServiceStarted();
456      int version = VersionInfoUtil.getCurrentClientVersionNumber();
457      ClusterStatusProtos.ServerLoad sl = request.getLoad();
458      ServerName serverName = ProtobufUtil.toServerName(request.getServer());
459      ServerMetrics oldLoad = master.getServerManager().getLoad(serverName);
460      ServerMetrics newLoad = ServerMetricsBuilder.toServerMetrics(serverName, version, sl);
461      master.getServerManager().regionServerReport(serverName, newLoad);
462      master.getAssignmentManager()
463          .reportOnlineRegions(serverName, newLoad.getRegionMetrics().keySet());
464      if (sl != null && master.metricsMaster != null) {
465        // Up our metrics.
466        master.metricsMaster.incrementRequests(sl.getTotalNumberOfRequests()
467            - (oldLoad != null ? oldLoad.getRequestCount() : 0));
468      }
469    } catch (IOException ioe) {
470      throw new ServiceException(ioe);
471    }
472    return RegionServerReportResponse.newBuilder().build();
473  }
474
475  @Override
476  public RegionServerStartupResponse regionServerStartup(
477      RpcController controller, RegionServerStartupRequest request) throws ServiceException {
478    // Register with server manager
479    try {
480      master.checkServiceStarted();
481      int version = VersionInfoUtil.getCurrentClientVersionNumber();
482      InetAddress ia = master.getRemoteInetAddress(
483        request.getPort(), request.getServerStartCode());
484      // if regionserver passed hostname to use,
485      // then use it instead of doing a reverse DNS lookup
486      ServerName rs = master.getServerManager().regionServerStartup(request, version, ia);
487
488      // Send back some config info
489      RegionServerStartupResponse.Builder resp = createConfigurationSubset();
490      NameStringPair.Builder entry = NameStringPair.newBuilder()
491        .setName(HConstants.KEY_FOR_HOSTNAME_SEEN_BY_MASTER)
492        .setValue(rs.getHostname());
493      resp.addMapEntries(entry.build());
494
495      return resp.build();
496    } catch (IOException ioe) {
497      throw new ServiceException(ioe);
498    }
499  }
500
501  @Override
502  public ReportRSFatalErrorResponse reportRSFatalError(
503      RpcController controller, ReportRSFatalErrorRequest request) throws ServiceException {
504    String errorText = request.getErrorMessage();
505    ServerName sn = ProtobufUtil.toServerName(request.getServer());
506    String msg = "Region server " + sn
507      + " reported a fatal error:\n" + errorText;
508    LOG.error(msg);
509    master.rsFatals.add(msg);
510    return ReportRSFatalErrorResponse.newBuilder().build();
511  }
512
513  @Override
514  public AddColumnResponse addColumn(RpcController controller,
515      AddColumnRequest req) throws ServiceException {
516    try {
517      long procId = master.addColumn(
518          ProtobufUtil.toTableName(req.getTableName()),
519          ProtobufUtil.toColumnFamilyDescriptor(req.getColumnFamilies()),
520          req.getNonceGroup(),
521          req.getNonce());
522      if (procId == -1) {
523        // This mean operation was not performed in server, so do not set any procId
524        return AddColumnResponse.newBuilder().build();
525      } else {
526        return AddColumnResponse.newBuilder().setProcId(procId).build();
527      }
528    } catch (IOException ioe) {
529      throw new ServiceException(ioe);
530    }
531  }
532
533  @Override
534  public AssignRegionResponse assignRegion(RpcController controller,
535      AssignRegionRequest req) throws ServiceException {
536    try {
537      master.checkInitialized();
538
539      final RegionSpecifierType type = req.getRegion().getType();
540      if (type != RegionSpecifierType.REGION_NAME) {
541        LOG.warn("assignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
542          + " actual: " + type);
543      }
544
545      final byte[] regionName = req.getRegion().getValue().toByteArray();
546      final RegionInfo regionInfo = master.getAssignmentManager().getRegionInfo(regionName);
547      if (regionInfo == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName));
548
549      final AssignRegionResponse arr = AssignRegionResponse.newBuilder().build();
550      if (master.cpHost != null) {
551        master.cpHost.preAssign(regionInfo);
552      }
553      LOG.info(master.getClientIdAuditPrefix() + " assign " + regionInfo.getRegionNameAsString());
554      master.getAssignmentManager().assign(regionInfo);
555      if (master.cpHost != null) {
556        master.cpHost.postAssign(regionInfo);
557      }
558      return arr;
559    } catch (IOException ioe) {
560      throw new ServiceException(ioe);
561    }
562  }
563
564
565  @Override
566  public BalanceResponse balance(RpcController controller,
567      BalanceRequest request) throws ServiceException {
568    try {
569      return BalanceResponse.newBuilder().setBalancerRan(master.balance(
570        request.hasForce() ? request.getForce() : false)).build();
571    } catch (IOException ex) {
572      throw new ServiceException(ex);
573    }
574  }
575
576  @Override
577  public CreateNamespaceResponse createNamespace(RpcController controller,
578     CreateNamespaceRequest request) throws ServiceException {
579    try {
580      long procId = master.createNamespace(
581        ProtobufUtil.toNamespaceDescriptor(request.getNamespaceDescriptor()),
582        request.getNonceGroup(),
583        request.getNonce());
584      return CreateNamespaceResponse.newBuilder().setProcId(procId).build();
585    } catch (IOException e) {
586      throw new ServiceException(e);
587    }
588  }
589
590  @Override
591  public CreateTableResponse createTable(RpcController controller, CreateTableRequest req)
592  throws ServiceException {
593    TableDescriptor tableDescriptor = ProtobufUtil.toTableDescriptor(req.getTableSchema());
594    byte [][] splitKeys = ProtobufUtil.getSplitKeysArray(req);
595    try {
596      long procId =
597          master.createTable(tableDescriptor, splitKeys, req.getNonceGroup(), req.getNonce());
598      LOG.info(master.getClientIdAuditPrefix() + " procedure request for creating table: " +
599              req.getTableSchema().getTableName() + " procId is: " + procId);
600      return CreateTableResponse.newBuilder().setProcId(procId).build();
601    } catch (IOException ioe) {
602      throw new ServiceException(ioe);
603    }
604  }
605
606  @Override
607  public DeleteColumnResponse deleteColumn(RpcController controller,
608      DeleteColumnRequest req) throws ServiceException {
609    try {
610      long procId = master.deleteColumn(
611        ProtobufUtil.toTableName(req.getTableName()),
612        req.getColumnName().toByteArray(),
613        req.getNonceGroup(),
614        req.getNonce());
615      if (procId == -1) {
616        // This mean operation was not performed in server, so do not set any procId
617        return DeleteColumnResponse.newBuilder().build();
618      } else {
619        return DeleteColumnResponse.newBuilder().setProcId(procId).build();
620      }
621    } catch (IOException ioe) {
622      throw new ServiceException(ioe);
623    }
624  }
625
626  @Override
627  public DeleteNamespaceResponse deleteNamespace(RpcController controller,
628      DeleteNamespaceRequest request) throws ServiceException {
629    try {
630      long procId = master.deleteNamespace(
631        request.getNamespaceName(),
632        request.getNonceGroup(),
633        request.getNonce());
634      return DeleteNamespaceResponse.newBuilder().setProcId(procId).build();
635    } catch (IOException e) {
636      throw new ServiceException(e);
637    }
638  }
639
640  /**
641   * Execute Delete Snapshot operation.
642   * @return DeleteSnapshotResponse (a protobuf wrapped void) if the snapshot existed and was
643   *    deleted properly.
644   * @throws ServiceException wrapping SnapshotDoesNotExistException if specified snapshot did not
645   *    exist.
646   */
647  @Override
648  public DeleteSnapshotResponse deleteSnapshot(RpcController controller,
649      DeleteSnapshotRequest request) throws ServiceException {
650    try {
651      master.checkInitialized();
652      master.snapshotManager.checkSnapshotSupport();
653
654      LOG.info(master.getClientIdAuditPrefix() + " delete " + request.getSnapshot());
655      master.snapshotManager.deleteSnapshot(request.getSnapshot());
656      return DeleteSnapshotResponse.newBuilder().build();
657    } catch (IOException e) {
658      throw new ServiceException(e);
659    }
660  }
661
662  @Override
663  public DeleteTableResponse deleteTable(RpcController controller,
664      DeleteTableRequest request) throws ServiceException {
665    try {
666      long procId = master.deleteTable(ProtobufUtil.toTableName(
667          request.getTableName()), request.getNonceGroup(), request.getNonce());
668      return DeleteTableResponse.newBuilder().setProcId(procId).build();
669    } catch (IOException ioe) {
670      throw new ServiceException(ioe);
671    }
672  }
673
674  @Override
675  public TruncateTableResponse truncateTable(RpcController controller, TruncateTableRequest request)
676      throws ServiceException {
677    try {
678      long procId = master.truncateTable(
679        ProtobufUtil.toTableName(request.getTableName()),
680        request.getPreserveSplits(),
681        request.getNonceGroup(),
682        request.getNonce());
683      return TruncateTableResponse.newBuilder().setProcId(procId).build();
684    } catch (IOException ioe) {
685      throw new ServiceException(ioe);
686    }
687  }
688
689  @Override
690  public DisableTableResponse disableTable(RpcController controller,
691      DisableTableRequest request) throws ServiceException {
692    try {
693      long procId = master.disableTable(
694        ProtobufUtil.toTableName(request.getTableName()),
695        request.getNonceGroup(),
696        request.getNonce());
697      return DisableTableResponse.newBuilder().setProcId(procId).build();
698    } catch (IOException ioe) {
699      throw new ServiceException(ioe);
700    }
701  }
702
703  @Override
704  public EnableCatalogJanitorResponse enableCatalogJanitor(RpcController c,
705      EnableCatalogJanitorRequest req) throws ServiceException {
706    rpcPreCheck("enableCatalogJanitor");
707    return EnableCatalogJanitorResponse.newBuilder().setPrevValue(
708      master.catalogJanitorChore.setEnabled(req.getEnable())).build();
709  }
710
711  @Override
712  public SetCleanerChoreRunningResponse setCleanerChoreRunning(
713    RpcController c, SetCleanerChoreRunningRequest req) throws ServiceException {
714    rpcPreCheck("setCleanerChoreRunning");
715
716    boolean prevValue =
717      master.getLogCleaner().getEnabled() && master.getHFileCleaner().getEnabled();
718    master.getLogCleaner().setEnabled(req.getOn());
719    master.getHFileCleaner().setEnabled(req.getOn());
720    return SetCleanerChoreRunningResponse.newBuilder().setPrevValue(prevValue).build();
721  }
722
723  @Override
724  public EnableTableResponse enableTable(RpcController controller,
725      EnableTableRequest request) throws ServiceException {
726    try {
727      long procId = master.enableTable(
728        ProtobufUtil.toTableName(request.getTableName()),
729        request.getNonceGroup(),
730        request.getNonce());
731      return EnableTableResponse.newBuilder().setProcId(procId).build();
732    } catch (IOException ioe) {
733      throw new ServiceException(ioe);
734    }
735  }
736
737  @Override
738  public MergeTableRegionsResponse mergeTableRegions(
739      RpcController c, MergeTableRegionsRequest request) throws ServiceException {
740    try {
741      master.checkInitialized();
742    } catch (IOException ioe) {
743      throw new ServiceException(ioe);
744    }
745
746    RegionStates regionStates = master.getAssignmentManager().getRegionStates();
747
748    assert(request.getRegionCount() == 2);
749    RegionInfo[] regionsToMerge = new RegionInfo[request.getRegionCount()];
750    for (int i = 0; i < request.getRegionCount(); i++) {
751      final byte[] encodedNameOfRegion = request.getRegion(i).getValue().toByteArray();
752      if (request.getRegion(i).getType() != RegionSpecifierType.ENCODED_REGION_NAME) {
753        LOG.warn("MergeRegions specifier type: expected: "
754          + RegionSpecifierType.ENCODED_REGION_NAME + " actual: region " + i + " ="
755          + request.getRegion(i).getType());
756      }
757      RegionState regionState = regionStates.getRegionState(Bytes.toString(encodedNameOfRegion));
758      if (regionState == null) {
759        throw new ServiceException(
760          new UnknownRegionException(Bytes.toStringBinary(encodedNameOfRegion)));
761      }
762      regionsToMerge[i] = regionState.getRegion();
763    }
764
765    try {
766      long procId = master.mergeRegions(
767        regionsToMerge,
768        request.getForcible(),
769        request.getNonceGroup(),
770        request.getNonce());
771      return MergeTableRegionsResponse.newBuilder().setProcId(procId).build();
772    } catch (IOException ioe) {
773      throw new ServiceException(ioe);
774    }
775  }
776
777  @Override
778  public SplitTableRegionResponse splitRegion(final RpcController controller,
779      final SplitTableRegionRequest request) throws ServiceException {
780    try {
781      long procId = master.splitRegion(
782        ProtobufUtil.toRegionInfo(request.getRegionInfo()),
783        request.hasSplitRow() ? request.getSplitRow().toByteArray() : null,
784        request.getNonceGroup(),
785        request.getNonce());
786      return SplitTableRegionResponse.newBuilder().setProcId(procId).build();
787    } catch (IOException ie) {
788      throw new ServiceException(ie);
789    }
790  }
791
792  @Override
793  public ClientProtos.CoprocessorServiceResponse execMasterService(final RpcController controller,
794      final ClientProtos.CoprocessorServiceRequest request) throws ServiceException {
795    rpcPreCheck("execMasterService");
796    try {
797      ServerRpcController execController = new ServerRpcController();
798      ClientProtos.CoprocessorServiceCall call = request.getCall();
799      String serviceName = call.getServiceName();
800      String methodName = call.getMethodName();
801      if (!master.coprocessorServiceHandlers.containsKey(serviceName)) {
802        throw new UnknownProtocolException(null,
803          "No registered Master Coprocessor Endpoint found for " + serviceName +
804          ". Has it been enabled?");
805      }
806
807      com.google.protobuf.Service service = master.coprocessorServiceHandlers.get(serviceName);
808      com.google.protobuf.Descriptors.ServiceDescriptor serviceDesc = service.getDescriptorForType();
809      com.google.protobuf.Descriptors.MethodDescriptor methodDesc =
810          CoprocessorRpcUtils.getMethodDescriptor(methodName, serviceDesc);
811
812      com.google.protobuf.Message execRequest =
813          CoprocessorRpcUtils.getRequest(service, methodDesc, call.getRequest());
814      final com.google.protobuf.Message.Builder responseBuilder =
815          service.getResponsePrototype(methodDesc).newBuilderForType();
816      service.callMethod(methodDesc, execController, execRequest,
817        (message) -> {
818          if (message != null) {
819            responseBuilder.mergeFrom(message);
820          }
821        });
822      com.google.protobuf.Message execResult = responseBuilder.build();
823      if (execController.getFailedOn() != null) {
824        throw execController.getFailedOn();
825      }
826      return CoprocessorRpcUtils.getResponse(execResult, HConstants.EMPTY_BYTE_ARRAY);
827    } catch (IOException ie) {
828      throw new ServiceException(ie);
829    }
830  }
831
832  /**
833   * Triggers an asynchronous attempt to run a distributed procedure.
834   * {@inheritDoc}
835   */
836  @Override
837  public ExecProcedureResponse execProcedure(RpcController controller,
838      ExecProcedureRequest request) throws ServiceException {
839    try {
840      master.checkInitialized();
841      ProcedureDescription desc = request.getProcedure();
842      MasterProcedureManager mpm = master.getMasterProcedureManagerHost().getProcedureManager(
843        desc.getSignature());
844      if (mpm == null) {
845        throw new ServiceException(new DoNotRetryIOException("The procedure is not registered: "
846          + desc.getSignature()));
847      }
848      LOG.info(master.getClientIdAuditPrefix() + " procedure request for: " + desc.getSignature());
849      mpm.checkPermissions(desc, accessChecker, RpcServer.getRequestUser().orElse(null));
850      mpm.execProcedure(desc);
851      // send back the max amount of time the client should wait for the procedure
852      // to complete
853      long waitTime = SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME;
854      return ExecProcedureResponse.newBuilder().setExpectedTimeout(
855        waitTime).build();
856    } catch (ForeignException e) {
857      throw new ServiceException(e.getCause());
858    } catch (IOException e) {
859      throw new ServiceException(e);
860    }
861  }
862
863  /**
864   * Triggers a synchronous attempt to run a distributed procedure and sets
865   * return data in response.
866   * {@inheritDoc}
867   */
868  @Override
869  public ExecProcedureResponse execProcedureWithRet(RpcController controller,
870      ExecProcedureRequest request) throws ServiceException {
871    rpcPreCheck("execProcedureWithRet");
872    try {
873      ProcedureDescription desc = request.getProcedure();
874      MasterProcedureManager mpm =
875        master.getMasterProcedureManagerHost().getProcedureManager(desc.getSignature());
876      if (mpm == null) {
877        throw new ServiceException("The procedure is not registered: " + desc.getSignature());
878      }
879      LOG.info(master.getClientIdAuditPrefix() + " procedure request for: " + desc.getSignature());
880      byte[] data = mpm.execProcedureWithRet(desc);
881      ExecProcedureResponse.Builder builder = ExecProcedureResponse.newBuilder();
882      // set return data if available
883      if (data != null) {
884        builder.setReturnData(UnsafeByteOperations.unsafeWrap(data));
885      }
886      return builder.build();
887    } catch (IOException e) {
888      throw new ServiceException(e);
889    }
890  }
891
892  @Override
893  public GetClusterStatusResponse getClusterStatus(RpcController controller,
894      GetClusterStatusRequest req) throws ServiceException {
895    GetClusterStatusResponse.Builder response = GetClusterStatusResponse.newBuilder();
896    try {
897      master.checkInitialized();
898      response.setClusterStatus(ClusterMetricsBuilder.toClusterStatus(
899        master.getClusterMetrics(ClusterMetricsBuilder.toOptions(req.getOptionsList()))));
900    } catch (IOException e) {
901      throw new ServiceException(e);
902    }
903    return response.build();
904  }
905
906  /**
907   * List the currently available/stored snapshots. Any in-progress snapshots are ignored
908   */
909  @Override
910  public GetCompletedSnapshotsResponse getCompletedSnapshots(RpcController controller,
911      GetCompletedSnapshotsRequest request) throws ServiceException {
912    try {
913      master.checkInitialized();
914      GetCompletedSnapshotsResponse.Builder builder = GetCompletedSnapshotsResponse.newBuilder();
915      List<SnapshotDescription> snapshots = master.snapshotManager.getCompletedSnapshots();
916
917      // convert to protobuf
918      for (SnapshotDescription snapshot : snapshots) {
919        builder.addSnapshots(snapshot);
920      }
921      return builder.build();
922    } catch (IOException e) {
923      throw new ServiceException(e);
924    }
925  }
926
927  @Override
928  public GetNamespaceDescriptorResponse getNamespaceDescriptor(
929      RpcController controller, GetNamespaceDescriptorRequest request)
930      throws ServiceException {
931    try {
932      return GetNamespaceDescriptorResponse.newBuilder()
933        .setNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(
934            master.getNamespace(request.getNamespaceName())))
935        .build();
936    } catch (IOException e) {
937      throw new ServiceException(e);
938    }
939  }
940
941  /**
942   * Get the number of regions of the table that have been updated by the alter.
943   *
944   * @return Pair indicating the number of regions updated Pair.getFirst is the
945   *         regions that are yet to be updated Pair.getSecond is the total number
946   *         of regions of the table
947   * @throws ServiceException
948   */
949  @Override
950  public GetSchemaAlterStatusResponse getSchemaAlterStatus(
951      RpcController controller, GetSchemaAlterStatusRequest req) throws ServiceException {
952    // TODO: currently, we query using the table name on the client side. this
953    // may overlap with other table operations or the table operation may
954    // have completed before querying this API. We need to refactor to a
955    // transaction system in the future to avoid these ambiguities.
956    TableName tableName = ProtobufUtil.toTableName(req.getTableName());
957
958    try {
959      master.checkInitialized();
960      Pair<Integer,Integer> pair = master.getAssignmentManager().getReopenStatus(tableName);
961      GetSchemaAlterStatusResponse.Builder ret = GetSchemaAlterStatusResponse.newBuilder();
962      ret.setYetToUpdateRegions(pair.getFirst());
963      ret.setTotalRegions(pair.getSecond());
964      return ret.build();
965    } catch (IOException ioe) {
966      throw new ServiceException(ioe);
967    }
968  }
969
970  /**
971   * Get list of TableDescriptors for requested tables.
972   * @param c Unused (set to null).
973   * @param req GetTableDescriptorsRequest that contains:
974   * - tableNames: requested tables, or if empty, all are requested
975   * @return GetTableDescriptorsResponse
976   * @throws ServiceException
977   */
978  @Override
979  public GetTableDescriptorsResponse getTableDescriptors(RpcController c,
980      GetTableDescriptorsRequest req) throws ServiceException {
981    try {
982      master.checkInitialized();
983
984      final String regex = req.hasRegex() ? req.getRegex() : null;
985      final String namespace = req.hasNamespace() ? req.getNamespace() : null;
986      List<TableName> tableNameList = null;
987      if (req.getTableNamesCount() > 0) {
988        tableNameList = new ArrayList<TableName>(req.getTableNamesCount());
989        for (HBaseProtos.TableName tableNamePB: req.getTableNamesList()) {
990          tableNameList.add(ProtobufUtil.toTableName(tableNamePB));
991        }
992      }
993
994      List<TableDescriptor> descriptors = master.listTableDescriptors(namespace, regex,
995          tableNameList, req.getIncludeSysTables());
996
997      GetTableDescriptorsResponse.Builder builder = GetTableDescriptorsResponse.newBuilder();
998      if (descriptors != null && descriptors.size() > 0) {
999        // Add the table descriptors to the response
1000        for (TableDescriptor htd: descriptors) {
1001          builder.addTableSchema(ProtobufUtil.toTableSchema(htd));
1002        }
1003      }
1004      return builder.build();
1005    } catch (IOException ioe) {
1006      throw new ServiceException(ioe);
1007    }
1008  }
1009
1010  /**
1011   * Get list of userspace table names
1012   * @param controller Unused (set to null).
1013   * @param req GetTableNamesRequest
1014   * @return GetTableNamesResponse
1015   * @throws ServiceException
1016   */
1017  @Override
1018  public GetTableNamesResponse getTableNames(RpcController controller,
1019      GetTableNamesRequest req) throws ServiceException {
1020    try {
1021      master.checkServiceStarted();
1022
1023      final String regex = req.hasRegex() ? req.getRegex() : null;
1024      final String namespace = req.hasNamespace() ? req.getNamespace() : null;
1025      List<TableName> tableNames = master.listTableNames(namespace, regex,
1026          req.getIncludeSysTables());
1027
1028      GetTableNamesResponse.Builder builder = GetTableNamesResponse.newBuilder();
1029      if (tableNames != null && tableNames.size() > 0) {
1030        // Add the table names to the response
1031        for (TableName table: tableNames) {
1032          builder.addTableNames(ProtobufUtil.toProtoTableName(table));
1033        }
1034      }
1035      return builder.build();
1036    } catch (IOException e) {
1037      throw new ServiceException(e);
1038    }
1039  }
1040
1041  @Override
1042  public GetTableStateResponse getTableState(RpcController controller,
1043      GetTableStateRequest request) throws ServiceException {
1044    try {
1045      master.checkServiceStarted();
1046      TableName tableName = ProtobufUtil.toTableName(request.getTableName());
1047      TableState ts = master.getTableStateManager().getTableState(tableName);
1048      GetTableStateResponse.Builder builder = GetTableStateResponse.newBuilder();
1049      builder.setTableState(ts.convert());
1050      return builder.build();
1051    } catch (IOException e) {
1052      throw new ServiceException(e);
1053    }
1054  }
1055
1056  @Override
1057  public IsCatalogJanitorEnabledResponse isCatalogJanitorEnabled(RpcController c,
1058      IsCatalogJanitorEnabledRequest req) throws ServiceException {
1059    return IsCatalogJanitorEnabledResponse.newBuilder().setValue(
1060      master.isCatalogJanitorEnabled()).build();
1061  }
1062
1063  @Override
1064  public IsCleanerChoreEnabledResponse isCleanerChoreEnabled(RpcController c,
1065                                                             IsCleanerChoreEnabledRequest req)
1066    throws ServiceException {
1067    return IsCleanerChoreEnabledResponse.newBuilder().setValue(master.isCleanerChoreEnabled())
1068                                        .build();
1069  }
1070
1071  @Override
1072  public IsMasterRunningResponse isMasterRunning(RpcController c,
1073      IsMasterRunningRequest req) throws ServiceException {
1074    try {
1075      master.checkServiceStarted();
1076      return IsMasterRunningResponse.newBuilder().setIsMasterRunning(
1077        !master.isStopped()).build();
1078    } catch (IOException e) {
1079      throw new ServiceException(e);
1080    }
1081  }
1082
1083  /**
1084   * Checks if the specified procedure is done.
1085   * @return true if the procedure is done, false if the procedure is in the process of completing
1086   * @throws ServiceException if invalid procedure or failed procedure with progress failure reason.
1087   */
1088  @Override
1089  public IsProcedureDoneResponse isProcedureDone(RpcController controller,
1090      IsProcedureDoneRequest request) throws ServiceException {
1091    try {
1092      master.checkInitialized();
1093      ProcedureDescription desc = request.getProcedure();
1094      MasterProcedureManager mpm = master.getMasterProcedureManagerHost().getProcedureManager(
1095        desc.getSignature());
1096      if (mpm == null) {
1097        throw new ServiceException("The procedure is not registered: "
1098          + desc.getSignature());
1099      }
1100      LOG.debug("Checking to see if procedure from request:"
1101        + desc.getSignature() + " is done");
1102
1103      IsProcedureDoneResponse.Builder builder =
1104        IsProcedureDoneResponse.newBuilder();
1105      boolean done = mpm.isProcedureDone(desc);
1106      builder.setDone(done);
1107      return builder.build();
1108    } catch (ForeignException e) {
1109      throw new ServiceException(e.getCause());
1110    } catch (IOException e) {
1111      throw new ServiceException(e);
1112    }
1113  }
1114
1115  /**
1116   * Checks if the specified snapshot is done.
1117   * @return true if the snapshot is in file system ready to use,
1118   *   false if the snapshot is in the process of completing
1119   * @throws ServiceException wrapping UnknownSnapshotException if invalid snapshot, or
1120   *  a wrapped HBaseSnapshotException with progress failure reason.
1121   */
1122  @Override
1123  public IsSnapshotDoneResponse isSnapshotDone(RpcController controller,
1124      IsSnapshotDoneRequest request) throws ServiceException {
1125    LOG.debug("Checking to see if snapshot from request:" +
1126      ClientSnapshotDescriptionUtils.toString(request.getSnapshot()) + " is done");
1127    try {
1128      master.checkInitialized();
1129      IsSnapshotDoneResponse.Builder builder = IsSnapshotDoneResponse.newBuilder();
1130      boolean done = master.snapshotManager.isSnapshotDone(request.getSnapshot());
1131      builder.setDone(done);
1132      return builder.build();
1133    } catch (ForeignException e) {
1134      throw new ServiceException(e.getCause());
1135    } catch (IOException e) {
1136      throw new ServiceException(e);
1137    }
1138  }
1139
1140  @Override
1141  public GetProcedureResultResponse getProcedureResult(RpcController controller,
1142      GetProcedureResultRequest request) throws ServiceException {
1143    LOG.debug("Checking to see if procedure is done pid=" + request.getProcId());
1144    try {
1145      master.checkInitialized();
1146      GetProcedureResultResponse.Builder builder = GetProcedureResultResponse.newBuilder();
1147      long procId = request.getProcId();
1148      ProcedureExecutor<?> executor = master.getMasterProcedureExecutor();
1149      Procedure<?> result = executor.getResultOrProcedure(procId);
1150      if (result != null) {
1151        builder.setSubmittedTime(result.getSubmittedTime());
1152        builder.setLastUpdate(result.getLastUpdate());
1153        if (executor.isFinished(procId)) {
1154          builder.setState(GetProcedureResultResponse.State.FINISHED);
1155          if (result.isFailed()) {
1156            IOException exception = result.getException().unwrapRemoteIOException();
1157            builder.setException(ForeignExceptionUtil.toProtoForeignException(exception));
1158          }
1159          byte[] resultData = result.getResult();
1160          if (resultData != null) {
1161            builder.setResult(UnsafeByteOperations.unsafeWrap(resultData));
1162          }
1163          master.getMasterProcedureExecutor().removeResult(request.getProcId());
1164        } else {
1165          builder.setState(GetProcedureResultResponse.State.RUNNING);
1166        }
1167      } else {
1168        builder.setState(GetProcedureResultResponse.State.NOT_FOUND);
1169      }
1170      return builder.build();
1171    } catch (IOException e) {
1172      throw new ServiceException(e);
1173    }
1174  }
1175
1176  @Override
1177  public AbortProcedureResponse abortProcedure(
1178      RpcController rpcController, AbortProcedureRequest request) throws ServiceException {
1179    try {
1180      AbortProcedureResponse.Builder response = AbortProcedureResponse.newBuilder();
1181      boolean abortResult =
1182          master.abortProcedure(request.getProcId(), request.getMayInterruptIfRunning());
1183      response.setIsProcedureAborted(abortResult);
1184      return response.build();
1185    } catch (IOException e) {
1186      throw new ServiceException(e);
1187    }
1188  }
1189
1190  @Override
1191  public ListNamespaceDescriptorsResponse listNamespaceDescriptors(RpcController c,
1192      ListNamespaceDescriptorsRequest request) throws ServiceException {
1193    try {
1194      ListNamespaceDescriptorsResponse.Builder response =
1195        ListNamespaceDescriptorsResponse.newBuilder();
1196      for(NamespaceDescriptor ns: master.getNamespaces()) {
1197        response.addNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(ns));
1198      }
1199      return response.build();
1200    } catch (IOException e) {
1201      throw new ServiceException(e);
1202    }
1203  }
1204
1205  @Override
1206  public GetProceduresResponse getProcedures(
1207      RpcController rpcController,
1208      GetProceduresRequest request) throws ServiceException {
1209    try {
1210      final GetProceduresResponse.Builder response = GetProceduresResponse.newBuilder();
1211      for (Procedure<?> p: master.getProcedures()) {
1212        response.addProcedure(ProcedureUtil.convertToProtoProcedure(p));
1213      }
1214      return response.build();
1215    } catch (IOException e) {
1216      throw new ServiceException(e);
1217    }
1218  }
1219
1220  @Override
1221  public GetLocksResponse getLocks(
1222      RpcController controller,
1223      GetLocksRequest request) throws ServiceException {
1224    try {
1225      final GetLocksResponse.Builder builder = GetLocksResponse.newBuilder();
1226
1227      for (LockedResource lockedResource: master.getLocks()) {
1228        builder.addLock(ProcedureUtil.convertToProtoLockedResource(lockedResource));
1229      }
1230
1231      return builder.build();
1232    } catch (IOException e) {
1233      throw new ServiceException(e);
1234    }
1235  }
1236
1237  @Override
1238  public ListTableDescriptorsByNamespaceResponse listTableDescriptorsByNamespace(RpcController c,
1239      ListTableDescriptorsByNamespaceRequest request) throws ServiceException {
1240    try {
1241      ListTableDescriptorsByNamespaceResponse.Builder b =
1242          ListTableDescriptorsByNamespaceResponse.newBuilder();
1243      for (TableDescriptor htd : master
1244          .listTableDescriptorsByNamespace(request.getNamespaceName())) {
1245        b.addTableSchema(ProtobufUtil.toTableSchema(htd));
1246      }
1247      return b.build();
1248    } catch (IOException e) {
1249      throw new ServiceException(e);
1250    }
1251  }
1252
1253  @Override
1254  public ListTableNamesByNamespaceResponse listTableNamesByNamespace(RpcController c,
1255      ListTableNamesByNamespaceRequest request) throws ServiceException {
1256    try {
1257      ListTableNamesByNamespaceResponse.Builder b =
1258        ListTableNamesByNamespaceResponse.newBuilder();
1259      for (TableName tableName: master.listTableNamesByNamespace(request.getNamespaceName())) {
1260        b.addTableName(ProtobufUtil.toProtoTableName(tableName));
1261      }
1262      return b.build();
1263    } catch (IOException e) {
1264      throw new ServiceException(e);
1265    }
1266  }
1267
1268  @Override
1269  public ModifyColumnResponse modifyColumn(RpcController controller,
1270      ModifyColumnRequest req) throws ServiceException {
1271    try {
1272      long procId = master.modifyColumn(
1273        ProtobufUtil.toTableName(req.getTableName()),
1274        ProtobufUtil.toColumnFamilyDescriptor(req.getColumnFamilies()),
1275        req.getNonceGroup(),
1276        req.getNonce());
1277      if (procId == -1) {
1278        // This mean operation was not performed in server, so do not set any procId
1279        return ModifyColumnResponse.newBuilder().build();
1280      } else {
1281        return ModifyColumnResponse.newBuilder().setProcId(procId).build();
1282      }
1283    } catch (IOException ioe) {
1284      throw new ServiceException(ioe);
1285    }
1286  }
1287
1288  @Override
1289  public ModifyNamespaceResponse modifyNamespace(RpcController controller,
1290      ModifyNamespaceRequest request) throws ServiceException {
1291    try {
1292      long procId = master.modifyNamespace(
1293        ProtobufUtil.toNamespaceDescriptor(request.getNamespaceDescriptor()),
1294        request.getNonceGroup(),
1295        request.getNonce());
1296      return ModifyNamespaceResponse.newBuilder().setProcId(procId).build();
1297    } catch (IOException e) {
1298      throw new ServiceException(e);
1299    }
1300  }
1301
1302  @Override
1303  public ModifyTableResponse modifyTable(RpcController controller,
1304      ModifyTableRequest req) throws ServiceException {
1305    try {
1306      long procId = master.modifyTable(
1307        ProtobufUtil.toTableName(req.getTableName()),
1308        ProtobufUtil.toTableDescriptor(req.getTableSchema()),
1309        req.getNonceGroup(),
1310        req.getNonce());
1311      return ModifyTableResponse.newBuilder().setProcId(procId).build();
1312    } catch (IOException ioe) {
1313      throw new ServiceException(ioe);
1314    }
1315  }
1316
1317  @Override
1318  public MoveRegionResponse moveRegion(RpcController controller,
1319      MoveRegionRequest req) throws ServiceException {
1320    final byte [] encodedRegionName = req.getRegion().getValue().toByteArray();
1321    RegionSpecifierType type = req.getRegion().getType();
1322    final byte [] destServerName = (req.hasDestServerName())?
1323      Bytes.toBytes(ProtobufUtil.toServerName(req.getDestServerName()).getServerName()):null;
1324    MoveRegionResponse mrr = MoveRegionResponse.newBuilder().build();
1325
1326    if (type != RegionSpecifierType.ENCODED_REGION_NAME) {
1327      LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.ENCODED_REGION_NAME
1328        + " actual: " + type);
1329    }
1330
1331    try {
1332      master.checkInitialized();
1333      master.move(encodedRegionName, destServerName);
1334    } catch (IOException ioe) {
1335      throw new ServiceException(ioe);
1336    }
1337    return mrr;
1338  }
1339
1340  /**
1341   * Offline specified region from master's in-memory state. It will not attempt to
1342   * reassign the region as in unassign.
1343   *
1344   * This is a special method that should be used by experts or hbck.
1345   *
1346   */
1347  @Override
1348  public OfflineRegionResponse offlineRegion(RpcController controller,
1349      OfflineRegionRequest request) throws ServiceException {
1350    try {
1351      master.checkInitialized();
1352
1353      final RegionSpecifierType type = request.getRegion().getType();
1354      if (type != RegionSpecifierType.REGION_NAME) {
1355        LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
1356          + " actual: " + type);
1357      }
1358
1359      final byte[] regionName = request.getRegion().getValue().toByteArray();
1360      final RegionInfo hri = master.getAssignmentManager().getRegionInfo(regionName);
1361      if (hri == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName));
1362
1363      if (master.cpHost != null) {
1364        master.cpHost.preRegionOffline(hri);
1365      }
1366      LOG.info(master.getClientIdAuditPrefix() + " offline " + hri.getRegionNameAsString());
1367      master.getAssignmentManager().offlineRegion(hri);
1368      if (master.cpHost != null) {
1369        master.cpHost.postRegionOffline(hri);
1370      }
1371    } catch (IOException ioe) {
1372      throw new ServiceException(ioe);
1373    }
1374    return OfflineRegionResponse.newBuilder().build();
1375  }
1376
1377  /**
1378   * Execute Restore/Clone snapshot operation.
1379   *
1380   * <p>If the specified table exists a "Restore" is executed, replacing the table
1381   * schema and directory data with the content of the snapshot.
1382   * The table must be disabled, or a UnsupportedOperationException will be thrown.
1383   *
1384   * <p>If the table doesn't exist a "Clone" is executed, a new table is created
1385   * using the schema at the time of the snapshot, and the content of the snapshot.
1386   *
1387   * <p>The restore/clone operation does not require copying HFiles. Since HFiles
1388   * are immutable the table can point to and use the same files as the original one.
1389   */
1390  @Override
1391  public RestoreSnapshotResponse restoreSnapshot(RpcController controller,
1392      RestoreSnapshotRequest request) throws ServiceException {
1393    try {
1394      long procId = master.restoreSnapshot(request.getSnapshot(), request.getNonceGroup(),
1395        request.getNonce(), request.getRestoreACL());
1396      return RestoreSnapshotResponse.newBuilder().setProcId(procId).build();
1397    } catch (ForeignException e) {
1398      throw new ServiceException(e.getCause());
1399    } catch (IOException e) {
1400      throw new ServiceException(e);
1401    }
1402  }
1403
1404  @Override
1405  public RunCatalogScanResponse runCatalogScan(RpcController c,
1406      RunCatalogScanRequest req) throws ServiceException {
1407    rpcPreCheck("runCatalogScan");
1408    try {
1409      return ResponseConverter.buildRunCatalogScanResponse(master.catalogJanitorChore.scan());
1410    } catch (IOException ioe) {
1411      throw new ServiceException(ioe);
1412    }
1413  }
1414
1415  @Override
1416  public RunCleanerChoreResponse runCleanerChore(RpcController c, RunCleanerChoreRequest req)
1417    throws ServiceException {
1418    rpcPreCheck("runCleanerChore");
1419    boolean result = master.getHFileCleaner().runCleaner() && master.getLogCleaner().runCleaner();
1420    return ResponseConverter.buildRunCleanerChoreResponse(result);
1421  }
1422
1423  @Override
1424  public SetBalancerRunningResponse setBalancerRunning(RpcController c,
1425      SetBalancerRunningRequest req) throws ServiceException {
1426    try {
1427      master.checkInitialized();
1428      boolean prevValue = (req.getSynchronous())?
1429        synchronousBalanceSwitch(req.getOn()) : master.balanceSwitch(req.getOn());
1430      return SetBalancerRunningResponse.newBuilder().setPrevBalanceValue(prevValue).build();
1431    } catch (IOException ioe) {
1432      throw new ServiceException(ioe);
1433    }
1434  }
1435
1436  @Override
1437  public ShutdownResponse shutdown(RpcController controller,
1438      ShutdownRequest request) throws ServiceException {
1439    LOG.info(master.getClientIdAuditPrefix() + " shutdown");
1440    try {
1441      master.shutdown();
1442    } catch (IOException e) {
1443      LOG.error("Exception occurred in HMaster.shutdown()", e);
1444      throw new ServiceException(e);
1445    }
1446    return ShutdownResponse.newBuilder().build();
1447  }
1448
1449  /**
1450   * Triggers an asynchronous attempt to take a snapshot.
1451   * {@inheritDoc}
1452   */
1453  @Override
1454  public SnapshotResponse snapshot(RpcController controller,
1455      SnapshotRequest request) throws ServiceException {
1456    try {
1457      master.checkInitialized();
1458      master.snapshotManager.checkSnapshotSupport();
1459
1460      LOG.info(master.getClientIdAuditPrefix() + " snapshot request for:" +
1461        ClientSnapshotDescriptionUtils.toString(request.getSnapshot()));
1462      // get the snapshot information
1463      SnapshotDescription snapshot = SnapshotDescriptionUtils.validate(
1464        request.getSnapshot(), master.getConfiguration());
1465      master.snapshotManager.takeSnapshot(snapshot);
1466
1467      // send back the max amount of time the client should wait for the snapshot to complete
1468      long waitTime = SnapshotDescriptionUtils.getMaxMasterTimeout(master.getConfiguration(),
1469        snapshot.getType(), SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME);
1470      return SnapshotResponse.newBuilder().setExpectedTimeout(waitTime).build();
1471    } catch (ForeignException e) {
1472      throw new ServiceException(e.getCause());
1473    } catch (IOException e) {
1474      throw new ServiceException(e);
1475    }
1476  }
1477
1478  @Override
1479  public StopMasterResponse stopMaster(RpcController controller,
1480      StopMasterRequest request) throws ServiceException {
1481    LOG.info(master.getClientIdAuditPrefix() + " stop");
1482    try {
1483      master.stopMaster();
1484    } catch (IOException e) {
1485      LOG.error("Exception occurred while stopping master", e);
1486      throw new ServiceException(e);
1487    }
1488    return StopMasterResponse.newBuilder().build();
1489  }
1490
1491  @Override
1492  public IsInMaintenanceModeResponse isMasterInMaintenanceMode(
1493      final RpcController controller,
1494      final IsInMaintenanceModeRequest request) throws ServiceException {
1495    IsInMaintenanceModeResponse.Builder response = IsInMaintenanceModeResponse.newBuilder();
1496    try {
1497      response.setInMaintenanceMode(master.isInMaintenanceMode());
1498    } catch (IOException e) {
1499      throw new ServiceException(e);
1500    }
1501    return response.build();
1502  }
1503
1504  @Override
1505  public UnassignRegionResponse unassignRegion(RpcController controller,
1506      UnassignRegionRequest req) throws ServiceException {
1507    try {
1508      final byte [] regionName = req.getRegion().getValue().toByteArray();
1509      RegionSpecifierType type = req.getRegion().getType();
1510      final boolean force = req.getForce();
1511      UnassignRegionResponse urr = UnassignRegionResponse.newBuilder().build();
1512
1513      master.checkInitialized();
1514      if (type != RegionSpecifierType.REGION_NAME) {
1515        LOG.warn("unassignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
1516          + " actual: " + type);
1517      }
1518      Pair<RegionInfo, ServerName> pair =
1519        MetaTableAccessor.getRegion(master.getConnection(), regionName);
1520      if (Bytes.equals(RegionInfoBuilder.FIRST_META_REGIONINFO.getRegionName(),regionName)) {
1521        pair = new Pair<>(RegionInfoBuilder.FIRST_META_REGIONINFO,
1522            master.getMetaTableLocator().getMetaRegionLocation(master.getZooKeeper()));
1523      }
1524      if (pair == null) {
1525        throw new UnknownRegionException(Bytes.toString(regionName));
1526      }
1527
1528      RegionInfo hri = pair.getFirst();
1529      if (master.cpHost != null) {
1530        master.cpHost.preUnassign(hri, force);
1531      }
1532      LOG.debug(master.getClientIdAuditPrefix() + " unassign " + hri.getRegionNameAsString()
1533          + " in current location if it is online and reassign.force=" + force);
1534      master.getAssignmentManager().unassign(hri);
1535      if (master.cpHost != null) {
1536        master.cpHost.postUnassign(hri, force);
1537      }
1538
1539      return urr;
1540    } catch (IOException ioe) {
1541      throw new ServiceException(ioe);
1542    }
1543  }
1544
1545  @Override
1546  public ReportRegionStateTransitionResponse reportRegionStateTransition(RpcController c,
1547      ReportRegionStateTransitionRequest req) throws ServiceException {
1548    try {
1549      master.checkServiceStarted();
1550      return master.getAssignmentManager().reportRegionStateTransition(req);
1551    } catch (IOException ioe) {
1552      throw new ServiceException(ioe);
1553    }
1554  }
1555
1556  @Override
1557  public SetQuotaResponse setQuota(RpcController c, SetQuotaRequest req)
1558      throws ServiceException {
1559    try {
1560      master.checkInitialized();
1561      return master.getMasterQuotaManager().setQuota(req);
1562    } catch (Exception e) {
1563      throw new ServiceException(e);
1564    }
1565  }
1566
1567  @Override
1568  public MajorCompactionTimestampResponse getLastMajorCompactionTimestamp(RpcController controller,
1569      MajorCompactionTimestampRequest request) throws ServiceException {
1570    MajorCompactionTimestampResponse.Builder response =
1571        MajorCompactionTimestampResponse.newBuilder();
1572    try {
1573      master.checkInitialized();
1574      response.setCompactionTimestamp(master.getLastMajorCompactionTimestamp(ProtobufUtil
1575          .toTableName(request.getTableName())));
1576    } catch (IOException e) {
1577      throw new ServiceException(e);
1578    }
1579    return response.build();
1580  }
1581
1582  @Override
1583  public MajorCompactionTimestampResponse getLastMajorCompactionTimestampForRegion(
1584      RpcController controller, MajorCompactionTimestampForRegionRequest request)
1585      throws ServiceException {
1586    MajorCompactionTimestampResponse.Builder response =
1587        MajorCompactionTimestampResponse.newBuilder();
1588    try {
1589      master.checkInitialized();
1590      response.setCompactionTimestamp(master.getLastMajorCompactionTimestampForRegion(request
1591          .getRegion().getValue().toByteArray()));
1592    } catch (IOException e) {
1593      throw new ServiceException(e);
1594    }
1595    return response.build();
1596  }
1597
1598  /**
1599   * Compact a region on the master.
1600   *
1601   * @param controller the RPC controller
1602   * @param request the request
1603   * @throws ServiceException
1604   */
1605  @Override
1606  @QosPriority(priority=HConstants.ADMIN_QOS)
1607  public CompactRegionResponse compactRegion(final RpcController controller,
1608    final CompactRegionRequest request) throws ServiceException {
1609    try {
1610      master.checkInitialized();
1611      byte[] regionName = request.getRegion().getValue().toByteArray();
1612      TableName tableName = RegionInfo.getTable(regionName);
1613      // if the region is a mob region, do the mob file compaction.
1614      if (MobUtils.isMobRegionName(tableName, regionName)) {
1615        checkHFileFormatVersionForMob();
1616        return compactMob(request, tableName);
1617      } else {
1618        return super.compactRegion(controller, request);
1619      }
1620    } catch (IOException ie) {
1621      throw new ServiceException(ie);
1622    }
1623  }
1624
1625  /**
1626   * check configured hfile format version before to do compaction
1627   * @throws IOException throw IOException
1628   */
1629  private void checkHFileFormatVersionForMob() throws IOException {
1630    if (HFile.getFormatVersion(master.getConfiguration()) < HFile.MIN_FORMAT_VERSION_WITH_TAGS) {
1631      LOG.error("A minimum HFile version of " + HFile.MIN_FORMAT_VERSION_WITH_TAGS
1632          + " is required for MOB compaction. Compaction will not run.");
1633      throw new IOException("A minimum HFile version of " + HFile.MIN_FORMAT_VERSION_WITH_TAGS
1634          + " is required for MOB feature. Consider setting " + HFile.FORMAT_VERSION_KEY
1635          + " accordingly.");
1636    }
1637  }
1638
1639  @Override
1640  @QosPriority(priority=HConstants.ADMIN_QOS)
1641  public GetRegionInfoResponse getRegionInfo(final RpcController controller,
1642    final GetRegionInfoRequest request) throws ServiceException {
1643    byte[] regionName = request.getRegion().getValue().toByteArray();
1644    TableName tableName = RegionInfo.getTable(regionName);
1645    if (MobUtils.isMobRegionName(tableName, regionName)) {
1646      // a dummy region info contains the compaction state.
1647      RegionInfo mobRegionInfo = MobUtils.getMobRegionInfo(tableName);
1648      GetRegionInfoResponse.Builder builder = GetRegionInfoResponse.newBuilder();
1649      builder.setRegionInfo(ProtobufUtil.toRegionInfo(mobRegionInfo));
1650      if (request.hasCompactionState() && request.getCompactionState()) {
1651        builder.setCompactionState(master.getMobCompactionState(tableName));
1652      }
1653      return builder.build();
1654    } else {
1655      return super.getRegionInfo(controller, request);
1656    }
1657  }
1658
1659  /**
1660   * Compacts the mob files in the current table.
1661   * @param request the request.
1662   * @param tableName the current table name.
1663   * @return The response of the mob file compaction.
1664   * @throws IOException
1665   */
1666  private CompactRegionResponse compactMob(final CompactRegionRequest request,
1667    TableName tableName) throws IOException {
1668    if (!master.getTableStateManager().isTableState(tableName, TableState.State.ENABLED)) {
1669      throw new DoNotRetryIOException("Table " + tableName + " is not enabled");
1670    }
1671    boolean allFiles = false;
1672    List<ColumnFamilyDescriptor> compactedColumns = new ArrayList<>();
1673    ColumnFamilyDescriptor[] hcds = master.getTableDescriptors().get(tableName).getColumnFamilies();
1674    byte[] family = null;
1675    if (request.hasFamily()) {
1676      family = request.getFamily().toByteArray();
1677      for (ColumnFamilyDescriptor hcd : hcds) {
1678        if (Bytes.equals(family, hcd.getName())) {
1679          if (!hcd.isMobEnabled()) {
1680            LOG.error("Column family " + hcd.getNameAsString() + " is not a mob column family");
1681            throw new DoNotRetryIOException("Column family " + hcd.getNameAsString()
1682                    + " is not a mob column family");
1683          }
1684          compactedColumns.add(hcd);
1685        }
1686      }
1687    } else {
1688      for (ColumnFamilyDescriptor hcd : hcds) {
1689        if (hcd.isMobEnabled()) {
1690          compactedColumns.add(hcd);
1691        }
1692      }
1693    }
1694    if (compactedColumns.isEmpty()) {
1695      LOG.error("No mob column families are assigned in the mob compaction");
1696      throw new DoNotRetryIOException(
1697              "No mob column families are assigned in the mob compaction");
1698    }
1699    if (request.hasMajor() && request.getMajor()) {
1700      allFiles = true;
1701    }
1702    String familyLogMsg = (family != null) ? Bytes.toString(family) : "";
1703    if (LOG.isTraceEnabled()) {
1704      LOG.trace("User-triggered mob compaction requested for table: "
1705              + tableName.getNameAsString() + " for column family: " + familyLogMsg);
1706    }
1707    master.requestMobCompaction(tableName, compactedColumns, allFiles);
1708    return CompactRegionResponse.newBuilder().build();
1709  }
1710
1711  @Override
1712  public IsBalancerEnabledResponse isBalancerEnabled(RpcController controller,
1713      IsBalancerEnabledRequest request) throws ServiceException {
1714    IsBalancerEnabledResponse.Builder response = IsBalancerEnabledResponse.newBuilder();
1715    response.setEnabled(master.isBalancerOn());
1716    return response.build();
1717  }
1718
1719  @Override
1720  public SetSplitOrMergeEnabledResponse setSplitOrMergeEnabled(RpcController controller,
1721    SetSplitOrMergeEnabledRequest request) throws ServiceException {
1722    SetSplitOrMergeEnabledResponse.Builder response = SetSplitOrMergeEnabledResponse.newBuilder();
1723    try {
1724      master.checkInitialized();
1725      boolean newValue = request.getEnabled();
1726      for (MasterProtos.MasterSwitchType masterSwitchType: request.getSwitchTypesList()) {
1727        MasterSwitchType switchType = convert(masterSwitchType);
1728        boolean oldValue = master.isSplitOrMergeEnabled(switchType);
1729        response.addPrevValue(oldValue);
1730        if (master.cpHost != null) {
1731          master.cpHost.preSetSplitOrMergeEnabled(newValue, switchType);
1732        }
1733        master.getSplitOrMergeTracker().setSplitOrMergeEnabled(newValue, switchType);
1734        if (master.cpHost != null) {
1735          master.cpHost.postSetSplitOrMergeEnabled(newValue, switchType);
1736        }
1737      }
1738    } catch (IOException e) {
1739      throw new ServiceException(e);
1740    } catch (KeeperException e) {
1741      throw new ServiceException(e);
1742    }
1743    return response.build();
1744  }
1745
1746  @Override
1747  public IsSplitOrMergeEnabledResponse isSplitOrMergeEnabled(RpcController controller,
1748    IsSplitOrMergeEnabledRequest request) throws ServiceException {
1749    IsSplitOrMergeEnabledResponse.Builder response = IsSplitOrMergeEnabledResponse.newBuilder();
1750    response.setEnabled(master.isSplitOrMergeEnabled(convert(request.getSwitchType())));
1751    return response.build();
1752  }
1753
1754  @Override
1755  public NormalizeResponse normalize(RpcController controller,
1756      NormalizeRequest request) throws ServiceException {
1757    rpcPreCheck("normalize");
1758    try {
1759      return NormalizeResponse.newBuilder().setNormalizerRan(master.normalizeRegions()).build();
1760    } catch (IOException ex) {
1761      throw new ServiceException(ex);
1762    }
1763  }
1764
1765  @Override
1766  public SetNormalizerRunningResponse setNormalizerRunning(RpcController controller,
1767      SetNormalizerRunningRequest request) throws ServiceException {
1768    rpcPreCheck("setNormalizerRunning");
1769
1770    // Sets normalizer on/off flag in ZK.
1771    boolean prevValue = master.getRegionNormalizerTracker().isNormalizerOn();
1772    boolean newValue = request.getOn();
1773    try {
1774      master.getRegionNormalizerTracker().setNormalizerOn(newValue);
1775    } catch (KeeperException ke) {
1776      LOG.warn("Error flipping normalizer switch", ke);
1777    }
1778    LOG.info("{} set normalizerSwitch={}", master.getClientIdAuditPrefix(), newValue);
1779    return SetNormalizerRunningResponse.newBuilder().setPrevNormalizerValue(prevValue).build();
1780  }
1781
1782  @Override
1783  public IsNormalizerEnabledResponse isNormalizerEnabled(RpcController controller,
1784      IsNormalizerEnabledRequest request) throws ServiceException {
1785    IsNormalizerEnabledResponse.Builder response = IsNormalizerEnabledResponse.newBuilder();
1786    response.setEnabled(master.isNormalizerOn());
1787    return response.build();
1788  }
1789
1790  /**
1791   * Returns the security capabilities in effect on the cluster
1792   */
1793  @Override
1794  public SecurityCapabilitiesResponse getSecurityCapabilities(RpcController controller,
1795      SecurityCapabilitiesRequest request) throws ServiceException {
1796    SecurityCapabilitiesResponse.Builder response = SecurityCapabilitiesResponse.newBuilder();
1797    try {
1798      master.checkInitialized();
1799      Set<SecurityCapabilitiesResponse.Capability> capabilities = new HashSet<>();
1800      // Authentication
1801      if (User.isHBaseSecurityEnabled(master.getConfiguration())) {
1802        capabilities.add(SecurityCapabilitiesResponse.Capability.SECURE_AUTHENTICATION);
1803      } else {
1804        capabilities.add(SecurityCapabilitiesResponse.Capability.SIMPLE_AUTHENTICATION);
1805      }
1806      // A coprocessor that implements AccessControlService can provide AUTHORIZATION and
1807      // CELL_AUTHORIZATION
1808      if (master.cpHost != null && hasAccessControlServiceCoprocessor(master.cpHost)) {
1809        if (AccessChecker.isAuthorizationSupported(master.getConfiguration())) {
1810          capabilities.add(SecurityCapabilitiesResponse.Capability.AUTHORIZATION);
1811        }
1812        if (AccessController.isCellAuthorizationSupported(master.getConfiguration())) {
1813          capabilities.add(SecurityCapabilitiesResponse.Capability.CELL_AUTHORIZATION);
1814        }
1815      }
1816      // A coprocessor that implements VisibilityLabelsService can provide CELL_VISIBILITY.
1817      if (master.cpHost != null && hasVisibilityLabelsServiceCoprocessor(master.cpHost)) {
1818        if (VisibilityController.isCellAuthorizationSupported(master.getConfiguration())) {
1819          capabilities.add(SecurityCapabilitiesResponse.Capability.CELL_VISIBILITY);
1820        }
1821      }
1822      response.addAllCapabilities(capabilities);
1823    } catch (IOException e) {
1824      throw new ServiceException(e);
1825    }
1826    return response.build();
1827  }
1828
1829  /**
1830   * Determines if there is a MasterCoprocessor deployed which implements
1831   * {@link org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService.Interface}.
1832   */
1833  boolean hasAccessControlServiceCoprocessor(MasterCoprocessorHost cpHost) {
1834    return checkCoprocessorWithService(
1835        cpHost.findCoprocessors(MasterCoprocessor.class), AccessControlService.Interface.class);
1836  }
1837
1838  /**
1839   * Determines if there is a MasterCoprocessor deployed which implements
1840   * {@link org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService.Interface}.
1841   */
1842  boolean hasVisibilityLabelsServiceCoprocessor(MasterCoprocessorHost cpHost) {
1843    return checkCoprocessorWithService(
1844        cpHost.findCoprocessors(MasterCoprocessor.class),
1845        VisibilityLabelsService.Interface.class);
1846  }
1847
1848  /**
1849   * Determines if there is a coprocessor implementation in the provided argument which extends
1850   * or implements the provided {@code service}.
1851   */
1852  boolean checkCoprocessorWithService(
1853      List<MasterCoprocessor> coprocessorsToCheck, Class<?> service) {
1854    if (coprocessorsToCheck == null || coprocessorsToCheck.isEmpty()) {
1855      return false;
1856    }
1857    for (MasterCoprocessor cp : coprocessorsToCheck) {
1858      if (service.isAssignableFrom(cp.getClass())) {
1859        return true;
1860      }
1861    }
1862    return false;
1863  }
1864
1865  private MasterSwitchType convert(MasterProtos.MasterSwitchType switchType) {
1866    switch (switchType) {
1867      case SPLIT:
1868        return MasterSwitchType.SPLIT;
1869      case MERGE:
1870        return MasterSwitchType.MERGE;
1871      default:
1872        break;
1873    }
1874    return null;
1875  }
1876
1877  @Override
1878  public AddReplicationPeerResponse addReplicationPeer(RpcController controller,
1879      AddReplicationPeerRequest request) throws ServiceException {
1880    try {
1881      master.addReplicationPeer(request.getPeerId(),
1882        ReplicationPeerConfigUtil.convert(request.getPeerConfig()), request.getPeerState()
1883            .getState().equals(ReplicationState.State.ENABLED));
1884      return AddReplicationPeerResponse.newBuilder().build();
1885    } catch (ReplicationException | IOException e) {
1886      throw new ServiceException(e);
1887    }
1888  }
1889
1890  @Override
1891  public RemoveReplicationPeerResponse removeReplicationPeer(RpcController controller,
1892      RemoveReplicationPeerRequest request) throws ServiceException {
1893    try {
1894      master.removeReplicationPeer(request.getPeerId());
1895      return RemoveReplicationPeerResponse.newBuilder().build();
1896    } catch (ReplicationException | IOException e) {
1897      throw new ServiceException(e);
1898    }
1899  }
1900
1901  @Override
1902  public EnableReplicationPeerResponse enableReplicationPeer(RpcController controller,
1903      EnableReplicationPeerRequest request) throws ServiceException {
1904    try {
1905      master.enableReplicationPeer(request.getPeerId());
1906      return EnableReplicationPeerResponse.newBuilder().build();
1907    } catch (ReplicationException | IOException e) {
1908      throw new ServiceException(e);
1909    }
1910  }
1911
1912  @Override
1913  public DisableReplicationPeerResponse disableReplicationPeer(RpcController controller,
1914      DisableReplicationPeerRequest request) throws ServiceException {
1915    try {
1916      master.disableReplicationPeer(request.getPeerId());
1917      return DisableReplicationPeerResponse.newBuilder().build();
1918    } catch (ReplicationException | IOException e) {
1919      throw new ServiceException(e);
1920    }
1921  }
1922
1923  @Override
1924  public GetReplicationPeerConfigResponse getReplicationPeerConfig(RpcController controller,
1925      GetReplicationPeerConfigRequest request) throws ServiceException {
1926    GetReplicationPeerConfigResponse.Builder response = GetReplicationPeerConfigResponse
1927        .newBuilder();
1928    try {
1929      String peerId = request.getPeerId();
1930      ReplicationPeerConfig peerConfig = master.getReplicationPeerConfig(peerId);
1931      response.setPeerId(peerId);
1932      response.setPeerConfig(ReplicationPeerConfigUtil.convert(peerConfig));
1933    } catch (ReplicationException | IOException e) {
1934      throw new ServiceException(e);
1935    }
1936    return response.build();
1937  }
1938
1939  @Override
1940  public UpdateReplicationPeerConfigResponse updateReplicationPeerConfig(RpcController controller,
1941      UpdateReplicationPeerConfigRequest request) throws ServiceException {
1942    try {
1943      master.updateReplicationPeerConfig(request.getPeerId(),
1944        ReplicationPeerConfigUtil.convert(request.getPeerConfig()));
1945      return UpdateReplicationPeerConfigResponse.newBuilder().build();
1946    } catch (ReplicationException | IOException e) {
1947      throw new ServiceException(e);
1948    }
1949  }
1950
1951  @Override
1952  public ListReplicationPeersResponse listReplicationPeers(RpcController controller,
1953      ListReplicationPeersRequest request) throws ServiceException {
1954    ListReplicationPeersResponse.Builder response = ListReplicationPeersResponse.newBuilder();
1955    try {
1956      List<ReplicationPeerDescription> peers = master
1957          .listReplicationPeers(request.hasRegex() ? request.getRegex() : null);
1958      for (ReplicationPeerDescription peer : peers) {
1959        response.addPeerDesc(ReplicationPeerConfigUtil.toProtoReplicationPeerDescription(peer));
1960      }
1961    } catch (ReplicationException | IOException e) {
1962      throw new ServiceException(e);
1963    }
1964    return response.build();
1965  }
1966
1967  @Override
1968  public ListDecommissionedRegionServersResponse listDecommissionedRegionServers(
1969      RpcController controller, ListDecommissionedRegionServersRequest request)
1970      throws ServiceException {
1971    ListDecommissionedRegionServersResponse.Builder response =
1972        ListDecommissionedRegionServersResponse.newBuilder();
1973    try {
1974      master.checkInitialized();
1975      if (master.cpHost != null) {
1976        master.cpHost.preListDecommissionedRegionServers();
1977      }
1978      List<ServerName> servers = master.listDecommissionedRegionServers();
1979      response.addAllServerName((servers.stream().map(server -> ProtobufUtil.toServerName(server)))
1980          .collect(Collectors.toList()));
1981      if (master.cpHost != null) {
1982        master.cpHost.postListDecommissionedRegionServers();
1983      }
1984    } catch (IOException io) {
1985      throw new ServiceException(io);
1986    }
1987
1988    return response.build();
1989  }
1990
1991  @Override
1992  public DecommissionRegionServersResponse decommissionRegionServers(RpcController controller,
1993      DecommissionRegionServersRequest request) throws ServiceException {
1994    try {
1995      master.checkInitialized();
1996      List<ServerName> servers = request.getServerNameList().stream()
1997          .map(pbServer -> ProtobufUtil.toServerName(pbServer)).collect(Collectors.toList());
1998      boolean offload = request.getOffload();
1999      if (master.cpHost != null) {
2000        master.cpHost.preDecommissionRegionServers(servers, offload);
2001      }
2002      master.decommissionRegionServers(servers, offload);
2003      if (master.cpHost != null) {
2004        master.cpHost.postDecommissionRegionServers(servers, offload);
2005      }
2006    } catch (IOException io) {
2007      throw new ServiceException(io);
2008    }
2009
2010    return DecommissionRegionServersResponse.newBuilder().build();
2011  }
2012
2013  @Override
2014  public RecommissionRegionServerResponse recommissionRegionServer(RpcController controller,
2015      RecommissionRegionServerRequest request) throws ServiceException {
2016    try {
2017      master.checkInitialized();
2018      ServerName server = ProtobufUtil.toServerName(request.getServerName());
2019      List<byte[]> encodedRegionNames = request.getRegionList().stream()
2020          .map(regionSpecifier -> regionSpecifier.getValue().toByteArray())
2021          .collect(Collectors.toList());
2022      if (master.cpHost != null) {
2023        master.cpHost.preRecommissionRegionServer(server, encodedRegionNames);
2024      }
2025      master.recommissionRegionServer(server, encodedRegionNames);
2026      if (master.cpHost != null) {
2027        master.cpHost.postRecommissionRegionServer(server, encodedRegionNames);
2028      }
2029    } catch (IOException io) {
2030      throw new ServiceException(io);
2031    }
2032
2033    return RecommissionRegionServerResponse.newBuilder().build();
2034  }
2035
2036  @Override
2037  public LockResponse requestLock(RpcController controller, final LockRequest request)
2038      throws ServiceException {
2039    try {
2040      if (request.getDescription().isEmpty()) {
2041        throw new IllegalArgumentException("Empty description");
2042      }
2043      NonceProcedureRunnable npr;
2044      LockType type = LockType.valueOf(request.getLockType().name());
2045      if (request.getRegionInfoCount() > 0) {
2046        final RegionInfo[] regionInfos = new RegionInfo[request.getRegionInfoCount()];
2047        for (int i = 0; i < request.getRegionInfoCount(); ++i) {
2048          regionInfos[i] = ProtobufUtil.toRegionInfo(request.getRegionInfo(i));
2049        }
2050        npr = new NonceProcedureRunnable(master, request.getNonceGroup(), request.getNonce()) {
2051          @Override
2052          protected void run() throws IOException {
2053            setProcId(master.getLockManager().remoteLocks().requestRegionsLock(regionInfos,
2054                request.getDescription(), getNonceKey()));
2055          }
2056
2057          @Override
2058          protected String getDescription() {
2059            return "RequestLock";
2060          }
2061        };
2062      } else if (request.hasTableName()) {
2063        final TableName tableName = ProtobufUtil.toTableName(request.getTableName());
2064        npr = new NonceProcedureRunnable(master, request.getNonceGroup(), request.getNonce()) {
2065          @Override
2066          protected void run() throws IOException {
2067            setProcId(master.getLockManager().remoteLocks().requestTableLock(tableName, type,
2068                request.getDescription(), getNonceKey()));
2069          }
2070
2071          @Override
2072          protected String getDescription() {
2073            return "RequestLock";
2074          }
2075        };
2076      } else if (request.hasNamespace()) {
2077        npr = new NonceProcedureRunnable(master, request.getNonceGroup(), request.getNonce()) {
2078          @Override
2079          protected void run() throws IOException {
2080            setProcId(master.getLockManager().remoteLocks().requestNamespaceLock(
2081                request.getNamespace(), type, request.getDescription(), getNonceKey()));
2082          }
2083
2084          @Override
2085          protected String getDescription() {
2086            return "RequestLock";
2087          }
2088        };
2089      } else {
2090        throw new IllegalArgumentException("one of table/namespace/region should be specified");
2091      }
2092      long procId = MasterProcedureUtil.submitProcedure(npr);
2093      return LockResponse.newBuilder().setProcId(procId).build();
2094    } catch (IllegalArgumentException e) {
2095      LOG.warn("Exception when queuing lock", e);
2096      throw new ServiceException(new DoNotRetryIOException(e));
2097    } catch (IOException e) {
2098      LOG.warn("Exception when queuing lock", e);
2099      throw new ServiceException(e);
2100    }
2101  }
2102
2103  /**
2104   * @return LOCKED, if procedure is found and it has the lock; else UNLOCKED.
2105   * @throws ServiceException if given proc id is found but it is not a LockProcedure.
2106   */
2107  @Override
2108  public LockHeartbeatResponse lockHeartbeat(RpcController controller, LockHeartbeatRequest request)
2109      throws ServiceException {
2110    try {
2111      if (master.getLockManager().remoteLocks().lockHeartbeat(request.getProcId(),
2112          request.getKeepAlive())) {
2113        return LockHeartbeatResponse.newBuilder().setTimeoutMs(
2114            master.getConfiguration().getInt(LockProcedure.REMOTE_LOCKS_TIMEOUT_MS_CONF,
2115                LockProcedure.DEFAULT_REMOTE_LOCKS_TIMEOUT_MS))
2116            .setLockStatus(LockHeartbeatResponse.LockStatus.LOCKED).build();
2117      } else {
2118        return LockHeartbeatResponse.newBuilder()
2119            .setLockStatus(LockHeartbeatResponse.LockStatus.UNLOCKED).build();
2120      }
2121    } catch (IOException e) {
2122      throw new ServiceException(e);
2123    }
2124  }
2125
2126  @Override
2127  public RegionSpaceUseReportResponse reportRegionSpaceUse(RpcController controller,
2128      RegionSpaceUseReportRequest request) throws ServiceException {
2129    try {
2130      master.checkInitialized();
2131      if (!QuotaUtil.isQuotaEnabled(master.getConfiguration())) {
2132        return RegionSpaceUseReportResponse.newBuilder().build();
2133      }
2134      MasterQuotaManager quotaManager = this.master.getMasterQuotaManager();
2135      final long now = EnvironmentEdgeManager.currentTime();
2136      for (RegionSpaceUse report : request.getSpaceUseList()) {
2137        quotaManager.addRegionSize(ProtobufUtil.toRegionInfo(
2138            report.getRegionInfo()), report.getRegionSize(), now);
2139      }
2140      return RegionSpaceUseReportResponse.newBuilder().build();
2141    } catch (Exception e) {
2142      throw new ServiceException(e);
2143    }
2144  }
2145
2146  @Override
2147  public GetSpaceQuotaRegionSizesResponse getSpaceQuotaRegionSizes(
2148      RpcController controller, GetSpaceQuotaRegionSizesRequest request) throws ServiceException {
2149    try {
2150      master.checkInitialized();
2151      MasterQuotaManager quotaManager = this.master.getMasterQuotaManager();
2152      GetSpaceQuotaRegionSizesResponse.Builder builder =
2153          GetSpaceQuotaRegionSizesResponse.newBuilder();
2154      if (quotaManager != null) {
2155        Map<RegionInfo,Long> regionSizes = quotaManager.snapshotRegionSizes();
2156        Map<TableName,Long> regionSizesByTable = new HashMap<>();
2157        // Translate hregioninfo+long -> tablename+long
2158        for (Entry<RegionInfo,Long> entry : regionSizes.entrySet()) {
2159          final TableName tableName = entry.getKey().getTable();
2160          Long prevSize = regionSizesByTable.get(tableName);
2161          if (prevSize == null) {
2162            prevSize = 0L;
2163          }
2164          regionSizesByTable.put(tableName, prevSize + entry.getValue());
2165        }
2166        // Serialize them into the protobuf
2167        for (Entry<TableName,Long> tableSize : regionSizesByTable.entrySet()) {
2168          builder.addSizes(RegionSizes.newBuilder()
2169              .setTableName(ProtobufUtil.toProtoTableName(tableSize.getKey()))
2170              .setSize(tableSize.getValue()).build());
2171        }
2172        return builder.build();
2173      }
2174      return builder.build();
2175    } catch (Exception e) {
2176      throw new ServiceException(e);
2177    }
2178  }
2179
2180  @Override
2181  public GetQuotaStatesResponse getQuotaStates(
2182      RpcController controller, GetQuotaStatesRequest request) throws ServiceException {
2183    try {
2184      master.checkInitialized();
2185      QuotaObserverChore quotaChore = this.master.getQuotaObserverChore();
2186      GetQuotaStatesResponse.Builder builder = GetQuotaStatesResponse.newBuilder();
2187      if (quotaChore != null) {
2188        // The "current" view of all tables with quotas
2189        Map<TableName, SpaceQuotaSnapshot> tableSnapshots = quotaChore.getTableQuotaSnapshots();
2190        for (Entry<TableName, SpaceQuotaSnapshot> entry : tableSnapshots.entrySet()) {
2191          builder.addTableSnapshots(
2192              TableQuotaSnapshot.newBuilder()
2193                  .setTableName(ProtobufUtil.toProtoTableName(entry.getKey()))
2194                  .setSnapshot(SpaceQuotaSnapshot.toProtoSnapshot(entry.getValue())).build());
2195        }
2196        // The "current" view of all namespaces with quotas
2197        Map<String, SpaceQuotaSnapshot> nsSnapshots = quotaChore.getNamespaceQuotaSnapshots();
2198        for (Entry<String, SpaceQuotaSnapshot> entry : nsSnapshots.entrySet()) {
2199          builder.addNsSnapshots(
2200              NamespaceQuotaSnapshot.newBuilder()
2201                  .setNamespace(entry.getKey())
2202                  .setSnapshot(SpaceQuotaSnapshot.toProtoSnapshot(entry.getValue())).build());
2203        }
2204        return builder.build();
2205      }
2206      return builder.build();
2207    } catch (Exception e) {
2208      throw new ServiceException(e);
2209    }
2210  }
2211
2212  @Override
2213  public ClearDeadServersResponse clearDeadServers(RpcController controller,
2214      ClearDeadServersRequest request) throws ServiceException {
2215    LOG.debug(master.getClientIdAuditPrefix() + " clear dead region servers.");
2216    ClearDeadServersResponse.Builder response = ClearDeadServersResponse.newBuilder();
2217    try {
2218      master.checkInitialized();
2219      if (master.cpHost != null) {
2220        master.cpHost.preClearDeadServers();
2221      }
2222
2223      if (master.getServerManager().areDeadServersInProgress()) {
2224        LOG.debug("Some dead server is still under processing, won't clear the dead server list");
2225        response.addAllServerName(request.getServerNameList());
2226      } else {
2227        for (HBaseProtos.ServerName pbServer : request.getServerNameList()) {
2228          if (!master.getServerManager().getDeadServers()
2229                  .removeDeadServer(ProtobufUtil.toServerName(pbServer))) {
2230            response.addServerName(pbServer);
2231          }
2232        }
2233      }
2234
2235      if (master.cpHost != null) {
2236        master.cpHost.postClearDeadServers(
2237            ProtobufUtil.toServerNameList(request.getServerNameList()),
2238            ProtobufUtil.toServerNameList(response.getServerNameList()));
2239      }
2240    } catch (IOException io) {
2241      throw new ServiceException(io);
2242    }
2243    return response.build();
2244  }
2245
2246  // HBCK Services
2247
2248  /**
2249   * Update state of the table in meta only. This is required by hbck in some situations to cleanup
2250   * stuck assign/ unassign regions procedures for the table.
2251   *
2252   * @return previous state of the table
2253   */
2254  @Override
2255  public GetTableStateResponse setTableStateInMeta(RpcController controller,
2256      SetTableStateInMetaRequest request) throws ServiceException {
2257    Connection conn = master.getConnection();
2258    TableName tn = ProtobufUtil.toTableName(request.getTableName());
2259
2260    try {
2261      HBaseProtos.TableState prevState = MetaTableAccessor.getTableState(conn, tn).convert();
2262      MetaTableAccessor.updateTableState(conn, tn,
2263          TableState.convert(tn, request.getTableState()).getState());
2264      return GetTableStateResponse.newBuilder().setTableState(prevState).build();
2265    } catch (Exception e) {
2266      throw new ServiceException(e);
2267    }
2268  }
2269}