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