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