001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.master;
019
020import java.io.IOException;
021import java.lang.reflect.InvocationTargetException;
022import java.lang.reflect.Method;
023import java.net.InetAddress;
024import java.util.ArrayList;
025import java.util.Collections;
026import java.util.HashMap;
027import java.util.HashSet;
028import java.util.List;
029import java.util.Map;
030import java.util.Map.Entry;
031import java.util.Optional;
032import java.util.Set;
033import java.util.concurrent.CompletableFuture;
034import java.util.concurrent.ExecutionException;
035import java.util.concurrent.ThreadLocalRandom;
036import java.util.stream.Collectors;
037import org.apache.hadoop.conf.Configuration;
038import org.apache.hadoop.hbase.ClusterMetricsBuilder;
039import org.apache.hadoop.hbase.DoNotRetryIOException;
040import org.apache.hadoop.hbase.HBaseRpcServicesBase;
041import org.apache.hadoop.hbase.HConstants;
042import org.apache.hadoop.hbase.MasterNotRunningException;
043import org.apache.hadoop.hbase.MetaTableAccessor;
044import org.apache.hadoop.hbase.NamespaceDescriptor;
045import org.apache.hadoop.hbase.ServerMetrics;
046import org.apache.hadoop.hbase.ServerMetricsBuilder;
047import org.apache.hadoop.hbase.ServerName;
048import org.apache.hadoop.hbase.TableName;
049import org.apache.hadoop.hbase.UnknownRegionException;
050import org.apache.hadoop.hbase.client.BalanceRequest;
051import org.apache.hadoop.hbase.client.BalanceResponse;
052import org.apache.hadoop.hbase.client.MasterSwitchType;
053import org.apache.hadoop.hbase.client.NormalizeTableFilterParams;
054import org.apache.hadoop.hbase.client.RegionInfo;
055import org.apache.hadoop.hbase.client.Table;
056import org.apache.hadoop.hbase.client.TableDescriptor;
057import org.apache.hadoop.hbase.client.TableState;
058import org.apache.hadoop.hbase.client.VersionInfoUtil;
059import org.apache.hadoop.hbase.client.replication.ReplicationPeerConfigUtil;
060import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
061import org.apache.hadoop.hbase.errorhandling.ForeignException;
062import org.apache.hadoop.hbase.exceptions.UnknownProtocolException;
063import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
064import org.apache.hadoop.hbase.ipc.PriorityFunction;
065import org.apache.hadoop.hbase.ipc.QosPriority;
066import org.apache.hadoop.hbase.ipc.RpcServer;
067import org.apache.hadoop.hbase.ipc.RpcServer.BlockingServiceAndInterface;
068import org.apache.hadoop.hbase.ipc.ServerRpcController;
069import org.apache.hadoop.hbase.master.assignment.AssignmentManager;
070import org.apache.hadoop.hbase.master.assignment.RegionStateNode;
071import org.apache.hadoop.hbase.master.assignment.RegionStates;
072import org.apache.hadoop.hbase.master.cleaner.HFileCleaner;
073import org.apache.hadoop.hbase.master.hbck.HbckChore;
074import org.apache.hadoop.hbase.master.janitor.MetaFixer;
075import org.apache.hadoop.hbase.master.locking.LockProcedure;
076import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
077import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil;
078import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil.NonceProcedureRunnable;
079import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure;
080import org.apache.hadoop.hbase.master.replication.AbstractPeerNoLockProcedure;
081import org.apache.hadoop.hbase.mob.MobUtils;
082import org.apache.hadoop.hbase.namequeues.BalancerDecisionDetails;
083import org.apache.hadoop.hbase.namequeues.BalancerRejectionDetails;
084import org.apache.hadoop.hbase.namequeues.NamedQueueRecorder;
085import org.apache.hadoop.hbase.namequeues.request.NamedQueueGetRequest;
086import org.apache.hadoop.hbase.namequeues.response.NamedQueueGetResponse;
087import org.apache.hadoop.hbase.net.Address;
088import org.apache.hadoop.hbase.procedure.MasterProcedureManager;
089import org.apache.hadoop.hbase.procedure2.LockType;
090import org.apache.hadoop.hbase.procedure2.LockedResource;
091import org.apache.hadoop.hbase.procedure2.Procedure;
092import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
093import org.apache.hadoop.hbase.procedure2.ProcedureUtil;
094import org.apache.hadoop.hbase.procedure2.RemoteProcedureException;
095import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
096import org.apache.hadoop.hbase.quotas.QuotaObserverChore;
097import org.apache.hadoop.hbase.quotas.QuotaUtil;
098import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
099import org.apache.hadoop.hbase.regionserver.SimpleRpcSchedulerFactory;
100import org.apache.hadoop.hbase.replication.ReplicationException;
101import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
102import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
103import org.apache.hadoop.hbase.rsgroup.RSGroupInfo;
104import org.apache.hadoop.hbase.rsgroup.RSGroupUtil;
105import org.apache.hadoop.hbase.security.Superusers;
106import org.apache.hadoop.hbase.security.User;
107import org.apache.hadoop.hbase.security.access.AccessChecker;
108import org.apache.hadoop.hbase.security.access.AccessChecker.InputUser;
109import org.apache.hadoop.hbase.security.access.AccessController;
110import org.apache.hadoop.hbase.security.access.Permission;
111import org.apache.hadoop.hbase.security.access.Permission.Action;
112import org.apache.hadoop.hbase.security.access.PermissionStorage;
113import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil;
114import org.apache.hadoop.hbase.security.access.UserPermission;
115import org.apache.hadoop.hbase.security.visibility.VisibilityController;
116import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
117import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
118import org.apache.hadoop.hbase.util.Bytes;
119import org.apache.hadoop.hbase.util.DNS;
120import org.apache.hadoop.hbase.util.DNS.ServerType;
121import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
122import org.apache.hadoop.hbase.util.ForeignExceptionUtil;
123import org.apache.hadoop.hbase.util.Pair;
124import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
125import org.apache.yetus.audience.InterfaceAudience;
126import org.slf4j.Logger;
127import org.slf4j.LoggerFactory;
128
129import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
130import org.apache.hbase.thirdparty.com.google.protobuf.ByteString;
131import org.apache.hbase.thirdparty.com.google.protobuf.Descriptors.MethodDescriptor;
132import org.apache.hbase.thirdparty.com.google.protobuf.Descriptors.ServiceDescriptor;
133import org.apache.hbase.thirdparty.com.google.protobuf.Message;
134import org.apache.hbase.thirdparty.com.google.protobuf.RpcController;
135import org.apache.hbase.thirdparty.com.google.protobuf.Service;
136import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
137import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;
138
139import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
140import org.apache.hadoop.hbase.shaded.protobuf.ResponseConverter;
141import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos;
142import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.AccessControlService;
143import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GetUserPermissionsRequest;
144import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GetUserPermissionsResponse;
145import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantRequest;
146import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantResponse;
147import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsRequest;
148import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsResponse;
149import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type;
150import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest;
151import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeResponse;
152import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.AdminService;
153import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesRequest;
154import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesResponse;
155import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearRegionBlockCacheRequest;
156import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearRegionBlockCacheResponse;
157import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CloseRegionRequest;
158import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CloseRegionResponse;
159import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactRegionRequest;
160import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactRegionResponse;
161import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactionSwitchRequest;
162import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactionSwitchResponse;
163import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresRequest;
164import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresResponse;
165import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.FlushRegionRequest;
166import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.FlushRegionResponse;
167import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetCachedFilesListRequest;
168import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetCachedFilesListResponse;
169import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionRequest;
170import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse;
171import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest;
172import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse;
173import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionLoadRequest;
174import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionLoadResponse;
175import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetServerInfoRequest;
176import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetServerInfoResponse;
177import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetStoreFileRequest;
178import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetStoreFileResponse;
179import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.OpenRegionRequest;
180import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.OpenRegionResponse;
181import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ReplicateWALEntryRequest;
182import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ReplicateWALEntryResponse;
183import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.RollWALWriterRequest;
184import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.RollWALWriterResponse;
185import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.StopServerRequest;
186import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.StopServerResponse;
187import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.UpdateFavoredNodesRequest;
188import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.UpdateFavoredNodesResponse;
189import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.WarmupRegionRequest;
190import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.WarmupRegionResponse;
191import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos;
192import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos;
193import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;
194import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
195import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameStringPair;
196import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ProcedureDescription;
197import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier;
198import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
199import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.VersionInfo;
200import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockHeartbeatRequest;
201import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockHeartbeatResponse;
202import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockRequest;
203import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockResponse;
204import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos.LockService;
205import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos;
206import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureRequest;
207import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureResponse;
208import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AddColumnRequest;
209import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AddColumnResponse;
210import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AssignRegionRequest;
211import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AssignRegionResponse;
212import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ClearDeadServersRequest;
213import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ClearDeadServersResponse;
214import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateNamespaceRequest;
215import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateNamespaceResponse;
216import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableRequest;
217import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableResponse;
218import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DecommissionRegionServersRequest;
219import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DecommissionRegionServersResponse;
220import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteColumnRequest;
221import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteColumnResponse;
222import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteNamespaceRequest;
223import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteNamespaceResponse;
224import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteSnapshotRequest;
225import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteSnapshotResponse;
226import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTableRequest;
227import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTableResponse;
228import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableRequest;
229import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableResponse;
230import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest;
231import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableCatalogJanitorResponse;
232import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableRequest;
233import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableResponse;
234import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ExecProcedureRequest;
235import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ExecProcedureResponse;
236import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.FixMetaRequest;
237import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.FixMetaResponse;
238import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.FlushMasterStoreRequest;
239import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.FlushMasterStoreResponse;
240import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.FlushTableRequest;
241import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.FlushTableResponse;
242import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetClusterStatusRequest;
243import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetClusterStatusResponse;
244import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetCompletedSnapshotsRequest;
245import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetCompletedSnapshotsResponse;
246import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetLocksRequest;
247import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetLocksResponse;
248import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest;
249import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorResponse;
250import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultRequest;
251import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultResponse;
252import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProceduresRequest;
253import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProceduresResponse;
254import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
255import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusResponse;
256import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
257import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
258import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesRequest;
259import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesResponse;
260import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateRequest;
261import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateResponse;
262import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.HbckService;
263import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsBalancerEnabledRequest;
264import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsBalancerEnabledResponse;
265import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
266import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledResponse;
267import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCleanerChoreEnabledRequest;
268import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCleanerChoreEnabledResponse;
269import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsInMaintenanceModeRequest;
270import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsInMaintenanceModeResponse;
271import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsMasterRunningRequest;
272import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsMasterRunningResponse;
273import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsNormalizerEnabledRequest;
274import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsNormalizerEnabledResponse;
275import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedureDoneRequest;
276import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsProcedureDoneResponse;
277import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotCleanupEnabledRequest;
278import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotCleanupEnabledResponse;
279import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
280import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
281import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSplitOrMergeEnabledRequest;
282import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsSplitOrMergeEnabledResponse;
283import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListDecommissionedRegionServersRequest;
284import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListDecommissionedRegionServersResponse;
285import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest;
286import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsResponse;
287import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespacesRequest;
288import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespacesResponse;
289import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceRequest;
290import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceResponse;
291import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByStateRequest;
292import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByStateResponse;
293import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableNamesByNamespaceRequest;
294import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableNamesByNamespaceResponse;
295import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableNamesByStateRequest;
296import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableNamesByStateResponse;
297import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MajorCompactionTimestampForRegionRequest;
298import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MajorCompactionTimestampRequest;
299import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MajorCompactionTimestampResponse;
300import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MasterService;
301import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MergeTableRegionsRequest;
302import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MergeTableRegionsResponse;
303import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyColumnRequest;
304import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyColumnResponse;
305import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyColumnStoreFileTrackerRequest;
306import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyColumnStoreFileTrackerResponse;
307import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyNamespaceRequest;
308import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyNamespaceResponse;
309import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyTableRequest;
310import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyTableResponse;
311import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyTableStoreFileTrackerRequest;
312import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyTableStoreFileTrackerResponse;
313import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MoveRegionRequest;
314import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MoveRegionResponse;
315import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.NormalizeRequest;
316import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.NormalizeResponse;
317import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.OfflineRegionRequest;
318import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.OfflineRegionResponse;
319import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RecommissionRegionServerRequest;
320import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RecommissionRegionServerResponse;
321import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RegionSpecifierAndState;
322import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ReopenTableRegionsRequest;
323import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ReopenTableRegionsResponse;
324import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
325import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
326import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RollAllWALWritersRequest;
327import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RollAllWALWritersResponse;
328import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanRequest;
329import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanResponse;
330import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreRequest;
331import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreResponse;
332import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunHbckChoreRequest;
333import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunHbckChoreResponse;
334import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
335import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse;
336import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
337import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
338import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest;
339import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningResponse;
340import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningRequest;
341import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningResponse;
342import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest;
343import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaResponse;
344import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetRegionStateInMetaRequest;
345import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetRegionStateInMetaResponse;
346import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSnapshotCleanupRequest;
347import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSnapshotCleanupResponse;
348import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledRequest;
349import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledResponse;
350import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetTableStateInMetaRequest;
351import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownRequest;
352import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownResponse;
353import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SnapshotRequest;
354import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SnapshotResponse;
355import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SplitTableRegionRequest;
356import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SplitTableRegionResponse;
357import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.StopMasterRequest;
358import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.StopMasterResponse;
359import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SwitchExceedThrottleQuotaRequest;
360import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SwitchExceedThrottleQuotaResponse;
361import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SwitchRpcThrottleRequest;
362import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SwitchRpcThrottleResponse;
363import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.TruncateTableRequest;
364import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.TruncateTableResponse;
365import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignRegionRequest;
366import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignRegionResponse;
367import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetQuotaStatesRequest;
368import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetQuotaStatesResponse;
369import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetQuotaStatesResponse.NamespaceQuotaSnapshot;
370import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetQuotaStatesResponse.TableQuotaSnapshot;
371import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaRegionSizesRequest;
372import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaRegionSizesResponse;
373import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaRegionSizesResponse.RegionSizes;
374import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaSnapshotsRequest;
375import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.GetSpaceQuotaSnapshotsResponse;
376import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.AddRSGroupRequest;
377import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.AddRSGroupResponse;
378import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupRequest;
379import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupResponse;
380import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetConfiguredNamespacesAndTablesInRSGroupRequest;
381import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetConfiguredNamespacesAndTablesInRSGroupResponse;
382import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerRequest;
383import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerResponse;
384import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableRequest;
385import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableResponse;
386import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoRequest;
387import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoResponse;
388import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosRequest;
389import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosResponse;
390import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListTablesInRSGroupRequest;
391import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListTablesInRSGroupResponse;
392import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersRequest;
393import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersResponse;
394import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupRequest;
395import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupResponse;
396import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest;
397import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse;
398import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RenameRSGroupRequest;
399import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RenameRSGroupResponse;
400import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.UpdateRSGroupConfigRequest;
401import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.UpdateRSGroupConfigResponse;
402import org.apache.hadoop.hbase.shaded.protobuf.generated.RecentLogs;
403import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos;
404import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.FileArchiveNotificationRequest;
405import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.FileArchiveNotificationResponse;
406import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdRequest;
407import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdResponse;
408import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.GetLiveRegionServersRequest;
409import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.GetLiveRegionServersResponse;
410import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest;
411import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerReportResponse;
412import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;
413import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupResponse;
414import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStatusService;
415import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionSpaceUse;
416import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionSpaceUseReportRequest;
417import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionSpaceUseReportResponse;
418import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RemoteProcedureResult;
419import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportProcedureDoneRequest;
420import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportProcedureDoneResponse;
421import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRSFatalErrorRequest;
422import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRSFatalErrorResponse;
423import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionRequest;
424import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionResponse;
425import org.apache.hadoop.hbase.shaded.protobuf.generated.RegistryProtos.ClientMetaService;
426import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.AddReplicationPeerRequest;
427import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.AddReplicationPeerResponse;
428import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.DisableReplicationPeerRequest;
429import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.DisableReplicationPeerResponse;
430import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.EnableReplicationPeerRequest;
431import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.EnableReplicationPeerResponse;
432import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerConfigRequest;
433import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerConfigResponse;
434import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerModificationProceduresRequest;
435import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerModificationProceduresResponse;
436import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerStateRequest;
437import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.GetReplicationPeerStateResponse;
438import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.IsReplicationPeerModificationEnabledRequest;
439import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.IsReplicationPeerModificationEnabledResponse;
440import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.ListReplicationPeersRequest;
441import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.ListReplicationPeersResponse;
442import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.RemoveReplicationPeerRequest;
443import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.RemoveReplicationPeerResponse;
444import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.ReplicationPeerModificationSwitchRequest;
445import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.ReplicationPeerModificationSwitchResponse;
446import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.ReplicationState;
447import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.TransitReplicationPeerSyncReplicationStateRequest;
448import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.TransitReplicationPeerSyncReplicationStateResponse;
449import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigRequest;
450import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigResponse;
451import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;
452import org.apache.hadoop.hbase.shaded.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService;
453
454/**
455 * Implements the master RPC services.
456 */
457@InterfaceAudience.Private
458public class MasterRpcServices extends HBaseRpcServicesBase<HMaster>
459  implements MasterService.BlockingInterface, RegionServerStatusService.BlockingInterface,
460  LockService.BlockingInterface, HbckService.BlockingInterface {
461
462  private static final Logger LOG = LoggerFactory.getLogger(MasterRpcServices.class.getName());
463  private static final Logger AUDITLOG =
464    LoggerFactory.getLogger("SecurityLogger." + MasterRpcServices.class.getName());
465
466  /** RPC scheduler to use for the master. */
467  public static final String MASTER_RPC_SCHEDULER_FACTORY_CLASS =
468    "hbase.master.rpc.scheduler.factory.class";
469
470  /**
471   * @return Subset of configuration to pass initializing regionservers: e.g. the filesystem to use
472   *         and root directory to use.
473   */
474  private RegionServerStartupResponse.Builder createConfigurationSubset() {
475    RegionServerStartupResponse.Builder resp =
476      addConfig(RegionServerStartupResponse.newBuilder(), HConstants.HBASE_DIR);
477    resp = addConfig(resp, "fs.defaultFS");
478    return addConfig(resp, "hbase.master.info.port");
479  }
480
481  private RegionServerStartupResponse.Builder
482    addConfig(final RegionServerStartupResponse.Builder resp, final String key) {
483    NameStringPair.Builder entry =
484      NameStringPair.newBuilder().setName(key).setValue(server.getConfiguration().get(key));
485    resp.addMapEntries(entry.build());
486    return resp;
487  }
488
489  public MasterRpcServices(HMaster m) throws IOException {
490    super(m, m.getProcessName());
491  }
492
493  @Override
494  protected boolean defaultReservoirEnabled() {
495    return false;
496  }
497
498  @Override
499  protected ServerType getDNSServerType() {
500    return DNS.ServerType.MASTER;
501  }
502
503  @Override
504  protected String getHostname(Configuration conf, String defaultHostname) {
505    return conf.get("hbase.master.ipc.address", defaultHostname);
506  }
507
508  @Override
509  protected String getPortConfigName() {
510    return HConstants.MASTER_PORT;
511  }
512
513  @Override
514  protected int getDefaultPort() {
515    return HConstants.DEFAULT_MASTER_PORT;
516  }
517
518  @Override
519  protected Class<?> getRpcSchedulerFactoryClass(Configuration conf) {
520    return conf.getClass(MASTER_RPC_SCHEDULER_FACTORY_CLASS, SimpleRpcSchedulerFactory.class);
521  }
522
523  @Override
524  protected PriorityFunction createPriority() {
525    return new MasterAnnotationReadingPriorityFunction(this);
526  }
527
528  /**
529   * Checks for the following pre-checks in order:
530   * <ol>
531   * <li>Master is initialized</li>
532   * <li>Rpc caller has admin permissions</li>
533   * </ol>
534   * @param requestName name of rpc request. Used in reporting failures to provide context.
535   * @throws ServiceException If any of the above listed pre-check fails.
536   */
537  private void rpcPreCheck(String requestName) throws ServiceException {
538    try {
539      server.checkInitialized();
540      requirePermission(requestName, Permission.Action.ADMIN);
541    } catch (IOException ioe) {
542      throw new ServiceException(ioe);
543    }
544  }
545
546  enum BalanceSwitchMode {
547    SYNC,
548    ASYNC
549  }
550
551  /**
552   * Assigns balancer switch according to BalanceSwitchMode
553   * @param b    new balancer switch
554   * @param mode BalanceSwitchMode
555   * @return old balancer switch
556   */
557  boolean switchBalancer(final boolean b, BalanceSwitchMode mode) throws IOException {
558    boolean oldValue = server.loadBalancerStateStore.get();
559    boolean newValue = b;
560    try {
561      if (server.cpHost != null) {
562        server.cpHost.preBalanceSwitch(newValue);
563      }
564      if (mode == BalanceSwitchMode.SYNC) {
565        synchronized (server.getLoadBalancer()) {
566          server.loadBalancerStateStore.set(newValue);
567        }
568      } else {
569        server.loadBalancerStateStore.set(newValue);
570      }
571      LOG.info(server.getClientIdAuditPrefix() + " set balanceSwitch=" + newValue);
572      if (server.cpHost != null) {
573        server.cpHost.postBalanceSwitch(oldValue, newValue);
574      }
575      server.getLoadBalancer().updateBalancerStatus(newValue);
576    } catch (IOException ioe) {
577      LOG.warn("Error flipping balance switch", ioe);
578    }
579    return oldValue;
580  }
581
582  boolean synchronousBalanceSwitch(final boolean b) throws IOException {
583    return switchBalancer(b, BalanceSwitchMode.SYNC);
584  }
585
586  /** Returns list of blocking services and their security info classes that this server supports */
587  @Override
588  protected List<BlockingServiceAndInterface> getServices() {
589    List<BlockingServiceAndInterface> bssi = new ArrayList<>(5);
590    bssi.add(new BlockingServiceAndInterface(MasterService.newReflectiveBlockingService(this),
591      MasterService.BlockingInterface.class));
592    bssi.add(
593      new BlockingServiceAndInterface(RegionServerStatusService.newReflectiveBlockingService(this),
594        RegionServerStatusService.BlockingInterface.class));
595    bssi.add(new BlockingServiceAndInterface(LockService.newReflectiveBlockingService(this),
596      LockService.BlockingInterface.class));
597    bssi.add(new BlockingServiceAndInterface(HbckService.newReflectiveBlockingService(this),
598      HbckService.BlockingInterface.class));
599    bssi.add(new BlockingServiceAndInterface(ClientMetaService.newReflectiveBlockingService(this),
600      ClientMetaService.BlockingInterface.class));
601    bssi.add(new BlockingServiceAndInterface(AdminService.newReflectiveBlockingService(this),
602      AdminService.BlockingInterface.class));
603    return bssi;
604  }
605
606  void start(ZKWatcher zkWatcher) {
607    internalStart(zkWatcher);
608  }
609
610  void stop() {
611    internalStop();
612  }
613
614  @Override
615  // priority for all RegionServerStatusProtos rpc's are set HIGH_QOS in
616  // MasterAnnotationReadingPriorityFunction itself
617  public GetLastFlushedSequenceIdResponse getLastFlushedSequenceId(RpcController controller,
618    GetLastFlushedSequenceIdRequest request) throws ServiceException {
619    try {
620      server.checkServiceStarted();
621    } catch (IOException ioe) {
622      throw new ServiceException(ioe);
623    }
624    byte[] encodedRegionName = request.getRegionName().toByteArray();
625    RegionStoreSequenceIds ids =
626      server.getServerManager().getLastFlushedSequenceId(encodedRegionName);
627    return ResponseConverter.buildGetLastFlushedSequenceIdResponse(ids);
628  }
629
630  @Override
631  public RegionServerReportResponse regionServerReport(RpcController controller,
632    RegionServerReportRequest request) throws ServiceException {
633    try {
634      server.checkServiceStarted();
635      int versionNumber = 0;
636      String version = "0.0.0";
637      VersionInfo versionInfo = VersionInfoUtil.getCurrentClientVersionInfo();
638      if (versionInfo != null) {
639        version = versionInfo.getVersion();
640        versionNumber = VersionInfoUtil.getVersionNumber(versionInfo);
641      }
642      ClusterStatusProtos.ServerLoad sl = request.getLoad();
643      ServerName serverName = ProtobufUtil.toServerName(request.getServer());
644      ServerMetrics oldLoad = server.getServerManager().getLoad(serverName);
645      ServerMetrics newLoad =
646        ServerMetricsBuilder.toServerMetrics(serverName, versionNumber, version, sl);
647      server.getServerManager().regionServerReport(serverName, newLoad);
648      server.getAssignmentManager().reportOnlineRegions(serverName,
649        newLoad.getRegionMetrics().keySet());
650      if (sl != null && server.metricsMaster != null) {
651        // Up our metrics.
652        server.metricsMaster.incrementRequests(
653          sl.getTotalNumberOfRequests() - (oldLoad != null ? oldLoad.getRequestCount() : 0));
654        server.metricsMaster.incrementReadRequests(
655          sl.getReadRequestsCount() - (oldLoad != null ? oldLoad.getReadRequestsCount() : 0));
656        server.metricsMaster.incrementWriteRequests(
657          sl.getWriteRequestsCount() - (oldLoad != null ? oldLoad.getWriteRequestsCount() : 0));
658      }
659    } catch (IOException ioe) {
660      throw new ServiceException(ioe);
661    }
662    return RegionServerReportResponse.newBuilder().build();
663  }
664
665  @Override
666  public RegionServerStartupResponse regionServerStartup(RpcController controller,
667    RegionServerStartupRequest request) throws ServiceException {
668    // Register with server manager
669    try {
670      server.checkServiceStarted();
671      int versionNumber = 0;
672      String version = "0.0.0";
673      VersionInfo versionInfo = VersionInfoUtil.getCurrentClientVersionInfo();
674      if (versionInfo != null) {
675        version = versionInfo.getVersion();
676        versionNumber = VersionInfoUtil.getVersionNumber(versionInfo);
677      }
678      InetAddress ia = server.getRemoteInetAddress(request.getPort(), request.getServerStartCode());
679      // if regionserver passed hostname to use,
680      // then use it instead of doing a reverse DNS lookup
681      ServerName rs =
682        server.getServerManager().regionServerStartup(request, versionNumber, version, ia);
683
684      // Send back some config info
685      RegionServerStartupResponse.Builder resp = createConfigurationSubset();
686      NameStringPair.Builder entry = NameStringPair.newBuilder()
687        .setName(HConstants.KEY_FOR_HOSTNAME_SEEN_BY_MASTER).setValue(rs.getHostname());
688      resp.addMapEntries(entry.build());
689
690      return resp.build();
691    } catch (IOException ioe) {
692      throw new ServiceException(ioe);
693    }
694  }
695
696  @Override
697  public ReportRSFatalErrorResponse reportRSFatalError(RpcController controller,
698    ReportRSFatalErrorRequest request) throws ServiceException {
699    String errorText = request.getErrorMessage();
700    ServerName sn = ProtobufUtil.toServerName(request.getServer());
701    String msg = sn + " reported a fatal error:\n" + errorText;
702    LOG.warn(msg);
703    server.rsFatals.add(msg);
704    return ReportRSFatalErrorResponse.newBuilder().build();
705  }
706
707  @Override
708  public AddColumnResponse addColumn(RpcController controller, AddColumnRequest req)
709    throws ServiceException {
710    try {
711      long procId = server.addColumn(ProtobufUtil.toTableName(req.getTableName()),
712        ProtobufUtil.toColumnFamilyDescriptor(req.getColumnFamilies()), req.getNonceGroup(),
713        req.getNonce());
714      if (procId == -1) {
715        // This mean operation was not performed in server, so do not set any procId
716        return AddColumnResponse.newBuilder().build();
717      } else {
718        return AddColumnResponse.newBuilder().setProcId(procId).build();
719      }
720    } catch (IOException ioe) {
721      throw new ServiceException(ioe);
722    }
723  }
724
725  @Override
726  public AssignRegionResponse assignRegion(RpcController controller, AssignRegionRequest req)
727    throws ServiceException {
728    try {
729      server.checkInitialized();
730
731      final RegionSpecifierType type = req.getRegion().getType();
732      if (type != RegionSpecifierType.REGION_NAME) {
733        LOG.warn("assignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
734          + " actual: " + type);
735      }
736
737      final byte[] regionName = req.getRegion().getValue().toByteArray();
738      final RegionInfo regionInfo = server.getAssignmentManager().getRegionInfo(regionName);
739      if (regionInfo == null) {
740        throw new UnknownRegionException(Bytes.toStringBinary(regionName));
741      }
742
743      final AssignRegionResponse arr = AssignRegionResponse.newBuilder().build();
744      if (server.cpHost != null) {
745        server.cpHost.preAssign(regionInfo);
746      }
747      LOG.info(server.getClientIdAuditPrefix() + " assign " + regionInfo.getRegionNameAsString());
748      server.getAssignmentManager().assign(regionInfo);
749      if (server.cpHost != null) {
750        server.cpHost.postAssign(regionInfo);
751      }
752      return arr;
753    } catch (IOException ioe) {
754      throw new ServiceException(ioe);
755    }
756  }
757
758  @Override
759  public MasterProtos.BalanceResponse balance(RpcController controller,
760    MasterProtos.BalanceRequest request) throws ServiceException {
761    try {
762      return ProtobufUtil.toBalanceResponse(server.balance(ProtobufUtil.toBalanceRequest(request)));
763    } catch (IOException ex) {
764      throw new ServiceException(ex);
765    }
766  }
767
768  @Override
769  public CreateNamespaceResponse createNamespace(RpcController controller,
770    CreateNamespaceRequest request) throws ServiceException {
771    try {
772      long procId =
773        server.createNamespace(ProtobufUtil.toNamespaceDescriptor(request.getNamespaceDescriptor()),
774          request.getNonceGroup(), request.getNonce());
775      return CreateNamespaceResponse.newBuilder().setProcId(procId).build();
776    } catch (IOException e) {
777      throw new ServiceException(e);
778    }
779  }
780
781  @Override
782  public CreateTableResponse createTable(RpcController controller, CreateTableRequest req)
783    throws ServiceException {
784    TableDescriptor tableDescriptor = ProtobufUtil.toTableDescriptor(req.getTableSchema());
785    byte[][] splitKeys = ProtobufUtil.getSplitKeysArray(req);
786    try {
787      long procId =
788        server.createTable(tableDescriptor, splitKeys, req.getNonceGroup(), req.getNonce());
789      LOG.info(server.getClientIdAuditPrefix() + " procedure request for creating table: "
790        + req.getTableSchema().getTableName() + " procId is: " + procId);
791      return CreateTableResponse.newBuilder().setProcId(procId).build();
792    } catch (IOException ioe) {
793      throw new ServiceException(ioe);
794    }
795  }
796
797  @Override
798  public DeleteColumnResponse deleteColumn(RpcController controller, DeleteColumnRequest req)
799    throws ServiceException {
800    try {
801      long procId = server.deleteColumn(ProtobufUtil.toTableName(req.getTableName()),
802        req.getColumnName().toByteArray(), req.getNonceGroup(), req.getNonce());
803      if (procId == -1) {
804        // This mean operation was not performed in server, so do not set any procId
805        return DeleteColumnResponse.newBuilder().build();
806      } else {
807        return DeleteColumnResponse.newBuilder().setProcId(procId).build();
808      }
809    } catch (IOException ioe) {
810      throw new ServiceException(ioe);
811    }
812  }
813
814  @Override
815  public DeleteNamespaceResponse deleteNamespace(RpcController controller,
816    DeleteNamespaceRequest request) throws ServiceException {
817    try {
818      long procId = server.deleteNamespace(request.getNamespaceName(), request.getNonceGroup(),
819        request.getNonce());
820      return DeleteNamespaceResponse.newBuilder().setProcId(procId).build();
821    } catch (IOException e) {
822      throw new ServiceException(e);
823    }
824  }
825
826  /**
827   * Execute Delete Snapshot operation.
828   * @return DeleteSnapshotResponse (a protobuf wrapped void) if the snapshot existed and was
829   *         deleted properly.
830   * @throws ServiceException wrapping SnapshotDoesNotExistException if specified snapshot did not
831   *                          exist.
832   */
833  @Override
834  public DeleteSnapshotResponse deleteSnapshot(RpcController controller,
835    DeleteSnapshotRequest request) throws ServiceException {
836    try {
837      server.checkInitialized();
838      server.snapshotManager.checkSnapshotSupport();
839
840      LOG.info(server.getClientIdAuditPrefix() + " delete " + request.getSnapshot());
841      server.snapshotManager.deleteSnapshot(request.getSnapshot());
842      return DeleteSnapshotResponse.newBuilder().build();
843    } catch (IOException e) {
844      throw new ServiceException(e);
845    }
846  }
847
848  @Override
849  public DeleteTableResponse deleteTable(RpcController controller, DeleteTableRequest request)
850    throws ServiceException {
851    try {
852      long procId = server.deleteTable(ProtobufUtil.toTableName(request.getTableName()),
853        request.getNonceGroup(), request.getNonce());
854      return DeleteTableResponse.newBuilder().setProcId(procId).build();
855    } catch (IOException ioe) {
856      throw new ServiceException(ioe);
857    }
858  }
859
860  @Override
861  public TruncateTableResponse truncateTable(RpcController controller, TruncateTableRequest request)
862    throws ServiceException {
863    try {
864      long procId = server.truncateTable(ProtobufUtil.toTableName(request.getTableName()),
865        request.getPreserveSplits(), request.getNonceGroup(), request.getNonce());
866      return TruncateTableResponse.newBuilder().setProcId(procId).build();
867    } catch (IOException ioe) {
868      throw new ServiceException(ioe);
869    }
870  }
871
872  @Override
873  public DisableTableResponse disableTable(RpcController controller, DisableTableRequest request)
874    throws ServiceException {
875    try {
876      long procId = server.disableTable(ProtobufUtil.toTableName(request.getTableName()),
877        request.getNonceGroup(), request.getNonce());
878      return DisableTableResponse.newBuilder().setProcId(procId).build();
879    } catch (IOException ioe) {
880      throw new ServiceException(ioe);
881    }
882  }
883
884  @Override
885  public EnableCatalogJanitorResponse enableCatalogJanitor(RpcController c,
886    EnableCatalogJanitorRequest req) throws ServiceException {
887    rpcPreCheck("enableCatalogJanitor");
888    return EnableCatalogJanitorResponse.newBuilder()
889      .setPrevValue(server.catalogJanitorChore.setEnabled(req.getEnable())).build();
890  }
891
892  @Override
893  public SetCleanerChoreRunningResponse setCleanerChoreRunning(RpcController c,
894    SetCleanerChoreRunningRequest req) throws ServiceException {
895    rpcPreCheck("setCleanerChoreRunning");
896
897    boolean prevValue =
898      server.getLogCleaner().getEnabled() && server.getHFileCleaner().getEnabled();
899    server.getLogCleaner().setEnabled(req.getOn());
900    for (HFileCleaner hFileCleaner : server.getHFileCleaners()) {
901      hFileCleaner.setEnabled(req.getOn());
902    }
903    return SetCleanerChoreRunningResponse.newBuilder().setPrevValue(prevValue).build();
904  }
905
906  @Override
907  public EnableTableResponse enableTable(RpcController controller, EnableTableRequest request)
908    throws ServiceException {
909    try {
910      long procId = server.enableTable(ProtobufUtil.toTableName(request.getTableName()),
911        request.getNonceGroup(), request.getNonce());
912      return EnableTableResponse.newBuilder().setProcId(procId).build();
913    } catch (IOException ioe) {
914      throw new ServiceException(ioe);
915    }
916  }
917
918  @Override
919  public MergeTableRegionsResponse mergeTableRegions(RpcController c,
920    MergeTableRegionsRequest request) throws ServiceException {
921    try {
922      server.checkInitialized();
923    } catch (IOException ioe) {
924      throw new ServiceException(ioe);
925    }
926
927    RegionStates regionStates = server.getAssignmentManager().getRegionStates();
928
929    RegionInfo[] regionsToMerge = new RegionInfo[request.getRegionCount()];
930    for (int i = 0; i < request.getRegionCount(); i++) {
931      final byte[] encodedNameOfRegion = request.getRegion(i).getValue().toByteArray();
932      if (request.getRegion(i).getType() != RegionSpecifierType.ENCODED_REGION_NAME) {
933        LOG.warn("MergeRegions specifier type: expected: " + RegionSpecifierType.ENCODED_REGION_NAME
934          + " actual: region " + i + " =" + request.getRegion(i).getType());
935      }
936      RegionState regionState = regionStates.getRegionState(Bytes.toString(encodedNameOfRegion));
937      if (regionState == null) {
938        throw new ServiceException(
939          new UnknownRegionException(Bytes.toStringBinary(encodedNameOfRegion)));
940      }
941      regionsToMerge[i] = regionState.getRegion();
942    }
943
944    try {
945      long procId = server.mergeRegions(regionsToMerge, request.getForcible(),
946        request.getNonceGroup(), request.getNonce());
947      return MergeTableRegionsResponse.newBuilder().setProcId(procId).build();
948    } catch (IOException ioe) {
949      throw new ServiceException(ioe);
950    }
951  }
952
953  @Override
954  public SplitTableRegionResponse splitRegion(final RpcController controller,
955    final SplitTableRegionRequest request) throws ServiceException {
956    try {
957      long procId = server.splitRegion(ProtobufUtil.toRegionInfo(request.getRegionInfo()),
958        request.hasSplitRow() ? request.getSplitRow().toByteArray() : null, request.getNonceGroup(),
959        request.getNonce());
960      return SplitTableRegionResponse.newBuilder().setProcId(procId).build();
961    } catch (IOException ie) {
962      throw new ServiceException(ie);
963    }
964  }
965
966  @Override
967  public MasterProtos.TruncateRegionResponse truncateRegion(RpcController controller,
968    final MasterProtos.TruncateRegionRequest request) throws ServiceException {
969    try {
970      long procId = server.truncateRegion(ProtobufUtil.toRegionInfo(request.getRegionInfo()),
971        request.getNonceGroup(), request.getNonce());
972      return MasterProtos.TruncateRegionResponse.newBuilder().setProcId(procId).build();
973    } catch (IOException ie) {
974      throw new ServiceException(ie);
975    }
976  }
977
978  @Override
979  public ClientProtos.CoprocessorServiceResponse execMasterService(final RpcController controller,
980    final ClientProtos.CoprocessorServiceRequest request) throws ServiceException {
981    rpcPreCheck("execMasterService");
982    try {
983      ServerRpcController execController = new ServerRpcController();
984      ClientProtos.CoprocessorServiceCall call = request.getCall();
985      String serviceName = call.getServiceName();
986      String methodName = call.getMethodName();
987      if (!server.coprocessorServiceHandlers.containsKey(serviceName)) {
988        throw new UnknownProtocolException(null,
989          "No registered Master Coprocessor Endpoint found for " + serviceName
990            + ". Has it been enabled?");
991      }
992
993      Service service = server.coprocessorServiceHandlers.get(serviceName);
994      ServiceDescriptor serviceDesc = service.getDescriptorForType();
995      MethodDescriptor methodDesc =
996        CoprocessorRpcUtils.getMethodDescriptor(methodName, serviceDesc);
997
998      Message execRequest = CoprocessorRpcUtils.getRequest(service, methodDesc, call.getRequest());
999      final Message.Builder responseBuilder =
1000        service.getResponsePrototype(methodDesc).newBuilderForType();
1001      service.callMethod(methodDesc, execController, execRequest, (message) -> {
1002        if (message != null) {
1003          responseBuilder.mergeFrom(message);
1004        }
1005      });
1006      Message execResult = responseBuilder.build();
1007      if (execController.getFailedOn() != null) {
1008        throw execController.getFailedOn();
1009      }
1010
1011      String remoteAddress = RpcServer.getRemoteAddress().map(InetAddress::toString).orElse("");
1012      User caller = RpcServer.getRequestUser().orElse(null);
1013      AUDITLOG.info("User {} (remote address: {}) master service request for {}.{}", caller,
1014        remoteAddress, serviceName, methodName);
1015
1016      return CoprocessorRpcUtils.getResponse(execResult, HConstants.EMPTY_BYTE_ARRAY);
1017    } catch (IOException ie) {
1018      throw new ServiceException(ie);
1019    }
1020  }
1021
1022  /**
1023   * Triggers an asynchronous attempt to run a distributed procedure. {@inheritDoc}
1024   */
1025  @Override
1026  public ExecProcedureResponse execProcedure(RpcController controller, ExecProcedureRequest request)
1027    throws ServiceException {
1028    try {
1029      server.checkInitialized();
1030      ProcedureDescription desc = request.getProcedure();
1031      MasterProcedureManager mpm =
1032        server.getMasterProcedureManagerHost().getProcedureManager(desc.getSignature());
1033      if (mpm == null) {
1034        throw new ServiceException(
1035          new DoNotRetryIOException("The procedure is not registered: " + desc.getSignature()));
1036      }
1037      LOG.info(server.getClientIdAuditPrefix() + " procedure request for: " + desc.getSignature());
1038      mpm.checkPermissions(desc, getAccessChecker(), RpcServer.getRequestUser().orElse(null));
1039      mpm.execProcedure(desc);
1040      // send back the max amount of time the client should wait for the procedure
1041      // to complete
1042      long waitTime = SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME;
1043      return ExecProcedureResponse.newBuilder().setExpectedTimeout(waitTime).build();
1044    } catch (ForeignException e) {
1045      throw new ServiceException(e.getCause());
1046    } catch (IOException e) {
1047      throw new ServiceException(e);
1048    }
1049  }
1050
1051  /**
1052   * Triggers a synchronous attempt to run a distributed procedure and sets return data in response.
1053   * {@inheritDoc}
1054   */
1055  @Override
1056  public ExecProcedureResponse execProcedureWithRet(RpcController controller,
1057    ExecProcedureRequest request) throws ServiceException {
1058    rpcPreCheck("execProcedureWithRet");
1059    try {
1060      ProcedureDescription desc = request.getProcedure();
1061      MasterProcedureManager mpm =
1062        server.getMasterProcedureManagerHost().getProcedureManager(desc.getSignature());
1063      if (mpm == null) {
1064        throw new ServiceException("The procedure is not registered: " + desc.getSignature());
1065      }
1066      LOG.info(server.getClientIdAuditPrefix() + " procedure request for: " + desc.getSignature());
1067      byte[] data = mpm.execProcedureWithRet(desc);
1068      ExecProcedureResponse.Builder builder = ExecProcedureResponse.newBuilder();
1069      // set return data if available
1070      if (data != null) {
1071        builder.setReturnData(UnsafeByteOperations.unsafeWrap(data));
1072      }
1073      return builder.build();
1074    } catch (IOException e) {
1075      throw new ServiceException(e);
1076    }
1077  }
1078
1079  @Override
1080  public GetClusterStatusResponse getClusterStatus(RpcController controller,
1081    GetClusterStatusRequest req) throws ServiceException {
1082    GetClusterStatusResponse.Builder response = GetClusterStatusResponse.newBuilder();
1083    try {
1084      // We used to check if Master was up at this point but let this call proceed even if
1085      // Master is initializing... else we shut out stuff like hbck2 tool from making progress
1086      // since it queries this method to figure cluster version. hbck2 wants to be able to work
1087      // against Master even if it is 'initializing' so it can do fixup.
1088      response.setClusterStatus(ClusterMetricsBuilder.toClusterStatus(
1089        server.getClusterMetrics(ClusterMetricsBuilder.toOptions(req.getOptionsList()))));
1090    } catch (IOException e) {
1091      throw new ServiceException(e);
1092    }
1093    return response.build();
1094  }
1095
1096  /**
1097   * List the currently available/stored snapshots. Any in-progress snapshots are ignored
1098   */
1099  @Override
1100  public GetCompletedSnapshotsResponse getCompletedSnapshots(RpcController controller,
1101    GetCompletedSnapshotsRequest request) throws ServiceException {
1102    try {
1103      server.checkInitialized();
1104      GetCompletedSnapshotsResponse.Builder builder = GetCompletedSnapshotsResponse.newBuilder();
1105      List<SnapshotDescription> snapshots = server.snapshotManager.getCompletedSnapshots();
1106
1107      // convert to protobuf
1108      for (SnapshotDescription snapshot : snapshots) {
1109        builder.addSnapshots(snapshot);
1110      }
1111      return builder.build();
1112    } catch (IOException e) {
1113      throw new ServiceException(e);
1114    }
1115  }
1116
1117  @Override
1118  public ListNamespacesResponse listNamespaces(RpcController controller,
1119    ListNamespacesRequest request) throws ServiceException {
1120    try {
1121      return ListNamespacesResponse.newBuilder().addAllNamespaceName(server.listNamespaces())
1122        .build();
1123    } catch (IOException e) {
1124      throw new ServiceException(e);
1125    }
1126  }
1127
1128  @Override
1129  public GetNamespaceDescriptorResponse getNamespaceDescriptor(RpcController controller,
1130    GetNamespaceDescriptorRequest request) throws ServiceException {
1131    try {
1132      return GetNamespaceDescriptorResponse.newBuilder()
1133        .setNamespaceDescriptor(
1134          ProtobufUtil.toProtoNamespaceDescriptor(server.getNamespace(request.getNamespaceName())))
1135        .build();
1136    } catch (IOException e) {
1137      throw new ServiceException(e);
1138    }
1139  }
1140
1141  /**
1142   * Get the number of regions of the table that have been updated by the alter.
1143   * @return Pair indicating the number of regions updated Pair.getFirst is the regions that are yet
1144   *         to be updated Pair.getSecond is the total number of regions of the table
1145   */
1146  @Override
1147  public GetSchemaAlterStatusResponse getSchemaAlterStatus(RpcController controller,
1148    GetSchemaAlterStatusRequest req) throws ServiceException {
1149    // TODO: currently, we query using the table name on the client side. this
1150    // may overlap with other table operations or the table operation may
1151    // have completed before querying this API. We need to refactor to a
1152    // transaction system in the future to avoid these ambiguities.
1153    TableName tableName = ProtobufUtil.toTableName(req.getTableName());
1154
1155    try {
1156      server.checkInitialized();
1157      Pair<Integer, Integer> pair = server.getAssignmentManager().getReopenStatus(tableName);
1158      GetSchemaAlterStatusResponse.Builder ret = GetSchemaAlterStatusResponse.newBuilder();
1159      ret.setYetToUpdateRegions(pair.getFirst());
1160      ret.setTotalRegions(pair.getSecond());
1161      return ret.build();
1162    } catch (IOException ioe) {
1163      throw new ServiceException(ioe);
1164    }
1165  }
1166
1167  /**
1168   * Get list of TableDescriptors for requested tables.
1169   * @param c   Unused (set to null).
1170   * @param req GetTableDescriptorsRequest that contains: - tableNames: requested tables, or if
1171   *            empty, all are requested.
1172   */
1173  @Override
1174  public GetTableDescriptorsResponse getTableDescriptors(RpcController c,
1175    GetTableDescriptorsRequest req) throws ServiceException {
1176    try {
1177      server.checkInitialized();
1178
1179      final String regex = req.hasRegex() ? req.getRegex() : null;
1180      final String namespace = req.hasNamespace() ? req.getNamespace() : null;
1181      List<TableName> tableNameList = null;
1182      if (req.getTableNamesCount() > 0) {
1183        tableNameList = new ArrayList<TableName>(req.getTableNamesCount());
1184        for (HBaseProtos.TableName tableNamePB : req.getTableNamesList()) {
1185          tableNameList.add(ProtobufUtil.toTableName(tableNamePB));
1186        }
1187      }
1188
1189      List<TableDescriptor> descriptors =
1190        server.listTableDescriptors(namespace, regex, tableNameList, req.getIncludeSysTables());
1191
1192      GetTableDescriptorsResponse.Builder builder = GetTableDescriptorsResponse.newBuilder();
1193      if (descriptors != null && descriptors.size() > 0) {
1194        // Add the table descriptors to the response
1195        for (TableDescriptor htd : descriptors) {
1196          builder.addTableSchema(ProtobufUtil.toTableSchema(htd));
1197        }
1198      }
1199      return builder.build();
1200    } catch (IOException ioe) {
1201      throw new ServiceException(ioe);
1202    }
1203  }
1204
1205  @Override
1206  public ListTableDescriptorsByStateResponse listTableDescriptorsByState(RpcController controller,
1207    ListTableDescriptorsByStateRequest request) throws ServiceException {
1208    try {
1209      server.checkInitialized();
1210      List<TableDescriptor> descriptors = server.listTableDescriptors(null, null, null, false);
1211
1212      ListTableDescriptorsByStateResponse.Builder builder =
1213        ListTableDescriptorsByStateResponse.newBuilder();
1214      if (descriptors != null && descriptors.size() > 0) {
1215        // Add the table descriptors to the response
1216        TableState.State state =
1217          request.getIsEnabled() ? TableState.State.ENABLED : TableState.State.DISABLED;
1218        for (TableDescriptor htd : descriptors) {
1219          if (server.getTableStateManager().isTableState(htd.getTableName(), state)) {
1220            builder.addTableSchema(ProtobufUtil.toTableSchema(htd));
1221          }
1222        }
1223      }
1224      return builder.build();
1225    } catch (IOException ioe) {
1226      throw new ServiceException(ioe);
1227    }
1228  }
1229
1230  /**
1231   * Get list of userspace table names
1232   * @param controller Unused (set to null).
1233   * @param req        GetTableNamesRequest
1234   */
1235  @Override
1236  public GetTableNamesResponse getTableNames(RpcController controller, GetTableNamesRequest req)
1237    throws ServiceException {
1238    try {
1239      server.checkServiceStarted();
1240
1241      final String regex = req.hasRegex() ? req.getRegex() : null;
1242      final String namespace = req.hasNamespace() ? req.getNamespace() : null;
1243      List<TableName> tableNames =
1244        server.listTableNames(namespace, regex, req.getIncludeSysTables());
1245
1246      GetTableNamesResponse.Builder builder = GetTableNamesResponse.newBuilder();
1247      if (tableNames != null && tableNames.size() > 0) {
1248        // Add the table names to the response
1249        for (TableName table : tableNames) {
1250          builder.addTableNames(ProtobufUtil.toProtoTableName(table));
1251        }
1252      }
1253      return builder.build();
1254    } catch (IOException e) {
1255      throw new ServiceException(e);
1256    }
1257  }
1258
1259  @Override
1260  public ListTableNamesByStateResponse listTableNamesByState(RpcController controller,
1261    ListTableNamesByStateRequest request) throws ServiceException {
1262    try {
1263      server.checkServiceStarted();
1264      List<TableName> tableNames = server.listTableNames(null, null, false);
1265      ListTableNamesByStateResponse.Builder builder = ListTableNamesByStateResponse.newBuilder();
1266      if (tableNames != null && tableNames.size() > 0) {
1267        // Add the disabled table names to the response
1268        TableState.State state =
1269          request.getIsEnabled() ? TableState.State.ENABLED : TableState.State.DISABLED;
1270        for (TableName table : tableNames) {
1271          if (server.getTableStateManager().isTableState(table, state)) {
1272            builder.addTableNames(ProtobufUtil.toProtoTableName(table));
1273          }
1274        }
1275      }
1276      return builder.build();
1277    } catch (IOException e) {
1278      throw new ServiceException(e);
1279    }
1280  }
1281
1282  @Override
1283  public GetTableStateResponse getTableState(RpcController controller, GetTableStateRequest request)
1284    throws ServiceException {
1285    try {
1286      server.checkServiceStarted();
1287      TableName tableName = ProtobufUtil.toTableName(request.getTableName());
1288      TableState ts = server.getTableStateManager().getTableState(tableName);
1289      GetTableStateResponse.Builder builder = GetTableStateResponse.newBuilder();
1290      builder.setTableState(ts.convert());
1291      return builder.build();
1292    } catch (IOException e) {
1293      throw new ServiceException(e);
1294    }
1295  }
1296
1297  @Override
1298  public IsCatalogJanitorEnabledResponse isCatalogJanitorEnabled(RpcController c,
1299    IsCatalogJanitorEnabledRequest req) throws ServiceException {
1300    return IsCatalogJanitorEnabledResponse.newBuilder().setValue(server.isCatalogJanitorEnabled())
1301      .build();
1302  }
1303
1304  @Override
1305  public IsCleanerChoreEnabledResponse isCleanerChoreEnabled(RpcController c,
1306    IsCleanerChoreEnabledRequest req) throws ServiceException {
1307    return IsCleanerChoreEnabledResponse.newBuilder().setValue(server.isCleanerChoreEnabled())
1308      .build();
1309  }
1310
1311  @Override
1312  public IsMasterRunningResponse isMasterRunning(RpcController c, IsMasterRunningRequest req)
1313    throws ServiceException {
1314    try {
1315      server.checkServiceStarted();
1316      return IsMasterRunningResponse.newBuilder().setIsMasterRunning(!server.isStopped()).build();
1317    } catch (IOException e) {
1318      throw new ServiceException(e);
1319    }
1320  }
1321
1322  /**
1323   * Checks if the specified procedure is done.
1324   * @return true if the procedure is done, false if the procedure is in the process of completing
1325   * @throws ServiceException if invalid procedure or failed procedure with progress failure reason.
1326   */
1327  @Override
1328  public IsProcedureDoneResponse isProcedureDone(RpcController controller,
1329    IsProcedureDoneRequest request) throws ServiceException {
1330    try {
1331      server.checkInitialized();
1332      ProcedureDescription desc = request.getProcedure();
1333      MasterProcedureManager mpm =
1334        server.getMasterProcedureManagerHost().getProcedureManager(desc.getSignature());
1335      if (mpm == null) {
1336        throw new ServiceException("The procedure is not registered: " + desc.getSignature());
1337      }
1338      LOG.debug("Checking to see if procedure from request:" + desc.getSignature() + " is done");
1339
1340      IsProcedureDoneResponse.Builder builder = IsProcedureDoneResponse.newBuilder();
1341      boolean done = mpm.isProcedureDone(desc);
1342      builder.setDone(done);
1343      return builder.build();
1344    } catch (ForeignException e) {
1345      throw new ServiceException(e.getCause());
1346    } catch (IOException e) {
1347      throw new ServiceException(e);
1348    }
1349  }
1350
1351  /**
1352   * Checks if the specified snapshot is done.
1353   * @return true if the snapshot is in file system ready to use, false if the snapshot is in the
1354   *         process of completing
1355   * @throws ServiceException wrapping UnknownSnapshotException if invalid snapshot, or a wrapped
1356   *                          HBaseSnapshotException with progress failure reason.
1357   */
1358  @Override
1359  public IsSnapshotDoneResponse isSnapshotDone(RpcController controller,
1360    IsSnapshotDoneRequest request) throws ServiceException {
1361    LOG.debug("Checking to see if snapshot from request:"
1362      + ClientSnapshotDescriptionUtils.toString(request.getSnapshot()) + " is done");
1363    try {
1364      server.checkInitialized();
1365      IsSnapshotDoneResponse.Builder builder = IsSnapshotDoneResponse.newBuilder();
1366      boolean done = server.snapshotManager.isSnapshotDone(request.getSnapshot());
1367      builder.setDone(done);
1368      return builder.build();
1369    } catch (ForeignException e) {
1370      throw new ServiceException(e.getCause());
1371    } catch (IOException e) {
1372      throw new ServiceException(e);
1373    }
1374  }
1375
1376  @Override
1377  public GetProcedureResultResponse getProcedureResult(RpcController controller,
1378    GetProcedureResultRequest request) throws ServiceException {
1379    LOG.debug("Checking to see if procedure is done pid={}", request.getProcId());
1380    try {
1381      server.checkInitialized();
1382      GetProcedureResultResponse.Builder builder = GetProcedureResultResponse.newBuilder();
1383      long procId = request.getProcId();
1384      ProcedureExecutor<?> executor = server.getMasterProcedureExecutor();
1385      Procedure<?> result = executor.getResultOrProcedure(procId);
1386      if (result != null) {
1387        builder.setSubmittedTime(result.getSubmittedTime());
1388        builder.setLastUpdate(result.getLastUpdate());
1389        if (executor.isFinished(procId)) {
1390          builder.setState(GetProcedureResultResponse.State.FINISHED);
1391          if (result.isFailed()) {
1392            IOException exception = MasterProcedureUtil.unwrapRemoteIOException(result);
1393            builder.setException(ForeignExceptionUtil.toProtoForeignException(exception));
1394          }
1395          byte[] resultData = result.getResult();
1396          if (resultData != null) {
1397            builder.setResult(UnsafeByteOperations.unsafeWrap(resultData));
1398          }
1399          server.getMasterProcedureExecutor().removeResult(request.getProcId());
1400        } else {
1401          builder.setState(GetProcedureResultResponse.State.RUNNING);
1402        }
1403      } else {
1404        builder.setState(GetProcedureResultResponse.State.NOT_FOUND);
1405      }
1406      return builder.build();
1407    } catch (IOException e) {
1408      throw new ServiceException(e);
1409    }
1410  }
1411
1412  @Override
1413  public AbortProcedureResponse abortProcedure(RpcController rpcController,
1414    AbortProcedureRequest request) throws ServiceException {
1415    try {
1416      AbortProcedureResponse.Builder response = AbortProcedureResponse.newBuilder();
1417      boolean abortResult =
1418        server.abortProcedure(request.getProcId(), request.getMayInterruptIfRunning());
1419      response.setIsProcedureAborted(abortResult);
1420      return response.build();
1421    } catch (IOException e) {
1422      throw new ServiceException(e);
1423    }
1424  }
1425
1426  @Override
1427  public ListNamespaceDescriptorsResponse listNamespaceDescriptors(RpcController c,
1428    ListNamespaceDescriptorsRequest request) throws ServiceException {
1429    try {
1430      ListNamespaceDescriptorsResponse.Builder response =
1431        ListNamespaceDescriptorsResponse.newBuilder();
1432      for (NamespaceDescriptor ns : server.getNamespaces()) {
1433        response.addNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(ns));
1434      }
1435      return response.build();
1436    } catch (IOException e) {
1437      throw new ServiceException(e);
1438    }
1439  }
1440
1441  @Override
1442  public GetProceduresResponse getProcedures(RpcController rpcController,
1443    GetProceduresRequest request) throws ServiceException {
1444    try {
1445      final GetProceduresResponse.Builder response = GetProceduresResponse.newBuilder();
1446      for (Procedure<?> p : server.getProcedures()) {
1447        response.addProcedure(ProcedureUtil.convertToProtoProcedure(p));
1448      }
1449      return response.build();
1450    } catch (IOException e) {
1451      throw new ServiceException(e);
1452    }
1453  }
1454
1455  @Override
1456  public GetLocksResponse getLocks(RpcController controller, GetLocksRequest request)
1457    throws ServiceException {
1458    try {
1459      final GetLocksResponse.Builder builder = GetLocksResponse.newBuilder();
1460
1461      for (LockedResource lockedResource : server.getLocks()) {
1462        builder.addLock(ProcedureUtil.convertToProtoLockedResource(lockedResource));
1463      }
1464
1465      return builder.build();
1466    } catch (IOException e) {
1467      throw new ServiceException(e);
1468    }
1469  }
1470
1471  @Override
1472  public ListTableDescriptorsByNamespaceResponse listTableDescriptorsByNamespace(RpcController c,
1473    ListTableDescriptorsByNamespaceRequest request) throws ServiceException {
1474    try {
1475      ListTableDescriptorsByNamespaceResponse.Builder b =
1476        ListTableDescriptorsByNamespaceResponse.newBuilder();
1477      for (TableDescriptor htd : server
1478        .listTableDescriptorsByNamespace(request.getNamespaceName())) {
1479        b.addTableSchema(ProtobufUtil.toTableSchema(htd));
1480      }
1481      return b.build();
1482    } catch (IOException e) {
1483      throw new ServiceException(e);
1484    }
1485  }
1486
1487  @Override
1488  public ListTableNamesByNamespaceResponse listTableNamesByNamespace(RpcController c,
1489    ListTableNamesByNamespaceRequest request) throws ServiceException {
1490    try {
1491      ListTableNamesByNamespaceResponse.Builder b = ListTableNamesByNamespaceResponse.newBuilder();
1492      for (TableName tableName : server.listTableNamesByNamespace(request.getNamespaceName())) {
1493        b.addTableName(ProtobufUtil.toProtoTableName(tableName));
1494      }
1495      return b.build();
1496    } catch (IOException e) {
1497      throw new ServiceException(e);
1498    }
1499  }
1500
1501  @Override
1502  public ModifyColumnResponse modifyColumn(RpcController controller, ModifyColumnRequest req)
1503    throws ServiceException {
1504    try {
1505      long procId = server.modifyColumn(ProtobufUtil.toTableName(req.getTableName()),
1506        ProtobufUtil.toColumnFamilyDescriptor(req.getColumnFamilies()), req.getNonceGroup(),
1507        req.getNonce());
1508      if (procId == -1) {
1509        // This mean operation was not performed in server, so do not set any procId
1510        return ModifyColumnResponse.newBuilder().build();
1511      } else {
1512        return ModifyColumnResponse.newBuilder().setProcId(procId).build();
1513      }
1514    } catch (IOException ioe) {
1515      throw new ServiceException(ioe);
1516    }
1517  }
1518
1519  @Override
1520  public ModifyColumnStoreFileTrackerResponse modifyColumnStoreFileTracker(RpcController controller,
1521    ModifyColumnStoreFileTrackerRequest req) throws ServiceException {
1522    try {
1523      long procId =
1524        server.modifyColumnStoreFileTracker(ProtobufUtil.toTableName(req.getTableName()),
1525          req.getFamily().toByteArray(), req.getDstSft(), req.getNonceGroup(), req.getNonce());
1526      return ModifyColumnStoreFileTrackerResponse.newBuilder().setProcId(procId).build();
1527    } catch (IOException ioe) {
1528      throw new ServiceException(ioe);
1529    }
1530  }
1531
1532  @Override
1533  public ModifyNamespaceResponse modifyNamespace(RpcController controller,
1534    ModifyNamespaceRequest request) throws ServiceException {
1535    try {
1536      long procId =
1537        server.modifyNamespace(ProtobufUtil.toNamespaceDescriptor(request.getNamespaceDescriptor()),
1538          request.getNonceGroup(), request.getNonce());
1539      return ModifyNamespaceResponse.newBuilder().setProcId(procId).build();
1540    } catch (IOException e) {
1541      throw new ServiceException(e);
1542    }
1543  }
1544
1545  @Override
1546  public ModifyTableResponse modifyTable(RpcController controller, ModifyTableRequest req)
1547    throws ServiceException {
1548    try {
1549      long procId = server.modifyTable(ProtobufUtil.toTableName(req.getTableName()),
1550        ProtobufUtil.toTableDescriptor(req.getTableSchema()), req.getNonceGroup(), req.getNonce(),
1551        req.getReopenRegions());
1552      return ModifyTableResponse.newBuilder().setProcId(procId).build();
1553    } catch (IOException ioe) {
1554      throw new ServiceException(ioe);
1555    }
1556  }
1557
1558  @Override
1559  public ReopenTableRegionsResponse reopenTableRegions(RpcController controller,
1560    ReopenTableRegionsRequest request) throws ServiceException {
1561    try {
1562      server.checkInitialized();
1563
1564      final TableName tableName = ProtobufUtil.toTableName(request.getTableName());
1565      final List<byte[]> regionNames = request.getRegionNamesList().stream()
1566        .map(ByteString::toByteArray).collect(Collectors.toList());
1567
1568      LOG.info("Reopening regions for table={}, regionCount={}", tableName,
1569        regionNames.isEmpty() ? "all" : regionNames.size());
1570
1571      long procId = server.reopenRegionsThrottled(tableName, regionNames, request.getNonceGroup(),
1572        request.getNonce());
1573
1574      return ReopenTableRegionsResponse.newBuilder().setProcId(procId).build();
1575
1576    } catch (IOException ioe) {
1577      throw new ServiceException(ioe);
1578    }
1579  }
1580
1581  @Override
1582  public ModifyTableStoreFileTrackerResponse modifyTableStoreFileTracker(RpcController controller,
1583    ModifyTableStoreFileTrackerRequest req) throws ServiceException {
1584    try {
1585      long procId = server.modifyTableStoreFileTracker(ProtobufUtil.toTableName(req.getTableName()),
1586        req.getDstSft(), req.getNonceGroup(), req.getNonce());
1587      return ModifyTableStoreFileTrackerResponse.newBuilder().setProcId(procId).build();
1588    } catch (IOException ioe) {
1589      throw new ServiceException(ioe);
1590    }
1591  }
1592
1593  @Override
1594  public MoveRegionResponse moveRegion(RpcController controller, MoveRegionRequest req)
1595    throws ServiceException {
1596    final byte[] encodedRegionName = req.getRegion().getValue().toByteArray();
1597    RegionSpecifierType type = req.getRegion().getType();
1598    final byte[] destServerName = (req.hasDestServerName())
1599      ? Bytes.toBytes(ProtobufUtil.toServerName(req.getDestServerName()).getServerName())
1600      : null;
1601    MoveRegionResponse mrr = MoveRegionResponse.newBuilder().build();
1602
1603    if (type != RegionSpecifierType.ENCODED_REGION_NAME) {
1604      LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.ENCODED_REGION_NAME
1605        + " actual: " + type);
1606    }
1607
1608    try {
1609      server.checkInitialized();
1610      server.move(encodedRegionName, destServerName);
1611    } catch (IOException ioe) {
1612      throw new ServiceException(ioe);
1613    }
1614    return mrr;
1615  }
1616
1617  /**
1618   * Offline specified region from master's in-memory state. It will not attempt to reassign the
1619   * region as in unassign. This is a special method that should be used by experts or hbck.
1620   */
1621  @Override
1622  public OfflineRegionResponse offlineRegion(RpcController controller, OfflineRegionRequest request)
1623    throws ServiceException {
1624    try {
1625      server.checkInitialized();
1626
1627      final RegionSpecifierType type = request.getRegion().getType();
1628      if (type != RegionSpecifierType.REGION_NAME) {
1629        LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
1630          + " actual: " + type);
1631      }
1632
1633      final byte[] regionName = request.getRegion().getValue().toByteArray();
1634      final RegionInfo hri = server.getAssignmentManager().getRegionInfo(regionName);
1635      if (hri == null) {
1636        throw new UnknownRegionException(Bytes.toStringBinary(regionName));
1637      }
1638
1639      if (server.cpHost != null) {
1640        server.cpHost.preRegionOffline(hri);
1641      }
1642      LOG.info(server.getClientIdAuditPrefix() + " offline " + hri.getRegionNameAsString());
1643      server.getAssignmentManager().offlineRegion(hri);
1644      if (server.cpHost != null) {
1645        server.cpHost.postRegionOffline(hri);
1646      }
1647    } catch (IOException ioe) {
1648      throw new ServiceException(ioe);
1649    }
1650    return OfflineRegionResponse.newBuilder().build();
1651  }
1652
1653  /**
1654   * Execute Restore/Clone snapshot operation.
1655   * <p>
1656   * If the specified table exists a "Restore" is executed, replacing the table schema and directory
1657   * data with the content of the snapshot. The table must be disabled, or a
1658   * UnsupportedOperationException will be thrown.
1659   * <p>
1660   * If the table doesn't exist a "Clone" is executed, a new table is created using the schema at
1661   * the time of the snapshot, and the content of the snapshot.
1662   * <p>
1663   * The restore/clone operation does not require copying HFiles. Since HFiles are immutable the
1664   * table can point to and use the same files as the original one.
1665   */
1666  @Override
1667  public RestoreSnapshotResponse restoreSnapshot(RpcController controller,
1668    RestoreSnapshotRequest request) throws ServiceException {
1669    try {
1670      long procId = server.restoreSnapshot(request.getSnapshot(), request.getNonceGroup(),
1671        request.getNonce(), request.getRestoreACL(), request.getCustomSFT());
1672      return RestoreSnapshotResponse.newBuilder().setProcId(procId).build();
1673    } catch (ForeignException e) {
1674      throw new ServiceException(e.getCause());
1675    } catch (IOException e) {
1676      throw new ServiceException(e);
1677    }
1678  }
1679
1680  @Override
1681  public SetSnapshotCleanupResponse switchSnapshotCleanup(RpcController controller,
1682    SetSnapshotCleanupRequest request) throws ServiceException {
1683    try {
1684      server.checkInitialized();
1685      final boolean enabled = request.getEnabled();
1686      final boolean isSynchronous = request.hasSynchronous() && request.getSynchronous();
1687      final boolean prevSnapshotCleanupRunning = this.switchSnapshotCleanup(enabled, isSynchronous);
1688      return SetSnapshotCleanupResponse.newBuilder()
1689        .setPrevSnapshotCleanup(prevSnapshotCleanupRunning).build();
1690    } catch (IOException e) {
1691      throw new ServiceException(e);
1692    }
1693  }
1694
1695  @Override
1696  public IsSnapshotCleanupEnabledResponse isSnapshotCleanupEnabled(RpcController controller,
1697    IsSnapshotCleanupEnabledRequest request) throws ServiceException {
1698    try {
1699      server.checkInitialized();
1700      final boolean isSnapshotCleanupEnabled = server.snapshotCleanupStateStore.get();
1701      return IsSnapshotCleanupEnabledResponse.newBuilder().setEnabled(isSnapshotCleanupEnabled)
1702        .build();
1703    } catch (IOException e) {
1704      throw new ServiceException(e);
1705    }
1706  }
1707
1708  /**
1709   * Turn on/off snapshot auto-cleanup based on TTL
1710   * @param enabledNewVal Set to <code>true</code> to enable, <code>false</code> to disable
1711   * @param synchronous   If <code>true</code>, it waits until current snapshot cleanup is
1712   *                      completed, if outstanding
1713   * @return previous snapshot auto-cleanup mode
1714   */
1715  private synchronized boolean switchSnapshotCleanup(final boolean enabledNewVal,
1716    final boolean synchronous) throws IOException {
1717    final boolean oldValue = server.snapshotCleanupStateStore.get();
1718    server.switchSnapshotCleanup(enabledNewVal, synchronous);
1719    LOG.info("{} Successfully set snapshot cleanup to {}", server.getClientIdAuditPrefix(),
1720      enabledNewVal);
1721    return oldValue;
1722  }
1723
1724  @Override
1725  public RunCatalogScanResponse runCatalogScan(RpcController c, RunCatalogScanRequest req)
1726    throws ServiceException {
1727    rpcPreCheck("runCatalogScan");
1728    try {
1729      return ResponseConverter.buildRunCatalogScanResponse(this.server.catalogJanitorChore.scan());
1730    } catch (IOException ioe) {
1731      throw new ServiceException(ioe);
1732    }
1733  }
1734
1735  @Override
1736  public RunCleanerChoreResponse runCleanerChore(RpcController c, RunCleanerChoreRequest req)
1737    throws ServiceException {
1738    rpcPreCheck("runCleanerChore");
1739    try {
1740      CompletableFuture<Boolean> fileCleanerFuture = server.getHFileCleaner().triggerCleanerNow();
1741      CompletableFuture<Boolean> logCleanerFuture = server.getLogCleaner().triggerCleanerNow();
1742      boolean result = fileCleanerFuture.get() && logCleanerFuture.get();
1743      return ResponseConverter.buildRunCleanerChoreResponse(result);
1744    } catch (InterruptedException e) {
1745      throw new ServiceException(e);
1746    } catch (ExecutionException e) {
1747      throw new ServiceException(e.getCause());
1748    }
1749  }
1750
1751  @Override
1752  public SetBalancerRunningResponse setBalancerRunning(RpcController c,
1753    SetBalancerRunningRequest req) throws ServiceException {
1754    try {
1755      server.checkInitialized();
1756      boolean prevValue = (req.getSynchronous())
1757        ? synchronousBalanceSwitch(req.getOn())
1758        : server.balanceSwitch(req.getOn());
1759      return SetBalancerRunningResponse.newBuilder().setPrevBalanceValue(prevValue).build();
1760    } catch (IOException ioe) {
1761      throw new ServiceException(ioe);
1762    }
1763  }
1764
1765  @Override
1766  public ShutdownResponse shutdown(RpcController controller, ShutdownRequest request)
1767    throws ServiceException {
1768    LOG.info(server.getClientIdAuditPrefix() + " shutdown");
1769    try {
1770      server.shutdown();
1771    } catch (IOException e) {
1772      LOG.error("Exception occurred in HMaster.shutdown()", e);
1773      throw new ServiceException(e);
1774    }
1775    return ShutdownResponse.newBuilder().build();
1776  }
1777
1778  /**
1779   * Triggers an asynchronous attempt to take a snapshot. {@inheritDoc}
1780   */
1781  @Override
1782  public SnapshotResponse snapshot(RpcController controller, SnapshotRequest request)
1783    throws ServiceException {
1784    try {
1785      server.checkInitialized();
1786      server.snapshotManager.checkSnapshotSupport();
1787
1788      LOG.info(server.getClientIdAuditPrefix() + " snapshot request for:"
1789        + ClientSnapshotDescriptionUtils.toString(request.getSnapshot()));
1790      // get the snapshot information
1791      SnapshotDescription snapshot = SnapshotDescriptionUtils.validate(server.getConnection(),
1792        request.getSnapshot(), server.getConfiguration());
1793      // send back the max amount of time the client should wait for the snapshot to complete
1794      long waitTime = SnapshotDescriptionUtils.getMaxMasterTimeout(server.getConfiguration(),
1795        snapshot.getType(), SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME);
1796
1797      SnapshotResponse.Builder builder = SnapshotResponse.newBuilder().setExpectedTimeout(waitTime);
1798
1799      // If there is nonce group and nonce in the snapshot request, then the client can
1800      // handle snapshot procedure procId. And if enable the snapshot procedure, we
1801      // will do the snapshot work with proc-v2, otherwise we will fall back to zk proc.
1802      if (
1803        request.hasNonceGroup() && request.hasNonce()
1804          && server.snapshotManager.snapshotProcedureEnabled()
1805      ) {
1806        long nonceGroup = request.getNonceGroup();
1807        long nonce = request.getNonce();
1808        long procId = server.snapshotManager.takeSnapshot(snapshot, nonceGroup, nonce);
1809        return builder.setProcId(procId).build();
1810      } else {
1811        server.snapshotManager.takeSnapshot(snapshot);
1812        return builder.build();
1813      }
1814    } catch (ForeignException e) {
1815      throw new ServiceException(e.getCause());
1816    } catch (IOException e) {
1817      throw new ServiceException(e);
1818    }
1819  }
1820
1821  @Override
1822  public StopMasterResponse stopMaster(RpcController controller, StopMasterRequest request)
1823    throws ServiceException {
1824    LOG.info(server.getClientIdAuditPrefix() + " stop");
1825    try {
1826      server.stopMaster();
1827    } catch (IOException e) {
1828      LOG.error("Exception occurred while stopping master", e);
1829      throw new ServiceException(e);
1830    }
1831    return StopMasterResponse.newBuilder().build();
1832  }
1833
1834  @Override
1835  public IsInMaintenanceModeResponse isMasterInMaintenanceMode(final RpcController controller,
1836    final IsInMaintenanceModeRequest request) throws ServiceException {
1837    IsInMaintenanceModeResponse.Builder response = IsInMaintenanceModeResponse.newBuilder();
1838    response.setInMaintenanceMode(server.isInMaintenanceMode());
1839    return response.build();
1840  }
1841
1842  @Override
1843  public UnassignRegionResponse unassignRegion(RpcController controller, UnassignRegionRequest req)
1844    throws ServiceException {
1845    try {
1846      final byte[] regionName = req.getRegion().getValue().toByteArray();
1847      RegionSpecifierType type = req.getRegion().getType();
1848      UnassignRegionResponse urr = UnassignRegionResponse.newBuilder().build();
1849
1850      server.checkInitialized();
1851      if (type != RegionSpecifierType.REGION_NAME) {
1852        LOG.warn("unassignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
1853          + " actual: " + type);
1854      }
1855      RegionStateNode rsn =
1856        server.getAssignmentManager().getRegionStates().getRegionStateNodeFromName(regionName);
1857      if (rsn == null) {
1858        throw new UnknownRegionException(Bytes.toString(regionName));
1859      }
1860
1861      RegionInfo hri = rsn.getRegionInfo();
1862      if (server.cpHost != null) {
1863        server.cpHost.preUnassign(hri);
1864      }
1865      LOG.debug(server.getClientIdAuditPrefix() + " unassign " + hri.getRegionNameAsString()
1866        + " in current location if it is online");
1867      server.getAssignmentManager().unassign(hri);
1868      if (server.cpHost != null) {
1869        server.cpHost.postUnassign(hri);
1870      }
1871
1872      return urr;
1873    } catch (IOException ioe) {
1874      throw new ServiceException(ioe);
1875    }
1876  }
1877
1878  @Override
1879  public ReportRegionStateTransitionResponse reportRegionStateTransition(RpcController c,
1880    ReportRegionStateTransitionRequest req) throws ServiceException {
1881    try {
1882      server.checkServiceStarted();
1883      for (RegionServerStatusProtos.RegionStateTransition transition : req.getTransitionList()) {
1884        long procId =
1885          transition.getProcIdCount() > 0 ? transition.getProcId(0) : Procedure.NO_PROC_ID;
1886        // -1 is less than any possible MasterActiveCode
1887        long initiatingMasterActiveTime = transition.hasInitiatingMasterActiveTime()
1888          ? transition.getInitiatingMasterActiveTime()
1889          : -1;
1890        throwOnOldMaster(procId, initiatingMasterActiveTime);
1891      }
1892      return server.getAssignmentManager().reportRegionStateTransition(req);
1893    } catch (IOException ioe) {
1894      throw new ServiceException(ioe);
1895    }
1896  }
1897
1898  @Override
1899  public SetQuotaResponse setQuota(RpcController c, SetQuotaRequest req) throws ServiceException {
1900    try {
1901      server.checkInitialized();
1902      SetQuotaResponse response = server.getMasterQuotaManager().setQuota(req);
1903      server.reloadRegionServerQuotas();
1904
1905      return response;
1906    } catch (Exception e) {
1907      throw new ServiceException(e);
1908    }
1909  }
1910
1911  @Override
1912  public MajorCompactionTimestampResponse getLastMajorCompactionTimestamp(RpcController controller,
1913    MajorCompactionTimestampRequest request) throws ServiceException {
1914    MajorCompactionTimestampResponse.Builder response =
1915      MajorCompactionTimestampResponse.newBuilder();
1916    try {
1917      server.checkInitialized();
1918      response.setCompactionTimestamp(
1919        server.getLastMajorCompactionTimestamp(ProtobufUtil.toTableName(request.getTableName())));
1920    } catch (IOException e) {
1921      throw new ServiceException(e);
1922    }
1923    return response.build();
1924  }
1925
1926  @Override
1927  public MajorCompactionTimestampResponse getLastMajorCompactionTimestampForRegion(
1928    RpcController controller, MajorCompactionTimestampForRegionRequest request)
1929    throws ServiceException {
1930    MajorCompactionTimestampResponse.Builder response =
1931      MajorCompactionTimestampResponse.newBuilder();
1932    try {
1933      server.checkInitialized();
1934      response.setCompactionTimestamp(server
1935        .getLastMajorCompactionTimestampForRegion(request.getRegion().getValue().toByteArray()));
1936    } catch (IOException e) {
1937      throw new ServiceException(e);
1938    }
1939    return response.build();
1940  }
1941
1942  @Override
1943  public IsBalancerEnabledResponse isBalancerEnabled(RpcController controller,
1944    IsBalancerEnabledRequest request) throws ServiceException {
1945    IsBalancerEnabledResponse.Builder response = IsBalancerEnabledResponse.newBuilder();
1946    response.setEnabled(server.isBalancerOn());
1947    return response.build();
1948  }
1949
1950  @Override
1951  public SetSplitOrMergeEnabledResponse setSplitOrMergeEnabled(RpcController controller,
1952    SetSplitOrMergeEnabledRequest request) throws ServiceException {
1953    SetSplitOrMergeEnabledResponse.Builder response = SetSplitOrMergeEnabledResponse.newBuilder();
1954    try {
1955      server.checkInitialized();
1956      boolean newValue = request.getEnabled();
1957      for (MasterProtos.MasterSwitchType masterSwitchType : request.getSwitchTypesList()) {
1958        MasterSwitchType switchType = convert(masterSwitchType);
1959        boolean oldValue = server.isSplitOrMergeEnabled(switchType);
1960        response.addPrevValue(oldValue);
1961        if (server.cpHost != null) {
1962          server.cpHost.preSetSplitOrMergeEnabled(newValue, switchType);
1963        }
1964        server.getSplitOrMergeStateStore().setSplitOrMergeEnabled(newValue, switchType);
1965        if (server.cpHost != null) {
1966          server.cpHost.postSetSplitOrMergeEnabled(newValue, switchType);
1967        }
1968      }
1969    } catch (IOException e) {
1970      throw new ServiceException(e);
1971    }
1972    return response.build();
1973  }
1974
1975  @Override
1976  public IsSplitOrMergeEnabledResponse isSplitOrMergeEnabled(RpcController controller,
1977    IsSplitOrMergeEnabledRequest request) throws ServiceException {
1978    IsSplitOrMergeEnabledResponse.Builder response = IsSplitOrMergeEnabledResponse.newBuilder();
1979    response.setEnabled(server.isSplitOrMergeEnabled(convert(request.getSwitchType())));
1980    return response.build();
1981  }
1982
1983  @Override
1984  public NormalizeResponse normalize(RpcController controller, NormalizeRequest request)
1985    throws ServiceException {
1986    rpcPreCheck("normalize");
1987    try {
1988      final NormalizeTableFilterParams ntfp = new NormalizeTableFilterParams.Builder()
1989        .tableNames(ProtobufUtil.toTableNameList(request.getTableNamesList()))
1990        .regex(request.hasRegex() ? request.getRegex() : null)
1991        .namespace(request.hasNamespace() ? request.getNamespace() : null).build();
1992      return NormalizeResponse.newBuilder()
1993        // all API requests are considered priority requests.
1994        .setNormalizerRan(server.normalizeRegions(ntfp, true)).build();
1995    } catch (IOException ex) {
1996      throw new ServiceException(ex);
1997    }
1998  }
1999
2000  @Override
2001  public SetNormalizerRunningResponse setNormalizerRunning(RpcController controller,
2002    SetNormalizerRunningRequest request) throws ServiceException {
2003    rpcPreCheck("setNormalizerRunning");
2004
2005    // Sets normalizer on/off flag in ZK.
2006    // TODO: this method is totally broken in terms of atomicity of actions and values read.
2007    // 1. The contract has this RPC returning the previous value. There isn't a ZKUtil method
2008    // that lets us retrieve the previous value as part of setting a new value, so we simply
2009    // perform a read before issuing the update. Thus we have a data race opportunity, between
2010    // when the `prevValue` is read and whatever is actually overwritten.
2011    // 2. Down in `setNormalizerOn`, the call to `createAndWatch` inside of the catch clause can
2012    // itself fail in the event that the znode already exists. Thus, another data race, between
2013    // when the initial `setData` call is notified of the absence of the target znode and the
2014    // subsequent `createAndWatch`, with another client creating said node.
2015    // That said, there's supposed to be only one active master and thus there's supposed to be
2016    // only one process with the authority to modify the value.
2017    final boolean prevValue = server.getRegionNormalizerManager().isNormalizerOn();
2018    final boolean newValue = request.getOn();
2019    try {
2020      server.getRegionNormalizerManager().setNormalizerOn(newValue);
2021    } catch (IOException e) {
2022      throw new ServiceException(e);
2023    }
2024    LOG.info("{} set normalizerSwitch={}", server.getClientIdAuditPrefix(), newValue);
2025    return SetNormalizerRunningResponse.newBuilder().setPrevNormalizerValue(prevValue).build();
2026  }
2027
2028  @Override
2029  public IsNormalizerEnabledResponse isNormalizerEnabled(RpcController controller,
2030    IsNormalizerEnabledRequest request) {
2031    IsNormalizerEnabledResponse.Builder response = IsNormalizerEnabledResponse.newBuilder();
2032    response.setEnabled(server.isNormalizerOn());
2033    return response.build();
2034  }
2035
2036  /**
2037   * Returns the security capabilities in effect on the cluster
2038   */
2039  @Override
2040  public SecurityCapabilitiesResponse getSecurityCapabilities(RpcController controller,
2041    SecurityCapabilitiesRequest request) throws ServiceException {
2042    SecurityCapabilitiesResponse.Builder response = SecurityCapabilitiesResponse.newBuilder();
2043    try {
2044      server.checkInitialized();
2045      Set<SecurityCapabilitiesResponse.Capability> capabilities = new HashSet<>();
2046      // Authentication
2047      if (User.isHBaseSecurityEnabled(server.getConfiguration())) {
2048        capabilities.add(SecurityCapabilitiesResponse.Capability.SECURE_AUTHENTICATION);
2049      } else {
2050        capabilities.add(SecurityCapabilitiesResponse.Capability.SIMPLE_AUTHENTICATION);
2051      }
2052      // A coprocessor that implements AccessControlService can provide AUTHORIZATION and
2053      // CELL_AUTHORIZATION
2054      if (server.cpHost != null && hasAccessControlServiceCoprocessor(server.cpHost)) {
2055        if (AccessChecker.isAuthorizationSupported(server.getConfiguration())) {
2056          capabilities.add(SecurityCapabilitiesResponse.Capability.AUTHORIZATION);
2057        }
2058        if (AccessController.isCellAuthorizationSupported(server.getConfiguration())) {
2059          capabilities.add(SecurityCapabilitiesResponse.Capability.CELL_AUTHORIZATION);
2060        }
2061      }
2062      // A coprocessor that implements VisibilityLabelsService can provide CELL_VISIBILITY.
2063      if (server.cpHost != null && hasVisibilityLabelsServiceCoprocessor(server.cpHost)) {
2064        if (VisibilityController.isCellAuthorizationSupported(server.getConfiguration())) {
2065          capabilities.add(SecurityCapabilitiesResponse.Capability.CELL_VISIBILITY);
2066        }
2067      }
2068      response.addAllCapabilities(capabilities);
2069    } catch (IOException e) {
2070      throw new ServiceException(e);
2071    }
2072    return response.build();
2073  }
2074
2075  /**
2076   * Determines if there is a MasterCoprocessor deployed which implements
2077   * {@link AccessControlService.Interface}.
2078   */
2079  boolean hasAccessControlServiceCoprocessor(MasterCoprocessorHost cpHost) {
2080    return checkCoprocessorWithService(cpHost.findCoprocessors(MasterCoprocessor.class),
2081      AccessControlService.Interface.class);
2082  }
2083
2084  /**
2085   * Determines if there is a MasterCoprocessor deployed which implements
2086   * {@link VisibilityLabelsService.Interface}.
2087   */
2088  boolean hasVisibilityLabelsServiceCoprocessor(MasterCoprocessorHost cpHost) {
2089    return checkCoprocessorWithService(cpHost.findCoprocessors(MasterCoprocessor.class),
2090      VisibilityLabelsService.Interface.class);
2091  }
2092
2093  /**
2094   * Determines if there is a coprocessor implementation in the provided argument which extends or
2095   * implements the provided {@code service}.
2096   */
2097  boolean checkCoprocessorWithService(List<MasterCoprocessor> coprocessorsToCheck,
2098    Class<?> service) {
2099    if (coprocessorsToCheck == null || coprocessorsToCheck.isEmpty()) {
2100      return false;
2101    }
2102    for (MasterCoprocessor cp : coprocessorsToCheck) {
2103      if (service.isAssignableFrom(cp.getClass())) {
2104        return true;
2105      }
2106    }
2107    return false;
2108  }
2109
2110  private MasterSwitchType convert(MasterProtos.MasterSwitchType switchType) {
2111    switch (switchType) {
2112      case SPLIT:
2113        return MasterSwitchType.SPLIT;
2114      case MERGE:
2115        return MasterSwitchType.MERGE;
2116      default:
2117        break;
2118    }
2119    return null;
2120  }
2121
2122  @Override
2123  public AddReplicationPeerResponse addReplicationPeer(RpcController controller,
2124    AddReplicationPeerRequest request) throws ServiceException {
2125    try {
2126      long procId = server.addReplicationPeer(request.getPeerId(),
2127        ReplicationPeerConfigUtil.convert(request.getPeerConfig()),
2128        request.getPeerState().getState().equals(ReplicationState.State.ENABLED));
2129      return AddReplicationPeerResponse.newBuilder().setProcId(procId).build();
2130    } catch (ReplicationException | IOException e) {
2131      throw new ServiceException(e);
2132    }
2133  }
2134
2135  @Override
2136  public RemoveReplicationPeerResponse removeReplicationPeer(RpcController controller,
2137    RemoveReplicationPeerRequest request) throws ServiceException {
2138    try {
2139      long procId = server.removeReplicationPeer(request.getPeerId());
2140      return RemoveReplicationPeerResponse.newBuilder().setProcId(procId).build();
2141    } catch (ReplicationException | IOException e) {
2142      throw new ServiceException(e);
2143    }
2144  }
2145
2146  @Override
2147  public EnableReplicationPeerResponse enableReplicationPeer(RpcController controller,
2148    EnableReplicationPeerRequest request) throws ServiceException {
2149    try {
2150      long procId = server.enableReplicationPeer(request.getPeerId());
2151      return EnableReplicationPeerResponse.newBuilder().setProcId(procId).build();
2152    } catch (ReplicationException | IOException e) {
2153      throw new ServiceException(e);
2154    }
2155  }
2156
2157  @Override
2158  public DisableReplicationPeerResponse disableReplicationPeer(RpcController controller,
2159    DisableReplicationPeerRequest request) throws ServiceException {
2160    try {
2161      long procId = server.disableReplicationPeer(request.getPeerId());
2162      return DisableReplicationPeerResponse.newBuilder().setProcId(procId).build();
2163    } catch (ReplicationException | IOException e) {
2164      throw new ServiceException(e);
2165    }
2166  }
2167
2168  @Override
2169  public GetReplicationPeerConfigResponse getReplicationPeerConfig(RpcController controller,
2170    GetReplicationPeerConfigRequest request) throws ServiceException {
2171    GetReplicationPeerConfigResponse.Builder response =
2172      GetReplicationPeerConfigResponse.newBuilder();
2173    try {
2174      String peerId = request.getPeerId();
2175      ReplicationPeerConfig peerConfig = server.getReplicationPeerConfig(peerId);
2176      response.setPeerId(peerId);
2177      response.setPeerConfig(ReplicationPeerConfigUtil.convert(peerConfig));
2178    } catch (ReplicationException | IOException e) {
2179      throw new ServiceException(e);
2180    }
2181    return response.build();
2182  }
2183
2184  @Override
2185  public UpdateReplicationPeerConfigResponse updateReplicationPeerConfig(RpcController controller,
2186    UpdateReplicationPeerConfigRequest request) throws ServiceException {
2187    try {
2188      long procId = server.updateReplicationPeerConfig(request.getPeerId(),
2189        ReplicationPeerConfigUtil.convert(request.getPeerConfig()));
2190      return UpdateReplicationPeerConfigResponse.newBuilder().setProcId(procId).build();
2191    } catch (ReplicationException | IOException e) {
2192      throw new ServiceException(e);
2193    }
2194  }
2195
2196  @Override
2197  public TransitReplicationPeerSyncReplicationStateResponse
2198    transitReplicationPeerSyncReplicationState(RpcController controller,
2199      TransitReplicationPeerSyncReplicationStateRequest request) throws ServiceException {
2200    try {
2201      long procId = server.transitReplicationPeerSyncReplicationState(request.getPeerId(),
2202        ReplicationPeerConfigUtil.toSyncReplicationState(request.getSyncReplicationState()));
2203      return TransitReplicationPeerSyncReplicationStateResponse.newBuilder().setProcId(procId)
2204        .build();
2205    } catch (ReplicationException | IOException e) {
2206      throw new ServiceException(e);
2207    }
2208  }
2209
2210  @Override
2211  public ListReplicationPeersResponse listReplicationPeers(RpcController controller,
2212    ListReplicationPeersRequest request) throws ServiceException {
2213    ListReplicationPeersResponse.Builder response = ListReplicationPeersResponse.newBuilder();
2214    try {
2215      List<ReplicationPeerDescription> peers =
2216        server.listReplicationPeers(request.hasRegex() ? request.getRegex() : null);
2217      for (ReplicationPeerDescription peer : peers) {
2218        response.addPeerDesc(ReplicationPeerConfigUtil.toProtoReplicationPeerDescription(peer));
2219      }
2220    } catch (ReplicationException | IOException e) {
2221      throw new ServiceException(e);
2222    }
2223    return response.build();
2224  }
2225
2226  @Override
2227  public GetReplicationPeerStateResponse isReplicationPeerEnabled(RpcController controller,
2228    GetReplicationPeerStateRequest request) throws ServiceException {
2229    boolean isEnabled;
2230    try {
2231      isEnabled = server.getReplicationPeerManager().getPeerState(request.getPeerId());
2232    } catch (ReplicationException ioe) {
2233      throw new ServiceException(ioe);
2234    }
2235    return GetReplicationPeerStateResponse.newBuilder().setIsEnabled(isEnabled).build();
2236  }
2237
2238  @Override
2239  public ReplicationPeerModificationSwitchResponse replicationPeerModificationSwitch(
2240    RpcController controller, ReplicationPeerModificationSwitchRequest request)
2241    throws ServiceException {
2242    try {
2243      server.checkInitialized();
2244      boolean prevValue = server.replicationPeerModificationSwitch(request.getOn());
2245      return ReplicationPeerModificationSwitchResponse.newBuilder().setPreviousValue(prevValue)
2246        .build();
2247    } catch (IOException ioe) {
2248      throw new ServiceException(ioe);
2249    }
2250  }
2251
2252  @Override
2253  public GetReplicationPeerModificationProceduresResponse getReplicationPeerModificationProcedures(
2254    RpcController controller, GetReplicationPeerModificationProceduresRequest request)
2255    throws ServiceException {
2256    try {
2257      server.checkInitialized();
2258      GetReplicationPeerModificationProceduresResponse.Builder builder =
2259        GetReplicationPeerModificationProceduresResponse.newBuilder();
2260      for (Procedure<?> proc : server.getProcedures()) {
2261        if (proc.isFinished()) {
2262          continue;
2263        }
2264        if (!(proc instanceof AbstractPeerNoLockProcedure)) {
2265          continue;
2266        }
2267        builder.addProcedure(ProcedureUtil.convertToProtoProcedure(proc));
2268      }
2269      return builder.build();
2270    } catch (IOException ioe) {
2271      throw new ServiceException(ioe);
2272    }
2273  }
2274
2275  @Override
2276  public IsReplicationPeerModificationEnabledResponse isReplicationPeerModificationEnabled(
2277    RpcController controller, IsReplicationPeerModificationEnabledRequest request)
2278    throws ServiceException {
2279    try {
2280      server.checkInitialized();
2281      return IsReplicationPeerModificationEnabledResponse.newBuilder()
2282        .setEnabled(server.isReplicationPeerModificationEnabled()).build();
2283    } catch (IOException ioe) {
2284      throw new ServiceException(ioe);
2285    }
2286  }
2287
2288  @Override
2289  public ListDecommissionedRegionServersResponse listDecommissionedRegionServers(
2290    RpcController controller, ListDecommissionedRegionServersRequest request)
2291    throws ServiceException {
2292    ListDecommissionedRegionServersResponse.Builder response =
2293      ListDecommissionedRegionServersResponse.newBuilder();
2294    try {
2295      server.checkInitialized();
2296      if (server.cpHost != null) {
2297        server.cpHost.preListDecommissionedRegionServers();
2298      }
2299      List<ServerName> servers = server.listDecommissionedRegionServers();
2300      response.addAllServerName((servers.stream().map(server -> ProtobufUtil.toServerName(server)))
2301        .collect(Collectors.toList()));
2302      if (server.cpHost != null) {
2303        server.cpHost.postListDecommissionedRegionServers();
2304      }
2305    } catch (IOException io) {
2306      throw new ServiceException(io);
2307    }
2308
2309    return response.build();
2310  }
2311
2312  @Override
2313  public DecommissionRegionServersResponse decommissionRegionServers(RpcController controller,
2314    DecommissionRegionServersRequest request) throws ServiceException {
2315    try {
2316      server.checkInitialized();
2317      List<ServerName> servers = request.getServerNameList().stream()
2318        .map(pbServer -> ProtobufUtil.toServerName(pbServer)).collect(Collectors.toList());
2319      boolean offload = request.getOffload();
2320      if (server.cpHost != null) {
2321        server.cpHost.preDecommissionRegionServers(servers, offload);
2322      }
2323      server.decommissionRegionServers(servers, offload);
2324      if (server.cpHost != null) {
2325        server.cpHost.postDecommissionRegionServers(servers, offload);
2326      }
2327    } catch (IOException io) {
2328      throw new ServiceException(io);
2329    }
2330
2331    return DecommissionRegionServersResponse.newBuilder().build();
2332  }
2333
2334  @Override
2335  public RecommissionRegionServerResponse recommissionRegionServer(RpcController controller,
2336    RecommissionRegionServerRequest request) throws ServiceException {
2337    try {
2338      server.checkInitialized();
2339      ServerName sn = ProtobufUtil.toServerName(request.getServerName());
2340      List<byte[]> encodedRegionNames = request.getRegionList().stream()
2341        .map(regionSpecifier -> regionSpecifier.getValue().toByteArray())
2342        .collect(Collectors.toList());
2343      if (server.cpHost != null) {
2344        server.cpHost.preRecommissionRegionServer(sn, encodedRegionNames);
2345      }
2346      server.recommissionRegionServer(sn, encodedRegionNames);
2347      if (server.cpHost != null) {
2348        server.cpHost.postRecommissionRegionServer(sn, encodedRegionNames);
2349      }
2350    } catch (IOException io) {
2351      throw new ServiceException(io);
2352    }
2353
2354    return RecommissionRegionServerResponse.newBuilder().build();
2355  }
2356
2357  @Override
2358  public LockResponse requestLock(RpcController controller, final LockRequest request)
2359    throws ServiceException {
2360    try {
2361      if (request.getDescription().isEmpty()) {
2362        throw new IllegalArgumentException("Empty description");
2363      }
2364      NonceProcedureRunnable npr;
2365      LockType type = LockType.valueOf(request.getLockType().name());
2366      if (request.getRegionInfoCount() > 0) {
2367        final RegionInfo[] regionInfos = new RegionInfo[request.getRegionInfoCount()];
2368        for (int i = 0; i < request.getRegionInfoCount(); ++i) {
2369          regionInfos[i] = ProtobufUtil.toRegionInfo(request.getRegionInfo(i));
2370        }
2371        npr = new NonceProcedureRunnable(server, request.getNonceGroup(), request.getNonce()) {
2372          @Override
2373          protected void run() throws IOException {
2374            setProcId(server.getLockManager().remoteLocks().requestRegionsLock(regionInfos,
2375              request.getDescription(), getNonceKey()));
2376          }
2377
2378          @Override
2379          protected String getDescription() {
2380            return "RequestLock";
2381          }
2382        };
2383      } else if (request.hasTableName()) {
2384        final TableName tableName = ProtobufUtil.toTableName(request.getTableName());
2385        npr = new NonceProcedureRunnable(server, request.getNonceGroup(), request.getNonce()) {
2386          @Override
2387          protected void run() throws IOException {
2388            setProcId(server.getLockManager().remoteLocks().requestTableLock(tableName, type,
2389              request.getDescription(), getNonceKey()));
2390          }
2391
2392          @Override
2393          protected String getDescription() {
2394            return "RequestLock";
2395          }
2396        };
2397      } else if (request.hasNamespace()) {
2398        npr = new NonceProcedureRunnable(server, request.getNonceGroup(), request.getNonce()) {
2399          @Override
2400          protected void run() throws IOException {
2401            setProcId(server.getLockManager().remoteLocks().requestNamespaceLock(
2402              request.getNamespace(), type, request.getDescription(), getNonceKey()));
2403          }
2404
2405          @Override
2406          protected String getDescription() {
2407            return "RequestLock";
2408          }
2409        };
2410      } else {
2411        throw new IllegalArgumentException("one of table/namespace/region should be specified");
2412      }
2413      long procId = MasterProcedureUtil.submitProcedure(npr);
2414      return LockResponse.newBuilder().setProcId(procId).build();
2415    } catch (IllegalArgumentException e) {
2416      LOG.warn("Exception when queuing lock", e);
2417      throw new ServiceException(new DoNotRetryIOException(e));
2418    } catch (IOException e) {
2419      LOG.warn("Exception when queuing lock", e);
2420      throw new ServiceException(e);
2421    }
2422  }
2423
2424  /**
2425   * @return LOCKED, if procedure is found and it has the lock; else UNLOCKED.
2426   * @throws ServiceException if given proc id is found but it is not a LockProcedure.
2427   */
2428  @Override
2429  public LockHeartbeatResponse lockHeartbeat(RpcController controller, LockHeartbeatRequest request)
2430    throws ServiceException {
2431    try {
2432      if (
2433        server.getLockManager().remoteLocks().lockHeartbeat(request.getProcId(),
2434          request.getKeepAlive())
2435      ) {
2436        return LockHeartbeatResponse.newBuilder()
2437          .setTimeoutMs(server.getConfiguration().getInt(LockProcedure.REMOTE_LOCKS_TIMEOUT_MS_CONF,
2438            LockProcedure.DEFAULT_REMOTE_LOCKS_TIMEOUT_MS))
2439          .setLockStatus(LockHeartbeatResponse.LockStatus.LOCKED).build();
2440      } else {
2441        return LockHeartbeatResponse.newBuilder()
2442          .setLockStatus(LockHeartbeatResponse.LockStatus.UNLOCKED).build();
2443      }
2444    } catch (IOException e) {
2445      throw new ServiceException(e);
2446    }
2447  }
2448
2449  @Override
2450  public RegionSpaceUseReportResponse reportRegionSpaceUse(RpcController controller,
2451    RegionSpaceUseReportRequest request) throws ServiceException {
2452    try {
2453      server.checkInitialized();
2454      if (!QuotaUtil.isQuotaEnabled(server.getConfiguration())) {
2455        return RegionSpaceUseReportResponse.newBuilder().build();
2456      }
2457      MasterQuotaManager quotaManager = this.server.getMasterQuotaManager();
2458      if (quotaManager != null) {
2459        final long now = EnvironmentEdgeManager.currentTime();
2460        for (RegionSpaceUse report : request.getSpaceUseList()) {
2461          quotaManager.addRegionSize(ProtobufUtil.toRegionInfo(report.getRegionInfo()),
2462            report.getRegionSize(), now);
2463        }
2464      } else {
2465        LOG.debug("Received region space usage report but HMaster is not ready to process it, "
2466          + "skipping");
2467      }
2468      return RegionSpaceUseReportResponse.newBuilder().build();
2469    } catch (Exception e) {
2470      throw new ServiceException(e);
2471    }
2472  }
2473
2474  @Override
2475  public GetSpaceQuotaRegionSizesResponse getSpaceQuotaRegionSizes(RpcController controller,
2476    GetSpaceQuotaRegionSizesRequest request) throws ServiceException {
2477    try {
2478      server.checkInitialized();
2479      MasterQuotaManager quotaManager = this.server.getMasterQuotaManager();
2480      GetSpaceQuotaRegionSizesResponse.Builder builder =
2481        GetSpaceQuotaRegionSizesResponse.newBuilder();
2482      if (quotaManager != null) {
2483        Map<RegionInfo, Long> regionSizes = quotaManager.snapshotRegionSizes();
2484        Map<TableName, Long> regionSizesByTable = new HashMap<>();
2485        // Translate hregioninfo+long -> tablename+long
2486        for (Entry<RegionInfo, Long> entry : regionSizes.entrySet()) {
2487          final TableName tableName = entry.getKey().getTable();
2488          Long prevSize = regionSizesByTable.get(tableName);
2489          if (prevSize == null) {
2490            prevSize = 0L;
2491          }
2492          regionSizesByTable.put(tableName, prevSize + entry.getValue());
2493        }
2494        // Serialize them into the protobuf
2495        for (Entry<TableName, Long> tableSize : regionSizesByTable.entrySet()) {
2496          builder.addSizes(
2497            RegionSizes.newBuilder().setTableName(ProtobufUtil.toProtoTableName(tableSize.getKey()))
2498              .setSize(tableSize.getValue()).build());
2499        }
2500        return builder.build();
2501      } else {
2502        LOG.debug("Received space quota region size report but HMaster is not ready to process it,"
2503          + "skipping");
2504      }
2505      return builder.build();
2506    } catch (Exception e) {
2507      throw new ServiceException(e);
2508    }
2509  }
2510
2511  @Override
2512  public GetQuotaStatesResponse getQuotaStates(RpcController controller,
2513    GetQuotaStatesRequest request) throws ServiceException {
2514    try {
2515      server.checkInitialized();
2516      QuotaObserverChore quotaChore = this.server.getQuotaObserverChore();
2517      GetQuotaStatesResponse.Builder builder = GetQuotaStatesResponse.newBuilder();
2518      if (quotaChore != null) {
2519        // The "current" view of all tables with quotas
2520        Map<TableName, SpaceQuotaSnapshot> tableSnapshots = quotaChore.getTableQuotaSnapshots();
2521        for (Entry<TableName, SpaceQuotaSnapshot> entry : tableSnapshots.entrySet()) {
2522          builder.addTableSnapshots(TableQuotaSnapshot.newBuilder()
2523            .setTableName(ProtobufUtil.toProtoTableName(entry.getKey()))
2524            .setSnapshot(SpaceQuotaSnapshot.toProtoSnapshot(entry.getValue())).build());
2525        }
2526        // The "current" view of all namespaces with quotas
2527        Map<String, SpaceQuotaSnapshot> nsSnapshots = quotaChore.getNamespaceQuotaSnapshots();
2528        for (Entry<String, SpaceQuotaSnapshot> entry : nsSnapshots.entrySet()) {
2529          builder.addNsSnapshots(NamespaceQuotaSnapshot.newBuilder().setNamespace(entry.getKey())
2530            .setSnapshot(SpaceQuotaSnapshot.toProtoSnapshot(entry.getValue())).build());
2531        }
2532        return builder.build();
2533      }
2534      return builder.build();
2535    } catch (Exception e) {
2536      throw new ServiceException(e);
2537    }
2538  }
2539
2540  @Override
2541  public ClearDeadServersResponse clearDeadServers(RpcController controller,
2542    ClearDeadServersRequest request) throws ServiceException {
2543    LOG.debug(server.getClientIdAuditPrefix() + " clear dead region servers.");
2544    ClearDeadServersResponse.Builder response = ClearDeadServersResponse.newBuilder();
2545    try {
2546      server.checkInitialized();
2547      if (server.cpHost != null) {
2548        server.cpHost.preClearDeadServers();
2549      }
2550
2551      if (server.getServerManager().areDeadServersInProgress()) {
2552        LOG.debug("Some dead server is still under processing, won't clear the dead server list");
2553        response.addAllServerName(request.getServerNameList());
2554      } else {
2555        DeadServer deadServer = server.getServerManager().getDeadServers();
2556        Set<Address> clearedServers = new HashSet<>();
2557        for (HBaseProtos.ServerName pbServer : request.getServerNameList()) {
2558          ServerName serverName = ProtobufUtil.toServerName(pbServer);
2559          final boolean deadInProcess =
2560            server.getProcedures().stream().anyMatch(p -> (p instanceof ServerCrashProcedure)
2561              && ((ServerCrashProcedure) p).getServerName().equals(serverName));
2562          if (deadInProcess) {
2563            throw new ServiceException(
2564              String.format("Dead server '%s' is not 'dead' in fact...", serverName));
2565          }
2566
2567          if (!deadServer.removeDeadServer(serverName)) {
2568            response.addServerName(pbServer);
2569          } else {
2570            clearedServers.add(serverName.getAddress());
2571          }
2572        }
2573        server.getRSGroupInfoManager().removeServers(clearedServers);
2574        LOG.info("Remove decommissioned servers {} from RSGroup done", clearedServers);
2575      }
2576
2577      if (server.cpHost != null) {
2578        server.cpHost.postClearDeadServers(
2579          ProtobufUtil.toServerNameList(request.getServerNameList()),
2580          ProtobufUtil.toServerNameList(response.getServerNameList()));
2581      }
2582    } catch (IOException io) {
2583      throw new ServiceException(io);
2584    }
2585    return response.build();
2586  }
2587
2588  @Override
2589  public ReportProcedureDoneResponse reportProcedureDone(RpcController controller,
2590    ReportProcedureDoneRequest request) throws ServiceException {
2591    // Check Masters is up and ready for duty before progressing. Remote side will keep trying.
2592    try {
2593      this.server.checkServiceStarted();
2594      for (RemoteProcedureResult result : request.getResultList()) {
2595        // -1 is less than any possible MasterActiveCode
2596        long initiatingMasterActiveTime =
2597          result.hasInitiatingMasterActiveTime() ? result.getInitiatingMasterActiveTime() : -1;
2598        throwOnOldMaster(result.getProcId(), initiatingMasterActiveTime);
2599      }
2600    } catch (IOException ioe) {
2601      throw new ServiceException(ioe);
2602    }
2603    request.getResultList().forEach(result -> {
2604      if (result.getStatus() == RemoteProcedureResult.Status.SUCCESS) {
2605        byte[] remoteResultData =
2606          result.hasProcResultData() ? result.getProcResultData().toByteArray() : null;
2607        server.remoteProcedureCompleted(result.getProcId(), remoteResultData);
2608      } else {
2609        server.remoteProcedureFailed(result.getProcId(),
2610          RemoteProcedureException.fromProto(result.getError()));
2611      }
2612    });
2613    return ReportProcedureDoneResponse.getDefaultInstance();
2614  }
2615
2616  private void throwOnOldMaster(long procId, long initiatingMasterActiveTime)
2617    throws MasterNotRunningException {
2618    if (initiatingMasterActiveTime > server.getMasterActiveTime()) {
2619      // procedure is initiated by new active master but report received on master with older active
2620      // time
2621      LOG.warn(
2622        "Report for procId: {} and initiatingMasterAT {} received on master with activeTime {}",
2623        procId, initiatingMasterActiveTime, server.getMasterActiveTime());
2624      throw new MasterNotRunningException("Another master is active");
2625    }
2626  }
2627
2628  @Override
2629  public FileArchiveNotificationResponse reportFileArchival(RpcController controller,
2630    FileArchiveNotificationRequest request) throws ServiceException {
2631    try {
2632      server.checkInitialized();
2633      if (!QuotaUtil.isQuotaEnabled(server.getConfiguration())) {
2634        return FileArchiveNotificationResponse.newBuilder().build();
2635      }
2636      server.getMasterQuotaManager().processFileArchivals(request, server.getConnection(),
2637        server.getConfiguration(), server.getFileSystem());
2638      return FileArchiveNotificationResponse.newBuilder().build();
2639    } catch (Exception e) {
2640      throw new ServiceException(e);
2641    }
2642  }
2643
2644  // HBCK Services
2645
2646  @Override
2647  public RunHbckChoreResponse runHbckChore(RpcController c, RunHbckChoreRequest req)
2648    throws ServiceException {
2649    rpcPreCheck("runHbckChore");
2650    LOG.info("{} request HBCK chore to run", server.getClientIdAuditPrefix());
2651    HbckChore hbckChore = server.getHbckChore();
2652    boolean ran = hbckChore.runChore();
2653    return RunHbckChoreResponse.newBuilder().setRan(ran).build();
2654  }
2655
2656  /**
2657   * Update state of the table in meta only. This is required by hbck in some situations to cleanup
2658   * stuck assign/ unassign regions procedures for the table.
2659   * @return previous state of the table
2660   */
2661  @Override
2662  public GetTableStateResponse setTableStateInMeta(RpcController controller,
2663    SetTableStateInMetaRequest request) throws ServiceException {
2664    rpcPreCheck("setTableStateInMeta");
2665    TableName tn = ProtobufUtil.toTableName(request.getTableName());
2666    try {
2667      TableState prevState = this.server.getTableStateManager().getTableState(tn);
2668      TableState newState = TableState.convert(tn, request.getTableState());
2669      LOG.info("{} set table={} state from {} to {}", server.getClientIdAuditPrefix(), tn,
2670        prevState.getState(), newState.getState());
2671      this.server.getTableStateManager().setTableState(tn, newState.getState());
2672      return GetTableStateResponse.newBuilder().setTableState(prevState.convert()).build();
2673    } catch (Exception e) {
2674      throw new ServiceException(e);
2675    }
2676  }
2677
2678  /**
2679   * Update state of the region in meta only. This is required by hbck in some situations to cleanup
2680   * stuck assign/ unassign regions procedures for the table.
2681   * @return previous states of the regions
2682   */
2683  @Override
2684  public SetRegionStateInMetaResponse setRegionStateInMeta(RpcController controller,
2685    SetRegionStateInMetaRequest request) throws ServiceException {
2686    rpcPreCheck("setRegionStateInMeta");
2687    SetRegionStateInMetaResponse.Builder builder = SetRegionStateInMetaResponse.newBuilder();
2688    final AssignmentManager am = server.getAssignmentManager();
2689    try {
2690      for (RegionSpecifierAndState s : request.getStatesList()) {
2691        final RegionSpecifier spec = s.getRegionSpecifier();
2692        final RegionInfo targetRegionInfo = getRegionInfo(spec);
2693        final RegionState.State targetState = RegionState.State.convert(s.getState());
2694        final RegionState.State currentState = Optional.ofNullable(targetRegionInfo)
2695          .map(info -> am.getRegionStates().getRegionState(info)).map(RegionState::getState)
2696          .orElseThrow(
2697            () -> new ServiceException("No existing state known for region '" + spec + "'."));
2698        LOG.info("{} set region={} state from {} to {}", server.getClientIdAuditPrefix(),
2699          targetRegionInfo, currentState, targetState);
2700        if (currentState == targetState) {
2701          LOG.debug("Proposed state matches current state. {}, {}", targetRegionInfo, currentState);
2702          continue;
2703        }
2704        MetaTableAccessor.updateRegionState(server.getConnection(), targetRegionInfo, targetState);
2705        // Loads from meta again to refresh AM cache with the new region state
2706        am.populateRegionStatesFromMeta(targetRegionInfo);
2707        builder.addStates(RegionSpecifierAndState.newBuilder().setRegionSpecifier(spec)
2708          .setState(currentState.convert()));
2709      }
2710    } catch (IOException e) {
2711      throw new ServiceException(e);
2712    }
2713    return builder.build();
2714  }
2715
2716  /**
2717   * Get {@link RegionInfo} from Master using content of {@link RegionSpecifier} as key.
2718   * @return {@link RegionInfo} found by decoding {@code rs} or {@code null} if {@code rs} is
2719   *         unknown to the master.
2720   * @throws ServiceException If some error occurs while querying META or parsing results.
2721   */
2722  private RegionInfo getRegionInfo(HBaseProtos.RegionSpecifier rs) throws ServiceException {
2723    // TODO: this doesn't handle MOB regions. Should it? See the public method #getRegionInfo
2724    final AssignmentManager am = server.getAssignmentManager();
2725    final String encodedRegionName;
2726    final RegionInfo info;
2727    // first try resolving from the AM's caches.
2728    switch (rs.getType()) {
2729      case REGION_NAME:
2730        final byte[] regionName = rs.getValue().toByteArray();
2731        encodedRegionName = RegionInfo.encodeRegionName(regionName);
2732        info = am.getRegionInfo(regionName);
2733        break;
2734      case ENCODED_REGION_NAME:
2735        encodedRegionName = rs.getValue().toStringUtf8();
2736        info = am.getRegionInfo(encodedRegionName);
2737        break;
2738      default:
2739        throw new IllegalArgumentException("Unrecognized RegionSpecifierType " + rs.getType());
2740    }
2741    if (info != null) {
2742      return info;
2743    }
2744    // fall back to a meta scan and check the cache again.
2745    try {
2746      am.populateRegionStatesFromMeta(encodedRegionName);
2747    } catch (IOException e) {
2748      throw new ServiceException(e);
2749    }
2750    return am.getRegionInfo(encodedRegionName);
2751  }
2752
2753  /**
2754   * @throws ServiceException If no MasterProcedureExecutor
2755   */
2756  private void checkMasterProcedureExecutor() throws ServiceException {
2757    if (this.server.getMasterProcedureExecutor() == null) {
2758      throw new ServiceException("Master's ProcedureExecutor not initialized; retry later");
2759    }
2760  }
2761
2762  /**
2763   * A 'raw' version of assign that does bulk and can skirt Master state checks if override is set;
2764   * i.e. assigns can be forced during Master startup or if RegionState is unclean. Used by HBCK2.
2765   */
2766  @Override
2767  public MasterProtos.AssignsResponse assigns(RpcController controller,
2768    MasterProtos.AssignsRequest request) throws ServiceException {
2769    checkMasterProcedureExecutor();
2770    final ProcedureExecutor<MasterProcedureEnv> pe = server.getMasterProcedureExecutor();
2771    final AssignmentManager am = server.getAssignmentManager();
2772    MasterProtos.AssignsResponse.Builder responseBuilder =
2773      MasterProtos.AssignsResponse.newBuilder();
2774    final boolean override = request.getOverride();
2775    final boolean force = request.getForce();
2776    LOG.info("{} assigns, override={}", server.getClientIdAuditPrefix(), override);
2777    for (HBaseProtos.RegionSpecifier rs : request.getRegionList()) {
2778      final RegionInfo info = getRegionInfo(rs);
2779      if (info == null) {
2780        LOG.info("Unknown region {}", rs);
2781        continue;
2782      }
2783      responseBuilder.addPid(Optional.ofNullable(am.createOneAssignProcedure(info, override, force))
2784        .map(pe::submitProcedure).orElse(Procedure.NO_PROC_ID));
2785    }
2786    return responseBuilder.build();
2787  }
2788
2789  /**
2790   * A 'raw' version of unassign that does bulk and can skirt Master state checks if override is
2791   * set; i.e. unassigns can be forced during Master startup or if RegionState is unclean. Used by
2792   * HBCK2.
2793   */
2794  @Override
2795  public MasterProtos.UnassignsResponse unassigns(RpcController controller,
2796    MasterProtos.UnassignsRequest request) throws ServiceException {
2797    checkMasterProcedureExecutor();
2798    final ProcedureExecutor<MasterProcedureEnv> pe = server.getMasterProcedureExecutor();
2799    final AssignmentManager am = server.getAssignmentManager();
2800    MasterProtos.UnassignsResponse.Builder responseBuilder =
2801      MasterProtos.UnassignsResponse.newBuilder();
2802    final boolean override = request.getOverride();
2803    final boolean force = request.getForce();
2804    LOG.info("{} unassigns, override={}", server.getClientIdAuditPrefix(), override);
2805    for (HBaseProtos.RegionSpecifier rs : request.getRegionList()) {
2806      final RegionInfo info = getRegionInfo(rs);
2807      if (info == null) {
2808        LOG.info("Unknown region {}", rs);
2809        continue;
2810      }
2811      responseBuilder
2812        .addPid(Optional.ofNullable(am.createOneUnassignProcedure(info, override, force))
2813          .map(pe::submitProcedure).orElse(Procedure.NO_PROC_ID));
2814    }
2815    return responseBuilder.build();
2816  }
2817
2818  /**
2819   * Bypass specified procedure to completion. Procedure is marked completed but no actual work is
2820   * done from the current state/ step onwards. Parents of the procedure are also marked for bypass.
2821   * NOTE: this is a dangerous operation and may be used to unstuck buggy procedures. This may leave
2822   * system in incoherent state. This may need to be followed by some cleanup steps/ actions by
2823   * operator.
2824   * @return BypassProcedureToCompletionResponse indicating success or failure
2825   */
2826  @Override
2827  public MasterProtos.BypassProcedureResponse bypassProcedure(RpcController controller,
2828    MasterProtos.BypassProcedureRequest request) throws ServiceException {
2829    try {
2830      LOG.info("{} bypass procedures={}, waitTime={}, override={}, recursive={}",
2831        server.getClientIdAuditPrefix(), request.getProcIdList(), request.getWaitTime(),
2832        request.getOverride(), request.getRecursive());
2833      List<Boolean> ret =
2834        server.getMasterProcedureExecutor().bypassProcedure(request.getProcIdList(),
2835          request.getWaitTime(), request.getOverride(), request.getRecursive());
2836      return MasterProtos.BypassProcedureResponse.newBuilder().addAllBypassed(ret).build();
2837    } catch (IOException e) {
2838      throw new ServiceException(e);
2839    }
2840  }
2841
2842  @Override
2843  public MasterProtos.ScheduleServerCrashProcedureResponse scheduleServerCrashProcedure(
2844    RpcController controller, MasterProtos.ScheduleServerCrashProcedureRequest request)
2845    throws ServiceException {
2846    List<Long> pids = new ArrayList<>();
2847    for (HBaseProtos.ServerName sn : request.getServerNameList()) {
2848      ServerName serverName = ProtobufUtil.toServerName(sn);
2849      LOG.info("{} schedule ServerCrashProcedure for {}", this.server.getClientIdAuditPrefix(),
2850        serverName);
2851      if (shouldSubmitSCP(serverName)) {
2852        pids.add(this.server.getServerManager().expireServer(serverName, true));
2853      } else {
2854        pids.add(Procedure.NO_PROC_ID);
2855      }
2856    }
2857    return MasterProtos.ScheduleServerCrashProcedureResponse.newBuilder().addAllPid(pids).build();
2858  }
2859
2860  @Override
2861  public MasterProtos.ScheduleSCPsForUnknownServersResponse scheduleSCPsForUnknownServers(
2862    RpcController controller, MasterProtos.ScheduleSCPsForUnknownServersRequest request)
2863    throws ServiceException {
2864    List<Long> pids = new ArrayList<>();
2865    final Set<ServerName> serverNames = server.getAssignmentManager().getRegionStates()
2866      .getRegionStates().stream().map(RegionState::getServerName).collect(Collectors.toSet());
2867
2868    final Set<ServerName> unknownServerNames = serverNames.stream()
2869      .filter(sn -> server.getServerManager().isServerUnknown(sn)).collect(Collectors.toSet());
2870
2871    for (ServerName sn : unknownServerNames) {
2872      LOG.info("{} schedule ServerCrashProcedure for unknown {}",
2873        this.server.getClientIdAuditPrefix(), sn);
2874      if (shouldSubmitSCP(sn)) {
2875        pids.add(this.server.getServerManager().expireServer(sn, true));
2876      } else {
2877        pids.add(Procedure.NO_PROC_ID);
2878      }
2879    }
2880    return MasterProtos.ScheduleSCPsForUnknownServersResponse.newBuilder().addAllPid(pids).build();
2881  }
2882
2883  @Override
2884  public FixMetaResponse fixMeta(RpcController controller, FixMetaRequest request)
2885    throws ServiceException {
2886    rpcPreCheck("fixMeta");
2887    try {
2888      MetaFixer mf = new MetaFixer(this.server);
2889      mf.fix();
2890      return FixMetaResponse.newBuilder().build();
2891    } catch (IOException ioe) {
2892      throw new ServiceException(ioe);
2893    }
2894  }
2895
2896  @Override
2897  public SwitchRpcThrottleResponse switchRpcThrottle(RpcController controller,
2898    SwitchRpcThrottleRequest request) throws ServiceException {
2899    try {
2900      server.checkInitialized();
2901      return server.getMasterQuotaManager().switchRpcThrottle(request);
2902    } catch (Exception e) {
2903      throw new ServiceException(e);
2904    }
2905  }
2906
2907  @Override
2908  public MasterProtos.IsRpcThrottleEnabledResponse isRpcThrottleEnabled(RpcController controller,
2909    MasterProtos.IsRpcThrottleEnabledRequest request) throws ServiceException {
2910    try {
2911      server.checkInitialized();
2912      return server.getMasterQuotaManager().isRpcThrottleEnabled(request);
2913    } catch (Exception e) {
2914      throw new ServiceException(e);
2915    }
2916  }
2917
2918  @Override
2919  public SwitchExceedThrottleQuotaResponse switchExceedThrottleQuota(RpcController controller,
2920    SwitchExceedThrottleQuotaRequest request) throws ServiceException {
2921    try {
2922      server.checkInitialized();
2923      return server.getMasterQuotaManager().switchExceedThrottleQuota(request);
2924    } catch (Exception e) {
2925      throw new ServiceException(e);
2926    }
2927  }
2928
2929  @Override
2930  public GrantResponse grant(RpcController controller, GrantRequest request)
2931    throws ServiceException {
2932    try {
2933      server.checkInitialized();
2934      if (server.cpHost != null && hasAccessControlServiceCoprocessor(server.cpHost)) {
2935        final UserPermission perm =
2936          ShadedAccessControlUtil.toUserPermission(request.getUserPermission());
2937        boolean mergeExistingPermissions = request.getMergeExistingPermissions();
2938        server.cpHost.preGrant(perm, mergeExistingPermissions);
2939        try (Table table = server.getConnection().getTable(PermissionStorage.ACL_TABLE_NAME)) {
2940          PermissionStorage.addUserPermission(getConfiguration(), perm, table,
2941            mergeExistingPermissions);
2942        }
2943        server.cpHost.postGrant(perm, mergeExistingPermissions);
2944        return GrantResponse.getDefaultInstance();
2945      } else {
2946        throw new DoNotRetryIOException(
2947          new UnsupportedOperationException(AccessController.class.getName() + " is not loaded"));
2948      }
2949    } catch (IOException ioe) {
2950      throw new ServiceException(ioe);
2951    }
2952  }
2953
2954  @Override
2955  public RevokeResponse revoke(RpcController controller, RevokeRequest request)
2956    throws ServiceException {
2957    try {
2958      server.checkInitialized();
2959      if (server.cpHost != null && hasAccessControlServiceCoprocessor(server.cpHost)) {
2960        final UserPermission userPermission =
2961          ShadedAccessControlUtil.toUserPermission(request.getUserPermission());
2962        server.cpHost.preRevoke(userPermission);
2963        try (Table table = server.getConnection().getTable(PermissionStorage.ACL_TABLE_NAME)) {
2964          PermissionStorage.removeUserPermission(server.getConfiguration(), userPermission, table);
2965        }
2966        server.cpHost.postRevoke(userPermission);
2967        return RevokeResponse.getDefaultInstance();
2968      } else {
2969        throw new DoNotRetryIOException(
2970          new UnsupportedOperationException(AccessController.class.getName() + " is not loaded"));
2971      }
2972    } catch (IOException ioe) {
2973      throw new ServiceException(ioe);
2974    }
2975  }
2976
2977  @Override
2978  public GetUserPermissionsResponse getUserPermissions(RpcController controller,
2979    GetUserPermissionsRequest request) throws ServiceException {
2980    try {
2981      server.checkInitialized();
2982      if (server.cpHost != null && hasAccessControlServiceCoprocessor(server.cpHost)) {
2983        final String userName = request.hasUserName() ? request.getUserName().toStringUtf8() : null;
2984        String namespace =
2985          request.hasNamespaceName() ? request.getNamespaceName().toStringUtf8() : null;
2986        TableName table =
2987          request.hasTableName() ? ProtobufUtil.toTableName(request.getTableName()) : null;
2988        byte[] cf = request.hasColumnFamily() ? request.getColumnFamily().toByteArray() : null;
2989        byte[] cq =
2990          request.hasColumnQualifier() ? request.getColumnQualifier().toByteArray() : null;
2991        Type permissionType = request.hasType() ? request.getType() : null;
2992        server.getMasterCoprocessorHost().preGetUserPermissions(userName, namespace, table, cf, cq);
2993
2994        List<UserPermission> perms = null;
2995        if (permissionType == Type.Table) {
2996          boolean filter = (cf != null || userName != null) ? true : false;
2997          perms = PermissionStorage.getUserTablePermissions(server.getConfiguration(), table, cf,
2998            cq, userName, filter);
2999        } else if (permissionType == Type.Namespace) {
3000          perms = PermissionStorage.getUserNamespacePermissions(server.getConfiguration(),
3001            namespace, userName, userName != null ? true : false);
3002        } else {
3003          perms = PermissionStorage.getUserPermissions(server.getConfiguration(), null, null, null,
3004            userName, userName != null ? true : false);
3005          // Skip super users when filter user is specified
3006          if (userName == null) {
3007            // Adding superusers explicitly to the result set as PermissionStorage do not store
3008            // them. Also using acl as table name to be inline with the results of global admin and
3009            // will help in avoiding any leakage of information about being superusers.
3010            for (String user : Superusers.getSuperUsers()) {
3011              perms.add(new UserPermission(user,
3012                Permission.newBuilder().withActions(Action.values()).build()));
3013            }
3014          }
3015        }
3016
3017        server.getMasterCoprocessorHost().postGetUserPermissions(userName, namespace, table, cf,
3018          cq);
3019        AccessControlProtos.GetUserPermissionsResponse response =
3020          ShadedAccessControlUtil.buildGetUserPermissionsResponse(perms);
3021        return response;
3022      } else {
3023        throw new DoNotRetryIOException(
3024          new UnsupportedOperationException(AccessController.class.getName() + " is not loaded"));
3025      }
3026    } catch (IOException ioe) {
3027      throw new ServiceException(ioe);
3028    }
3029  }
3030
3031  @Override
3032  public HasUserPermissionsResponse hasUserPermissions(RpcController controller,
3033    HasUserPermissionsRequest request) throws ServiceException {
3034    try {
3035      server.checkInitialized();
3036      if (server.cpHost != null && hasAccessControlServiceCoprocessor(server.cpHost)) {
3037        User caller = RpcServer.getRequestUser().orElse(null);
3038        String userName =
3039          request.hasUserName() ? request.getUserName().toStringUtf8() : caller.getShortName();
3040        List<Permission> permissions = new ArrayList<>();
3041        for (int i = 0; i < request.getPermissionCount(); i++) {
3042          permissions.add(ShadedAccessControlUtil.toPermission(request.getPermission(i)));
3043        }
3044        server.getMasterCoprocessorHost().preHasUserPermissions(userName, permissions);
3045        if (!caller.getShortName().equals(userName)) {
3046          List<String> groups = AccessChecker.getUserGroups(userName);
3047          caller = new InputUser(userName, groups.toArray(new String[groups.size()]));
3048        }
3049        List<Boolean> hasUserPermissions = new ArrayList<>();
3050        if (getAccessChecker() != null) {
3051          for (Permission permission : permissions) {
3052            boolean hasUserPermission =
3053              getAccessChecker().hasUserPermission(caller, "hasUserPermissions", permission);
3054            hasUserPermissions.add(hasUserPermission);
3055          }
3056        } else {
3057          for (int i = 0; i < permissions.size(); i++) {
3058            hasUserPermissions.add(true);
3059          }
3060        }
3061        server.getMasterCoprocessorHost().postHasUserPermissions(userName, permissions);
3062        HasUserPermissionsResponse.Builder builder =
3063          HasUserPermissionsResponse.newBuilder().addAllHasUserPermission(hasUserPermissions);
3064        return builder.build();
3065      } else {
3066        throw new DoNotRetryIOException(
3067          new UnsupportedOperationException(AccessController.class.getName() + " is not loaded"));
3068      }
3069    } catch (IOException ioe) {
3070      throw new ServiceException(ioe);
3071    }
3072  }
3073
3074  private boolean shouldSubmitSCP(ServerName serverName) {
3075    // check if there is already a SCP of this server running
3076    List<Procedure<MasterProcedureEnv>> procedures =
3077      server.getMasterProcedureExecutor().getProcedures();
3078    for (Procedure<MasterProcedureEnv> procedure : procedures) {
3079      if (procedure instanceof ServerCrashProcedure) {
3080        if (
3081          serverName.compareTo(((ServerCrashProcedure) procedure).getServerName()) == 0
3082            && !procedure.isFinished()
3083        ) {
3084          LOG.info("there is already a SCP of this server {} running, pid {}", serverName,
3085            procedure.getProcId());
3086          return false;
3087        }
3088      }
3089    }
3090    return true;
3091  }
3092
3093  @Override
3094  public GetRSGroupInfoResponse getRSGroupInfo(RpcController controller,
3095    GetRSGroupInfoRequest request) throws ServiceException {
3096    String groupName = request.getRSGroupName();
3097    LOG.info(
3098      server.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, group=" + groupName);
3099    try {
3100      if (server.getMasterCoprocessorHost() != null) {
3101        server.getMasterCoprocessorHost().preGetRSGroupInfo(groupName);
3102      }
3103      RSGroupInfo rsGroupInfo = server.getRSGroupInfoManager().getRSGroup(groupName);
3104      GetRSGroupInfoResponse resp;
3105      if (rsGroupInfo != null) {
3106        resp = GetRSGroupInfoResponse.newBuilder()
3107          .setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(rsGroupInfo)).build();
3108      } else {
3109        resp = GetRSGroupInfoResponse.getDefaultInstance();
3110      }
3111      if (server.getMasterCoprocessorHost() != null) {
3112        server.getMasterCoprocessorHost().postGetRSGroupInfo(groupName);
3113      }
3114      return resp;
3115    } catch (IOException e) {
3116      throw new ServiceException(e);
3117    }
3118  }
3119
3120  @Override
3121  public GetRSGroupInfoOfTableResponse getRSGroupInfoOfTable(RpcController controller,
3122    GetRSGroupInfoOfTableRequest request) throws ServiceException {
3123    TableName tableName = ProtobufUtil.toTableName(request.getTableName());
3124    LOG.info(
3125      server.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table=" + tableName);
3126    try {
3127      if (server.getMasterCoprocessorHost() != null) {
3128        server.getMasterCoprocessorHost().preGetRSGroupInfoOfTable(tableName);
3129      }
3130      GetRSGroupInfoOfTableResponse resp;
3131      TableDescriptor td = server.getTableDescriptors().get(tableName);
3132      if (td == null) {
3133        resp = GetRSGroupInfoOfTableResponse.getDefaultInstance();
3134      } else {
3135        RSGroupInfo rsGroupInfo =
3136          RSGroupUtil.getRSGroupInfo(server, server.getRSGroupInfoManager(), tableName)
3137            .orElse(server.getRSGroupInfoManager().getRSGroup(RSGroupInfo.DEFAULT_GROUP));
3138        resp = GetRSGroupInfoOfTableResponse.newBuilder()
3139          .setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(rsGroupInfo)).build();
3140      }
3141      if (server.getMasterCoprocessorHost() != null) {
3142        server.getMasterCoprocessorHost().postGetRSGroupInfoOfTable(tableName);
3143      }
3144      return resp;
3145    } catch (IOException e) {
3146      throw new ServiceException(e);
3147    }
3148  }
3149
3150  @Override
3151  public GetRSGroupInfoOfServerResponse getRSGroupInfoOfServer(RpcController controller,
3152    GetRSGroupInfoOfServerRequest request) throws ServiceException {
3153    Address hp =
3154      Address.fromParts(request.getServer().getHostName(), request.getServer().getPort());
3155    LOG.info(server.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server=" + hp);
3156    try {
3157      if (server.getMasterCoprocessorHost() != null) {
3158        server.getMasterCoprocessorHost().preGetRSGroupInfoOfServer(hp);
3159      }
3160      RSGroupInfo rsGroupInfo = server.getRSGroupInfoManager().getRSGroupOfServer(hp);
3161      GetRSGroupInfoOfServerResponse resp;
3162      if (rsGroupInfo != null) {
3163        resp = GetRSGroupInfoOfServerResponse.newBuilder()
3164          .setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(rsGroupInfo)).build();
3165      } else {
3166        resp = GetRSGroupInfoOfServerResponse.getDefaultInstance();
3167      }
3168      if (server.getMasterCoprocessorHost() != null) {
3169        server.getMasterCoprocessorHost().postGetRSGroupInfoOfServer(hp);
3170      }
3171      return resp;
3172    } catch (IOException e) {
3173      throw new ServiceException(e);
3174    }
3175  }
3176
3177  @Override
3178  public MoveServersResponse moveServers(RpcController controller, MoveServersRequest request)
3179    throws ServiceException {
3180    Set<Address> hostPorts = Sets.newHashSet();
3181    MoveServersResponse.Builder builder = MoveServersResponse.newBuilder();
3182    for (HBaseProtos.ServerName el : request.getServersList()) {
3183      hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
3184    }
3185    LOG.info(server.getClientIdAuditPrefix() + " move servers " + hostPorts + " to rsgroup "
3186      + request.getTargetGroup());
3187    try {
3188      if (server.getMasterCoprocessorHost() != null) {
3189        server.getMasterCoprocessorHost().preMoveServers(hostPorts, request.getTargetGroup());
3190      }
3191      server.getRSGroupInfoManager().moveServers(hostPorts, request.getTargetGroup());
3192      if (server.getMasterCoprocessorHost() != null) {
3193        server.getMasterCoprocessorHost().postMoveServers(hostPorts, request.getTargetGroup());
3194      }
3195    } catch (IOException e) {
3196      throw new ServiceException(e);
3197    }
3198    return builder.build();
3199  }
3200
3201  @Override
3202  public AddRSGroupResponse addRSGroup(RpcController controller, AddRSGroupRequest request)
3203    throws ServiceException {
3204    AddRSGroupResponse.Builder builder = AddRSGroupResponse.newBuilder();
3205    LOG.info(server.getClientIdAuditPrefix() + " add rsgroup " + request.getRSGroupName());
3206    try {
3207      if (server.getMasterCoprocessorHost() != null) {
3208        server.getMasterCoprocessorHost().preAddRSGroup(request.getRSGroupName());
3209      }
3210      server.getRSGroupInfoManager().addRSGroup(new RSGroupInfo(request.getRSGroupName()));
3211      if (server.getMasterCoprocessorHost() != null) {
3212        server.getMasterCoprocessorHost().postAddRSGroup(request.getRSGroupName());
3213      }
3214    } catch (IOException e) {
3215      throw new ServiceException(e);
3216    }
3217    return builder.build();
3218  }
3219
3220  @Override
3221  public RemoveRSGroupResponse removeRSGroup(RpcController controller, RemoveRSGroupRequest request)
3222    throws ServiceException {
3223    RemoveRSGroupResponse.Builder builder = RemoveRSGroupResponse.newBuilder();
3224    LOG.info(server.getClientIdAuditPrefix() + " remove rsgroup " + request.getRSGroupName());
3225    try {
3226      if (server.getMasterCoprocessorHost() != null) {
3227        server.getMasterCoprocessorHost().preRemoveRSGroup(request.getRSGroupName());
3228      }
3229      server.getRSGroupInfoManager().removeRSGroup(request.getRSGroupName());
3230      if (server.getMasterCoprocessorHost() != null) {
3231        server.getMasterCoprocessorHost().postRemoveRSGroup(request.getRSGroupName());
3232      }
3233    } catch (IOException e) {
3234      throw new ServiceException(e);
3235    }
3236    return builder.build();
3237  }
3238
3239  @Override
3240  public BalanceRSGroupResponse balanceRSGroup(RpcController controller,
3241    BalanceRSGroupRequest request) throws ServiceException {
3242    BalanceRequest balanceRequest = ProtobufUtil.toBalanceRequest(request);
3243
3244    BalanceRSGroupResponse.Builder builder =
3245      BalanceRSGroupResponse.newBuilder().setBalanceRan(false);
3246
3247    LOG.info(
3248      server.getClientIdAuditPrefix() + " balance rsgroup, group=" + request.getRSGroupName());
3249    try {
3250      if (server.getMasterCoprocessorHost() != null) {
3251        server.getMasterCoprocessorHost().preBalanceRSGroup(request.getRSGroupName(),
3252          balanceRequest);
3253      }
3254      BalanceResponse response =
3255        server.getRSGroupInfoManager().balanceRSGroup(request.getRSGroupName(), balanceRequest);
3256      ProtobufUtil.populateBalanceRSGroupResponse(builder, response);
3257      if (server.getMasterCoprocessorHost() != null) {
3258        server.getMasterCoprocessorHost().postBalanceRSGroup(request.getRSGroupName(),
3259          balanceRequest, response);
3260      }
3261    } catch (IOException e) {
3262      throw new ServiceException(e);
3263    }
3264    return builder.build();
3265  }
3266
3267  @Override
3268  public ListRSGroupInfosResponse listRSGroupInfos(RpcController controller,
3269    ListRSGroupInfosRequest request) throws ServiceException {
3270    ListRSGroupInfosResponse.Builder builder = ListRSGroupInfosResponse.newBuilder();
3271    LOG.info(server.getClientIdAuditPrefix() + " list rsgroup");
3272    try {
3273      if (server.getMasterCoprocessorHost() != null) {
3274        server.getMasterCoprocessorHost().preListRSGroups();
3275      }
3276      List<RSGroupInfo> rsGroupInfos = server.getRSGroupInfoManager().listRSGroups().stream()
3277        .map(RSGroupInfo::new).collect(Collectors.toList());
3278      Map<String, RSGroupInfo> name2Info = new HashMap<>();
3279      List<TableDescriptor> needToFill =
3280        new ArrayList<>(server.getTableDescriptors().getAll().values());
3281      for (RSGroupInfo rsGroupInfo : rsGroupInfos) {
3282        name2Info.put(rsGroupInfo.getName(), rsGroupInfo);
3283        for (TableDescriptor td : server.getTableDescriptors().getAll().values()) {
3284          if (rsGroupInfo.containsTable(td.getTableName())) {
3285            needToFill.remove(td);
3286          }
3287        }
3288      }
3289      for (TableDescriptor td : needToFill) {
3290        String groupName = td.getRegionServerGroup().orElse(RSGroupInfo.DEFAULT_GROUP);
3291        RSGroupInfo rsGroupInfo = name2Info.get(groupName);
3292        if (rsGroupInfo != null) {
3293          rsGroupInfo.addTable(td.getTableName());
3294        }
3295      }
3296      for (RSGroupInfo rsGroupInfo : rsGroupInfos) {
3297        // TODO: this can be done at once outside this loop, do not need to scan all every time.
3298        builder.addRSGroupInfo(ProtobufUtil.toProtoGroupInfo(rsGroupInfo));
3299      }
3300      if (server.getMasterCoprocessorHost() != null) {
3301        server.getMasterCoprocessorHost().postListRSGroups();
3302      }
3303    } catch (IOException e) {
3304      throw new ServiceException(e);
3305    }
3306    return builder.build();
3307  }
3308
3309  @Override
3310  public RemoveServersResponse removeServers(RpcController controller, RemoveServersRequest request)
3311    throws ServiceException {
3312    RemoveServersResponse.Builder builder = RemoveServersResponse.newBuilder();
3313    Set<Address> servers = Sets.newHashSet();
3314    for (HBaseProtos.ServerName el : request.getServersList()) {
3315      servers.add(Address.fromParts(el.getHostName(), el.getPort()));
3316    }
3317    LOG.info(
3318      server.getClientIdAuditPrefix() + " remove decommissioned servers from rsgroup: " + servers);
3319    try {
3320      if (server.getMasterCoprocessorHost() != null) {
3321        server.getMasterCoprocessorHost().preRemoveServers(servers);
3322      }
3323      server.getRSGroupInfoManager().removeServers(servers);
3324      if (server.getMasterCoprocessorHost() != null) {
3325        server.getMasterCoprocessorHost().postRemoveServers(servers);
3326      }
3327    } catch (IOException e) {
3328      throw new ServiceException(e);
3329    }
3330    return builder.build();
3331  }
3332
3333  @Override
3334  public ListTablesInRSGroupResponse listTablesInRSGroup(RpcController controller,
3335    ListTablesInRSGroupRequest request) throws ServiceException {
3336    ListTablesInRSGroupResponse.Builder builder = ListTablesInRSGroupResponse.newBuilder();
3337    String groupName = request.getGroupName();
3338    LOG.info(server.getClientIdAuditPrefix() + " list tables in rsgroup " + groupName);
3339    try {
3340      if (server.getMasterCoprocessorHost() != null) {
3341        server.getMasterCoprocessorHost().preListTablesInRSGroup(groupName);
3342      }
3343      RSGroupUtil.listTablesInRSGroup(server, groupName).stream()
3344        .map(ProtobufUtil::toProtoTableName).forEach(builder::addTableName);
3345      if (server.getMasterCoprocessorHost() != null) {
3346        server.getMasterCoprocessorHost().postListTablesInRSGroup(groupName);
3347      }
3348    } catch (IOException e) {
3349      throw new ServiceException(e);
3350    }
3351    return builder.build();
3352  }
3353
3354  @Override
3355  public GetConfiguredNamespacesAndTablesInRSGroupResponse
3356    getConfiguredNamespacesAndTablesInRSGroup(RpcController controller,
3357      GetConfiguredNamespacesAndTablesInRSGroupRequest request) throws ServiceException {
3358    GetConfiguredNamespacesAndTablesInRSGroupResponse.Builder builder =
3359      GetConfiguredNamespacesAndTablesInRSGroupResponse.newBuilder();
3360    String groupName = request.getGroupName();
3361    LOG.info(server.getClientIdAuditPrefix() + " get configured namespaces and tables in rsgroup "
3362      + groupName);
3363    try {
3364      if (server.getMasterCoprocessorHost() != null) {
3365        server.getMasterCoprocessorHost().preGetConfiguredNamespacesAndTablesInRSGroup(groupName);
3366      }
3367      for (NamespaceDescriptor nd : server.getClusterSchema().getNamespaces()) {
3368        if (groupName.equals(nd.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP))) {
3369          builder.addNamespace(nd.getName());
3370        }
3371      }
3372      for (TableDescriptor td : server.getTableDescriptors().getAll().values()) {
3373        if (td.getRegionServerGroup().map(g -> g.equals(groupName)).orElse(false)) {
3374          builder.addTableName(ProtobufUtil.toProtoTableName(td.getTableName()));
3375        }
3376      }
3377      if (server.getMasterCoprocessorHost() != null) {
3378        server.getMasterCoprocessorHost().postGetConfiguredNamespacesAndTablesInRSGroup(groupName);
3379      }
3380    } catch (IOException e) {
3381      throw new ServiceException(e);
3382    }
3383    return builder.build();
3384  }
3385
3386  @Override
3387  public RenameRSGroupResponse renameRSGroup(RpcController controller, RenameRSGroupRequest request)
3388    throws ServiceException {
3389    RenameRSGroupResponse.Builder builder = RenameRSGroupResponse.newBuilder();
3390    String oldRSGroup = request.getOldRsgroupName();
3391    String newRSGroup = request.getNewRsgroupName();
3392    LOG.info("{} rename rsgroup from {} to {} ", server.getClientIdAuditPrefix(), oldRSGroup,
3393      newRSGroup);
3394    try {
3395      if (server.getMasterCoprocessorHost() != null) {
3396        server.getMasterCoprocessorHost().preRenameRSGroup(oldRSGroup, newRSGroup);
3397      }
3398      server.getRSGroupInfoManager().renameRSGroup(oldRSGroup, newRSGroup);
3399      if (server.getMasterCoprocessorHost() != null) {
3400        server.getMasterCoprocessorHost().postRenameRSGroup(oldRSGroup, newRSGroup);
3401      }
3402    } catch (IOException e) {
3403      throw new ServiceException(e);
3404    }
3405    return builder.build();
3406  }
3407
3408  @Override
3409  public UpdateRSGroupConfigResponse updateRSGroupConfig(RpcController controller,
3410    UpdateRSGroupConfigRequest request) throws ServiceException {
3411    UpdateRSGroupConfigResponse.Builder builder = UpdateRSGroupConfigResponse.newBuilder();
3412    String groupName = request.getGroupName();
3413    Map<String, String> configuration = new HashMap<>();
3414    request.getConfigurationList().forEach(p -> configuration.put(p.getName(), p.getValue()));
3415    LOG.info("{} update rsgroup {} configuration {}", server.getClientIdAuditPrefix(), groupName,
3416      configuration);
3417    try {
3418      if (server.getMasterCoprocessorHost() != null) {
3419        server.getMasterCoprocessorHost().preUpdateRSGroupConfig(groupName, configuration);
3420      }
3421      server.getRSGroupInfoManager().updateRSGroupConfig(groupName, configuration);
3422      if (server.getMasterCoprocessorHost() != null) {
3423        server.getMasterCoprocessorHost().postUpdateRSGroupConfig(groupName, configuration);
3424      }
3425    } catch (IOException e) {
3426      throw new ServiceException(e);
3427    }
3428    return builder.build();
3429  }
3430
3431  @Override
3432  public HBaseProtos.LogEntry getLogEntries(RpcController controller,
3433    HBaseProtos.LogRequest request) throws ServiceException {
3434    try {
3435      final String logClassName = request.getLogClassName();
3436      Class<?> logClass = Class.forName(logClassName).asSubclass(Message.class);
3437      Method method = logClass.getMethod("parseFrom", ByteString.class);
3438      if (logClassName.contains("BalancerDecisionsRequest")) {
3439        MasterProtos.BalancerDecisionsRequest balancerDecisionsRequest =
3440          (MasterProtos.BalancerDecisionsRequest) method.invoke(null, request.getLogMessage());
3441        MasterProtos.BalancerDecisionsResponse balancerDecisionsResponse =
3442          getBalancerDecisions(balancerDecisionsRequest);
3443        return HBaseProtos.LogEntry.newBuilder()
3444          .setLogClassName(balancerDecisionsResponse.getClass().getName())
3445          .setLogMessage(balancerDecisionsResponse.toByteString()).build();
3446      } else if (logClassName.contains("BalancerRejectionsRequest")) {
3447        MasterProtos.BalancerRejectionsRequest balancerRejectionsRequest =
3448          (MasterProtos.BalancerRejectionsRequest) method.invoke(null, request.getLogMessage());
3449        MasterProtos.BalancerRejectionsResponse balancerRejectionsResponse =
3450          getBalancerRejections(balancerRejectionsRequest);
3451        return HBaseProtos.LogEntry.newBuilder()
3452          .setLogClassName(balancerRejectionsResponse.getClass().getName())
3453          .setLogMessage(balancerRejectionsResponse.toByteString()).build();
3454      }
3455    } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
3456      | InvocationTargetException e) {
3457      LOG.error("Error while retrieving log entries.", e);
3458      throw new ServiceException(e);
3459    }
3460    throw new ServiceException("Invalid request params");
3461  }
3462
3463  private MasterProtos.BalancerDecisionsResponse
3464    getBalancerDecisions(MasterProtos.BalancerDecisionsRequest request) {
3465    final NamedQueueRecorder namedQueueRecorder = this.server.getNamedQueueRecorder();
3466    if (namedQueueRecorder == null) {
3467      return MasterProtos.BalancerDecisionsResponse.newBuilder()
3468        .addAllBalancerDecision(Collections.emptyList()).build();
3469    }
3470    final NamedQueueGetRequest namedQueueGetRequest = new NamedQueueGetRequest();
3471    namedQueueGetRequest.setNamedQueueEvent(BalancerDecisionDetails.BALANCER_DECISION_EVENT);
3472    namedQueueGetRequest.setBalancerDecisionsRequest(request);
3473    NamedQueueGetResponse namedQueueGetResponse =
3474      namedQueueRecorder.getNamedQueueRecords(namedQueueGetRequest);
3475    List<RecentLogs.BalancerDecision> balancerDecisions = namedQueueGetResponse != null
3476      ? namedQueueGetResponse.getBalancerDecisions()
3477      : Collections.emptyList();
3478    return MasterProtos.BalancerDecisionsResponse.newBuilder()
3479      .addAllBalancerDecision(balancerDecisions).build();
3480  }
3481
3482  private MasterProtos.BalancerRejectionsResponse
3483    getBalancerRejections(MasterProtos.BalancerRejectionsRequest request) {
3484    final NamedQueueRecorder namedQueueRecorder = this.server.getNamedQueueRecorder();
3485    if (namedQueueRecorder == null) {
3486      return MasterProtos.BalancerRejectionsResponse.newBuilder()
3487        .addAllBalancerRejection(Collections.emptyList()).build();
3488    }
3489    final NamedQueueGetRequest namedQueueGetRequest = new NamedQueueGetRequest();
3490    namedQueueGetRequest.setNamedQueueEvent(BalancerRejectionDetails.BALANCER_REJECTION_EVENT);
3491    namedQueueGetRequest.setBalancerRejectionsRequest(request);
3492    NamedQueueGetResponse namedQueueGetResponse =
3493      namedQueueRecorder.getNamedQueueRecords(namedQueueGetRequest);
3494    List<RecentLogs.BalancerRejection> balancerRejections = namedQueueGetResponse != null
3495      ? namedQueueGetResponse.getBalancerRejections()
3496      : Collections.emptyList();
3497    return MasterProtos.BalancerRejectionsResponse.newBuilder()
3498      .addAllBalancerRejection(balancerRejections).build();
3499  }
3500
3501  @Override
3502  @QosPriority(priority = HConstants.ADMIN_QOS)
3503  public GetRegionInfoResponse getRegionInfo(final RpcController controller,
3504    final GetRegionInfoRequest request) throws ServiceException {
3505    final GetRegionInfoResponse.Builder builder = GetRegionInfoResponse.newBuilder();
3506    final RegionInfo info = getRegionInfo(request.getRegion());
3507    if (info != null) {
3508      builder.setRegionInfo(ProtobufUtil.toRegionInfo(info));
3509    } else {
3510      // Is it a MOB name? These work differently.
3511      byte[] regionName = request.getRegion().getValue().toByteArray();
3512      TableName tableName = RegionInfo.getTable(regionName);
3513      if (MobUtils.isMobRegionName(tableName, regionName)) {
3514        // a dummy region info contains the compaction state.
3515        RegionInfo mobRegionInfo = MobUtils.getMobRegionInfo(tableName);
3516        builder.setRegionInfo(ProtobufUtil.toRegionInfo(mobRegionInfo));
3517        if (request.hasCompactionState() && request.getCompactionState()) {
3518          builder.setCompactionState(server.getMobCompactionState(tableName));
3519        }
3520      } else {
3521        // If unknown RegionInfo and not a MOB region, it is unknown.
3522        throw new ServiceException(new UnknownRegionException(Bytes.toString(regionName)));
3523      }
3524    }
3525    return builder.build();
3526  }
3527
3528  @Override
3529  public GetStoreFileResponse getStoreFile(RpcController controller, GetStoreFileRequest request)
3530    throws ServiceException {
3531    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3532  }
3533
3534  @Override
3535  public GetOnlineRegionResponse getOnlineRegion(RpcController controller,
3536    GetOnlineRegionRequest request) throws ServiceException {
3537    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3538  }
3539
3540  @Override
3541  public OpenRegionResponse openRegion(RpcController controller, OpenRegionRequest request)
3542    throws ServiceException {
3543    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3544  }
3545
3546  @Override
3547  public WarmupRegionResponse warmupRegion(RpcController controller, WarmupRegionRequest request)
3548    throws ServiceException {
3549    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3550  }
3551
3552  @Override
3553  public CloseRegionResponse closeRegion(RpcController controller, CloseRegionRequest request)
3554    throws ServiceException {
3555    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3556  }
3557
3558  @Override
3559  public FlushRegionResponse flushRegion(RpcController controller, FlushRegionRequest request)
3560    throws ServiceException {
3561    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3562  }
3563
3564  @Override
3565  public CompactionSwitchResponse compactionSwitch(RpcController controller,
3566    CompactionSwitchRequest request) throws ServiceException {
3567    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3568  }
3569
3570  @Override
3571  public CompactRegionResponse compactRegion(RpcController controller, CompactRegionRequest request)
3572    throws ServiceException {
3573    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3574  }
3575
3576  @Override
3577  public ReplicateWALEntryResponse replicateWALEntry(RpcController controller,
3578    ReplicateWALEntryRequest request) throws ServiceException {
3579    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3580  }
3581
3582  @Override
3583  public ReplicateWALEntryResponse replay(RpcController controller,
3584    ReplicateWALEntryRequest request) throws ServiceException {
3585    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3586  }
3587
3588  @Override
3589  public RollWALWriterResponse rollWALWriter(RpcController controller, RollWALWriterRequest request)
3590    throws ServiceException {
3591    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3592  }
3593
3594  @Override
3595  public GetServerInfoResponse getServerInfo(RpcController controller, GetServerInfoRequest request)
3596    throws ServiceException {
3597    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3598  }
3599
3600  @Override
3601  public StopServerResponse stopServer(RpcController controller, StopServerRequest request)
3602    throws ServiceException {
3603    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3604  }
3605
3606  @Override
3607  public UpdateFavoredNodesResponse updateFavoredNodes(RpcController controller,
3608    UpdateFavoredNodesRequest request) throws ServiceException {
3609    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3610  }
3611
3612  @Override
3613  public GetRegionLoadResponse getRegionLoad(RpcController controller, GetRegionLoadRequest request)
3614    throws ServiceException {
3615    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3616  }
3617
3618  @Override
3619  public ClearCompactionQueuesResponse clearCompactionQueues(RpcController controller,
3620    ClearCompactionQueuesRequest request) throws ServiceException {
3621    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3622  }
3623
3624  @Override
3625  public ClearRegionBlockCacheResponse clearRegionBlockCache(RpcController controller,
3626    ClearRegionBlockCacheRequest request) throws ServiceException {
3627    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3628  }
3629
3630  @Override
3631  public GetSpaceQuotaSnapshotsResponse getSpaceQuotaSnapshots(RpcController controller,
3632    GetSpaceQuotaSnapshotsRequest request) throws ServiceException {
3633    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3634  }
3635
3636  @Override
3637  public ExecuteProceduresResponse executeProcedures(RpcController controller,
3638    ExecuteProceduresRequest request) throws ServiceException {
3639    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3640  }
3641
3642  @Override
3643  public GetCachedFilesListResponse getCachedFilesList(RpcController controller,
3644    GetCachedFilesListRequest request) throws ServiceException {
3645    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3646  }
3647
3648  @Override
3649  public GetLiveRegionServersResponse getLiveRegionServers(RpcController controller,
3650    GetLiveRegionServersRequest request) throws ServiceException {
3651    List<ServerName> regionServers = new ArrayList<>(server.getLiveRegionServers());
3652    Collections.shuffle(regionServers, ThreadLocalRandom.current());
3653    GetLiveRegionServersResponse.Builder builder =
3654      GetLiveRegionServersResponse.newBuilder().setTotal(regionServers.size());
3655    regionServers.stream().limit(request.getCount()).map(ProtobufUtil::toServerName)
3656      .forEach(builder::addServer);
3657    return builder.build();
3658  }
3659
3660  @Override
3661  public ReplicateWALEntryResponse replicateToReplica(RpcController controller,
3662    ReplicateWALEntryRequest request) throws ServiceException {
3663    throw new ServiceException(new DoNotRetryIOException("Unsupported method on master"));
3664  }
3665
3666  @Override
3667  public FlushMasterStoreResponse flushMasterStore(RpcController controller,
3668    FlushMasterStoreRequest request) throws ServiceException {
3669    rpcPreCheck("flushMasterStore");
3670    try {
3671      server.flushMasterStore();
3672    } catch (IOException ioe) {
3673      throw new ServiceException(ioe);
3674    }
3675    return FlushMasterStoreResponse.newBuilder().build();
3676  }
3677
3678  @Override
3679  public FlushTableResponse flushTable(RpcController controller, FlushTableRequest req)
3680    throws ServiceException {
3681    TableName tableName = ProtobufUtil.toTableName(req.getTableName());
3682    List<byte[]> columnFamilies = req.getColumnFamilyCount() > 0
3683      ? req.getColumnFamilyList().stream().filter(cf -> !cf.isEmpty()).map(ByteString::toByteArray)
3684        .collect(Collectors.toList())
3685      : null;
3686    try {
3687      long procId =
3688        server.flushTable(tableName, columnFamilies, req.getNonceGroup(), req.getNonce());
3689      return FlushTableResponse.newBuilder().setProcId(procId).build();
3690    } catch (IOException ioe) {
3691      throw new ServiceException(ioe);
3692    }
3693  }
3694
3695  @Override
3696  public RollAllWALWritersResponse rollAllWALWriters(RpcController rpcController,
3697    RollAllWALWritersRequest request) throws ServiceException {
3698    try {
3699      long procId = server.rollAllWALWriters(request.getNonceGroup(), request.getNonce());
3700      return RollAllWALWritersResponse.newBuilder().setProcId(procId).build();
3701    } catch (IOException ioe) {
3702      throw new ServiceException(ioe);
3703    }
3704  }
3705}