View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.master;
20  
21  import java.io.IOException;
22  import java.net.InetAddress;
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Set;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.hadoop.hbase.CoordinatedStateException;
31  import org.apache.hadoop.hbase.classification.InterfaceAudience;
32  import org.apache.hadoop.hbase.HColumnDescriptor;
33  import org.apache.hadoop.hbase.HConstants;
34  import org.apache.hadoop.hbase.HRegionInfo;
35  import org.apache.hadoop.hbase.HTableDescriptor;
36  import org.apache.hadoop.hbase.NamespaceDescriptor;
37  import org.apache.hadoop.hbase.PleaseHoldException;
38  import org.apache.hadoop.hbase.ProcedureInfo;
39  import org.apache.hadoop.hbase.ServerLoad;
40  import org.apache.hadoop.hbase.ServerName;
41  import org.apache.hadoop.hbase.TableName;
42  import org.apache.hadoop.hbase.UnknownRegionException;
43  import org.apache.hadoop.hbase.MetaTableAccessor;
44  import org.apache.hadoop.hbase.client.Admin;
45  import org.apache.hadoop.hbase.errorhandling.ForeignException;
46  import org.apache.hadoop.hbase.exceptions.MergeRegionException;
47  import org.apache.hadoop.hbase.exceptions.UnknownProtocolException;
48  import org.apache.hadoop.hbase.ipc.PriorityFunction;
49  import org.apache.hadoop.hbase.ipc.QosPriority;
50  import org.apache.hadoop.hbase.ipc.RpcServer;
51  import org.apache.hadoop.hbase.ipc.RpcServer.BlockingServiceAndInterface;
52  import org.apache.hadoop.hbase.ipc.ServerRpcController;
53  import org.apache.hadoop.hbase.procedure.MasterProcedureManager;
54  import org.apache.hadoop.hbase.procedure2.Procedure;
55  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
56  import org.apache.hadoop.hbase.protobuf.RequestConverter;
57  import org.apache.hadoop.hbase.protobuf.ResponseConverter;
58  import org.apache.hadoop.hbase.protobuf.generated.*;
59  import org.apache.hadoop.hbase.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;
60  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
61  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ProcedureDescription;
62  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
63  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
64  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureRequest;
65  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureResponse;
66  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AddColumnRequest;
67  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AddColumnResponse;
68  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
69  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionResponse;
70  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BalanceRequest;
71  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BalanceResponse;
72  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ClearDeadServersRequest;
73  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ClearDeadServersResponse;
74  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateNamespaceRequest;
75  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateNamespaceResponse;
76  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
77  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableResponse;
78  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteColumnRequest;
79  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteColumnResponse;
80  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteNamespaceRequest;
81  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteNamespaceResponse;
82  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteSnapshotRequest;
83  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteSnapshotResponse;
84  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteTableRequest;
85  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteTableResponse;
86  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DisableTableRequest;
87  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DisableTableResponse;
88  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
89  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsResponse;
90  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest;
91  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableCatalogJanitorResponse;
92  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableTableRequest;
93  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableTableResponse;
94  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ExecProcedureRequest;
95  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ExecProcedureResponse;
96  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetClusterStatusRequest;
97  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetClusterStatusResponse;
98  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetCompletedSnapshotsRequest;
99  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetCompletedSnapshotsResponse;
100 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest;
101 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetNamespaceDescriptorResponse;
102 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetProcedureResultRequest;
103 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetProcedureResultResponse;
104 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
105 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusResponse;
106 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
107 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
108 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest;
109 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesResponse;
110 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsBalancerEnabledRequest;
111 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsBalancerEnabledResponse;
112 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCleanerChoreEnabledRequest;
113 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCleanerChoreEnabledResponse;
114 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
115 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledResponse;
116 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsInMaintenanceModeRequest;
117 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsInMaintenanceModeResponse;
118 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsMasterRunningRequest;
119 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsMasterRunningResponse;
120 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsNormalizerEnabledRequest;
121 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsNormalizerEnabledResponse;
122 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsProcedureDoneRequest;
123 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsProcedureDoneResponse;
124 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsRestoreSnapshotDoneRequest;
125 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsRestoreSnapshotDoneResponse;
126 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
127 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
128 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest;
129 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListNamespaceDescriptorsResponse;
130 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresRequest;
131 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse;
132 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceRequest;
133 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceResponse;
134 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableNamesByNamespaceRequest;
135 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableNamesByNamespaceResponse;
136 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MajorCompactionTimestampForRegionRequest;
137 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MajorCompactionTimestampRequest;
138 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MajorCompactionTimestampResponse;
139 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MasterService;
140 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyColumnRequest;
141 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyColumnResponse;
142 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyNamespaceRequest;
143 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyNamespaceResponse;
144 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyTableRequest;
145 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyTableResponse;
146 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
147 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionResponse;
148 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.NormalizeRequest;
149 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.NormalizeResponse;
150 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.OfflineRegionRequest;
151 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.OfflineRegionResponse;
152 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
153 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
154 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
155 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanResponse;
156 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCleanerChoreRequest;
157 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCleanerChoreResponse;
158 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
159 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse;
160 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse.Capability;
161 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
162 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningResponse;
163 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest;
164 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetCleanerChoreRunningResponse;
165 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetNormalizerRunningRequest;
166 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetNormalizerRunningResponse;
167 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetQuotaRequest;
168 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetQuotaResponse;
169 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ShutdownRequest;
170 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ShutdownResponse;
171 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotRequest;
172 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotResponse;
173 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.StopMasterRequest;
174 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.StopMasterResponse;
175 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.TruncateTableRequest;
176 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.TruncateTableResponse;
177 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
178 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionResponse;
179 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdRequest;
180 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdResponse;
181 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest;
182 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerReportResponse;
183 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;
184 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerStartupResponse;
185 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerStatusService;
186 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionStateTransition;
187 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRSFatalErrorRequest;
188 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRSFatalErrorResponse;
189 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionRequest;
190 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRegionStateTransitionResponse;
191 import org.apache.hadoop.hbase.regionserver.RSRpcServices;
192 import org.apache.hadoop.hbase.security.User;
193 import org.apache.hadoop.hbase.security.access.AccessChecker;
194 import org.apache.hadoop.hbase.security.access.AccessController;
195 import org.apache.hadoop.hbase.security.visibility.VisibilityController;
196 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
197 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
198 import org.apache.hadoop.hbase.util.Bytes;
199 import org.apache.hadoop.hbase.util.ByteStringer;
200 import org.apache.hadoop.hbase.util.Pair;
201 import org.apache.zookeeper.KeeperException;
202 
203 import com.google.protobuf.ByteString;
204 import com.google.protobuf.Descriptors;
205 import com.google.protobuf.Message;
206 import com.google.protobuf.RpcCallback;
207 import com.google.protobuf.RpcController;
208 import com.google.protobuf.Service;
209 import com.google.protobuf.ServiceException;
210 
211 /**
212  * Implements the master RPC services.
213  */
214 @InterfaceAudience.Private
215 @SuppressWarnings("deprecation")
216 public class MasterRpcServices extends RSRpcServices
217     implements MasterService.BlockingInterface, RegionServerStatusService.BlockingInterface {
218   private static final Log LOG = LogFactory.getLog(MasterRpcServices.class.getName());
219 
220   private final HMaster master;
221 
222   /**
223    * @return Subset of configuration to pass initializing regionservers: e.g.
224    * the filesystem to use and root directory to use.
225    */
226   private RegionServerStartupResponse.Builder createConfigurationSubset() {
227     RegionServerStartupResponse.Builder resp = addConfig(
228       RegionServerStartupResponse.newBuilder(), HConstants.HBASE_DIR);
229     resp = addConfig(resp, "fs.defaultFS");
230     return addConfig(resp, "hbase.master.info.port");
231   }
232 
233   private RegionServerStartupResponse.Builder addConfig(
234       final RegionServerStartupResponse.Builder resp, final String key) {
235     NameStringPair.Builder entry = NameStringPair.newBuilder()
236       .setName(key)
237       .setValue(master.getConfiguration().get(key));
238     resp.addMapEntries(entry.build());
239     return resp;
240   }
241 
242   public MasterRpcServices(HMaster m) throws IOException {
243     super(m);
244     master = m;
245   }
246 
247   @Override
248   protected PriorityFunction createPriority() {
249     return new MasterAnnotationReadingPriorityFunction(this);
250   }
251 
252   enum BalanceSwitchMode {
253     SYNC,
254     ASYNC
255   }
256 
257   /**
258    * Assigns balancer switch according to BalanceSwitchMode
259    * @param b new balancer switch
260    * @param mode BalanceSwitchMode
261    * @return old balancer switch
262    */
263   boolean switchBalancer(final boolean b, BalanceSwitchMode mode) throws IOException {
264     boolean oldValue = master.loadBalancerTracker.isBalancerOn();
265     boolean newValue = b;
266     try {
267       if (master.cpHost != null) {
268         newValue = master.cpHost.preBalanceSwitch(newValue);
269       }
270       try {
271         if (mode == BalanceSwitchMode.SYNC) {
272           synchronized (master.balancer) {
273             master.loadBalancerTracker.setBalancerOn(newValue);
274           }
275         } else {
276           master.loadBalancerTracker.setBalancerOn(newValue);
277         }
278       } catch (KeeperException ke) {
279         throw new IOException(ke);
280       }
281       LOG.info(master.getClientIdAuditPrefix() + " set balanceSwitch=" + newValue);
282       if (master.cpHost != null) {
283         master.cpHost.postBalanceSwitch(oldValue, newValue);
284       }
285       master.getLoadBalancer().updateBalancerStatus(newValue);
286     } catch (IOException ioe) {
287       LOG.warn("Error flipping balance switch", ioe);
288     }
289     return oldValue;
290   }
291 
292   boolean synchronousBalanceSwitch(final boolean b) throws IOException {
293     return switchBalancer(b, BalanceSwitchMode.SYNC);
294   }
295 
296   /**
297    * Sets normalizer on/off flag in ZK.
298    */
299   public boolean normalizerSwitch(boolean on) {
300     boolean oldValue = master.getRegionNormalizerTracker().isNormalizerOn();
301     boolean newValue = on;
302     try {
303       try {
304         master.getRegionNormalizerTracker().setNormalizerOn(newValue);
305       } catch (KeeperException ke) {
306         throw new IOException(ke);
307       }
308       LOG.info(master.getClientIdAuditPrefix() + " set normalizerSwitch=" + newValue);
309     } catch (IOException ioe) {
310       LOG.warn("Error flipping normalizer switch", ioe);
311     }
312     return oldValue;
313   }
314 
315   /**
316    * @return list of blocking services and their security info classes that this server supports
317    */
318   @Override
319   protected List<BlockingServiceAndInterface> getServices() {
320     List<BlockingServiceAndInterface> bssi = new ArrayList<BlockingServiceAndInterface>(4);
321     bssi.add(new BlockingServiceAndInterface(
322       MasterService.newReflectiveBlockingService(this),
323       MasterService.BlockingInterface.class));
324     bssi.add(new BlockingServiceAndInterface(
325       RegionServerStatusService.newReflectiveBlockingService(this),
326       RegionServerStatusService.BlockingInterface.class));
327     bssi.addAll(super.getServices());
328     return bssi;
329   }
330 
331   @Override
332   @QosPriority(priority = HConstants.ADMIN_QOS)
333   public GetLastFlushedSequenceIdResponse getLastFlushedSequenceId(RpcController controller,
334       GetLastFlushedSequenceIdRequest request) throws ServiceException {
335     try {
336       master.checkServiceStarted();
337     } catch (IOException ioe) {
338       throw new ServiceException(ioe);
339     }
340     byte[] encodedRegionName = request.getRegionName().toByteArray();
341     RegionStoreSequenceIds ids = master.serverManager.getLastFlushedSequenceId(encodedRegionName);
342     return ResponseConverter.buildGetLastFlushedSequenceIdResponse(ids);
343   }
344 
345   @Override
346   public RegionServerReportResponse regionServerReport(
347       RpcController controller, RegionServerReportRequest request) throws ServiceException {
348     try {
349       master.checkServiceStarted();
350       ClusterStatusProtos.ServerLoad sl = request.getLoad();
351       ServerName serverName = ProtobufUtil.toServerName(request.getServer());
352       ServerLoad oldLoad = master.serverManager.getLoad(serverName);
353       master.serverManager.regionServerReport(serverName, new ServerLoad(sl));
354       if (sl != null && master.metricsMaster != null) {
355         // Up our metrics.
356         master.metricsMaster.incrementRequests(sl.getTotalNumberOfRequests()
357             - (oldLoad != null ? oldLoad.getTotalNumberOfRequests() : 0));
358       }
359     } catch (IOException ioe) {
360       throw new ServiceException(ioe);
361     }
362     return RegionServerReportResponse.newBuilder().build();
363   }
364 
365   @Override
366   public RegionServerStartupResponse regionServerStartup(
367       RpcController controller, RegionServerStartupRequest request) throws ServiceException {
368     // Register with server manager
369     try {
370       master.checkServiceStarted();
371       InetAddress ia = master.getRemoteInetAddress(
372         request.getPort(), request.getServerStartCode());
373       // if regionserver passed hostname to use,
374       // then use it instead of doing a reverse DNS lookup
375       ServerName rs = master.serverManager.regionServerStartup(request, ia);
376 
377       // Send back some config info
378       RegionServerStartupResponse.Builder resp = createConfigurationSubset();
379       NameStringPair.Builder entry = NameStringPair.newBuilder()
380         .setName(HConstants.KEY_FOR_HOSTNAME_SEEN_BY_MASTER)
381         .setValue(rs.getHostname());
382       resp.addMapEntries(entry.build());
383 
384       return resp.build();
385     } catch (IOException ioe) {
386       throw new ServiceException(ioe);
387     }
388   }
389 
390   @Override
391   public ReportRSFatalErrorResponse reportRSFatalError(
392       RpcController controller, ReportRSFatalErrorRequest request) throws ServiceException {
393     String errorText = request.getErrorMessage();
394     ServerName sn = ProtobufUtil.toServerName(request.getServer());
395     String msg = "Region server " + sn
396       + " reported a fatal error:\n" + errorText;
397     LOG.error(msg);
398     master.rsFatals.add(msg);
399     return ReportRSFatalErrorResponse.newBuilder().build();
400   }
401 
402   @Override
403   public AddColumnResponse addColumn(RpcController controller,
404       AddColumnRequest req) throws ServiceException {
405     try {
406       master.addColumn(
407           ProtobufUtil.toTableName(req.getTableName()),
408           HColumnDescriptor.convert(req.getColumnFamilies()),
409           req.getNonceGroup(),
410           req.getNonce());
411     } catch (IOException ioe) {
412       throw new ServiceException(ioe);
413     }
414     return AddColumnResponse.newBuilder().build();
415   }
416 
417   @Override
418   public AssignRegionResponse assignRegion(RpcController controller,
419       AssignRegionRequest req) throws ServiceException {
420     try {
421       final byte [] regionName = req.getRegion().getValue().toByteArray();
422       RegionSpecifierType type = req.getRegion().getType();
423       AssignRegionResponse arr = AssignRegionResponse.newBuilder().build();
424 
425       master.checkInitialized();
426       if (type != RegionSpecifierType.REGION_NAME) {
427         LOG.warn("assignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
428           + " actual: " + type);
429       }
430       RegionStates regionStates = master.assignmentManager.getRegionStates();
431       HRegionInfo regionInfo = regionStates.getRegionInfo(regionName);
432       if (regionInfo == null) throw new UnknownRegionException(Bytes.toString(regionName));
433       if (master.cpHost != null) {
434         if (master.cpHost.preAssign(regionInfo)) {
435           return arr;
436         }
437       }
438       LOG.info(master.getClientIdAuditPrefix()
439         + " assign " + regionInfo.getRegionNameAsString());
440       master.assignmentManager.assign(regionInfo, true, true);
441       if (master.cpHost != null) {
442         master.cpHost.postAssign(regionInfo);
443       }
444       return arr;
445     } catch (IOException ioe) {
446       throw new ServiceException(ioe);
447     }
448   }
449 
450   @Override
451   public BalanceResponse balance(RpcController controller,
452       BalanceRequest request) throws ServiceException {
453     try {
454       return BalanceResponse.newBuilder().setBalancerRan(master.balance(
455         request.hasForce() ? request.getForce() : false)).build();
456     } catch (IOException ex) {
457       throw new ServiceException(ex);
458     }
459   }
460 
461   @Override
462   public CreateNamespaceResponse createNamespace(RpcController controller,
463      CreateNamespaceRequest request) throws ServiceException {
464     try {
465       master.createNamespace(
466         ProtobufUtil.toNamespaceDescriptor(request.getNamespaceDescriptor()),
467         request.getNonceGroup(),
468         request.getNonce());
469       return CreateNamespaceResponse.getDefaultInstance();
470     } catch (IOException e) {
471       throw new ServiceException(e);
472     }
473   }
474 
475   @Override
476   public CreateTableResponse createTable(RpcController controller, CreateTableRequest req)
477   throws ServiceException {
478     HTableDescriptor hTableDescriptor = HTableDescriptor.convert(req.getTableSchema());
479     byte [][] splitKeys = ProtobufUtil.getSplitKeysArray(req);
480     try {
481       long procId =
482           master.createTable(hTableDescriptor, splitKeys, req.getNonceGroup(), req.getNonce());
483       return CreateTableResponse.newBuilder().setProcId(procId).build();
484     } catch (IOException ioe) {
485       throw new ServiceException(ioe);
486     }
487   }
488 
489   @Override
490   public DeleteColumnResponse deleteColumn(RpcController controller,
491       DeleteColumnRequest req) throws ServiceException {
492     try {
493       master.deleteColumn(
494         ProtobufUtil.toTableName(req.getTableName()),
495         req.getColumnName().toByteArray(),
496         req.getNonceGroup(),
497         req.getNonce());
498     } catch (IOException ioe) {
499       throw new ServiceException(ioe);
500     }
501     return DeleteColumnResponse.newBuilder().build();
502   }
503 
504   @Override
505   public DeleteNamespaceResponse deleteNamespace(RpcController controller,
506       DeleteNamespaceRequest request) throws ServiceException {
507     try {
508       master.deleteNamespace(
509         request.getNamespaceName(),
510         request.getNonceGroup(),
511         request.getNonce());
512       return DeleteNamespaceResponse.getDefaultInstance();
513     } catch (IOException e) {
514       throw new ServiceException(e);
515     }
516   }
517 
518   /**
519    * Execute Delete Snapshot operation.
520    * @return DeleteSnapshotResponse (a protobuf wrapped void) if the snapshot existed and was
521    *    deleted properly.
522    * @throws ServiceException wrapping SnapshotDoesNotExistException if specified snapshot did not
523    *    exist.
524    */
525   @Override
526   public DeleteSnapshotResponse deleteSnapshot(RpcController controller,
527       DeleteSnapshotRequest request) throws ServiceException {
528     try {
529       master.checkInitialized();
530       master.snapshotManager.checkSnapshotSupport();
531 
532       LOG.info(master.getClientIdAuditPrefix() + " delete " + request.getSnapshot());
533       master.snapshotManager.deleteSnapshot(request.getSnapshot());
534       return DeleteSnapshotResponse.newBuilder().build();
535     } catch (IOException e) {
536       throw new ServiceException(e);
537     }
538   }
539 
540   @Override
541   public DeleteTableResponse deleteTable(RpcController controller,
542       DeleteTableRequest request) throws ServiceException {
543     try {
544       long procId = master.deleteTable(ProtobufUtil.toTableName(
545           request.getTableName()), request.getNonceGroup(), request.getNonce());
546       return DeleteTableResponse.newBuilder().setProcId(procId).build();
547     } catch (IOException ioe) {
548       throw new ServiceException(ioe);
549     }
550   }
551 
552   @Override
553   public TruncateTableResponse truncateTable(RpcController controller, TruncateTableRequest request)
554       throws ServiceException {
555     try {
556       master.truncateTable(
557         ProtobufUtil.toTableName(request.getTableName()),
558         request.getPreserveSplits(),
559         request.getNonceGroup(),
560         request.getNonce());
561     } catch (IOException ioe) {
562       throw new ServiceException(ioe);
563     }
564     return TruncateTableResponse.newBuilder().build();
565   }
566 
567   @Override
568   public DisableTableResponse disableTable(RpcController controller,
569       DisableTableRequest request) throws ServiceException {
570     try {
571       long procId = master.disableTable(
572         ProtobufUtil.toTableName(request.getTableName()),
573         request.getNonceGroup(),
574         request.getNonce());
575       return DisableTableResponse.newBuilder().setProcId(procId).build();
576     } catch (IOException ioe) {
577       throw new ServiceException(ioe);
578     }
579   }
580 
581   @Override
582   public DispatchMergingRegionsResponse dispatchMergingRegions(RpcController c,
583       DispatchMergingRegionsRequest request) throws ServiceException {
584     try {
585       master.checkInitialized();
586     } catch (IOException ioe) {
587       throw new ServiceException(ioe);
588     }
589 
590     final byte[] encodedNameOfRegionA = request.getRegionA().getValue()
591       .toByteArray();
592     final byte[] encodedNameOfRegionB = request.getRegionB().getValue()
593       .toByteArray();
594     final boolean forcible = request.getForcible();
595     if (request.getRegionA().getType() != RegionSpecifierType.ENCODED_REGION_NAME
596         || request.getRegionB().getType() != RegionSpecifierType.ENCODED_REGION_NAME) {
597       LOG.warn("mergeRegions specifier type: expected: "
598         + RegionSpecifierType.ENCODED_REGION_NAME + " actual: region_a="
599         + request.getRegionA().getType() + ", region_b="
600         + request.getRegionB().getType());
601     }
602     RegionStates regionStates = master.assignmentManager.getRegionStates();
603     RegionState regionStateA = regionStates.getRegionState(Bytes.toString(encodedNameOfRegionA));
604     RegionState regionStateB = regionStates.getRegionState(Bytes.toString(encodedNameOfRegionB));
605     if (regionStateA == null || regionStateB == null) {
606       throw new ServiceException(new UnknownRegionException(
607           Bytes.toStringBinary(regionStateA == null ? encodedNameOfRegionA
608               : encodedNameOfRegionB)));
609     }
610 
611     if (!regionStateA.isOpened() || !regionStateB.isOpened()) {
612       throw new ServiceException(new MergeRegionException(
613         "Unable to merge regions not online " + regionStateA + ", " + regionStateB));
614     }
615 
616     final HRegionInfo regionInfoA = regionStateA.getRegion();
617     final HRegionInfo regionInfoB = regionStateB.getRegion();
618     if (regionInfoA.getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID ||
619         regionInfoB.getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID) {
620       throw new ServiceException(new MergeRegionException("Can't merge non-default replicas"));
621     }
622     if (regionInfoA.compareTo(regionInfoB) == 0) {
623       throw new ServiceException(new MergeRegionException(
624         "Unable to merge a region to itself " + regionInfoA + ", " + regionInfoB));
625     }
626     try {
627       master.cpHost.preDispatchMerge(regionInfoA, regionInfoB);
628     } catch (IOException ioe) {
629       throw new ServiceException(ioe);
630     }
631 
632     if (!forcible && !HRegionInfo.areAdjacent(regionInfoA, regionInfoB)) {
633       throw new ServiceException(new MergeRegionException(
634         "Unable to merge not adjacent regions "
635           + regionInfoA.getRegionNameAsString() + ", "
636           + regionInfoB.getRegionNameAsString()
637           + " where forcible = " + forcible));
638     }
639 
640     try {
641       master.dispatchMergingRegions(regionInfoA, regionInfoB, forcible, RpcServer.getRequestUser());
642       master.cpHost.postDispatchMerge(regionInfoA, regionInfoB);
643     } catch (IOException ioe) {
644       throw new ServiceException(ioe);
645     }
646 
647     return DispatchMergingRegionsResponse.newBuilder().build();
648   }
649 
650   @Override
651   public EnableCatalogJanitorResponse enableCatalogJanitor(RpcController c,
652       EnableCatalogJanitorRequest req) throws ServiceException {
653     try {
654       master.checkInitialized();
655     } catch (IOException ioe) {
656       throw new ServiceException(ioe);
657     }
658     return EnableCatalogJanitorResponse.newBuilder().setPrevValue(
659       master.catalogJanitorChore.setEnabled(req.getEnable())).build();
660   }
661 
662   @Override
663   public SetCleanerChoreRunningResponse setCleanerChoreRunning(RpcController c,
664       SetCleanerChoreRunningRequest req) throws ServiceException {
665     try {
666       master.checkInitialized();
667     } catch (IOException ioe) {
668       throw new ServiceException(ioe);
669     }
670     boolean prevValue =
671       master.getLogCleaner().getEnabled() && master.getHFileCleaner().getEnabled();
672     master.getLogCleaner().setEnabled(req.getOn());
673     master.getHFileCleaner().setEnabled(req.getOn());
674     return SetCleanerChoreRunningResponse.newBuilder().setPrevValue(prevValue).build();
675   }
676 
677   @Override
678   public EnableTableResponse enableTable(RpcController controller,
679       EnableTableRequest request) throws ServiceException {
680     try {
681       long procId = master.enableTable(
682         ProtobufUtil.toTableName(request.getTableName()),
683         request.getNonceGroup(),
684         request.getNonce());
685       return EnableTableResponse.newBuilder().setProcId(procId).build();
686     } catch (IOException ioe) {
687       throw new ServiceException(ioe);
688     }
689   }
690 
691   @Override
692   public ClientProtos.CoprocessorServiceResponse execMasterService(final RpcController controller,
693       final ClientProtos.CoprocessorServiceRequest request) throws ServiceException {
694     try {
695       master.checkInitialized();
696       ServerRpcController execController = new ServerRpcController();
697 
698       ClientProtos.CoprocessorServiceCall call = request.getCall();
699       String serviceName = call.getServiceName();
700       String methodName = call.getMethodName();
701       if (!master.coprocessorServiceHandlers.containsKey(serviceName)) {
702         throw new UnknownProtocolException(null,
703           "No registered master coprocessor service found for name "+serviceName);
704       }
705 
706       Service service = master.coprocessorServiceHandlers.get(serviceName);
707       Descriptors.ServiceDescriptor serviceDesc = service.getDescriptorForType();
708       Descriptors.MethodDescriptor methodDesc = serviceDesc.findMethodByName(methodName);
709       if (methodDesc == null) {
710         throw new UnknownProtocolException(service.getClass(),
711           "Unknown method "+methodName+" called on master service "+serviceName);
712       }
713 
714       //invoke the method
715       Message.Builder builderForType = service.getRequestPrototype(methodDesc).newBuilderForType();
716       ProtobufUtil.mergeFrom(builderForType, call.getRequest());
717       Message execRequest = builderForType.build();
718       final Message.Builder responseBuilder =
719           service.getResponsePrototype(methodDesc).newBuilderForType();
720       service.callMethod(methodDesc, execController, execRequest, new RpcCallback<Message>() {
721         @Override
722         public void run(Message message) {
723           if (message != null) {
724             responseBuilder.mergeFrom(message);
725           }
726         }
727       });
728       Message execResult = responseBuilder.build();
729 
730       if (execController.getFailedOn() != null) {
731         throw execController.getFailedOn();
732       }
733       ClientProtos.CoprocessorServiceResponse.Builder builder =
734         ClientProtos.CoprocessorServiceResponse.newBuilder();
735       builder.setRegion(RequestConverter.buildRegionSpecifier(
736         RegionSpecifierType.REGION_NAME, HConstants.EMPTY_BYTE_ARRAY));
737       builder.setValue(
738         builder.getValueBuilder().setName(execResult.getClass().getName())
739           .setValue(execResult.toByteString()));
740       return builder.build();
741     } catch (IOException ie) {
742       throw new ServiceException(ie);
743     }
744   }
745 
746   /**
747    * Triggers an asynchronous attempt to run a distributed procedure.
748    * {@inheritDoc}
749    */
750   @Override
751   public ExecProcedureResponse execProcedure(RpcController controller,
752       ExecProcedureRequest request) throws ServiceException {
753     try {
754       master.checkInitialized();
755       ProcedureDescription desc = request.getProcedure();
756       MasterProcedureManager mpm = master.getMasterProcedureManagerHost().getProcedureManager(
757         desc.getSignature());
758       if (mpm == null) {
759         throw new ServiceException("The procedure is not registered: "
760           + desc.getSignature());
761       }
762 
763       LOG.info(master.getClientIdAuditPrefix() + " procedure request for: "
764         + desc.getSignature());
765 
766       mpm.execProcedure(desc);
767 
768       // send back the max amount of time the client should wait for the procedure
769       // to complete
770       long waitTime = SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME;
771       return ExecProcedureResponse.newBuilder().setExpectedTimeout(
772         waitTime).build();
773     } catch (ForeignException e) {
774       throw new ServiceException(e.getCause());
775     } catch (IOException e) {
776       throw new ServiceException(e);
777     }
778   }
779 
780   /**
781    * Triggers a synchronous attempt to run a distributed procedure and sets
782    * return data in response.
783    * {@inheritDoc}
784    */
785   @Override
786   public ExecProcedureResponse execProcedureWithRet(RpcController controller,
787       ExecProcedureRequest request) throws ServiceException {
788     try {
789       master.checkInitialized();
790       ProcedureDescription desc = request.getProcedure();
791       MasterProcedureManager mpm = master.getMasterProcedureManagerHost().getProcedureManager(
792         desc.getSignature());
793       if (mpm == null) {
794         throw new ServiceException("The procedure is not registered: "
795           + desc.getSignature());
796       }
797 
798       LOG.info(master.getClientIdAuditPrefix() + " procedure request for: "
799         + desc.getSignature());
800 
801       byte[] data = mpm.execProcedureWithRet(desc);
802 
803       ExecProcedureResponse.Builder builder = ExecProcedureResponse.newBuilder();
804       // set return data if available
805       if (data != null) {
806         builder.setReturnData(ByteString.copyFrom(data));
807       }
808       return builder.build();
809     } catch (IOException e) {
810       throw new ServiceException(e);
811     }
812   }
813 
814   @Override
815   public GetClusterStatusResponse getClusterStatus(RpcController controller,
816       GetClusterStatusRequest req) throws ServiceException {
817     GetClusterStatusResponse.Builder response = GetClusterStatusResponse.newBuilder();
818     try {
819       master.checkInitialized();
820       response.setClusterStatus(master.getClusterStatus().convert());
821     } catch (IOException e) {
822       throw new ServiceException(e);
823     }
824     return response.build();
825   }
826 
827   /**
828    * List the currently available/stored snapshots. Any in-progress snapshots are ignored
829    */
830   @Override
831   public GetCompletedSnapshotsResponse getCompletedSnapshots(RpcController controller,
832       GetCompletedSnapshotsRequest request) throws ServiceException {
833     try {
834       master.checkInitialized();
835       GetCompletedSnapshotsResponse.Builder builder = GetCompletedSnapshotsResponse.newBuilder();
836       List<SnapshotDescription> snapshots = master.snapshotManager.getCompletedSnapshots();
837 
838       // convert to protobuf
839       for (SnapshotDescription snapshot : snapshots) {
840         builder.addSnapshots(snapshot);
841       }
842       return builder.build();
843     } catch (IOException e) {
844       throw new ServiceException(e);
845     }
846   }
847 
848   @Override
849   public GetNamespaceDescriptorResponse getNamespaceDescriptor(
850       RpcController controller, GetNamespaceDescriptorRequest request)
851       throws ServiceException {
852     try {
853       return GetNamespaceDescriptorResponse.newBuilder()
854         .setNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(
855             master.getNamespaceDescriptor(request.getNamespaceName())))
856         .build();
857     } catch (IOException e) {
858       throw new ServiceException(e);
859     }
860   }
861 
862   /**
863    * Get the number of regions of the table that have been updated by the alter.
864    *
865    * @return Pair indicating the number of regions updated Pair.getFirst is the
866    *         regions that are yet to be updated Pair.getSecond is the total number
867    *         of regions of the table
868    * @throws ServiceException
869    */
870   @Override
871   public GetSchemaAlterStatusResponse getSchemaAlterStatus(
872       RpcController controller, GetSchemaAlterStatusRequest req) throws ServiceException {
873     // TODO: currently, we query using the table name on the client side. this
874     // may overlap with other table operations or the table operation may
875     // have completed before querying this API. We need to refactor to a
876     // transaction system in the future to avoid these ambiguities.
877     TableName tableName = ProtobufUtil.toTableName(req.getTableName());
878 
879     try {
880       master.checkInitialized();
881       Pair<Integer,Integer> pair = master.assignmentManager.getReopenStatus(tableName);
882       GetSchemaAlterStatusResponse.Builder ret = GetSchemaAlterStatusResponse.newBuilder();
883       ret.setYetToUpdateRegions(pair.getFirst());
884       ret.setTotalRegions(pair.getSecond());
885       return ret.build();
886     } catch (IOException ioe) {
887       throw new ServiceException(ioe);
888     }
889   }
890 
891   /**
892    * Get list of TableDescriptors for requested tables.
893    * @param c Unused (set to null).
894    * @param req GetTableDescriptorsRequest that contains:
895    * - tableNames: requested tables, or if empty, all are requested
896    * @return GetTableDescriptorsResponse
897    * @throws ServiceException
898    */
899   @Override
900   public GetTableDescriptorsResponse getTableDescriptors(RpcController c,
901       GetTableDescriptorsRequest req) throws ServiceException {
902     try {
903       master.checkInitialized();
904 
905       final String regex = req.hasRegex() ? req.getRegex() : null;
906       final String namespace = req.hasNamespace() ? req.getNamespace() : null;
907       List<TableName> tableNameList = null;
908       if (req.getTableNamesCount() > 0) {
909         tableNameList = new ArrayList<TableName>(req.getTableNamesCount());
910         for (TableProtos.TableName tableNamePB: req.getTableNamesList()) {
911           tableNameList.add(ProtobufUtil.toTableName(tableNamePB));
912         }
913       }
914 
915       List<HTableDescriptor> descriptors = master.listTableDescriptors(namespace, regex,
916           tableNameList, req.getIncludeSysTables());
917 
918       GetTableDescriptorsResponse.Builder builder = GetTableDescriptorsResponse.newBuilder();
919       if (descriptors != null && descriptors.size() > 0) {
920         // Add the table descriptors to the response
921         for (HTableDescriptor htd: descriptors) {
922           builder.addTableSchema(htd.convert());
923         }
924       }
925       return builder.build();
926     } catch (IOException ioe) {
927       throw new ServiceException(ioe);
928     }
929   }
930 
931   /**
932    * Get list of userspace table names
933    * @param controller Unused (set to null).
934    * @param req GetTableNamesRequest
935    * @return GetTableNamesResponse
936    * @throws ServiceException
937    */
938   @Override
939   public GetTableNamesResponse getTableNames(RpcController controller,
940       GetTableNamesRequest req) throws ServiceException {
941     try {
942       master.checkInitialized();
943 
944       final String regex = req.hasRegex() ? req.getRegex() : null;
945       final String namespace = req.hasNamespace() ? req.getNamespace() : null;
946       List<TableName> tableNames = master.listTableNames(namespace, regex,
947           req.getIncludeSysTables());
948 
949       GetTableNamesResponse.Builder builder = GetTableNamesResponse.newBuilder();
950       if (tableNames != null && tableNames.size() > 0) {
951         // Add the table names to the response
952         for (TableName table: tableNames) {
953           builder.addTableNames(ProtobufUtil.toProtoTableName(table));
954         }
955       }
956       return builder.build();
957     } catch (IOException e) {
958       throw new ServiceException(e);
959     }
960   }
961 
962   @Override
963   public IsCatalogJanitorEnabledResponse isCatalogJanitorEnabled(RpcController c,
964       IsCatalogJanitorEnabledRequest req) throws ServiceException {
965     return IsCatalogJanitorEnabledResponse.newBuilder().setValue(
966       master.isCatalogJanitorEnabled()).build();
967   }
968 
969   @Override
970   public IsCleanerChoreEnabledResponse isCleanerChoreEnabled(RpcController c,
971       IsCleanerChoreEnabledRequest req) throws ServiceException {
972     return IsCleanerChoreEnabledResponse.newBuilder()
973         .setValue(master.isCleanerChoreEnabled()).build();
974   }
975 
976   @Override
977   public IsMasterRunningResponse isMasterRunning(RpcController c,
978       IsMasterRunningRequest req) throws ServiceException {
979     try {
980       master.checkServiceStarted();
981       return IsMasterRunningResponse.newBuilder().setIsMasterRunning(
982         !master.isStopped()).build();
983     } catch (IOException e) {
984       throw new ServiceException(e);
985     }
986   }
987 
988   /**
989    * Checks if the specified procedure is done.
990    * @return true if the procedure is done,
991    *   false if the procedure is in the process of completing
992    * @throws ServiceException if invalid procedure, or
993    *  a failed procedure with progress failure reason.
994    */
995   @Override
996   public IsProcedureDoneResponse isProcedureDone(RpcController controller,
997       IsProcedureDoneRequest request) throws ServiceException {
998     try {
999       master.checkInitialized();
1000       ProcedureDescription desc = request.getProcedure();
1001       MasterProcedureManager mpm = master.getMasterProcedureManagerHost().getProcedureManager(
1002         desc.getSignature());
1003       if (mpm == null) {
1004         throw new ServiceException("The procedure is not registered: "
1005           + desc.getSignature());
1006       }
1007       LOG.debug("Checking to see if procedure from request:"
1008         + desc.getSignature() + " is done");
1009 
1010       IsProcedureDoneResponse.Builder builder =
1011         IsProcedureDoneResponse.newBuilder();
1012       boolean done = mpm.isProcedureDone(desc);
1013       builder.setDone(done);
1014       return builder.build();
1015     } catch (ForeignException e) {
1016       throw new ServiceException(e.getCause());
1017     } catch (IOException e) {
1018       throw new ServiceException(e);
1019     }
1020   }
1021 
1022   /**
1023    * Returns the status of the requested snapshot restore/clone operation.
1024    * This method is not exposed to the user, it is just used internally by HBaseAdmin
1025    * to verify if the restore is completed.
1026    *
1027    * No exceptions are thrown if the restore is not running, the result will be "done".
1028    *
1029    * @return done <tt>true</tt> if the restore/clone operation is completed.
1030    * @throws ServiceException if the operation failed.
1031    */
1032   @Override
1033   public IsRestoreSnapshotDoneResponse isRestoreSnapshotDone(RpcController controller,
1034       IsRestoreSnapshotDoneRequest request) throws ServiceException {
1035     try {
1036       master.checkInitialized();
1037       SnapshotDescription snapshot = request.getSnapshot();
1038       IsRestoreSnapshotDoneResponse.Builder builder = IsRestoreSnapshotDoneResponse.newBuilder();
1039       boolean done = master.snapshotManager.isRestoreDone(snapshot);
1040       builder.setDone(done);
1041       return builder.build();
1042     } catch (ForeignException e) {
1043       throw new ServiceException(e.getCause());
1044     } catch (IOException e) {
1045       throw new ServiceException(e);
1046     }
1047   }
1048 
1049   /**
1050    * Checks if the specified snapshot is done.
1051    * @return true if the snapshot is in file system ready to use,
1052    *   false if the snapshot is in the process of completing
1053    * @throws ServiceException wrapping UnknownSnapshotException if invalid snapshot, or
1054    *  a wrapped HBaseSnapshotException with progress failure reason.
1055    */
1056   @Override
1057   public IsSnapshotDoneResponse isSnapshotDone(RpcController controller,
1058       IsSnapshotDoneRequest request) throws ServiceException {
1059     LOG.debug("Checking to see if snapshot from request:" +
1060       ClientSnapshotDescriptionUtils.toString(request.getSnapshot()) + " is done");
1061     try {
1062       master.checkInitialized();
1063       IsSnapshotDoneResponse.Builder builder = IsSnapshotDoneResponse.newBuilder();
1064       boolean done = master.snapshotManager.isSnapshotDone(request.getSnapshot());
1065       builder.setDone(done);
1066       return builder.build();
1067     } catch (ForeignException e) {
1068       throw new ServiceException(e.getCause());
1069     } catch (IOException e) {
1070       throw new ServiceException(e);
1071     }
1072   }
1073 
1074   @Override
1075   public GetProcedureResultResponse getProcedureResult(RpcController controller,
1076       GetProcedureResultRequest request) throws ServiceException {
1077     LOG.debug("Checking to see if procedure is done procId=" + request.getProcId());
1078     try {
1079       master.checkInitialized();
1080       GetProcedureResultResponse.Builder builder = GetProcedureResultResponse.newBuilder();
1081 
1082       Pair<ProcedureInfo, Procedure> v = master.getMasterProcedureExecutor()
1083           .getResultOrProcedure(request.getProcId());
1084       if (v.getFirst() != null) {
1085         ProcedureInfo result = v.getFirst();
1086         builder.setState(GetProcedureResultResponse.State.FINISHED);
1087         builder.setStartTime(result.getStartTime());
1088         builder.setLastUpdate(result.getLastUpdate());
1089         if (result.isFailed()) {
1090           builder.setException(result.getForeignExceptionMessage());
1091         }
1092         if (result.hasResultData()) {
1093           builder.setResult(ByteStringer.wrap(result.getResult()));
1094         }
1095         master.getMasterProcedureExecutor().removeResult(request.getProcId());
1096       } else {
1097         Procedure proc = v.getSecond();
1098         if (proc == null) {
1099           builder.setState(GetProcedureResultResponse.State.NOT_FOUND);
1100         } else {
1101           builder.setState(GetProcedureResultResponse.State.RUNNING);
1102           builder.setStartTime(proc.getStartTime());
1103           builder.setLastUpdate(proc.getLastUpdate());
1104         }
1105       }
1106       return builder.build();
1107     } catch (IOException e) {
1108       throw new ServiceException(e);
1109     }
1110   }
1111 
1112   @Override
1113   public AbortProcedureResponse abortProcedure(
1114       RpcController rpcController,
1115       AbortProcedureRequest request) throws ServiceException {
1116     try {
1117       AbortProcedureResponse.Builder response = AbortProcedureResponse.newBuilder();
1118       boolean abortResult =
1119           master.abortProcedure(request.getProcId(), request.getMayInterruptIfRunning());
1120       response.setIsProcedureAborted(abortResult);
1121       return response.build();
1122     } catch (IOException e) {
1123       throw new ServiceException(e);
1124     }
1125   }
1126 
1127   @Override
1128   public ListProceduresResponse listProcedures(
1129       RpcController rpcController,
1130       ListProceduresRequest request) throws ServiceException {
1131     try {
1132       ListProceduresResponse.Builder response =
1133           ListProceduresResponse.newBuilder();
1134       for(ProcedureInfo p: master.listProcedures()) {
1135         response.addProcedure(ProcedureInfo.convertToProcedureProto(p));
1136       }
1137       return response.build();
1138     } catch (IOException e) {
1139       throw new ServiceException(e);
1140     }
1141   }
1142 
1143   @Override
1144   public ClearDeadServersResponse clearDeadServers(RpcController controller,
1145       ClearDeadServersRequest request) throws ServiceException {
1146     LOG.debug(master.getClientIdAuditPrefix() + " clear dead region servers.");
1147     ClearDeadServersResponse.Builder response = ClearDeadServersResponse.newBuilder();
1148     try {
1149       master.checkInitialized();
1150       if (master.cpHost != null) {
1151         master.cpHost.preClearDeadServers();
1152       }
1153 
1154       if (master.getServerManager().areDeadServersInProgress()) {
1155         LOG.debug("Some dead server is still under processing, won't clear the dead server list");
1156         response.addAllServerName(request.getServerNameList());
1157       } else {
1158         for (HBaseProtos.ServerName pbServer : request.getServerNameList()) {
1159           if (!master.getServerManager().getDeadServers()
1160                   .removeDeadServer(ProtobufUtil.toServerName(pbServer))) {
1161             response.addServerName(pbServer);
1162           }
1163         }
1164       }
1165 
1166       if (master.cpHost != null) {
1167         master.cpHost.postClearDeadServers(
1168             ProtobufUtil.toServerNameList(request.getServerNameList()),
1169             ProtobufUtil.toServerNameList(response.getServerNameList()));
1170       }
1171     } catch (IOException io) {
1172       throw new ServiceException(io);
1173     }
1174     return response.build();
1175   }
1176 
1177 
1178   @Override
1179   public ListNamespaceDescriptorsResponse listNamespaceDescriptors(RpcController c,
1180       ListNamespaceDescriptorsRequest request) throws ServiceException {
1181     try {
1182       ListNamespaceDescriptorsResponse.Builder response =
1183         ListNamespaceDescriptorsResponse.newBuilder();
1184       for(NamespaceDescriptor ns: master.listNamespaceDescriptors()) {
1185         response.addNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(ns));
1186       }
1187       return response.build();
1188     } catch (IOException e) {
1189       throw new ServiceException(e);
1190     }
1191   }
1192 
1193   @Override
1194   public ListTableDescriptorsByNamespaceResponse listTableDescriptorsByNamespace(RpcController c,
1195       ListTableDescriptorsByNamespaceRequest request) throws ServiceException {
1196     try {
1197       ListTableDescriptorsByNamespaceResponse.Builder b =
1198           ListTableDescriptorsByNamespaceResponse.newBuilder();
1199       for (HTableDescriptor htd : master
1200           .listTableDescriptorsByNamespace(request.getNamespaceName())) {
1201         b.addTableSchema(htd.convert());
1202       }
1203       return b.build();
1204     } catch (IOException e) {
1205       throw new ServiceException(e);
1206     }
1207   }
1208 
1209   @Override
1210   public ListTableNamesByNamespaceResponse listTableNamesByNamespace(RpcController c,
1211       ListTableNamesByNamespaceRequest request) throws ServiceException {
1212     try {
1213       ListTableNamesByNamespaceResponse.Builder b =
1214         ListTableNamesByNamespaceResponse.newBuilder();
1215       for (TableName tableName: master.listTableNamesByNamespace(request.getNamespaceName())) {
1216         b.addTableName(ProtobufUtil.toProtoTableName(tableName));
1217       }
1218       return b.build();
1219     } catch (IOException e) {
1220       throw new ServiceException(e);
1221     }
1222   }
1223 
1224   @Override
1225   public ModifyColumnResponse modifyColumn(RpcController controller,
1226       ModifyColumnRequest req) throws ServiceException {
1227     try {
1228       master.modifyColumn(
1229         ProtobufUtil.toTableName(req.getTableName()),
1230         HColumnDescriptor.convert(req.getColumnFamilies()),
1231         req.getNonceGroup(),
1232         req.getNonce());
1233     } catch (IOException ioe) {
1234       throw new ServiceException(ioe);
1235     }
1236     return ModifyColumnResponse.newBuilder().build();
1237   }
1238 
1239   @Override
1240   public ModifyNamespaceResponse modifyNamespace(RpcController controller,
1241       ModifyNamespaceRequest request) throws ServiceException {
1242     try {
1243       master.modifyNamespace(
1244         ProtobufUtil.toNamespaceDescriptor(request.getNamespaceDescriptor()),
1245         request.getNonceGroup(),
1246         request.getNonce());
1247       return ModifyNamespaceResponse.getDefaultInstance();
1248     } catch (IOException e) {
1249       throw new ServiceException(e);
1250     }
1251   }
1252 
1253   @Override
1254   public ModifyTableResponse modifyTable(RpcController controller,
1255       ModifyTableRequest req) throws ServiceException {
1256     try {
1257       master.modifyTable(
1258         ProtobufUtil.toTableName(req.getTableName()),
1259         HTableDescriptor.convert(req.getTableSchema()),
1260         req.getNonceGroup(),
1261         req.getNonce());
1262     } catch (IOException ioe) {
1263       throw new ServiceException(ioe);
1264     }
1265     return ModifyTableResponse.newBuilder().build();
1266   }
1267 
1268   @Override
1269   public MoveRegionResponse moveRegion(RpcController controller,
1270       MoveRegionRequest req) throws ServiceException {
1271     final byte [] encodedRegionName = req.getRegion().getValue().toByteArray();
1272     RegionSpecifierType type = req.getRegion().getType();
1273     final byte [] destServerName = (req.hasDestServerName())?
1274       Bytes.toBytes(ProtobufUtil.toServerName(req.getDestServerName()).getServerName()):null;
1275     MoveRegionResponse mrr = MoveRegionResponse.newBuilder().build();
1276 
1277     if (type != RegionSpecifierType.ENCODED_REGION_NAME) {
1278       LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.ENCODED_REGION_NAME
1279         + " actual: " + type);
1280     }
1281 
1282     try {
1283       master.checkInitialized();
1284       master.move(encodedRegionName, destServerName);
1285     } catch (IOException ioe) {
1286       throw new ServiceException(ioe);
1287     }
1288     return mrr;
1289   }
1290 
1291   /**
1292    * Offline specified region from master's in-memory state. It will not attempt to
1293    * reassign the region as in unassign.
1294    *
1295    * This is a special method that should be used by experts or hbck.
1296    *
1297    */
1298   @Override
1299   public OfflineRegionResponse offlineRegion(RpcController controller,
1300       OfflineRegionRequest request) throws ServiceException {
1301     final byte [] regionName = request.getRegion().getValue().toByteArray();
1302     RegionSpecifierType type = request.getRegion().getType();
1303     if (type != RegionSpecifierType.REGION_NAME) {
1304       LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
1305         + " actual: " + type);
1306     }
1307 
1308     try {
1309       master.checkInitialized();
1310       Pair<HRegionInfo, ServerName> pair =
1311         MetaTableAccessor.getRegion(master.getConnection(), regionName);
1312       if (pair == null) throw new UnknownRegionException(Bytes.toStringBinary(regionName));
1313       HRegionInfo hri = pair.getFirst();
1314       if (master.cpHost != null) {
1315         master.cpHost.preRegionOffline(hri);
1316       }
1317       LOG.info(master.getClientIdAuditPrefix() + " offline " + hri.getRegionNameAsString());
1318       master.assignmentManager.regionOffline(hri);
1319       if (master.cpHost != null) {
1320         master.cpHost.postRegionOffline(hri);
1321       }
1322     } catch (IOException ioe) {
1323       throw new ServiceException(ioe);
1324     }
1325     return OfflineRegionResponse.newBuilder().build();
1326   }
1327 
1328   /**
1329    * Execute Restore/Clone snapshot operation.
1330    *
1331    * <p>If the specified table exists a "Restore" is executed, replacing the table
1332    * schema and directory data with the content of the snapshot.
1333    * The table must be disabled, or a UnsupportedOperationException will be thrown.
1334    *
1335    * <p>If the table doesn't exist a "Clone" is executed, a new table is created
1336    * using the schema at the time of the snapshot, and the content of the snapshot.
1337    *
1338    * <p>The restore/clone operation does not require copying HFiles. Since HFiles
1339    * are immutable the table can point to and use the same files as the original one.
1340    */
1341   @Override
1342   public RestoreSnapshotResponse restoreSnapshot(RpcController controller,
1343       RestoreSnapshotRequest request) throws ServiceException {
1344     try {
1345       master.checkInitialized();
1346       master.snapshotManager.checkSnapshotSupport();
1347 
1348       // ensure namespace exists
1349       TableName dstTable = TableName.valueOf(request.getSnapshot().getTable());
1350       master.ensureNamespaceExists(dstTable.getNamespaceAsString());
1351 
1352       SnapshotDescription reqSnapshot = request.getSnapshot();
1353       master.snapshotManager.restoreSnapshot(reqSnapshot,
1354         request.hasRestoreACL() && request.getRestoreACL());
1355       return RestoreSnapshotResponse.newBuilder().build();
1356     } catch (ForeignException e) {
1357       throw new ServiceException(e.getCause());
1358     } catch (IOException e) {
1359       throw new ServiceException(e);
1360     }
1361   }
1362 
1363   @Override
1364   public RunCatalogScanResponse runCatalogScan(RpcController c,
1365       RunCatalogScanRequest req) throws ServiceException {
1366     try {
1367       master.checkInitialized();
1368       return ResponseConverter.buildRunCatalogScanResponse(master.catalogJanitorChore.scan());
1369     } catch (IOException ioe) {
1370       throw new ServiceException(ioe);
1371     }
1372   }
1373 
1374   @Override
1375   public RunCleanerChoreResponse runCleanerChore(RpcController c, RunCleanerChoreRequest req)
1376       throws ServiceException {
1377     try {
1378       master.checkInitialized();
1379       Boolean result = master.getHFileCleaner().runCleaner()
1380           && master.getLogCleaner().runCleaner();
1381       return ResponseConverter.buildRunCleanerChoreResponse(result);
1382     } catch (IOException ioe) {
1383       throw new ServiceException(ioe);
1384     }
1385   }
1386 
1387   @Override
1388   public SetBalancerRunningResponse setBalancerRunning(RpcController c,
1389       SetBalancerRunningRequest req) throws ServiceException {
1390     try {
1391       master.checkInitialized();
1392       boolean prevValue = (req.getSynchronous())?
1393         synchronousBalanceSwitch(req.getOn()) : master.balanceSwitch(req.getOn());
1394       return SetBalancerRunningResponse.newBuilder().setPrevBalanceValue(prevValue).build();
1395     } catch (IOException ioe) {
1396       throw new ServiceException(ioe);
1397     }
1398   }
1399 
1400   @Override
1401   public ShutdownResponse shutdown(RpcController controller,
1402       ShutdownRequest request) throws ServiceException {
1403     LOG.info(master.getClientIdAuditPrefix() + " shutdown");
1404     try {
1405       master.shutdown();
1406     } catch (IOException e) {
1407       LOG.error("Exception occurred in HMaster.shutdown()", e);
1408       throw new ServiceException(e);
1409     }
1410     return ShutdownResponse.newBuilder().build();
1411   }
1412 
1413   /**
1414    * Triggers an asynchronous attempt to take a snapshot.
1415    * {@inheritDoc}
1416    */
1417   @Override
1418   public SnapshotResponse snapshot(RpcController controller,
1419       SnapshotRequest request) throws ServiceException {
1420     try {
1421       master.checkInitialized();
1422       master.snapshotManager.checkSnapshotSupport();
1423 
1424       LOG.info(master.getClientIdAuditPrefix() + " snapshot request for:" +
1425         ClientSnapshotDescriptionUtils.toString(request.getSnapshot()));
1426       // get the snapshot information
1427       SnapshotDescription snapshot = SnapshotDescriptionUtils.validate(
1428         request.getSnapshot(), master.getConfiguration());
1429       master.snapshotManager.takeSnapshot(snapshot);
1430 
1431       // send back the max amount of time the client should wait for the snapshot to complete
1432       long waitTime = SnapshotDescriptionUtils.getMaxMasterTimeout(master.getConfiguration(),
1433         snapshot.getType(), SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME);
1434       return SnapshotResponse.newBuilder().setExpectedTimeout(waitTime).build();
1435     } catch (ForeignException e) {
1436       throw new ServiceException(e.getCause());
1437     } catch (IOException e) {
1438       throw new ServiceException(e);
1439     }
1440   }
1441 
1442   @Override
1443   public StopMasterResponse stopMaster(RpcController controller,
1444       StopMasterRequest request) throws ServiceException {
1445     LOG.info(master.getClientIdAuditPrefix() + " stop");
1446     try {
1447       master.stopMaster();
1448     } catch (IOException e) {
1449       LOG.error("Exception occurred while stopping master", e);
1450       throw new ServiceException(e);
1451     }
1452     return StopMasterResponse.newBuilder().build();
1453   }
1454 
1455   @Override
1456   public IsInMaintenanceModeResponse isMasterInMaintenanceMode(
1457       final RpcController controller,
1458       final IsInMaintenanceModeRequest request) throws ServiceException {
1459     IsInMaintenanceModeResponse.Builder response = IsInMaintenanceModeResponse.newBuilder();
1460     try {
1461       response.setInMaintenanceMode(master.isInMaintenanceMode());
1462     } catch (IOException e) {
1463       throw new ServiceException(e);
1464     }
1465     return response.build();
1466   }
1467 
1468   @Override
1469   public UnassignRegionResponse unassignRegion(RpcController controller,
1470       UnassignRegionRequest req) throws ServiceException {
1471     try {
1472       final byte [] regionName = req.getRegion().getValue().toByteArray();
1473       RegionSpecifierType type = req.getRegion().getType();
1474       final boolean force = req.getForce();
1475       UnassignRegionResponse urr = UnassignRegionResponse.newBuilder().build();
1476 
1477       master.checkInitialized();
1478       if (type != RegionSpecifierType.REGION_NAME) {
1479         LOG.warn("unassignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
1480           + " actual: " + type);
1481       }
1482       Pair<HRegionInfo, ServerName> pair =
1483         MetaTableAccessor.getRegion(master.getConnection(), regionName);
1484       if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
1485       HRegionInfo hri = pair.getFirst();
1486       if (master.cpHost != null) {
1487         if (master.cpHost.preUnassign(hri, force)) {
1488           return urr;
1489         }
1490       }
1491       LOG.debug(master.getClientIdAuditPrefix() + " unassign " + hri.getRegionNameAsString()
1492           + " in current location if it is online and reassign.force=" + force);
1493       master.assignmentManager.unassign(hri, force);
1494       if (master.assignmentManager.getRegionStates().isRegionOffline(hri)) {
1495         LOG.debug("Region " + hri.getRegionNameAsString()
1496             + " is not online on any region server, reassigning it.");
1497         master.assignmentManager.assign(hri, true);
1498       }
1499       if (master.cpHost != null) {
1500         master.cpHost.postUnassign(hri, force);
1501       }
1502 
1503       return urr;
1504     } catch (IOException ioe) {
1505       throw new ServiceException(ioe);
1506     }
1507   }
1508 
1509   @Override
1510   public ReportRegionStateTransitionResponse reportRegionStateTransition(RpcController c,
1511       ReportRegionStateTransitionRequest req) throws ServiceException {
1512     try {
1513       master.checkServiceStarted();
1514       RegionStateTransition rt = req.getTransition(0);
1515       RegionStates regionStates = master.getAssignmentManager().getRegionStates();
1516       for (HBaseProtos.RegionInfo ri : rt.getRegionInfoList())  {
1517         TableName tableName = ProtobufUtil.toTableName(ri.getTableName());
1518         if (!(TableName.META_TABLE_NAME.equals(tableName)
1519             && regionStates.getRegionState(HRegionInfo.FIRST_META_REGIONINFO) != null)
1520               && !master.getAssignmentManager().isFailoverCleanupDone()) {
1521           // Meta region is assigned before master finishes the
1522           // failover cleanup. So no need this check for it
1523           throw new PleaseHoldException("Master is rebuilding user regions");
1524         }
1525       }
1526       ServerName sn = ProtobufUtil.toServerName(req.getServer());
1527       String error = master.assignmentManager.onRegionTransition(sn, rt);
1528       ReportRegionStateTransitionResponse.Builder rrtr =
1529         ReportRegionStateTransitionResponse.newBuilder();
1530       if (error != null) {
1531         rrtr.setErrorMessage(error);
1532       }
1533       return rrtr.build();
1534     } catch (IOException ioe) {
1535       throw new ServiceException(ioe);
1536     }
1537   }
1538 
1539   @Override
1540   public MajorCompactionTimestampResponse getLastMajorCompactionTimestamp(RpcController controller,
1541       MajorCompactionTimestampRequest request) throws ServiceException {
1542     MajorCompactionTimestampResponse.Builder response =
1543         MajorCompactionTimestampResponse.newBuilder();
1544     try {
1545       master.checkInitialized();
1546       response.setCompactionTimestamp(master.getLastMajorCompactionTimestamp(ProtobufUtil
1547           .toTableName(request.getTableName())));
1548     } catch (IOException e) {
1549       throw new ServiceException(e);
1550     }
1551     return response.build();
1552   }
1553 
1554   @Override
1555   public MajorCompactionTimestampResponse getLastMajorCompactionTimestampForRegion(
1556       RpcController controller, MajorCompactionTimestampForRegionRequest request)
1557       throws ServiceException {
1558     MajorCompactionTimestampResponse.Builder response =
1559         MajorCompactionTimestampResponse.newBuilder();
1560     try {
1561       master.checkInitialized();
1562       response.setCompactionTimestamp(master.getLastMajorCompactionTimestampForRegion(request
1563           .getRegion().getValue().toByteArray()));
1564     } catch (IOException e) {
1565       throw new ServiceException(e);
1566     }
1567     return response.build();
1568   }
1569 
1570   @Override
1571   public IsBalancerEnabledResponse isBalancerEnabled(RpcController controller,
1572       IsBalancerEnabledRequest request) throws ServiceException {
1573     IsBalancerEnabledResponse.Builder response = IsBalancerEnabledResponse.newBuilder();
1574     response.setEnabled(master.isBalancerOn());
1575     return response.build();
1576   }
1577 
1578   @Override
1579   public MasterProtos.SetSplitOrMergeEnabledResponse setSplitOrMergeEnabled(
1580     RpcController controller,
1581     MasterProtos.SetSplitOrMergeEnabledRequest request) throws ServiceException {
1582     MasterProtos.SetSplitOrMergeEnabledResponse.Builder response =
1583             MasterProtos.SetSplitOrMergeEnabledResponse.newBuilder();
1584     try {
1585       master.checkInitialized();
1586       boolean newValue = request.getEnabled();
1587       for (MasterProtos.MasterSwitchType masterSwitchType : request.getSwitchTypesList()) {
1588         Admin.MasterSwitchType switchType = convert(masterSwitchType);
1589         boolean oldValue = master.isSplitOrMergeEnabled(switchType);
1590         response.addPrevValue(oldValue);
1591         boolean bypass = false;
1592         if (master.cpHost != null) {
1593           bypass = master.cpHost.preSetSplitOrMergeEnabled(newValue, switchType);
1594         }
1595         if (!bypass) {
1596           master.getSplitOrMergeTracker().setSplitOrMergeEnabled(newValue, switchType);
1597         }
1598         if (master.cpHost != null) {
1599           master.cpHost.postSetSplitOrMergeEnabled(newValue, switchType);
1600         }
1601       }
1602     } catch (IOException e) {
1603       throw new ServiceException(e);
1604     } catch (KeeperException e) {
1605       throw new ServiceException(e);
1606     }
1607     return response.build();
1608   }
1609 
1610   @Override
1611   public MasterProtos.IsSplitOrMergeEnabledResponse isSplitOrMergeEnabled(RpcController controller,
1612     MasterProtos.IsSplitOrMergeEnabledRequest request) throws ServiceException {
1613     MasterProtos.IsSplitOrMergeEnabledResponse.Builder response =
1614             MasterProtos.IsSplitOrMergeEnabledResponse.newBuilder();
1615     response.setEnabled(master.isSplitOrMergeEnabled(convert(request.getSwitchType())));
1616     return response.build();
1617   }
1618 
1619   @Override
1620   public NormalizeResponse normalize(RpcController controller,
1621       NormalizeRequest request) throws ServiceException {
1622     try {
1623       return NormalizeResponse.newBuilder().setNormalizerRan(master.normalizeRegions()).build();
1624     } catch (IOException | CoordinatedStateException ex) {
1625       throw new ServiceException(ex);
1626     }
1627   }
1628 
1629   @Override
1630   public SetNormalizerRunningResponse setNormalizerRunning(RpcController controller,
1631       SetNormalizerRunningRequest request) throws ServiceException {
1632     try {
1633       master.checkInitialized();
1634       boolean prevValue = normalizerSwitch(request.getOn());
1635       return SetNormalizerRunningResponse.newBuilder().setPrevNormalizerValue(prevValue).build();
1636     } catch (IOException ioe) {
1637       throw new ServiceException(ioe);
1638     }
1639   }
1640 
1641   @Override
1642   public IsNormalizerEnabledResponse isNormalizerEnabled(RpcController controller,
1643       IsNormalizerEnabledRequest request) throws ServiceException {
1644     IsNormalizerEnabledResponse.Builder response = IsNormalizerEnabledResponse.newBuilder();
1645     response.setEnabled(master.isNormalizerOn());
1646     return response.build();
1647   }
1648 
1649   @Override
1650   public SetQuotaResponse setQuota(RpcController c, SetQuotaRequest req) throws ServiceException {
1651     try {
1652       master.checkInitialized();
1653       return master.getMasterQuotaManager().setQuota(req);
1654     } catch (Exception e) {
1655       throw new ServiceException(e);
1656     }
1657   }
1658 
1659   /**
1660    * Returns the security capabilities in effect on the cluster
1661    */
1662   @Override
1663   public SecurityCapabilitiesResponse getSecurityCapabilities(RpcController controller,
1664       SecurityCapabilitiesRequest request) throws ServiceException {
1665     SecurityCapabilitiesResponse.Builder response = SecurityCapabilitiesResponse.newBuilder();
1666     try {
1667       master.checkInitialized();
1668       Set<Capability> capabilities = new HashSet<>();
1669       // Authentication
1670       if (User.isHBaseSecurityEnabled(master.getConfiguration())) {
1671         capabilities.add(Capability.SECURE_AUTHENTICATION);
1672       } else {
1673         capabilities.add(Capability.SIMPLE_AUTHENTICATION);
1674       }
1675       // The AccessController can provide AUTHORIZATION and CELL_AUTHORIZATION
1676       if (master.cpHost != null &&
1677             master.cpHost.findCoprocessor(AccessController.class.getName()) != null) {
1678         if (AccessChecker.isAuthorizationSupported(master.getConfiguration())) {
1679           capabilities.add(Capability.AUTHORIZATION);
1680         }
1681         if (AccessController.isCellAuthorizationSupported(master.getConfiguration())) {
1682           capabilities.add(Capability.CELL_AUTHORIZATION);
1683         }
1684       }
1685       // The VisibilityController can provide CELL_VISIBILITY
1686       if (master.cpHost != null &&
1687             master.cpHost.findCoprocessor(VisibilityController.class.getName()) != null) {
1688         if (VisibilityController.isCellAuthorizationSupported(master.getConfiguration())) {
1689           capabilities.add(Capability.CELL_VISIBILITY);
1690         }
1691       }
1692       response.addAllCapabilities(capabilities);
1693     } catch (IOException e) {
1694       throw new ServiceException(e);
1695     }
1696     return response.build();
1697   }
1698 
1699   private Admin.MasterSwitchType convert(MasterProtos.MasterSwitchType switchType) {
1700     switch (switchType) {
1701       case SPLIT:
1702         return Admin.MasterSwitchType.SPLIT;
1703       case MERGE:
1704         return Admin.MasterSwitchType.MERGE;
1705       default:
1706         break;
1707     }
1708     return null;
1709   }
1710 }