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