1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.client;
20
21 import java.io.IOException;
22 import java.io.InterruptedIOException;
23 import java.net.SocketTimeoutException;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.concurrent.atomic.AtomicInteger;
32 import java.util.concurrent.atomic.AtomicReference;
33 import java.util.concurrent.ExecutionException;
34 import java.util.concurrent.Future;
35 import java.util.concurrent.TimeUnit;
36 import java.util.concurrent.TimeoutException;
37 import java.util.regex.Pattern;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.apache.hadoop.conf.Configuration;
42 import org.apache.hadoop.hbase.Abortable;
43 import org.apache.hadoop.hbase.ClusterStatus;
44 import org.apache.hadoop.hbase.DoNotRetryIOException;
45 import org.apache.hadoop.hbase.HBaseConfiguration;
46 import org.apache.hadoop.hbase.HColumnDescriptor;
47 import org.apache.hadoop.hbase.HConstants;
48 import org.apache.hadoop.hbase.HRegionInfo;
49 import org.apache.hadoop.hbase.HRegionLocation;
50 import org.apache.hadoop.hbase.HTableDescriptor;
51 import org.apache.hadoop.hbase.MasterNotRunningException;
52 import org.apache.hadoop.hbase.MetaTableAccessor;
53 import org.apache.hadoop.hbase.NamespaceDescriptor;
54 import org.apache.hadoop.hbase.NamespaceNotFoundException;
55 import org.apache.hadoop.hbase.NotServingRegionException;
56 import org.apache.hadoop.hbase.ProcedureInfo;
57 import org.apache.hadoop.hbase.RegionException;
58 import org.apache.hadoop.hbase.RegionLocations;
59 import org.apache.hadoop.hbase.ServerName;
60 import org.apache.hadoop.hbase.TableExistsException;
61 import org.apache.hadoop.hbase.TableName;
62 import org.apache.hadoop.hbase.TableNotDisabledException;
63 import org.apache.hadoop.hbase.TableNotEnabledException;
64 import org.apache.hadoop.hbase.TableNotFoundException;
65 import org.apache.hadoop.hbase.UnknownRegionException;
66 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
67 import org.apache.hadoop.hbase.classification.InterfaceAudience;
68 import org.apache.hadoop.hbase.classification.InterfaceStability;
69 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
70 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitorBase;
71 import org.apache.hadoop.hbase.client.security.SecurityCapability;
72 import org.apache.hadoop.hbase.exceptions.DeserializationException;
73 import org.apache.hadoop.hbase.exceptions.TimeoutIOException;
74 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
75 import org.apache.hadoop.hbase.ipc.MasterCoprocessorRpcChannel;
76 import org.apache.hadoop.hbase.ipc.PayloadCarryingRpcController;
77 import org.apache.hadoop.hbase.ipc.RegionServerCoprocessorRpcChannel;
78 import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
79 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
80 import org.apache.hadoop.hbase.protobuf.RequestConverter;
81 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
82 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
83 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse;
84 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
85 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionRequest;
86 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
87 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse;
88 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse.CompactionState;
89 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterRequest;
90 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterResponse;
91 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
92 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateConfigurationRequest;
93 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
94 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
95 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ProcedureDescription;
96 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
97 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
98 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableSchema;
99 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos;
100 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureRequest;
101 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureResponse;
102 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AddColumnRequest;
103 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
104 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateNamespaceRequest;
105 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
106 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableResponse;
107 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteColumnRequest;
108 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteNamespaceRequest;
109 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteSnapshotRequest;
110 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteTableRequest;
111 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteTableResponse;
112 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DisableTableRequest;
113 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DisableTableResponse;
114 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
115 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableTableRequest;
116 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableTableResponse;
117 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ExecProcedureRequest;
118 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ExecProcedureResponse;
119 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetClusterStatusRequest;
120 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetCompletedSnapshotsRequest;
121 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest;
122 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetProcedureResultRequest;
123 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetProcedureResultResponse;
124 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
125 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusResponse;
126 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
127 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
128 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest;
129 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsProcedureDoneRequest;
130 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsProcedureDoneResponse;
131 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsRestoreSnapshotDoneRequest;
132 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsRestoreSnapshotDoneResponse;
133 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
134 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
135 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest;
136 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresRequest;
137 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceRequest;
138 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableNamesByNamespaceRequest;
139 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MajorCompactionTimestampForRegionRequest;
140 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MajorCompactionTimestampRequest;
141 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyColumnRequest;
142 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyNamespaceRequest;
143 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyTableRequest;
144 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
145 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
146 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
147 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
148 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
149 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetNormalizerRunningRequest;
150 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ShutdownRequest;
151 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotRequest;
152 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotResponse;
153 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.StopMasterRequest;
154 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.TruncateTableRequest;
155 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
156 import org.apache.hadoop.hbase.protobuf.generated.ProcedureProtos;
157 import org.apache.hadoop.hbase.quotas.QuotaFilter;
158 import org.apache.hadoop.hbase.quotas.QuotaRetriever;
159 import org.apache.hadoop.hbase.quotas.QuotaSettings;
160 import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
161 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
162 import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
163 import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
164 import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
165 import org.apache.hadoop.hbase.snapshot.UnknownSnapshotException;
166 import org.apache.hadoop.hbase.util.Addressing;
167 import org.apache.hadoop.hbase.util.Bytes;
168 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
169 import org.apache.hadoop.hbase.util.ForeignExceptionUtil;
170 import org.apache.hadoop.hbase.util.Pair;
171 import org.apache.hadoop.hbase.zookeeper.MasterAddressTracker;
172 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
173 import org.apache.hadoop.ipc.RemoteException;
174 import org.apache.hadoop.util.StringUtils;
175 import org.apache.zookeeper.KeeperException;
176
177 import com.google.common.annotations.VisibleForTesting;
178 import com.google.protobuf.ByteString;
179 import com.google.protobuf.ServiceException;
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 @InterfaceAudience.Private
198 @InterfaceStability.Evolving
199 public class HBaseAdmin implements Admin {
200 private static final Log LOG = LogFactory.getLog(HBaseAdmin.class);
201
202 private static final String ZK_IDENTIFIER_PREFIX = "hbase-admin-on-";
203
204 private ClusterConnection connection;
205
206 private volatile Configuration conf;
207 private final long pause;
208 private final int numRetries;
209
210
211
212 private final int retryLongerMultiplier;
213 private final int syncWaitTimeout;
214 private boolean aborted;
215 private boolean cleanupConnectionOnClose = false;
216 private boolean closed = false;
217 private int operationTimeout;
218 private int rpcTimeout;
219
220 private RpcRetryingCallerFactory rpcCallerFactory;
221 private RpcControllerFactory rpcControllerFactory;
222
223 private NonceGenerator ng;
224
225
226
227
228
229
230
231
232
233 @Deprecated
234 public HBaseAdmin(Configuration c)
235 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
236
237
238 this(ConnectionManager.getConnectionInternal(new Configuration(c)));
239 this.cleanupConnectionOnClose = true;
240 }
241
242 @Override
243 public int getOperationTimeout() {
244 return operationTimeout;
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259 @Deprecated
260 public HBaseAdmin(Connection connection)
261 throws MasterNotRunningException, ZooKeeperConnectionException {
262 this((ClusterConnection)connection);
263 }
264
265 HBaseAdmin(ClusterConnection connection) {
266 this.conf = connection.getConfiguration();
267 this.connection = connection;
268
269
270 this.pause = this.conf.getLong(HConstants.HBASE_CLIENT_PAUSE,
271 HConstants.DEFAULT_HBASE_CLIENT_PAUSE);
272 this.numRetries = this.conf.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER,
273 HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER);
274 this.retryLongerMultiplier = this.conf.getInt(
275 "hbase.client.retries.longer.multiplier", 10);
276 this.operationTimeout = this.conf.getInt(HConstants.HBASE_CLIENT_OPERATION_TIMEOUT,
277 HConstants.DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT);
278 this.rpcTimeout = this.conf.getInt(HConstants.HBASE_RPC_TIMEOUT_KEY,
279 HConstants.DEFAULT_HBASE_RPC_TIMEOUT);
280 this.syncWaitTimeout = this.conf.getInt(
281 "hbase.client.sync.wait.timeout.msec", 10 * 60000);
282
283 this.rpcCallerFactory = connection.getRpcRetryingCallerFactory();
284 this.rpcControllerFactory = connection.getRpcControllerFactory();
285
286 this.ng = this.connection.getNonceGenerator();
287 }
288
289 @Override
290 public void abort(String why, Throwable e) {
291
292 this.aborted = true;
293 throw new RuntimeException(why, e);
294 }
295
296 @Override
297 public boolean isAborted(){
298 return this.aborted;
299 }
300
301
302
303
304
305
306
307
308 @Override
309 public boolean abortProcedure(
310 final long procId,
311 final boolean mayInterruptIfRunning) throws IOException {
312 Future<Boolean> future = abortProcedureAsync(procId, mayInterruptIfRunning);
313 try {
314 return future.get(syncWaitTimeout, TimeUnit.MILLISECONDS);
315 } catch (InterruptedException e) {
316 throw new InterruptedIOException("Interrupted when waiting for procedure to be cancelled");
317 } catch (TimeoutException e) {
318 throw new TimeoutIOException(e);
319 } catch (ExecutionException e) {
320 if (e.getCause() instanceof IOException) {
321 throw (IOException)e.getCause();
322 } else {
323 throw new IOException(e.getCause());
324 }
325 }
326 }
327
328
329
330
331
332
333
334
335
336
337
338
339
340 @Override
341 public Future<Boolean> abortProcedureAsync(
342 final long procId,
343 final boolean mayInterruptIfRunning) throws IOException {
344 Boolean abortProcResponse = executeCallable(
345 new MasterCallable<AbortProcedureResponse>(getConnection()) {
346 @Override
347 public AbortProcedureResponse call(int callTimeout) throws ServiceException {
348 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
349 controller.setCallTimeout(callTimeout);
350 AbortProcedureRequest abortProcRequest =
351 AbortProcedureRequest.newBuilder().setProcId(procId).build();
352 return master.abortProcedure(controller, abortProcRequest);
353 }
354 }).getIsProcedureAborted();
355
356 AbortProcedureFuture abortProcFuture =
357 new AbortProcedureFuture(this, procId, abortProcResponse);
358 return abortProcFuture;
359 }
360
361 private static class AbortProcedureFuture extends ProcedureFuture<Boolean> {
362 private boolean isAbortInProgress;
363
364 public AbortProcedureFuture(
365 final HBaseAdmin admin,
366 final Long procId,
367 final Boolean abortProcResponse) {
368 super(admin, procId);
369 this.isAbortInProgress = abortProcResponse;
370 }
371
372 @Override
373 public Boolean get(long timeout, TimeUnit unit)
374 throws InterruptedException, ExecutionException, TimeoutException {
375 if (!this.isAbortInProgress) {
376 return false;
377 }
378 super.get(timeout, unit);
379 return true;
380 }
381 }
382
383
384 @Override
385 public HConnection getConnection() {
386 return connection;
387 }
388
389
390
391
392
393
394
395 @Deprecated
396 public boolean isMasterRunning()
397 throws MasterNotRunningException, ZooKeeperConnectionException {
398 return connection.isMasterRunning();
399 }
400
401
402
403
404
405
406 @Override
407 public boolean tableExists(final TableName tableName) throws IOException {
408 return MetaTableAccessor.tableExists(connection, tableName);
409 }
410
411 public boolean tableExists(final byte[] tableName)
412 throws IOException {
413 return tableExists(TableName.valueOf(tableName));
414 }
415
416 public boolean tableExists(final String tableName)
417 throws IOException {
418 return tableExists(TableName.valueOf(tableName));
419 }
420
421 @Override
422 public HTableDescriptor[] listTables() throws IOException {
423 return listTables((Pattern)null, false);
424 }
425
426 @Override
427 public HTableDescriptor[] listTables(Pattern pattern) throws IOException {
428 return listTables(pattern, false);
429 }
430
431 @Override
432 public HTableDescriptor[] listTables(String regex) throws IOException {
433 return listTables(Pattern.compile(regex), false);
434 }
435
436 @Override
437 public HTableDescriptor[] listTables(final Pattern pattern, final boolean includeSysTables)
438 throws IOException {
439 return executeCallable(new MasterCallable<HTableDescriptor[]>(getConnection()) {
440 @Override
441 public HTableDescriptor[] call(int callTimeout) throws ServiceException {
442 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
443 controller.setCallTimeout(callTimeout);
444 GetTableDescriptorsRequest req =
445 RequestConverter.buildGetTableDescriptorsRequest(pattern, includeSysTables);
446 return ProtobufUtil.getHTableDescriptorArray(master.getTableDescriptors(controller, req));
447 }
448 });
449 }
450
451 @Override
452 public HTableDescriptor[] listTables(String regex, boolean includeSysTables)
453 throws IOException {
454 return listTables(Pattern.compile(regex), includeSysTables);
455 }
456
457
458
459
460
461
462
463 @Deprecated
464 public String[] getTableNames() throws IOException {
465 TableName[] tableNames = listTableNames();
466 String result[] = new String[tableNames.length];
467 for (int i = 0; i < tableNames.length; i++) {
468 result[i] = tableNames[i].getNameAsString();
469 }
470 return result;
471 }
472
473
474
475
476
477
478
479
480 @Deprecated
481 public String[] getTableNames(Pattern pattern) throws IOException {
482 TableName[] tableNames = listTableNames(pattern);
483 String result[] = new String[tableNames.length];
484 for (int i = 0; i < tableNames.length; i++) {
485 result[i] = tableNames[i].getNameAsString();
486 }
487 return result;
488 }
489
490
491
492
493
494
495
496
497 @Deprecated
498 public String[] getTableNames(String regex) throws IOException {
499 return getTableNames(Pattern.compile(regex));
500 }
501
502 @Override
503 public TableName[] listTableNames() throws IOException {
504 return listTableNames((Pattern)null, false);
505 }
506
507 @Override
508 public TableName[] listTableNames(Pattern pattern) throws IOException {
509 return listTableNames(pattern, false);
510 }
511
512 @Override
513 public TableName[] listTableNames(String regex) throws IOException {
514 return listTableNames(Pattern.compile(regex), false);
515 }
516
517 @Override
518 public TableName[] listTableNames(final Pattern pattern, final boolean includeSysTables)
519 throws IOException {
520 return executeCallable(new MasterCallable<TableName[]>(getConnection()) {
521 @Override
522 public TableName[] call(int callTimeout) throws ServiceException {
523 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
524 controller.setCallTimeout(callTimeout);
525 GetTableNamesRequest req =
526 RequestConverter.buildGetTableNamesRequest(pattern, includeSysTables);
527 return ProtobufUtil.getTableNameArray(master.getTableNames(controller, req)
528 .getTableNamesList());
529 }
530 });
531 }
532
533 @Override
534 public TableName[] listTableNames(final String regex, final boolean includeSysTables)
535 throws IOException {
536 return listTableNames(Pattern.compile(regex), includeSysTables);
537 }
538
539
540
541
542
543
544
545
546 @Override
547 public HTableDescriptor getTableDescriptor(final TableName tableName)
548 throws TableNotFoundException, IOException {
549 return getTableDescriptor(tableName, getConnection(), rpcCallerFactory, rpcControllerFactory,
550 operationTimeout, rpcTimeout);
551 }
552
553 static HTableDescriptor getTableDescriptor(final TableName tableName, HConnection connection,
554 RpcRetryingCallerFactory rpcCallerFactory, final RpcControllerFactory rpcControllerFactory,
555 int operationTimeout, int rpcTimeout) throws TableNotFoundException, IOException {
556
557 if (tableName == null) return null;
558 HTableDescriptor htd = executeCallable(new MasterCallable<HTableDescriptor>(connection) {
559 @Override
560 public HTableDescriptor call(int callTimeout) throws ServiceException {
561 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
562 controller.setCallTimeout(callTimeout);
563 GetTableDescriptorsResponse htds;
564 GetTableDescriptorsRequest req =
565 RequestConverter.buildGetTableDescriptorsRequest(tableName);
566 htds = master.getTableDescriptors(controller, req);
567
568 if (!htds.getTableSchemaList().isEmpty()) {
569 return HTableDescriptor.convert(htds.getTableSchemaList().get(0));
570 }
571 return null;
572 }
573 }, rpcCallerFactory, operationTimeout, rpcTimeout);
574 if (htd != null) {
575 return htd;
576 }
577 throw new TableNotFoundException(tableName.getNameAsString());
578 }
579
580 public HTableDescriptor getTableDescriptor(final byte[] tableName)
581 throws TableNotFoundException, IOException {
582 return getTableDescriptor(TableName.valueOf(tableName));
583 }
584
585 private long getPauseTime(int tries) {
586 int triesCount = tries;
587 if (triesCount >= HConstants.RETRY_BACKOFF.length) {
588 triesCount = HConstants.RETRY_BACKOFF.length - 1;
589 }
590 return this.pause * HConstants.RETRY_BACKOFF[triesCount];
591 }
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606 @Override
607 public void createTable(HTableDescriptor desc)
608 throws IOException {
609 createTable(desc, null);
610 }
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636 @Override
637 public void createTable(HTableDescriptor desc, byte [] startKey,
638 byte [] endKey, int numRegions)
639 throws IOException {
640 if(numRegions < 3) {
641 throw new IllegalArgumentException("Must create at least three regions");
642 } else if(Bytes.compareTo(startKey, endKey) >= 0) {
643 throw new IllegalArgumentException("Start key must be smaller than end key");
644 }
645 if (numRegions == 3) {
646 createTable(desc, new byte[][]{startKey, endKey});
647 return;
648 }
649 byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
650 if(splitKeys == null || splitKeys.length != numRegions - 1) {
651 throw new IllegalArgumentException("Unable to split key range into enough regions");
652 }
653 createTable(desc, splitKeys);
654 }
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673 @Override
674 public void createTable(final HTableDescriptor desc, byte [][] splitKeys)
675 throws IOException {
676 Future<Void> future = createTableAsyncV2(desc, splitKeys);
677 try {
678
679 future.get(syncWaitTimeout, TimeUnit.MILLISECONDS);
680 } catch (InterruptedException e) {
681 throw new InterruptedIOException("Interrupted when waiting" +
682 " for table to be enabled; meta scan was done");
683 } catch (TimeoutException e) {
684 throw new TimeoutIOException(e);
685 } catch (ExecutionException e) {
686 if (e.getCause() instanceof IOException) {
687 throw (IOException)e.getCause();
688 } else {
689 throw new IOException(e.getCause());
690 }
691 }
692 }
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710 @Override
711 public void createTableAsync(final HTableDescriptor desc, final byte [][] splitKeys)
712 throws IOException {
713 createTableAsyncV2(desc, splitKeys);
714 }
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732 private Future<Void> createTableAsyncV2(final HTableDescriptor desc, final byte[][] splitKeys)
733 throws IOException {
734 if (desc.getTableName() == null) {
735 throw new IllegalArgumentException("TableName cannot be null");
736 }
737 if (splitKeys != null && splitKeys.length > 0) {
738 Arrays.sort(splitKeys, Bytes.BYTES_COMPARATOR);
739
740 byte[] lastKey = null;
741 for (byte[] splitKey : splitKeys) {
742 if (Bytes.compareTo(splitKey, HConstants.EMPTY_BYTE_ARRAY) == 0) {
743 throw new IllegalArgumentException(
744 "Empty split key must not be passed in the split keys.");
745 }
746 if (lastKey != null && Bytes.equals(splitKey, lastKey)) {
747 throw new IllegalArgumentException("All split keys must be unique, " +
748 "found duplicate: " + Bytes.toStringBinary(splitKey) +
749 ", " + Bytes.toStringBinary(lastKey));
750 }
751 lastKey = splitKey;
752 }
753 }
754
755 CreateTableResponse response = executeCallable(
756 new MasterCallable<CreateTableResponse>(getConnection()) {
757 @Override
758 public CreateTableResponse call(int callTimeout) throws ServiceException {
759 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
760 controller.setCallTimeout(callTimeout);
761 controller.setPriority(desc.getTableName());
762 CreateTableRequest request = RequestConverter.buildCreateTableRequest(
763 desc, splitKeys, ng.getNonceGroup(), ng.newNonce());
764 return master.createTable(controller, request);
765 }
766 });
767 return new CreateTableFuture(this, desc, splitKeys, response);
768 }
769
770 private static class CreateTableFuture extends ProcedureFuture<Void> {
771 private final HTableDescriptor desc;
772 private final byte[][] splitKeys;
773
774 public CreateTableFuture(final HBaseAdmin admin, final HTableDescriptor desc,
775 final byte[][] splitKeys, final CreateTableResponse response) {
776 super(admin, (response != null && response.hasProcId()) ? response.getProcId() : null, true);
777 this.splitKeys = splitKeys;
778 this.desc = desc;
779 }
780
781 @Override
782 protected Void waitOperationResult(final long deadlineTs)
783 throws IOException, TimeoutException {
784 waitForTableEnabled(deadlineTs);
785 waitForAllRegionsOnline(deadlineTs);
786 return null;
787 }
788
789 @Override
790 protected Void postOperationResult(final Void result, final long deadlineTs)
791 throws IOException, TimeoutException {
792 LOG.info("Created " + desc.getTableName());
793 return result;
794 }
795
796 private void waitForTableEnabled(final long deadlineTs)
797 throws IOException, TimeoutException {
798 waitForState(deadlineTs, new WaitForStateCallable() {
799 @Override
800 public boolean checkState(int tries) throws IOException {
801 try {
802 if (getAdmin().isTableAvailable(desc.getTableName())) {
803 return true;
804 }
805 } catch (TableNotFoundException tnfe) {
806 LOG.debug("Table "+ desc.getTableName() +" was not enabled, sleeping. tries="+ tries);
807 }
808 return false;
809 }
810
811 @Override
812 public void throwInterruptedException() throws InterruptedIOException {
813 throw new InterruptedIOException("Interrupted when waiting for table " +
814 desc.getTableName() + " to be enabled");
815 }
816
817 @Override
818 public void throwTimeoutException(long elapsedTime) throws TimeoutException {
819 throw new TimeoutException("Table " + desc.getTableName() +
820 " not enabled after " + elapsedTime + "msec");
821 }
822 });
823 }
824
825 private void waitForAllRegionsOnline(final long deadlineTs)
826 throws IOException, TimeoutException {
827 final AtomicInteger actualRegCount = new AtomicInteger(0);
828 final MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
829 @Override
830 public boolean processRow(Result rowResult) throws IOException {
831 RegionLocations list = MetaTableAccessor.getRegionLocations(rowResult);
832 if (list == null) {
833 LOG.warn("No serialized HRegionInfo in " + rowResult);
834 return true;
835 }
836 HRegionLocation l = list.getRegionLocation();
837 if (l == null) {
838 return true;
839 }
840 if (!l.getRegionInfo().getTable().equals(desc.getTableName())) {
841 return false;
842 }
843 if (l.getRegionInfo().isOffline() || l.getRegionInfo().isSplit()) return true;
844 HRegionLocation[] locations = list.getRegionLocations();
845 for (HRegionLocation location : locations) {
846 if (location == null) continue;
847 ServerName serverName = location.getServerName();
848
849 if (serverName != null && serverName.getHostAndPort() != null) {
850 actualRegCount.incrementAndGet();
851 }
852 }
853 return true;
854 }
855 };
856
857 int tries = 0;
858 IOException serverEx = null;
859 int numRegs = (splitKeys == null ? 1 : splitKeys.length + 1) * desc.getRegionReplication();
860 while (EnvironmentEdgeManager.currentTime() < deadlineTs) {
861 actualRegCount.set(0);
862 MetaScanner.metaScan(getAdmin().getConnection(), visitor, desc.getTableName());
863 if (actualRegCount.get() == numRegs) {
864
865 return;
866 }
867
868 try {
869 Thread.sleep(getAdmin().getPauseTime(tries++));
870 } catch (InterruptedException e) {
871 throw new InterruptedIOException("Interrupted when opening" +
872 " regions; " + actualRegCount.get() + " of " + numRegs +
873 " regions processed so far");
874 }
875 }
876 throw new TimeoutException("Only " + actualRegCount.get() +
877 " of " + numRegs + " regions are online; retries exhausted.");
878 }
879 }
880
881 public void deleteTable(final String tableName) throws IOException {
882 deleteTable(TableName.valueOf(tableName));
883 }
884
885 public void deleteTable(final byte[] tableName) throws IOException {
886 deleteTable(TableName.valueOf(tableName));
887 }
888
889
890
891
892
893
894
895
896 @Override
897 public void deleteTable(final TableName tableName) throws IOException {
898 Future<Void> future = deleteTableAsyncV2(tableName);
899 try {
900 future.get(syncWaitTimeout, TimeUnit.MILLISECONDS);
901 } catch (InterruptedException e) {
902 throw new InterruptedIOException("Interrupted when waiting for table to be deleted");
903 } catch (TimeoutException e) {
904 throw new TimeoutIOException(e);
905 } catch (ExecutionException e) {
906 if (e.getCause() instanceof IOException) {
907 throw (IOException)e.getCause();
908 } else {
909 throw new IOException(e.getCause());
910 }
911 }
912 }
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928 private Future<Void> deleteTableAsyncV2(final TableName tableName) throws IOException {
929 DeleteTableResponse response = executeCallable(
930 new MasterCallable<DeleteTableResponse>(getConnection()) {
931 @Override
932 public DeleteTableResponse call(int callTimeout) throws ServiceException {
933 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
934 controller.setCallTimeout(callTimeout);
935 controller.setPriority(tableName);
936 DeleteTableRequest req =
937 RequestConverter.buildDeleteTableRequest(tableName, ng.getNonceGroup(),ng.newNonce());
938 return master.deleteTable(controller,req);
939 }
940 });
941 return new DeleteTableFuture(this, tableName, response);
942 }
943
944 private static class DeleteTableFuture extends ProcedureFuture<Void> {
945 private final TableName tableName;
946
947 public DeleteTableFuture(final HBaseAdmin admin, final TableName tableName,
948 final DeleteTableResponse response) {
949 super(admin, (response != null && response.hasProcId()) ? response.getProcId() : null);
950 this.tableName = tableName;
951 }
952
953 @Override
954 protected Void waitOperationResult(final long deadlineTs)
955 throws IOException, TimeoutException {
956 waitTableNotFound(deadlineTs);
957 return null;
958 }
959
960 @Override
961 protected Void postOperationResult(final Void result, final long deadlineTs)
962 throws IOException, TimeoutException {
963
964 getAdmin().getConnection().clearRegionCache(tableName);
965 LOG.info("Deleted " + tableName);
966 return result;
967 }
968
969 private void waitTableNotFound(final long deadlineTs)
970 throws IOException, TimeoutException {
971 waitForState(deadlineTs, new WaitForStateCallable() {
972 @Override
973 public boolean checkState(int tries) throws IOException {
974 return !getAdmin().tableExists(tableName);
975 }
976
977 @Override
978 public void throwInterruptedException() throws InterruptedIOException {
979 throw new InterruptedIOException("Interrupted when waiting for table to be deleted");
980 }
981
982 @Override
983 public void throwTimeoutException(long elapsedTime) throws TimeoutException {
984 throw new TimeoutException("Table " + tableName + " not yet deleted after " +
985 elapsedTime + "msec");
986 }
987 });
988 }
989 }
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004 @Override
1005 public HTableDescriptor[] deleteTables(String regex) throws IOException {
1006 return deleteTables(Pattern.compile(regex));
1007 }
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 @Override
1021 public HTableDescriptor[] deleteTables(Pattern pattern) throws IOException {
1022 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
1023 for (HTableDescriptor table : listTables(pattern)) {
1024 try {
1025 deleteTable(table.getTableName());
1026 } catch (IOException ex) {
1027 LOG.info("Failed to delete table " + table.getTableName(), ex);
1028 failed.add(table);
1029 }
1030 }
1031 return failed.toArray(new HTableDescriptor[failed.size()]);
1032 }
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042 @Override
1043 public void truncateTable(final TableName tableName, final boolean preserveSplits)
1044 throws IOException {
1045 executeCallable(new MasterCallable<Void>(getConnection()) {
1046 @Override
1047 public Void call(int callTimeout) throws ServiceException {
1048 TruncateTableRequest req = RequestConverter.buildTruncateTableRequest(
1049 tableName, preserveSplits, ng.getNonceGroup(), ng.newNonce());
1050 master.truncateTable(null, req);
1051 return null;
1052 }
1053 });
1054 }
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 @Override
1070 public void enableTable(final TableName tableName)
1071 throws IOException {
1072 Future<Void> future = enableTableAsyncV2(tableName);
1073 try {
1074 future.get(syncWaitTimeout, TimeUnit.MILLISECONDS);
1075 } catch (InterruptedException e) {
1076 throw new InterruptedIOException("Interrupted when waiting for table to be disabled");
1077 } catch (TimeoutException e) {
1078 throw new TimeoutIOException(e);
1079 } catch (ExecutionException e) {
1080 if (e.getCause() instanceof IOException) {
1081 throw (IOException)e.getCause();
1082 } else {
1083 throw new IOException(e.getCause());
1084 }
1085 }
1086 }
1087
1088 public void enableTable(final byte[] tableName)
1089 throws IOException {
1090 enableTable(TableName.valueOf(tableName));
1091 }
1092
1093 public void enableTable(final String tableName)
1094 throws IOException {
1095 enableTable(TableName.valueOf(tableName));
1096 }
1097
1098
1099
1100
1101
1102
1103
1104
1105 private void waitUntilTableIsEnabled(final TableName tableName) throws IOException {
1106 boolean enabled = false;
1107 long start = EnvironmentEdgeManager.currentTime();
1108 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
1109 try {
1110 enabled = isTableEnabled(tableName);
1111 } catch (TableNotFoundException tnfe) {
1112
1113 enabled = false;
1114 }
1115 enabled = enabled && isTableAvailable(tableName);
1116 if (enabled) {
1117 break;
1118 }
1119 long sleep = getPauseTime(tries);
1120 if (LOG.isDebugEnabled()) {
1121 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
1122 "enabled in " + tableName);
1123 }
1124 try {
1125 Thread.sleep(sleep);
1126 } catch (InterruptedException e) {
1127
1128
1129 throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
1130 }
1131 }
1132 if (!enabled) {
1133 long msec = EnvironmentEdgeManager.currentTime() - start;
1134 throw new IOException("Table '" + tableName +
1135 "' not yet enabled, after " + msec + "ms.");
1136 }
1137 }
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149 @Override
1150 public void enableTableAsync(final TableName tableName)
1151 throws IOException {
1152 enableTableAsyncV2(tableName);
1153 }
1154
1155 public void enableTableAsync(final byte[] tableName)
1156 throws IOException {
1157 enableTable(TableName.valueOf(tableName));
1158 }
1159
1160 public void enableTableAsync(final String tableName)
1161 throws IOException {
1162 enableTableAsync(TableName.valueOf(tableName));
1163 }
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178 private Future<Void> enableTableAsyncV2(final TableName tableName) throws IOException {
1179 TableName.isLegalFullyQualifiedTableName(tableName.getName());
1180 EnableTableResponse response = executeCallable(
1181 new MasterCallable<EnableTableResponse>(getConnection()) {
1182 @Override
1183 public EnableTableResponse call(int callTimeout) throws ServiceException {
1184 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1185 controller.setCallTimeout(callTimeout);
1186 controller.setPriority(tableName);
1187
1188 LOG.info("Started enable of " + tableName);
1189 EnableTableRequest req =
1190 RequestConverter.buildEnableTableRequest(tableName, ng.getNonceGroup(),ng.newNonce());
1191 return master.enableTable(controller,req);
1192 }
1193 });
1194 return new EnableTableFuture(this, tableName, response);
1195 }
1196
1197 private static class EnableTableFuture extends ProcedureFuture<Void> {
1198 private final TableName tableName;
1199
1200 public EnableTableFuture(final HBaseAdmin admin, final TableName tableName,
1201 final EnableTableResponse response) {
1202 super(admin, (response != null && response.hasProcId()) ? response.getProcId() : null, true);
1203 this.tableName = tableName;
1204 }
1205
1206 @Override
1207 protected Void waitOperationResult(final long deadlineTs)
1208 throws IOException, TimeoutException {
1209 waitTableEnabled(deadlineTs);
1210 return null;
1211 }
1212
1213 @Override
1214 protected Void postOperationResult(final Void result, final long deadlineTs)
1215 throws IOException, TimeoutException {
1216 LOG.info("Enabled " + tableName);
1217 return result;
1218 }
1219
1220 private void waitTableEnabled(final long deadlineTs)
1221 throws IOException, TimeoutException {
1222 waitForState(deadlineTs, new WaitForStateCallable() {
1223 @Override
1224 public boolean checkState(int tries) throws IOException {
1225 boolean enabled;
1226 try {
1227 enabled = getAdmin().isTableEnabled(tableName);
1228 } catch (TableNotFoundException tnfe) {
1229 return false;
1230 }
1231 return enabled && getAdmin().isTableAvailable(tableName);
1232 }
1233
1234 @Override
1235 public void throwInterruptedException() throws InterruptedIOException {
1236 throw new InterruptedIOException("Interrupted when waiting for table to be enabled");
1237 }
1238
1239 @Override
1240 public void throwTimeoutException(long elapsedTime) throws TimeoutException {
1241 throw new TimeoutException("Table " + tableName + " not yet enabled after " +
1242 elapsedTime + "msec");
1243 }
1244 });
1245 }
1246 }
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260 @Override
1261 public HTableDescriptor[] enableTables(String regex) throws IOException {
1262 return enableTables(Pattern.compile(regex));
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275 @Override
1276 public HTableDescriptor[] enableTables(Pattern pattern) throws IOException {
1277 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
1278 for (HTableDescriptor table : listTables(pattern)) {
1279 if (isTableDisabled(table.getTableName())) {
1280 try {
1281 enableTable(table.getTableName());
1282 } catch (IOException ex) {
1283 LOG.info("Failed to enable table " + table.getTableName(), ex);
1284 failed.add(table);
1285 }
1286 }
1287 }
1288 return failed.toArray(new HTableDescriptor[failed.size()]);
1289 }
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304 @Override
1305 public void disableTableAsync(final TableName tableName) throws IOException {
1306 disableTableAsyncV2(tableName);
1307 }
1308
1309 public void disableTableAsync(final byte[] tableName) throws IOException {
1310 disableTableAsync(TableName.valueOf(tableName));
1311 }
1312
1313 public void disableTableAsync(final String tableName) throws IOException {
1314 disableTableAsync(TableName.valueOf(tableName));
1315 }
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328 @Override
1329 public void disableTable(final TableName tableName)
1330 throws IOException {
1331 Future<Void> future = disableTableAsyncV2(tableName);
1332 try {
1333 future.get(syncWaitTimeout, TimeUnit.MILLISECONDS);
1334 } catch (InterruptedException e) {
1335 throw new InterruptedIOException("Interrupted when waiting for table to be disabled");
1336 } catch (TimeoutException e) {
1337 throw new TimeoutIOException(e);
1338 } catch (ExecutionException e) {
1339 if (e.getCause() instanceof IOException) {
1340 throw (IOException)e.getCause();
1341 } else {
1342 throw new IOException(e.getCause());
1343 }
1344 }
1345 }
1346
1347 public void disableTable(final byte[] tableName)
1348 throws IOException {
1349 disableTable(TableName.valueOf(tableName));
1350 }
1351
1352 public void disableTable(final String tableName)
1353 throws IOException {
1354 disableTable(TableName.valueOf(tableName));
1355 }
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370 private Future<Void> disableTableAsyncV2(final TableName tableName) throws IOException {
1371 TableName.isLegalFullyQualifiedTableName(tableName.getName());
1372 DisableTableResponse response = executeCallable(
1373 new MasterCallable<DisableTableResponse>(getConnection()) {
1374 @Override
1375 public DisableTableResponse call(int callTimeout) throws ServiceException {
1376 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1377 controller.setCallTimeout(callTimeout);
1378 controller.setPriority(tableName);
1379
1380 LOG.info("Started disable of " + tableName);
1381 DisableTableRequest req =
1382 RequestConverter.buildDisableTableRequest(
1383 tableName, ng.getNonceGroup(), ng.newNonce());
1384 return master.disableTable(controller, req);
1385 }
1386 });
1387 return new DisableTableFuture(this, tableName, response);
1388 }
1389
1390 private static class DisableTableFuture extends ProcedureFuture<Void> {
1391 private final TableName tableName;
1392
1393 public DisableTableFuture(final HBaseAdmin admin, final TableName tableName,
1394 final DisableTableResponse response) {
1395 super(admin, (response != null && response.hasProcId()) ? response.getProcId() : null);
1396 this.tableName = tableName;
1397 }
1398
1399 @Override
1400 protected Void waitOperationResult(final long deadlineTs)
1401 throws IOException, TimeoutException {
1402 waitTableDisabled(deadlineTs);
1403 return null;
1404 }
1405
1406 @Override
1407 protected Void postOperationResult(final Void result, final long deadlineTs)
1408 throws IOException, TimeoutException {
1409 LOG.info("Disabled " + tableName);
1410 return result;
1411 }
1412
1413 private void waitTableDisabled(final long deadlineTs)
1414 throws IOException, TimeoutException {
1415 waitForState(deadlineTs, new WaitForStateCallable() {
1416 @Override
1417 public boolean checkState(int tries) throws IOException {
1418 return getAdmin().isTableDisabled(tableName);
1419 }
1420
1421 @Override
1422 public void throwInterruptedException() throws InterruptedIOException {
1423 throw new InterruptedIOException("Interrupted when waiting for table to be disabled");
1424 }
1425
1426 @Override
1427 public void throwTimeoutException(long elapsedTime) throws TimeoutException {
1428 throw new TimeoutException("Table " + tableName + " not yet disabled after " +
1429 elapsedTime + "msec");
1430 }
1431 });
1432 }
1433 }
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448 @Override
1449 public HTableDescriptor[] disableTables(String regex) throws IOException {
1450 return disableTables(Pattern.compile(regex));
1451 }
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464 @Override
1465 public HTableDescriptor[] disableTables(Pattern pattern) throws IOException {
1466 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
1467 for (HTableDescriptor table : listTables(pattern)) {
1468 if (isTableEnabled(table.getTableName())) {
1469 try {
1470 disableTable(table.getTableName());
1471 } catch (IOException ex) {
1472 LOG.info("Failed to disable table " + table.getTableName(), ex);
1473 failed.add(table);
1474 }
1475 }
1476 }
1477 return failed.toArray(new HTableDescriptor[failed.size()]);
1478 }
1479
1480
1481
1482
1483
1484 private void checkTableExistence(TableName tableName) throws IOException {
1485 if (!tableExists(tableName)) {
1486 throw new TableNotFoundException(tableName);
1487 }
1488 }
1489
1490
1491
1492
1493
1494
1495 @Override
1496 public boolean isTableEnabled(TableName tableName) throws IOException {
1497 checkTableExistence(tableName);
1498 return connection.isTableEnabled(tableName);
1499 }
1500
1501 public boolean isTableEnabled(byte[] tableName) throws IOException {
1502 return isTableEnabled(TableName.valueOf(tableName));
1503 }
1504
1505 public boolean isTableEnabled(String tableName) throws IOException {
1506 return isTableEnabled(TableName.valueOf(tableName));
1507 }
1508
1509
1510
1511
1512
1513
1514
1515
1516 @Override
1517 public boolean isTableDisabled(TableName tableName) throws IOException {
1518 checkTableExistence(tableName);
1519 return connection.isTableDisabled(tableName);
1520 }
1521
1522 public boolean isTableDisabled(byte[] tableName) throws IOException {
1523 return isTableDisabled(TableName.valueOf(tableName));
1524 }
1525
1526 public boolean isTableDisabled(String tableName) throws IOException {
1527 return isTableDisabled(TableName.valueOf(tableName));
1528 }
1529
1530
1531
1532
1533
1534
1535 @Override
1536 public boolean isTableAvailable(TableName tableName) throws IOException {
1537 return connection.isTableAvailable(tableName);
1538 }
1539
1540 public boolean isTableAvailable(byte[] tableName) throws IOException {
1541 return isTableAvailable(TableName.valueOf(tableName));
1542 }
1543
1544 public boolean isTableAvailable(String tableName) throws IOException {
1545 return isTableAvailable(TableName.valueOf(tableName));
1546 }
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560 @Override
1561 public boolean isTableAvailable(TableName tableName,
1562 byte[][] splitKeys) throws IOException {
1563 return connection.isTableAvailable(tableName, splitKeys);
1564 }
1565
1566 public boolean isTableAvailable(byte[] tableName,
1567 byte[][] splitKeys) throws IOException {
1568 return isTableAvailable(TableName.valueOf(tableName), splitKeys);
1569 }
1570
1571 public boolean isTableAvailable(String tableName,
1572 byte[][] splitKeys) throws IOException {
1573 return isTableAvailable(TableName.valueOf(tableName), splitKeys);
1574 }
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587 @Override
1588 public Pair<Integer, Integer> getAlterStatus(final TableName tableName)
1589 throws IOException {
1590 return executeCallable(new MasterCallable<Pair<Integer, Integer>>(getConnection()) {
1591 @Override
1592 public Pair<Integer, Integer> call(int callTimeout) throws ServiceException {
1593 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1594 controller.setCallTimeout(callTimeout);
1595 controller.setPriority(tableName);
1596
1597 GetSchemaAlterStatusRequest req = RequestConverter
1598 .buildGetSchemaAlterStatusRequest(tableName);
1599 GetSchemaAlterStatusResponse ret = master.getSchemaAlterStatus(controller, req);
1600 Pair<Integer, Integer> pair = new Pair<Integer, Integer>(Integer.valueOf(ret
1601 .getYetToUpdateRegions()), Integer.valueOf(ret.getTotalRegions()));
1602 return pair;
1603 }
1604 });
1605 }
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619 @Override
1620 public Pair<Integer, Integer> getAlterStatus(final byte[] tableName)
1621 throws IOException {
1622 return getAlterStatus(TableName.valueOf(tableName));
1623 }
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633 public void addColumn(final byte[] tableName, HColumnDescriptor column)
1634 throws IOException {
1635 addColumn(TableName.valueOf(tableName), column);
1636 }
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646 public void addColumn(final String tableName, HColumnDescriptor column)
1647 throws IOException {
1648 addColumn(TableName.valueOf(tableName), column);
1649 }
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659 @Override
1660 public void addColumn(final TableName tableName, final HColumnDescriptor column)
1661 throws IOException {
1662 executeCallable(new MasterCallable<Void>(getConnection()) {
1663 @Override
1664 public Void call(int callTimeout) throws ServiceException {
1665 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1666 controller.setCallTimeout(callTimeout);
1667 controller.setPriority(tableName);
1668 AddColumnRequest req = RequestConverter.buildAddColumnRequest(
1669 tableName, column, ng.getNonceGroup(), ng.newNonce());
1670 master.addColumn(controller,req);
1671 return null;
1672 }
1673 });
1674 }
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684 public void deleteColumn(final byte[] tableName, final String columnName)
1685 throws IOException {
1686 deleteColumn(TableName.valueOf(tableName), Bytes.toBytes(columnName));
1687 }
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697 public void deleteColumn(final String tableName, final String columnName)
1698 throws IOException {
1699 deleteColumn(TableName.valueOf(tableName), Bytes.toBytes(columnName));
1700 }
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710 @Override
1711 public void deleteColumn(final TableName tableName, final byte [] columnName)
1712 throws IOException {
1713 executeCallable(new MasterCallable<Void>(getConnection()) {
1714 @Override
1715 public Void call(int callTimeout) throws ServiceException {
1716 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1717 controller.setCallTimeout(callTimeout);
1718 controller.setPriority(tableName);
1719 DeleteColumnRequest req = RequestConverter.buildDeleteColumnRequest(
1720 tableName, columnName, ng.getNonceGroup(), ng.newNonce());
1721 master.deleteColumn(controller, req);
1722 return null;
1723 }
1724 });
1725 }
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735 public void modifyColumn(final String tableName, HColumnDescriptor descriptor)
1736 throws IOException {
1737 modifyColumn(TableName.valueOf(tableName), descriptor);
1738 }
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748 public void modifyColumn(final byte[] tableName, HColumnDescriptor descriptor)
1749 throws IOException {
1750 modifyColumn(TableName.valueOf(tableName), descriptor);
1751 }
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761 @Override
1762 public void modifyColumn(final TableName tableName, final HColumnDescriptor descriptor)
1763 throws IOException {
1764 executeCallable(new MasterCallable<Void>(getConnection()) {
1765 @Override
1766 public Void call(int callTimeout) throws ServiceException {
1767 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1768 controller.setCallTimeout(callTimeout);
1769 controller.setPriority(tableName);
1770 ModifyColumnRequest req = RequestConverter.buildModifyColumnRequest(
1771 tableName, descriptor, ng.getNonceGroup(), ng.newNonce());
1772 master.modifyColumn(controller, req);
1773 return null;
1774 }
1775 });
1776 }
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786 @Override
1787 public void closeRegion(final String regionname, final String serverName)
1788 throws IOException {
1789 closeRegion(Bytes.toBytes(regionname), serverName);
1790 }
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802 @Override
1803 public void closeRegion(final byte [] regionname, final String serverName)
1804 throws IOException {
1805 if (serverName != null) {
1806 Pair<HRegionInfo, ServerName> pair = MetaTableAccessor.getRegion(connection, regionname);
1807 if (pair == null || pair.getFirst() == null) {
1808 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1809 } else {
1810 closeRegion(ServerName.valueOf(serverName), pair.getFirst());
1811 }
1812 } else {
1813 Pair<HRegionInfo, ServerName> pair = MetaTableAccessor.getRegion(connection, regionname);
1814 if (pair == null) {
1815 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1816 } else if (pair.getSecond() == null) {
1817 throw new NoServerForRegionException(Bytes.toStringBinary(regionname));
1818 } else {
1819 closeRegion(pair.getSecond(), pair.getFirst());
1820 }
1821 }
1822 }
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845 @Override
1846 public boolean closeRegionWithEncodedRegionName(final String encodedRegionName,
1847 final String serverName) throws IOException {
1848 if (null == serverName || ("").equals(serverName.trim())) {
1849 throw new IllegalArgumentException(
1850 "The servername cannot be null or empty.");
1851 }
1852 ServerName sn = ServerName.valueOf(serverName);
1853 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1854
1855 CloseRegionRequest request =
1856 RequestConverter.buildCloseRegionRequest(sn, encodedRegionName, false);
1857 try {
1858 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1859
1860
1861 CloseRegionResponse response = admin.closeRegion(controller, request);
1862 boolean isRegionClosed = response.getClosed();
1863 if (false == isRegionClosed) {
1864 LOG.error("Not able to close the region " + encodedRegionName + ".");
1865 }
1866 return isRegionClosed;
1867 } catch (ServiceException se) {
1868 throw ProtobufUtil.getRemoteException(se);
1869 }
1870 }
1871
1872
1873
1874
1875
1876
1877
1878
1879 @Override
1880 public void closeRegion(final ServerName sn, final HRegionInfo hri)
1881 throws IOException {
1882 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1883 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1884
1885
1886 ProtobufUtil.closeRegion(controller, admin, sn, hri.getRegionName(), false);
1887 }
1888
1889
1890
1891
1892 @Override
1893 public List<HRegionInfo> getOnlineRegions(final ServerName sn) throws IOException {
1894 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1895 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1896 return ProtobufUtil.getOnlineRegions(controller, admin);
1897 }
1898
1899
1900
1901
1902 @Override
1903 public void flush(final TableName tableName) throws IOException {
1904 checkTableExists(tableName);
1905 if (isTableDisabled(tableName)) {
1906 LOG.info("Table is disabled: " + tableName.getNameAsString());
1907 return;
1908 }
1909 execProcedure("flush-table-proc", tableName.getNameAsString(),
1910 new HashMap<String, String>());
1911 }
1912
1913
1914
1915
1916 @Override
1917 public void flushRegion(final byte[] regionName) throws IOException {
1918 Pair<HRegionInfo, ServerName> regionServerPair = getRegion(regionName);
1919 if (regionServerPair == null) {
1920 throw new IllegalArgumentException("Unknown regionname: " + Bytes.toStringBinary(regionName));
1921 }
1922 if (regionServerPair.getSecond() == null) {
1923 throw new NoServerForRegionException(Bytes.toStringBinary(regionName));
1924 }
1925 flush(regionServerPair.getSecond(), regionServerPair.getFirst());
1926 }
1927
1928
1929
1930
1931
1932 @Deprecated
1933 public void flush(final String tableNameOrRegionName)
1934 throws IOException, InterruptedException {
1935 flush(Bytes.toBytes(tableNameOrRegionName));
1936 }
1937
1938
1939
1940
1941
1942 @Deprecated
1943 public void flush(final byte[] tableNameOrRegionName)
1944 throws IOException, InterruptedException {
1945 try {
1946 flushRegion(tableNameOrRegionName);
1947 } catch (IllegalArgumentException e) {
1948
1949 flush(TableName.valueOf(tableNameOrRegionName));
1950 }
1951 }
1952
1953 private void flush(final ServerName sn, final HRegionInfo hri)
1954 throws IOException {
1955 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1956 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1957 FlushRegionRequest request =
1958 RequestConverter.buildFlushRegionRequest(hri.getRegionName());
1959 try {
1960 admin.flushRegion(controller, request);
1961 } catch (ServiceException se) {
1962 throw ProtobufUtil.getRemoteException(se);
1963 }
1964 }
1965
1966
1967
1968
1969 @Override
1970 public void compact(final TableName tableName)
1971 throws IOException {
1972 compact(tableName, null, false);
1973 }
1974
1975
1976
1977
1978 @Override
1979 public void compactRegion(final byte[] regionName)
1980 throws IOException {
1981 compactRegion(regionName, null, false);
1982 }
1983
1984
1985
1986
1987
1988 @Deprecated
1989 public void compact(final String tableNameOrRegionName)
1990 throws IOException {
1991 compact(Bytes.toBytes(tableNameOrRegionName));
1992 }
1993
1994
1995
1996
1997
1998 @Deprecated
1999 public void compact(final byte[] tableNameOrRegionName)
2000 throws IOException {
2001 try {
2002 compactRegion(tableNameOrRegionName, null, false);
2003 } catch (IllegalArgumentException e) {
2004 compact(TableName.valueOf(tableNameOrRegionName), null, false);
2005 }
2006 }
2007
2008
2009
2010
2011 @Override
2012 public void compact(final TableName tableName, final byte[] columnFamily)
2013 throws IOException {
2014 compact(tableName, columnFamily, false);
2015 }
2016
2017
2018
2019
2020 @Override
2021 public void compactRegion(final byte[] regionName, final byte[] columnFamily)
2022 throws IOException {
2023 compactRegion(regionName, columnFamily, false);
2024 }
2025
2026
2027
2028
2029
2030 @Deprecated
2031 public void compact(String tableOrRegionName, String columnFamily)
2032 throws IOException {
2033 compact(Bytes.toBytes(tableOrRegionName), Bytes.toBytes(columnFamily));
2034 }
2035
2036
2037
2038
2039
2040 @Deprecated
2041 public void compact(final byte[] tableNameOrRegionName, final byte[] columnFamily)
2042 throws IOException {
2043 try {
2044 compactRegion(tableNameOrRegionName, columnFamily, false);
2045 } catch (IllegalArgumentException e) {
2046
2047 compact(TableName.valueOf(tableNameOrRegionName), columnFamily, false);
2048 }
2049 }
2050
2051
2052
2053
2054 @Override
2055 public void compactRegionServer(final ServerName sn, boolean major)
2056 throws IOException, InterruptedException {
2057 for (HRegionInfo region : getOnlineRegions(sn)) {
2058 compact(sn, region, major, null);
2059 }
2060 }
2061
2062
2063
2064
2065 @Override
2066 public void majorCompact(final TableName tableName)
2067 throws IOException {
2068 compact(tableName, null, true);
2069 }
2070
2071
2072
2073
2074 @Override
2075 public void majorCompactRegion(final byte[] regionName)
2076 throws IOException {
2077 compactRegion(regionName, null, true);
2078 }
2079
2080
2081
2082
2083
2084 @Deprecated
2085 public void majorCompact(final String tableNameOrRegionName)
2086 throws IOException {
2087 majorCompact(Bytes.toBytes(tableNameOrRegionName));
2088 }
2089
2090
2091
2092
2093
2094 @Deprecated
2095 public void majorCompact(final byte[] tableNameOrRegionName)
2096 throws IOException {
2097 try {
2098 compactRegion(tableNameOrRegionName, null, true);
2099 } catch (IllegalArgumentException e) {
2100
2101 compact(TableName.valueOf(tableNameOrRegionName), null, true);
2102 }
2103 }
2104
2105
2106
2107
2108 @Override
2109 public void majorCompact(final TableName tableName, final byte[] columnFamily)
2110 throws IOException {
2111 compact(tableName, columnFamily, true);
2112 }
2113
2114
2115
2116
2117 @Override
2118 public void majorCompactRegion(final byte[] regionName, final byte[] columnFamily)
2119 throws IOException {
2120 compactRegion(regionName, columnFamily, true);
2121 }
2122
2123
2124
2125
2126
2127 @Deprecated
2128 public void majorCompact(final String tableNameOrRegionName, final String columnFamily)
2129 throws IOException {
2130 majorCompact(Bytes.toBytes(tableNameOrRegionName), Bytes.toBytes(columnFamily));
2131 }
2132
2133
2134
2135
2136
2137 @Deprecated
2138 public void majorCompact(final byte[] tableNameOrRegionName, final byte[] columnFamily)
2139 throws IOException {
2140 try {
2141 compactRegion(tableNameOrRegionName, columnFamily, true);
2142 } catch (IllegalArgumentException e) {
2143
2144 compact(TableName.valueOf(tableNameOrRegionName), columnFamily, true);
2145 }
2146 }
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158 private void compact(final TableName tableName, final byte[] columnFamily,final boolean major)
2159 throws IOException {
2160 ZooKeeperWatcher zookeeper = null;
2161 try {
2162 checkTableExists(tableName);
2163 zookeeper = new ZooKeeperWatcher(conf, ZK_IDENTIFIER_PREFIX + connection.toString(),
2164 new ThrowableAbortable());
2165 List<Pair<HRegionInfo, ServerName>> pairs =
2166 MetaTableAccessor.getTableRegionsAndLocations(zookeeper, connection, tableName);
2167 for (Pair<HRegionInfo, ServerName> pair: pairs) {
2168 if (pair.getFirst().isOffline()) continue;
2169 if (pair.getSecond() == null) continue;
2170 try {
2171 compact(pair.getSecond(), pair.getFirst(), major, columnFamily);
2172 } catch (NotServingRegionException e) {
2173 if (LOG.isDebugEnabled()) {
2174 LOG.debug("Trying to" + (major ? " major" : "") + " compact " +
2175 pair.getFirst() + ": " +
2176 StringUtils.stringifyException(e));
2177 }
2178 }
2179 }
2180 } finally {
2181 if (zookeeper != null) {
2182 zookeeper.close();
2183 }
2184 }
2185 }
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197 private void compactRegion(final byte[] regionName, final byte[] columnFamily,final boolean major)
2198 throws IOException {
2199 Pair<HRegionInfo, ServerName> regionServerPair = getRegion(regionName);
2200 if (regionServerPair == null) {
2201 throw new IllegalArgumentException("Invalid region: " + Bytes.toStringBinary(regionName));
2202 }
2203 if (regionServerPair.getSecond() == null) {
2204 throw new NoServerForRegionException(Bytes.toStringBinary(regionName));
2205 }
2206 compact(regionServerPair.getSecond(), regionServerPair.getFirst(), major, columnFamily);
2207 }
2208
2209 private void compact(final ServerName sn, final HRegionInfo hri,
2210 final boolean major, final byte [] family)
2211 throws IOException {
2212 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2213 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2214 CompactRegionRequest request =
2215 RequestConverter.buildCompactRegionRequest(hri.getRegionName(), major, family);
2216 try {
2217
2218 admin.compactRegion(controller, request);
2219 } catch (ServiceException se) {
2220 throw ProtobufUtil.getRemoteException(se);
2221 }
2222 }
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237 @Override
2238 public void move(final byte [] encodedRegionName, final byte [] destServerName)
2239 throws IOException {
2240
2241 executeCallable(new MasterCallable<Void>(getConnection()) {
2242 @Override
2243 public Void call(int callTimeout) throws ServiceException {
2244 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2245 controller.setCallTimeout(callTimeout);
2246
2247 if (isMetaRegion(encodedRegionName)) {
2248 controller.setPriority(TableName.META_TABLE_NAME);
2249 }
2250
2251 try {
2252 MoveRegionRequest request =
2253 RequestConverter.buildMoveRegionRequest(encodedRegionName, destServerName);
2254 master.moveRegion(controller, request);
2255 } catch (DeserializationException de) {
2256 LOG.error("Could not parse destination server name: " + de);
2257 throw new ServiceException(new DoNotRetryIOException(de));
2258 }
2259 return null;
2260 }
2261 });
2262 }
2263
2264 private boolean isMetaRegion(final byte[] regionName) {
2265 return Bytes.equals(regionName, HRegionInfo.FIRST_META_REGIONINFO.getRegionName())
2266 || Bytes.equals(regionName, HRegionInfo.FIRST_META_REGIONINFO.getEncodedNameAsBytes());
2267 }
2268
2269
2270
2271
2272
2273
2274
2275
2276 @Override
2277 public void assign(final byte[] regionName) throws MasterNotRunningException,
2278 ZooKeeperConnectionException, IOException {
2279 final byte[] toBeAssigned = getRegionName(regionName);
2280 executeCallable(new MasterCallable<Void>(getConnection()) {
2281 @Override
2282 public Void call(int callTimeout) throws ServiceException {
2283 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2284 controller.setCallTimeout(callTimeout);
2285
2286 if (isMetaRegion(regionName)) {
2287 controller.setPriority(TableName.META_TABLE_NAME);
2288 }
2289
2290 AssignRegionRequest request =
2291 RequestConverter.buildAssignRegionRequest(toBeAssigned);
2292 master.assignRegion(controller,request);
2293 return null;
2294 }
2295 });
2296 }
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312 @Override
2313 public void unassign(final byte [] regionName, final boolean force)
2314 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
2315 final byte[] toBeUnassigned = getRegionName(regionName);
2316 executeCallable(new MasterCallable<Void>(getConnection()) {
2317 @Override
2318 public Void call(int callTimeout) throws ServiceException {
2319 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2320 controller.setCallTimeout(callTimeout);
2321
2322 if (isMetaRegion(regionName)) {
2323 controller.setPriority(TableName.META_TABLE_NAME);
2324 }
2325 UnassignRegionRequest request =
2326 RequestConverter.buildUnassignRegionRequest(toBeUnassigned, force);
2327 master.unassignRegion(controller, request);
2328 return null;
2329 }
2330 });
2331 }
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345 @Override
2346 public void offline(final byte [] regionName)
2347 throws IOException {
2348 executeCallable(new MasterCallable<Void>(getConnection()) {
2349 @Override
2350 public Void call(int callTimeout) throws ServiceException {
2351 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2352 controller.setCallTimeout(callTimeout);
2353
2354 if (isMetaRegion(regionName)) {
2355 controller.setPriority(TableName.META_TABLE_NAME);
2356 }
2357 master.offlineRegion(controller, RequestConverter.buildOfflineRegionRequest(regionName));
2358 return null;
2359 }
2360 });
2361 }
2362
2363
2364
2365
2366
2367
2368
2369 @Override
2370 public boolean setBalancerRunning(final boolean on, final boolean synchronous)
2371 throws IOException {
2372 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2373 @Override
2374 public Boolean call(int callTimeout) throws ServiceException {
2375 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2376 controller.setCallTimeout(callTimeout);
2377
2378 SetBalancerRunningRequest req =
2379 RequestConverter.buildSetBalancerRunningRequest(on, synchronous);
2380 return master.setBalancerRunning(controller, req).getPrevBalanceValue();
2381 }
2382 });
2383 }
2384
2385
2386
2387
2388
2389
2390
2391 @Override
2392 public boolean balancer() throws IOException {
2393 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2394 @Override
2395 public Boolean call(int callTimeout) throws ServiceException {
2396 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2397 controller.setCallTimeout(callTimeout);
2398
2399 return master.balance(controller,
2400 RequestConverter.buildBalanceRequest(false)).getBalancerRan();
2401 }
2402 });
2403 }
2404
2405 @Override
2406 public boolean balancer(final boolean force) throws IOException {
2407 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2408 @Override
2409 public Boolean call(int callTimeout) throws ServiceException {
2410 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2411 controller.setCallTimeout(callTimeout);
2412
2413 return master.balance(controller,
2414 RequestConverter.buildBalanceRequest(force)).getBalancerRan();
2415 }
2416 });
2417 }
2418
2419
2420
2421
2422
2423
2424
2425 @Override
2426 public boolean isBalancerEnabled() throws IOException {
2427 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2428 @Override
2429 public Boolean call(int callTimeout) throws ServiceException {
2430 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2431 controller.setCallTimeout(callTimeout);
2432
2433 return master.isBalancerEnabled(controller,
2434 RequestConverter.buildIsBalancerEnabledRequest()).getEnabled();
2435 }
2436 });
2437 }
2438
2439
2440
2441
2442
2443
2444 @Override
2445 public boolean normalize() throws IOException {
2446 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2447 @Override
2448 public Boolean call(int callTimeout) throws ServiceException {
2449 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2450 controller.setCallTimeout(callTimeout);
2451
2452 return master.normalize(controller,
2453 RequestConverter.buildNormalizeRequest()).getNormalizerRan();
2454 }
2455 });
2456 }
2457
2458
2459
2460
2461
2462
2463 public boolean isNormalizerEnabled() throws IOException {
2464 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2465 @Override
2466 public Boolean call(int callTimeout) throws ServiceException {
2467 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2468 controller.setCallTimeout(callTimeout);
2469
2470 return master.isNormalizerEnabled(controller,
2471 RequestConverter.buildIsNormalizerEnabledRequest()).getEnabled();
2472 }
2473 });
2474 }
2475
2476
2477
2478
2479
2480
2481 public boolean setNormalizerRunning(final boolean on) throws IOException {
2482 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2483 @Override
2484 public Boolean call(int callTimeout) throws ServiceException {
2485 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2486 controller.setCallTimeout(callTimeout);
2487
2488 SetNormalizerRunningRequest req =
2489 RequestConverter.buildSetNormalizerRunningRequest(on);
2490 return master.setNormalizerRunning(controller, req).getPrevNormalizerValue();
2491 }
2492 });
2493 }
2494
2495
2496
2497
2498
2499
2500
2501 @Override
2502 public boolean enableCatalogJanitor(final boolean enable)
2503 throws IOException {
2504 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2505 @Override
2506 public Boolean call(int callTimeout) throws ServiceException {
2507 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2508 controller.setCallTimeout(callTimeout);
2509
2510 return master.enableCatalogJanitor(controller,
2511 RequestConverter.buildEnableCatalogJanitorRequest(enable)).getPrevValue();
2512 }
2513 });
2514 }
2515
2516
2517
2518
2519
2520
2521 @Override
2522 public int runCatalogScan() throws IOException {
2523 return executeCallable(new MasterCallable<Integer>(getConnection()) {
2524 @Override
2525 public Integer call(int callTimeout) throws ServiceException {
2526 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2527 controller.setCallTimeout(callTimeout);
2528
2529 return master.runCatalogScan(controller,
2530 RequestConverter.buildCatalogScanRequest()).getScanResult();
2531 }
2532 });
2533 }
2534
2535
2536
2537
2538
2539 @Override
2540 public boolean isCatalogJanitorEnabled() throws IOException {
2541 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
2542 @Override
2543 public Boolean call(int callTimeout) throws ServiceException {
2544 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2545 controller.setCallTimeout(callTimeout);
2546
2547 return master.isCatalogJanitorEnabled(controller,
2548 RequestConverter.buildIsCatalogJanitorEnabledRequest()).getValue();
2549 }
2550 });
2551 }
2552
2553 private boolean isEncodedRegionName(byte[] regionName) throws IOException {
2554 try {
2555 HRegionInfo.parseRegionName(regionName);
2556 return false;
2557 } catch (IOException e) {
2558 if (StringUtils.stringifyException(e)
2559 .contains(HRegionInfo.INVALID_REGION_NAME_FORMAT_MESSAGE)) {
2560 return true;
2561 }
2562 throw e;
2563 }
2564 }
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574 @Override
2575 public void mergeRegions(final byte[] nameOfRegionA,
2576 final byte[] nameOfRegionB, final boolean forcible)
2577 throws IOException {
2578 final byte[] encodedNameOfRegionA = isEncodedRegionName(nameOfRegionA) ?
2579 nameOfRegionA : HRegionInfo.encodeRegionName(nameOfRegionA).getBytes();
2580 final byte[] encodedNameOfRegionB = isEncodedRegionName(nameOfRegionB) ?
2581 nameOfRegionB : HRegionInfo.encodeRegionName(nameOfRegionB).getBytes();
2582
2583 Pair<HRegionInfo, ServerName> pair = getRegion(nameOfRegionA);
2584 if (pair != null && pair.getFirst().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID)
2585 throw new IllegalArgumentException("Can't invoke merge on non-default regions directly");
2586 pair = getRegion(nameOfRegionB);
2587 if (pair != null && pair.getFirst().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID)
2588 throw new IllegalArgumentException("Can't invoke merge on non-default regions directly");
2589 executeCallable(new MasterCallable<Void>(getConnection()) {
2590 @Override
2591 public Void call(int callTimeout) throws ServiceException {
2592 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2593 controller.setCallTimeout(callTimeout);
2594
2595 try {
2596 DispatchMergingRegionsRequest request = RequestConverter
2597 .buildDispatchMergingRegionsRequest(encodedNameOfRegionA,
2598 encodedNameOfRegionB, forcible);
2599 master.dispatchMergingRegions(controller, request);
2600 } catch (DeserializationException de) {
2601 LOG.error("Could not parse destination server name: " + de);
2602 }
2603 return null;
2604 }
2605 });
2606 }
2607
2608
2609
2610
2611 @Override
2612 public void split(final TableName tableName)
2613 throws IOException {
2614 split(tableName, null);
2615 }
2616
2617
2618
2619
2620 @Override
2621 public void splitRegion(final byte[] regionName)
2622 throws IOException {
2623 splitRegion(regionName, null);
2624 }
2625
2626
2627
2628
2629
2630 @Deprecated
2631 public void split(final String tableNameOrRegionName)
2632 throws IOException, InterruptedException {
2633 split(Bytes.toBytes(tableNameOrRegionName));
2634 }
2635
2636
2637
2638
2639
2640 @Deprecated
2641 public void split(final byte[] tableNameOrRegionName)
2642 throws IOException, InterruptedException {
2643 split(tableNameOrRegionName, null);
2644 }
2645
2646
2647
2648
2649 @Override
2650 public void split(final TableName tableName, final byte [] splitPoint)
2651 throws IOException {
2652 ZooKeeperWatcher zookeeper = null;
2653 try {
2654 checkTableExists(tableName);
2655 zookeeper = new ZooKeeperWatcher(conf, ZK_IDENTIFIER_PREFIX + connection.toString(),
2656 new ThrowableAbortable());
2657 List<Pair<HRegionInfo, ServerName>> pairs =
2658 MetaTableAccessor.getTableRegionsAndLocations(zookeeper, connection, tableName);
2659 for (Pair<HRegionInfo, ServerName> pair: pairs) {
2660
2661 if (pair.getSecond() == null) continue;
2662 HRegionInfo r = pair.getFirst();
2663
2664 if (r.isSplitParent()) continue;
2665
2666 if (r.getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID ||
2667 (splitPoint != null && !r.containsRow(splitPoint))) continue;
2668
2669 split(pair.getSecond(), pair.getFirst(), splitPoint);
2670 }
2671 } finally {
2672 if (zookeeper != null) {
2673 zookeeper.close();
2674 }
2675 }
2676 }
2677
2678
2679
2680
2681 @Override
2682 public void splitRegion(final byte[] regionName, final byte [] splitPoint)
2683 throws IOException {
2684 Pair<HRegionInfo, ServerName> regionServerPair = getRegion(regionName);
2685 if (regionServerPair == null) {
2686 throw new IllegalArgumentException("Invalid region: " + Bytes.toStringBinary(regionName));
2687 }
2688 if (regionServerPair.getFirst() != null &&
2689 regionServerPair.getFirst().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID) {
2690 throw new IllegalArgumentException("Can't split replicas directly. "
2691 + "Replicas are auto-split when their primary is split.");
2692 }
2693 if (regionServerPair.getSecond() == null) {
2694 throw new NoServerForRegionException(Bytes.toStringBinary(regionName));
2695 }
2696 split(regionServerPair.getSecond(), regionServerPair.getFirst(), splitPoint);
2697 }
2698
2699
2700
2701
2702
2703 @Deprecated
2704 public void split(final String tableNameOrRegionName,
2705 final String splitPoint) throws IOException {
2706 split(Bytes.toBytes(tableNameOrRegionName), Bytes.toBytes(splitPoint));
2707 }
2708
2709
2710
2711
2712
2713 @Deprecated
2714 public void split(final byte[] tableNameOrRegionName,
2715 final byte [] splitPoint) throws IOException {
2716 try {
2717 splitRegion(tableNameOrRegionName, splitPoint);
2718 } catch (IllegalArgumentException e) {
2719
2720 split(TableName.valueOf(tableNameOrRegionName), splitPoint);
2721 }
2722 }
2723
2724 @VisibleForTesting
2725 public void split(final ServerName sn, final HRegionInfo hri,
2726 byte[] splitPoint) throws IOException {
2727 if (hri.getStartKey() != null && splitPoint != null &&
2728 Bytes.compareTo(hri.getStartKey(), splitPoint) == 0) {
2729 throw new IOException("should not give a splitkey which equals to startkey!");
2730 }
2731 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2732 controller.setPriority(hri.getTable());
2733
2734
2735 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2736 ProtobufUtil.split(controller, admin, hri, splitPoint);
2737 }
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748 @Override
2749 public void modifyTable(final TableName tableName, final HTableDescriptor htd)
2750 throws IOException {
2751 if (!tableName.equals(htd.getTableName())) {
2752 throw new IllegalArgumentException("the specified table name '" + tableName +
2753 "' doesn't match with the HTD one: " + htd.getTableName());
2754 }
2755
2756 executeCallable(new MasterCallable<Void>(getConnection()) {
2757 @Override
2758 public Void call(int callTimeout) throws ServiceException {
2759 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2760 controller.setCallTimeout(callTimeout);
2761 controller.setPriority(tableName);
2762 ModifyTableRequest request = RequestConverter.buildModifyTableRequest(
2763 tableName, htd, ng.getNonceGroup(), ng.newNonce());
2764 master.modifyTable(controller, request);
2765 return null;
2766 }
2767 });
2768 }
2769
2770 public void modifyTable(final byte[] tableName, final HTableDescriptor htd)
2771 throws IOException {
2772 modifyTable(TableName.valueOf(tableName), htd);
2773 }
2774
2775 public void modifyTable(final String tableName, final HTableDescriptor htd)
2776 throws IOException {
2777 modifyTable(TableName.valueOf(tableName), htd);
2778 }
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789 Pair<HRegionInfo, ServerName> getRegion(final byte[] regionName) throws IOException {
2790 if (regionName == null) {
2791 throw new IllegalArgumentException("Pass a table name or region name");
2792 }
2793 Pair<HRegionInfo, ServerName> pair =
2794 MetaTableAccessor.getRegion(connection, regionName);
2795 if (pair == null) {
2796 final AtomicReference<Pair<HRegionInfo, ServerName>> result =
2797 new AtomicReference<Pair<HRegionInfo, ServerName>>(null);
2798 final String encodedName = Bytes.toString(regionName);
2799 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
2800 @Override
2801 public boolean processRow(Result data) throws IOException {
2802 HRegionInfo info = HRegionInfo.getHRegionInfo(data);
2803 if (info == null) {
2804 LOG.warn("No serialized HRegionInfo in " + data);
2805 return true;
2806 }
2807 RegionLocations rl = MetaTableAccessor.getRegionLocations(data);
2808 boolean matched = false;
2809 ServerName sn = null;
2810 for (HRegionLocation h : rl.getRegionLocations()) {
2811 if (h != null && encodedName.equals(h.getRegionInfo().getEncodedName())) {
2812 sn = h.getServerName();
2813 info = h.getRegionInfo();
2814 matched = true;
2815 }
2816 }
2817 if (!matched) return true;
2818 result.set(new Pair<HRegionInfo, ServerName>(info, sn));
2819 return false;
2820 }
2821 };
2822
2823 MetaScanner.metaScan(connection, visitor, null);
2824 pair = result.get();
2825 }
2826 return pair;
2827 }
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837 private byte[] getRegionName(
2838 final byte[] regionNameOrEncodedRegionName) throws IOException {
2839 if (Bytes.equals(regionNameOrEncodedRegionName,
2840 HRegionInfo.FIRST_META_REGIONINFO.getRegionName())
2841 || Bytes.equals(regionNameOrEncodedRegionName,
2842 HRegionInfo.FIRST_META_REGIONINFO.getEncodedNameAsBytes())) {
2843 return HRegionInfo.FIRST_META_REGIONINFO.getRegionName();
2844 }
2845 byte[] tmp = regionNameOrEncodedRegionName;
2846 Pair<HRegionInfo, ServerName> regionServerPair = getRegion(regionNameOrEncodedRegionName);
2847 if (regionServerPair != null && regionServerPair.getFirst() != null) {
2848 tmp = regionServerPair.getFirst().getRegionName();
2849 }
2850 return tmp;
2851 }
2852
2853
2854
2855
2856
2857
2858
2859
2860 private TableName checkTableExists(final TableName tableName)
2861 throws IOException {
2862 if (!MetaTableAccessor.tableExists(connection, tableName)) {
2863 throw new TableNotFoundException(tableName);
2864 }
2865 return tableName;
2866 }
2867
2868
2869
2870
2871
2872 @Override
2873 public synchronized void shutdown() throws IOException {
2874 executeCallable(new MasterCallable<Void>(getConnection()) {
2875 @Override
2876 public Void call(int callTimeout) throws ServiceException {
2877 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2878 controller.setCallTimeout(callTimeout);
2879 controller.setPriority(HConstants.HIGH_QOS);
2880 master.shutdown(controller, ShutdownRequest.newBuilder().build());
2881 return null;
2882 }
2883 });
2884 }
2885
2886
2887
2888
2889
2890
2891
2892 @Override
2893 public synchronized void stopMaster() throws IOException {
2894 executeCallable(new MasterCallable<Void>(getConnection()) {
2895 @Override
2896 public Void call(int callTimeout) throws ServiceException {
2897 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2898 controller.setCallTimeout(callTimeout);
2899 controller.setPriority(HConstants.HIGH_QOS);
2900 master.stopMaster(controller, StopMasterRequest.newBuilder().build());
2901 return null;
2902 }
2903 });
2904 }
2905
2906
2907
2908
2909
2910
2911
2912 @Override
2913 public synchronized void stopRegionServer(final String hostnamePort)
2914 throws IOException {
2915 String hostname = Addressing.parseHostname(hostnamePort);
2916 int port = Addressing.parsePort(hostnamePort);
2917 AdminService.BlockingInterface admin =
2918 this.connection.getAdmin(ServerName.valueOf(hostname, port, 0));
2919 StopServerRequest request = RequestConverter.buildStopServerRequest(
2920 "Called by admin client " + this.connection.toString());
2921 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2922
2923 controller.setPriority(HConstants.HIGH_QOS);
2924 try {
2925
2926 admin.stopServer(controller, request);
2927 } catch (ServiceException se) {
2928 throw ProtobufUtil.getRemoteException(se);
2929 }
2930 }
2931
2932
2933
2934
2935
2936
2937 @Override
2938 public ClusterStatus getClusterStatus() throws IOException {
2939 return executeCallable(new MasterCallable<ClusterStatus>(getConnection()) {
2940 @Override
2941 public ClusterStatus call(int callTimeout) throws ServiceException {
2942 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2943 controller.setCallTimeout(callTimeout);
2944 GetClusterStatusRequest req = RequestConverter.buildGetClusterStatusRequest();
2945 return ClusterStatus.convert(master.getClusterStatus(controller, req).getClusterStatus());
2946 }
2947 });
2948 }
2949
2950
2951
2952
2953 @Override
2954 public Configuration getConfiguration() {
2955 return this.conf;
2956 }
2957
2958
2959
2960
2961
2962
2963 @Override
2964 public void createNamespace(final NamespaceDescriptor descriptor) throws IOException {
2965 executeCallable(new MasterCallable<Void>(getConnection()) {
2966 @Override
2967 public Void call(int callTimeout) throws Exception {
2968 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2969 controller.setCallTimeout(callTimeout);
2970
2971 master.createNamespace(controller,
2972 CreateNamespaceRequest.newBuilder()
2973 .setNamespaceDescriptor(ProtobufUtil
2974 .toProtoNamespaceDescriptor(descriptor)).build()
2975 );
2976 return null;
2977 }
2978 });
2979 }
2980
2981
2982
2983
2984
2985
2986 @Override
2987 public void modifyNamespace(final NamespaceDescriptor descriptor) throws IOException {
2988 executeCallable(new MasterCallable<Void>(getConnection()) {
2989 @Override
2990 public Void call(int callTimeout) throws Exception {
2991 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
2992 controller.setCallTimeout(callTimeout);
2993 master.modifyNamespace(controller, ModifyNamespaceRequest.newBuilder().
2994 setNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(descriptor)).build());
2995 return null;
2996 }
2997 });
2998 }
2999
3000
3001
3002
3003
3004
3005 @Override
3006 public void deleteNamespace(final String name) throws IOException {
3007 executeCallable(new MasterCallable<Void>(getConnection()) {
3008 @Override
3009 public Void call(int callTimeout) throws Exception {
3010 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3011 controller.setCallTimeout(callTimeout);
3012 master.deleteNamespace(controller, DeleteNamespaceRequest.newBuilder().
3013 setNamespaceName(name).build());
3014 return null;
3015 }
3016 });
3017 }
3018
3019
3020
3021
3022
3023
3024
3025 @Override
3026 public NamespaceDescriptor getNamespaceDescriptor(final String name)
3027 throws NamespaceNotFoundException, IOException {
3028 return
3029 executeCallable(new MasterCallable<NamespaceDescriptor>(getConnection()) {
3030 @Override
3031 public NamespaceDescriptor call(int callTimeout) throws Exception {
3032 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3033 controller.setCallTimeout(callTimeout);
3034 return ProtobufUtil.toNamespaceDescriptor(
3035 master.getNamespaceDescriptor(controller, GetNamespaceDescriptorRequest.newBuilder().
3036 setNamespaceName(name).build()).getNamespaceDescriptor());
3037 }
3038 });
3039 }
3040
3041
3042
3043
3044
3045
3046 @Override
3047 public NamespaceDescriptor[] listNamespaceDescriptors() throws IOException {
3048 return
3049 executeCallable(new MasterCallable<NamespaceDescriptor[]>(getConnection()) {
3050 @Override
3051 public NamespaceDescriptor[] call(int callTimeout) throws Exception {
3052 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3053 controller.setCallTimeout(callTimeout);
3054 List<HBaseProtos.NamespaceDescriptor> list =
3055 master.listNamespaceDescriptors(controller,
3056 ListNamespaceDescriptorsRequest.newBuilder().build())
3057 .getNamespaceDescriptorList();
3058 NamespaceDescriptor[] res = new NamespaceDescriptor[list.size()];
3059 for(int i = 0; i < list.size(); i++) {
3060 res[i] = ProtobufUtil.toNamespaceDescriptor(list.get(i));
3061 }
3062 return res;
3063 }
3064 });
3065 }
3066
3067
3068
3069
3070
3071
3072 @Override
3073 public ProcedureInfo[] listProcedures() throws IOException {
3074 return
3075 executeCallable(new MasterCallable<ProcedureInfo[]>(getConnection()) {
3076 @Override
3077 public ProcedureInfo[] call(int callTimeout) throws Exception {
3078 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3079 controller.setCallTimeout(callTimeout);
3080 List<ProcedureProtos.Procedure> procList = master.listProcedures(
3081 controller, ListProceduresRequest.newBuilder().build()).getProcedureList();
3082 ProcedureInfo[] procInfoList = new ProcedureInfo[procList.size()];
3083 for (int i = 0; i < procList.size(); i++) {
3084 procInfoList[i] = ProcedureInfo.convert(procList.get(i));
3085 }
3086 return procInfoList;
3087 }
3088 });
3089 }
3090
3091
3092
3093
3094
3095
3096
3097 @Override
3098 public HTableDescriptor[] listTableDescriptorsByNamespace(final String name) throws IOException {
3099 return
3100 executeCallable(new MasterCallable<HTableDescriptor[]>(getConnection()) {
3101 @Override
3102 public HTableDescriptor[] call(int callTimeout) throws Exception {
3103 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3104 controller.setCallTimeout(callTimeout);
3105 List<TableSchema> list =
3106 master.listTableDescriptorsByNamespace(controller,
3107 ListTableDescriptorsByNamespaceRequest.newBuilder().setNamespaceName(name)
3108 .build()).getTableSchemaList();
3109 HTableDescriptor[] res = new HTableDescriptor[list.size()];
3110 for(int i=0; i < list.size(); i++) {
3111
3112 res[i] = HTableDescriptor.convert(list.get(i));
3113 }
3114 return res;
3115 }
3116 });
3117 }
3118
3119
3120
3121
3122
3123
3124
3125 @Override
3126 public TableName[] listTableNamesByNamespace(final String name) throws IOException {
3127 return
3128 executeCallable(new MasterCallable<TableName[]>(getConnection()) {
3129 @Override
3130 public TableName[] call(int callTimeout) throws Exception {
3131 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3132 controller.setCallTimeout(callTimeout);
3133 List<HBaseProtos.TableName> tableNames =
3134 master.listTableNamesByNamespace(controller, ListTableNamesByNamespaceRequest.
3135 newBuilder().setNamespaceName(name).build())
3136 .getTableNameList();
3137 TableName[] result = new TableName[tableNames.size()];
3138 for (int i = 0; i < tableNames.size(); i++) {
3139 result[i] = ProtobufUtil.toTableName(tableNames.get(i));
3140 }
3141 return result;
3142 }
3143 });
3144 }
3145
3146
3147
3148
3149
3150
3151
3152
3153 public static void checkHBaseAvailable(Configuration conf)
3154 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException, IOException {
3155 Configuration copyOfConf = HBaseConfiguration.create(conf);
3156
3157 copyOfConf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
3158 copyOfConf.setInt("zookeeper.recovery.retry", 0);
3159 try (ClusterConnection connection =
3160 (ClusterConnection)ConnectionFactory.createConnection(copyOfConf)) {
3161
3162
3163 ZooKeeperKeepAliveConnection zkw = null;
3164 try {
3165
3166 zkw = ((ConnectionManager.HConnectionImplementation)connection).
3167 getKeepAliveZooKeeperWatcher();
3168 zkw.getRecoverableZooKeeper().getZooKeeper().exists(zkw.baseZNode, false);
3169 } catch (IOException e) {
3170 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
3171 } catch (InterruptedException e) {
3172 throw (InterruptedIOException)
3173 new InterruptedIOException("Can't connect to ZooKeeper").initCause(e);
3174 } catch (KeeperException e) {
3175 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
3176 } finally {
3177 if (zkw != null) {
3178 zkw.close();
3179 }
3180 }
3181 connection.isMasterRunning();
3182 }
3183 }
3184
3185
3186
3187
3188
3189
3190
3191
3192 @Override
3193 public List<HRegionInfo> getTableRegions(final TableName tableName)
3194 throws IOException {
3195 ZooKeeperWatcher zookeeper =
3196 new ZooKeeperWatcher(conf, ZK_IDENTIFIER_PREFIX + connection.toString(),
3197 new ThrowableAbortable());
3198 List<HRegionInfo> Regions = null;
3199 try {
3200 Regions = MetaTableAccessor.getTableRegions(zookeeper, connection, tableName, true);
3201 } finally {
3202 zookeeper.close();
3203 }
3204 return Regions;
3205 }
3206
3207 public List<HRegionInfo> getTableRegions(final byte[] tableName)
3208 throws IOException {
3209 return getTableRegions(TableName.valueOf(tableName));
3210 }
3211
3212 @Override
3213 public synchronized void close() throws IOException {
3214 if (cleanupConnectionOnClose && this.connection != null && !this.closed) {
3215 this.connection.close();
3216 this.closed = true;
3217 }
3218 }
3219
3220
3221
3222
3223
3224
3225
3226 @Override
3227 public HTableDescriptor[] getTableDescriptorsByTableName(final List<TableName> tableNames)
3228 throws IOException {
3229 return executeCallable(new MasterCallable<HTableDescriptor[]>(getConnection()) {
3230 @Override
3231 public HTableDescriptor[] call(int callTimeout) throws Exception {
3232 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3233 controller.setCallTimeout(callTimeout);
3234 GetTableDescriptorsRequest req =
3235 RequestConverter.buildGetTableDescriptorsRequest(tableNames);
3236 return ProtobufUtil.getHTableDescriptorArray(master.getTableDescriptors(controller, req));
3237 }
3238 });
3239 }
3240
3241
3242
3243
3244
3245
3246
3247 private HTableDescriptor getTableDescriptorByTableName(TableName tableName)
3248 throws IOException {
3249 List<TableName> tableNames = new ArrayList<TableName>(1);
3250 tableNames.add(tableName);
3251
3252 HTableDescriptor[] htdl = getTableDescriptorsByTableName(tableNames);
3253
3254 if (htdl == null || htdl.length == 0) {
3255 return null;
3256 }
3257 else {
3258 return htdl[0];
3259 }
3260 }
3261
3262
3263
3264
3265
3266
3267
3268 @Override
3269 public HTableDescriptor[] getTableDescriptors(List<String> names)
3270 throws IOException {
3271 List<TableName> tableNames = new ArrayList<TableName>(names.size());
3272 for(String name : names) {
3273 tableNames.add(TableName.valueOf(name));
3274 }
3275 return getTableDescriptorsByTableName(tableNames);
3276 }
3277
3278 private RollWALWriterResponse rollWALWriterImpl(final ServerName sn) throws IOException,
3279 FailedLogCloseException {
3280 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
3281 RollWALWriterRequest request = RequestConverter.buildRollWALWriterRequest();
3282 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3283
3284 try {
3285
3286 return admin.rollWALWriter(controller, request);
3287 } catch (ServiceException se) {
3288 throw ProtobufUtil.getRemoteException(se);
3289 }
3290 }
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314 @Deprecated
3315 public synchronized byte[][] rollHLogWriter(String serverName)
3316 throws IOException, FailedLogCloseException {
3317 ServerName sn = ServerName.valueOf(serverName);
3318 final RollWALWriterResponse response = rollWALWriterImpl(sn);
3319 int regionCount = response.getRegionToFlushCount();
3320 if (0 == regionCount) {
3321 return null;
3322 }
3323 byte[][] regionsToFlush = new byte[regionCount][];
3324 for (int i = 0; i < regionCount; i++) {
3325 ByteString region = response.getRegionToFlush(i);
3326 regionsToFlush[i] = region.toByteArray();
3327 }
3328 return regionsToFlush;
3329 }
3330
3331 @Override
3332 public synchronized void rollWALWriter(ServerName serverName)
3333 throws IOException, FailedLogCloseException {
3334 rollWALWriterImpl(serverName);
3335 }
3336
3337 @Override
3338 public String[] getMasterCoprocessors() {
3339 try {
3340 return getClusterStatus().getMasterCoprocessors();
3341 } catch (IOException e) {
3342 LOG.error("Could not getClusterStatus()",e);
3343 return null;
3344 }
3345 }
3346
3347
3348
3349
3350 @Override
3351 public CompactionState getCompactionState(final TableName tableName)
3352 throws IOException {
3353 CompactionState state = CompactionState.NONE;
3354 ZooKeeperWatcher zookeeper =
3355 new ZooKeeperWatcher(conf, ZK_IDENTIFIER_PREFIX + connection.toString(),
3356 new ThrowableAbortable());
3357 try {
3358 checkTableExists(tableName);
3359 List<Pair<HRegionInfo, ServerName>> pairs =
3360 MetaTableAccessor.getTableRegionsAndLocations(zookeeper, connection, tableName);
3361 for (Pair<HRegionInfo, ServerName> pair: pairs) {
3362 if (pair.getFirst().isOffline()) continue;
3363 if (pair.getSecond() == null) continue;
3364 try {
3365 ServerName sn = pair.getSecond();
3366 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
3367 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
3368 pair.getFirst().getRegionName(), true);
3369 GetRegionInfoResponse response = admin.getRegionInfo(null, request);
3370 switch (response.getCompactionState()) {
3371 case MAJOR_AND_MINOR:
3372 return CompactionState.MAJOR_AND_MINOR;
3373 case MAJOR:
3374 if (state == CompactionState.MINOR) {
3375 return CompactionState.MAJOR_AND_MINOR;
3376 }
3377 state = CompactionState.MAJOR;
3378 break;
3379 case MINOR:
3380 if (state == CompactionState.MAJOR) {
3381 return CompactionState.MAJOR_AND_MINOR;
3382 }
3383 state = CompactionState.MINOR;
3384 break;
3385 case NONE:
3386 default:
3387 }
3388 } catch (NotServingRegionException e) {
3389 if (LOG.isDebugEnabled()) {
3390 LOG.debug("Trying to get compaction state of " +
3391 pair.getFirst() + ": " +
3392 StringUtils.stringifyException(e));
3393 }
3394 } catch (RemoteException e) {
3395 if (e.getMessage().indexOf(NotServingRegionException.class.getName()) >= 0) {
3396 if (LOG.isDebugEnabled()) {
3397 LOG.debug("Trying to get compaction state of " + pair.getFirst() + ": "
3398 + StringUtils.stringifyException(e));
3399 }
3400 } else {
3401 throw e;
3402 }
3403 }
3404 }
3405 } catch (ServiceException se) {
3406 throw ProtobufUtil.getRemoteException(se);
3407 } finally {
3408 zookeeper.close();
3409 }
3410 return state;
3411 }
3412
3413
3414
3415
3416 @Override
3417 public CompactionState getCompactionStateForRegion(final byte[] regionName)
3418 throws IOException {
3419 try {
3420 Pair<HRegionInfo, ServerName> regionServerPair = getRegion(regionName);
3421 if (regionServerPair == null) {
3422 throw new IllegalArgumentException("Invalid region: " + Bytes.toStringBinary(regionName));
3423 }
3424 if (regionServerPair.getSecond() == null) {
3425 throw new NoServerForRegionException(Bytes.toStringBinary(regionName));
3426 }
3427 ServerName sn = regionServerPair.getSecond();
3428 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
3429 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
3430 regionServerPair.getFirst().getRegionName(), true);
3431 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3432
3433 GetRegionInfoResponse response = admin.getRegionInfo(controller, request);
3434 return response.getCompactionState();
3435 } catch (ServiceException se) {
3436 throw ProtobufUtil.getRemoteException(se);
3437 }
3438 }
3439
3440
3441
3442
3443
3444 @Deprecated
3445 public CompactionState getCompactionState(final String tableNameOrRegionName)
3446 throws IOException, InterruptedException {
3447 return getCompactionState(Bytes.toBytes(tableNameOrRegionName));
3448 }
3449
3450
3451
3452
3453
3454 @Deprecated
3455 public CompactionState getCompactionState(final byte[] tableNameOrRegionName)
3456 throws IOException, InterruptedException {
3457 try {
3458 return getCompactionStateForRegion(tableNameOrRegionName);
3459 } catch (IllegalArgumentException e) {
3460
3461 return getCompactionState(TableName.valueOf(tableNameOrRegionName));
3462 }
3463 }
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481 @Override
3482 public void snapshot(final String snapshotName,
3483 final TableName tableName) throws IOException,
3484 SnapshotCreationException, IllegalArgumentException {
3485 snapshot(snapshotName, tableName, SnapshotDescription.Type.FLUSH);
3486 }
3487
3488 public void snapshot(final String snapshotName,
3489 final String tableName) throws IOException,
3490 SnapshotCreationException, IllegalArgumentException {
3491 snapshot(snapshotName, TableName.valueOf(tableName),
3492 SnapshotDescription.Type.FLUSH);
3493 }
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510 public void snapshot(final byte[] snapshotName, final byte[] tableName,
3511 final SnapshotDescription.Type flushType) throws
3512 IOException, SnapshotCreationException, IllegalArgumentException {
3513 snapshot(Bytes.toString(snapshotName), Bytes.toString(tableName), flushType);
3514 }
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531 @Override
3532 public void snapshot(final byte[] snapshotName,
3533 final TableName tableName) throws IOException,
3534 SnapshotCreationException, IllegalArgumentException {
3535 snapshot(Bytes.toString(snapshotName), tableName, SnapshotDescription.Type.FLUSH);
3536 }
3537
3538 public void snapshot(final byte[] snapshotName,
3539 final byte[] tableName) throws IOException,
3540 SnapshotCreationException, IllegalArgumentException {
3541 snapshot(Bytes.toString(snapshotName), TableName.valueOf(tableName),
3542 SnapshotDescription.Type.FLUSH);
3543 }
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563 @Override
3564 public void snapshot(final String snapshotName,
3565 final TableName tableName,
3566 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
3567 IllegalArgumentException {
3568 SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
3569 builder.setTable(tableName.getNameAsString());
3570 builder.setName(snapshotName);
3571 builder.setType(type);
3572 snapshot(builder.build());
3573 }
3574
3575 public void snapshot(final String snapshotName,
3576 final String tableName,
3577 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
3578 IllegalArgumentException {
3579 snapshot(snapshotName, TableName.valueOf(tableName), type);
3580 }
3581
3582 public void snapshot(final String snapshotName,
3583 final byte[] tableName,
3584 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
3585 IllegalArgumentException {
3586 snapshot(snapshotName, TableName.valueOf(tableName), type);
3587 }
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610 @Override
3611 public void snapshot(SnapshotDescription snapshot) throws IOException, SnapshotCreationException,
3612 IllegalArgumentException {
3613
3614 SnapshotResponse response = takeSnapshotAsync(snapshot);
3615 final IsSnapshotDoneRequest request = IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot)
3616 .build();
3617 IsSnapshotDoneResponse done = null;
3618 long start = EnvironmentEdgeManager.currentTime();
3619 long max = response.getExpectedTimeout();
3620 long maxPauseTime = max / this.numRetries;
3621 int tries = 0;
3622 LOG.debug("Waiting a max of " + max + " ms for snapshot '" +
3623 ClientSnapshotDescriptionUtils.toString(snapshot) + "'' to complete. (max " +
3624 maxPauseTime + " ms per retry)");
3625 while (tries == 0
3626 || ((EnvironmentEdgeManager.currentTime() - start) < max && !done.getDone())) {
3627 try {
3628
3629 long sleep = getPauseTime(tries++);
3630 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
3631 LOG.debug("(#" + tries + ") Sleeping: " + sleep +
3632 "ms while waiting for snapshot completion.");
3633 Thread.sleep(sleep);
3634 } catch (InterruptedException e) {
3635 throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
3636 }
3637 LOG.debug("Getting current status of snapshot from master...");
3638 done = executeCallable(new MasterCallable<IsSnapshotDoneResponse>(getConnection()) {
3639 @Override
3640 public IsSnapshotDoneResponse call(int callTimeout) throws ServiceException {
3641 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3642 controller.setCallTimeout(callTimeout);
3643 return master.isSnapshotDone(controller, request);
3644 }
3645 });
3646 }
3647 if (!done.getDone()) {
3648 throw new SnapshotCreationException("Snapshot '" + snapshot.getName()
3649 + "' wasn't completed in expectedTime:" + max + " ms", snapshot);
3650 }
3651 }
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663 @Override
3664 public SnapshotResponse takeSnapshotAsync(SnapshotDescription snapshot) throws IOException,
3665 SnapshotCreationException {
3666 ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
3667 final SnapshotRequest request = SnapshotRequest.newBuilder().setSnapshot(snapshot)
3668 .build();
3669
3670 return executeCallable(new MasterCallable<SnapshotResponse>(getConnection()) {
3671 @Override
3672 public SnapshotResponse call(int callTimeout) throws ServiceException {
3673 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3674 controller.setCallTimeout(callTimeout);
3675 return master.snapshot(controller, request);
3676 }
3677 });
3678 }
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700 @Override
3701 public boolean isSnapshotFinished(final SnapshotDescription snapshot)
3702 throws IOException, HBaseSnapshotException, UnknownSnapshotException {
3703
3704 return executeCallable(new MasterCallable<IsSnapshotDoneResponse>(getConnection()) {
3705 @Override
3706 public IsSnapshotDoneResponse call(int callTimeout) throws ServiceException {
3707 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3708 controller.setCallTimeout(callTimeout);
3709 return master.isSnapshotDone(controller,
3710 IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot).build());
3711 }
3712 }).getDone();
3713 }
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728 @Override
3729 public void restoreSnapshot(final byte[] snapshotName)
3730 throws IOException, RestoreSnapshotException {
3731 restoreSnapshot(Bytes.toString(snapshotName));
3732 }
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747 @Override
3748 public void restoreSnapshot(final String snapshotName)
3749 throws IOException, RestoreSnapshotException {
3750 boolean takeFailSafeSnapshot =
3751 conf.getBoolean("hbase.snapshot.restore.take.failsafe.snapshot", false);
3752 restoreSnapshot(snapshotName, takeFailSafeSnapshot);
3753 }
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771 @Override
3772 public void restoreSnapshot(final byte[] snapshotName, final boolean takeFailSafeSnapshot)
3773 throws IOException, RestoreSnapshotException {
3774 restoreSnapshot(Bytes.toString(snapshotName), takeFailSafeSnapshot);
3775 }
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793 @Override
3794 public void restoreSnapshot(final String snapshotName, boolean takeFailSafeSnapshot)
3795 throws IOException, RestoreSnapshotException {
3796 TableName tableName = null;
3797 for (SnapshotDescription snapshotInfo: listSnapshots()) {
3798 if (snapshotInfo.getName().equals(snapshotName)) {
3799 tableName = TableName.valueOf(snapshotInfo.getTable());
3800 break;
3801 }
3802 }
3803
3804 if (tableName == null) {
3805 throw new RestoreSnapshotException(
3806 "Unable to find the table name for snapshot=" + snapshotName);
3807 }
3808
3809
3810 if (!tableExists(tableName)) {
3811 cloneSnapshot(snapshotName, tableName);
3812 return;
3813 }
3814
3815
3816 if (!isTableDisabled(tableName)) {
3817 throw new TableNotDisabledException(tableName);
3818 }
3819
3820
3821 String failSafeSnapshotSnapshotName = null;
3822 if (takeFailSafeSnapshot) {
3823 failSafeSnapshotSnapshotName = conf.get("hbase.snapshot.restore.failsafe.name",
3824 "hbase-failsafe-{snapshot.name}-{restore.timestamp}");
3825 failSafeSnapshotSnapshotName = failSafeSnapshotSnapshotName
3826 .replace("{snapshot.name}", snapshotName)
3827 .replace("{table.name}", tableName.toString().replace(TableName.NAMESPACE_DELIM, '.'))
3828 .replace("{restore.timestamp}", String.valueOf(EnvironmentEdgeManager.currentTime()));
3829 LOG.info("Taking restore-failsafe snapshot: " + failSafeSnapshotSnapshotName);
3830 snapshot(failSafeSnapshotSnapshotName, tableName);
3831 }
3832
3833 try {
3834
3835 internalRestoreSnapshot(snapshotName, tableName);
3836 } catch (IOException e) {
3837
3838
3839 if (takeFailSafeSnapshot) {
3840 try {
3841 internalRestoreSnapshot(failSafeSnapshotSnapshotName, tableName);
3842 String msg = "Restore snapshot=" + snapshotName +
3843 " failed. Rollback to snapshot=" + failSafeSnapshotSnapshotName + " succeeded.";
3844 LOG.error(msg, e);
3845 throw new RestoreSnapshotException(msg, e);
3846 } catch (IOException ex) {
3847 String msg = "Failed to restore and rollback to snapshot=" + failSafeSnapshotSnapshotName;
3848 LOG.error(msg, ex);
3849 throw new RestoreSnapshotException(msg, e);
3850 }
3851 } else {
3852 throw new RestoreSnapshotException("Failed to restore snapshot=" + snapshotName, e);
3853 }
3854 }
3855
3856
3857 if (takeFailSafeSnapshot) {
3858 try {
3859 LOG.info("Deleting restore-failsafe snapshot: " + failSafeSnapshotSnapshotName);
3860 deleteSnapshot(failSafeSnapshotSnapshotName);
3861 } catch (IOException e) {
3862 LOG.error("Unable to remove the failsafe snapshot: " + failSafeSnapshotSnapshotName, e);
3863 }
3864 }
3865 }
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877 public void cloneSnapshot(final byte[] snapshotName, final byte[] tableName)
3878 throws IOException, TableExistsException, RestoreSnapshotException {
3879 cloneSnapshot(Bytes.toString(snapshotName), TableName.valueOf(tableName));
3880 }
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892 @Override
3893 public void cloneSnapshot(final byte[] snapshotName, final TableName tableName)
3894 throws IOException, TableExistsException, RestoreSnapshotException {
3895 cloneSnapshot(Bytes.toString(snapshotName), tableName);
3896 }
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910 public void cloneSnapshot(final String snapshotName, final String tableName)
3911 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
3912 cloneSnapshot(snapshotName, TableName.valueOf(tableName));
3913 }
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925 @Override
3926 public void cloneSnapshot(final String snapshotName, final TableName tableName)
3927 throws IOException, TableExistsException, RestoreSnapshotException {
3928 if (tableExists(tableName)) {
3929 throw new TableExistsException(tableName);
3930 }
3931 internalRestoreSnapshot(snapshotName, tableName);
3932 waitUntilTableIsEnabled(tableName);
3933 }
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946 @Override
3947 public byte[] execProcedureWithRet(String signature, String instance,
3948 Map<String, String> props) throws IOException {
3949 ProcedureDescription.Builder builder = ProcedureDescription.newBuilder();
3950 builder.setSignature(signature).setInstance(instance);
3951 for (Entry<String, String> entry : props.entrySet()) {
3952 NameStringPair pair = NameStringPair.newBuilder().setName(entry.getKey())
3953 .setValue(entry.getValue()).build();
3954 builder.addConfiguration(pair);
3955 }
3956
3957 final ExecProcedureRequest request = ExecProcedureRequest.newBuilder()
3958 .setProcedure(builder.build()).build();
3959
3960 ExecProcedureResponse response = executeCallable(new MasterCallable<ExecProcedureResponse>(
3961 getConnection()) {
3962 @Override
3963 public ExecProcedureResponse call(int callTimeout) throws ServiceException {
3964 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
3965 controller.setCallTimeout(callTimeout);
3966 return master.execProcedureWithRet(controller, request);
3967 }
3968 });
3969
3970 return response.hasReturnData() ? response.getReturnData().toByteArray() : null;
3971 }
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982 @Override
3983 public void execProcedure(String signature, String instance,
3984 Map<String, String> props) throws IOException {
3985 ProcedureDescription.Builder builder = ProcedureDescription.newBuilder();
3986 builder.setSignature(signature).setInstance(instance);
3987 for (Entry<String, String> entry : props.entrySet()) {
3988 NameStringPair pair = NameStringPair.newBuilder().setName(entry.getKey())
3989 .setValue(entry.getValue()).build();
3990 builder.addConfiguration(pair);
3991 }
3992
3993 final ExecProcedureRequest request = ExecProcedureRequest.newBuilder()
3994 .setProcedure(builder.build()).build();
3995
3996 ExecProcedureResponse response = executeCallable(new MasterCallable<ExecProcedureResponse>(
3997 getConnection()) {
3998 @Override
3999 public ExecProcedureResponse call(int callTimeout) throws ServiceException {
4000 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4001 controller.setCallTimeout(callTimeout);
4002 return master.execProcedure(controller, request);
4003 }
4004 });
4005
4006 long start = EnvironmentEdgeManager.currentTime();
4007 long max = response.getExpectedTimeout();
4008 long maxPauseTime = max / this.numRetries;
4009 int tries = 0;
4010 LOG.debug("Waiting a max of " + max + " ms for procedure '" +
4011 signature + " : " + instance + "'' to complete. (max " + maxPauseTime + " ms per retry)");
4012 boolean done = false;
4013 while (tries == 0
4014 || ((EnvironmentEdgeManager.currentTime() - start) < max && !done)) {
4015 try {
4016
4017 long sleep = getPauseTime(tries++);
4018 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
4019 LOG.debug("(#" + tries + ") Sleeping: " + sleep +
4020 "ms while waiting for procedure completion.");
4021 Thread.sleep(sleep);
4022 } catch (InterruptedException e) {
4023 throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
4024 }
4025 LOG.debug("Getting current status of procedure from master...");
4026 done = isProcedureFinished(signature, instance, props);
4027 }
4028 if (!done) {
4029 throw new IOException("Procedure '" + signature + " : " + instance
4030 + "' wasn't completed in expectedTime:" + max + " ms");
4031 }
4032 }
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051 @Override
4052 public boolean isProcedureFinished(String signature, String instance, Map<String, String> props)
4053 throws IOException {
4054 final ProcedureDescription.Builder builder = ProcedureDescription.newBuilder();
4055 builder.setSignature(signature).setInstance(instance);
4056 for (Entry<String, String> entry : props.entrySet()) {
4057 NameStringPair pair = NameStringPair.newBuilder().setName(entry.getKey())
4058 .setValue(entry.getValue()).build();
4059 builder.addConfiguration(pair);
4060 }
4061 final ProcedureDescription desc = builder.build();
4062 return executeCallable(
4063 new MasterCallable<IsProcedureDoneResponse>(getConnection()) {
4064 @Override
4065 public IsProcedureDoneResponse call(int callTimeout) throws ServiceException {
4066 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4067 controller.setCallTimeout(callTimeout);
4068 return master.isProcedureDone(controller, IsProcedureDoneRequest
4069 .newBuilder().setProcedure(desc).build());
4070 }
4071 }).getDone();
4072 }
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084 private void internalRestoreSnapshot(final String snapshotName, final TableName
4085 tableName)
4086 throws IOException, RestoreSnapshotException {
4087 SnapshotDescription snapshot = SnapshotDescription.newBuilder()
4088 .setName(snapshotName).setTable(tableName.getNameAsString()).build();
4089
4090
4091 internalRestoreSnapshotAsync(snapshot);
4092
4093 final IsRestoreSnapshotDoneRequest request = IsRestoreSnapshotDoneRequest.newBuilder()
4094 .setSnapshot(snapshot).build();
4095 IsRestoreSnapshotDoneResponse done = IsRestoreSnapshotDoneResponse.newBuilder()
4096 .setDone(false).buildPartial();
4097 final long maxPauseTime = 5000;
4098 int tries = 0;
4099 while (!done.getDone()) {
4100 try {
4101
4102 long sleep = getPauseTime(tries++);
4103 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
4104 LOG.debug(tries + ") Sleeping: " + sleep + " ms while we wait for snapshot restore to complete.");
4105 Thread.sleep(sleep);
4106 } catch (InterruptedException e) {
4107 throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
4108 }
4109 LOG.debug("Getting current status of snapshot restore from master...");
4110 done = executeCallable(new MasterCallable<IsRestoreSnapshotDoneResponse>(
4111 getConnection()) {
4112 @Override
4113 public IsRestoreSnapshotDoneResponse call(int callTimeout) throws ServiceException {
4114 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4115 controller.setCallTimeout(callTimeout);
4116 return master.isRestoreSnapshotDone(controller, request);
4117 }
4118 });
4119 }
4120 if (!done.getDone()) {
4121 throw new RestoreSnapshotException("Snapshot '" + snapshot.getName() + "' wasn't restored.");
4122 }
4123 }
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135 private RestoreSnapshotResponse internalRestoreSnapshotAsync(final SnapshotDescription snapshot)
4136 throws IOException, RestoreSnapshotException {
4137 ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
4138
4139 final RestoreSnapshotRequest request = RestoreSnapshotRequest.newBuilder().setSnapshot(snapshot)
4140 .build();
4141
4142
4143 return executeCallable(new MasterCallable<RestoreSnapshotResponse>(getConnection()) {
4144 @Override
4145 public RestoreSnapshotResponse call(int callTimeout) throws ServiceException {
4146 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4147 controller.setCallTimeout(callTimeout);
4148 return master.restoreSnapshot(controller, request);
4149 }
4150 });
4151 }
4152
4153
4154
4155
4156
4157
4158 @Override
4159 public List<SnapshotDescription> listSnapshots() throws IOException {
4160 return executeCallable(new MasterCallable<List<SnapshotDescription>>(getConnection()) {
4161 @Override
4162 public List<SnapshotDescription> call(int callTimeout) throws ServiceException {
4163 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4164 controller.setCallTimeout(callTimeout);
4165 return master.getCompletedSnapshots(controller,
4166 GetCompletedSnapshotsRequest.newBuilder().build()).getSnapshotsList();
4167 }
4168 });
4169 }
4170
4171
4172
4173
4174
4175
4176
4177
4178 @Override
4179 public List<SnapshotDescription> listSnapshots(String regex) throws IOException {
4180 return listSnapshots(Pattern.compile(regex));
4181 }
4182
4183
4184
4185
4186
4187
4188
4189
4190 @Override
4191 public List<SnapshotDescription> listSnapshots(Pattern pattern) throws IOException {
4192 List<SnapshotDescription> matched = new LinkedList<SnapshotDescription>();
4193 List<SnapshotDescription> snapshots = listSnapshots();
4194 for (SnapshotDescription snapshot : snapshots) {
4195 if (pattern.matcher(snapshot.getName()).matches()) {
4196 matched.add(snapshot);
4197 }
4198 }
4199 return matched;
4200 }
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210 @Override
4211 public List<SnapshotDescription> listTableSnapshots(String tableNameRegex,
4212 String snapshotNameRegex) throws IOException {
4213 return listTableSnapshots(Pattern.compile(tableNameRegex), Pattern.compile(snapshotNameRegex));
4214 }
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224 @Override
4225 public List<SnapshotDescription> listTableSnapshots(Pattern tableNamePattern,
4226 Pattern snapshotNamePattern) throws IOException {
4227 TableName[] tableNames = listTableNames(tableNamePattern);
4228
4229 List<SnapshotDescription> tableSnapshots = new LinkedList<SnapshotDescription>();
4230 List<SnapshotDescription> snapshots = listSnapshots(snapshotNamePattern);
4231
4232 List<TableName> listOfTableNames = Arrays.asList(tableNames);
4233 for (SnapshotDescription snapshot : snapshots) {
4234 if (listOfTableNames.contains(TableName.valueOf(snapshot.getTable()))) {
4235 tableSnapshots.add(snapshot);
4236 }
4237 }
4238 return tableSnapshots;
4239 }
4240
4241
4242
4243
4244
4245
4246 @Override
4247 public void deleteSnapshot(final byte[] snapshotName) throws IOException {
4248 deleteSnapshot(Bytes.toString(snapshotName));
4249 }
4250
4251
4252
4253
4254
4255
4256 @Override
4257 public void deleteSnapshot(final String snapshotName) throws IOException {
4258
4259 TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(snapshotName));
4260
4261 executeCallable(new MasterCallable<Void>(getConnection()) {
4262 @Override
4263 public Void call(int callTimeout) throws ServiceException {
4264 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4265 controller.setCallTimeout(callTimeout);
4266 master.deleteSnapshot(controller,
4267 DeleteSnapshotRequest.newBuilder().
4268 setSnapshot(SnapshotDescription.newBuilder().setName(snapshotName).build()).build()
4269 );
4270 return null;
4271 }
4272 });
4273 }
4274
4275
4276
4277
4278
4279
4280 @Override
4281 public void deleteSnapshots(final String regex) throws IOException {
4282 deleteSnapshots(Pattern.compile(regex));
4283 }
4284
4285
4286
4287
4288
4289
4290 @Override
4291 public void deleteSnapshots(final Pattern pattern) throws IOException {
4292 List<SnapshotDescription> snapshots = listSnapshots(pattern);
4293 for (final SnapshotDescription snapshot : snapshots) {
4294 try {
4295 internalDeleteSnapshot(snapshot);
4296 } catch (IOException ex) {
4297 LOG.info(
4298 "Failed to delete snapshot " + snapshot.getName() + " for table " + snapshot.getTable(),
4299 ex);
4300 }
4301 }
4302 }
4303
4304 private void internalDeleteSnapshot(final SnapshotDescription snapshot) throws IOException {
4305 executeCallable(new MasterCallable<Void>(getConnection()) {
4306 @Override
4307 public Void call(int callTimeout) throws ServiceException {
4308 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4309 controller.setCallTimeout(callTimeout);
4310 this.master.deleteSnapshot(controller, DeleteSnapshotRequest.newBuilder()
4311 .setSnapshot(snapshot).build());
4312 return null;
4313 }
4314 });
4315 }
4316
4317
4318
4319
4320
4321
4322
4323
4324 @Override
4325 public void deleteTableSnapshots(String tableNameRegex, String snapshotNameRegex)
4326 throws IOException {
4327 deleteTableSnapshots(Pattern.compile(tableNameRegex), Pattern.compile(snapshotNameRegex));
4328 }
4329
4330
4331
4332
4333
4334
4335
4336
4337 @Override
4338 public void deleteTableSnapshots(Pattern tableNamePattern, Pattern snapshotNamePattern)
4339 throws IOException {
4340 List<SnapshotDescription> snapshots = listTableSnapshots(tableNamePattern, snapshotNamePattern);
4341 for (SnapshotDescription snapshot : snapshots) {
4342 try {
4343 internalDeleteSnapshot(snapshot);
4344 LOG.debug("Successfully deleted snapshot: " + snapshot.getName());
4345 } catch (IOException e) {
4346 LOG.error("Failed to delete snapshot: " + snapshot.getName(), e);
4347 }
4348 }
4349 }
4350
4351
4352
4353
4354
4355
4356 @Override
4357 public void setQuota(final QuotaSettings quota) throws IOException {
4358 executeCallable(new MasterCallable<Void>(getConnection()) {
4359 @Override
4360 public Void call(int callTimeout) throws ServiceException {
4361 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4362 controller.setCallTimeout(callTimeout);
4363 this.master.setQuota(controller, QuotaSettings.buildSetQuotaRequestProto(quota));
4364 return null;
4365 }
4366 });
4367 }
4368
4369
4370
4371
4372
4373
4374
4375 @Override
4376 public QuotaRetriever getQuotaRetriever(final QuotaFilter filter) throws IOException {
4377 return QuotaRetriever.open(conf, filter);
4378 }
4379
4380 private <V> V executeCallable(MasterCallable<V> callable) throws IOException {
4381 return executeCallable(callable, rpcCallerFactory, operationTimeout, rpcTimeout);
4382 }
4383
4384 private static <V> V executeCallable(MasterCallable<V> callable,
4385 RpcRetryingCallerFactory rpcCallerFactory, int operationTimeout, int rpcTimeout)
4386 throws IOException {
4387 RpcRetryingCaller<V> caller = rpcCallerFactory.newCaller(rpcTimeout);
4388 try {
4389 return caller.callWithRetries(callable, operationTimeout);
4390 } finally {
4391 callable.close();
4392 }
4393 }
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416 @Override
4417 public CoprocessorRpcChannel coprocessorService() {
4418 return new MasterCoprocessorRpcChannel(connection);
4419 }
4420
4421
4422
4423
4424 private static class ThrowableAbortable implements Abortable {
4425
4426 @Override
4427 public void abort(String why, Throwable e) {
4428 throw new RuntimeException(why, e);
4429 }
4430
4431 @Override
4432 public boolean isAborted() {
4433 return true;
4434 }
4435 }
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459 @Override
4460 public CoprocessorRpcChannel coprocessorService(ServerName sn) {
4461 return new RegionServerCoprocessorRpcChannel(connection, sn);
4462 }
4463
4464 @Override
4465 public void updateConfiguration(ServerName server) throws IOException {
4466 try {
4467 this.connection.getAdmin(server).updateConfiguration(null,
4468 UpdateConfigurationRequest.getDefaultInstance());
4469 } catch (ServiceException e) {
4470 throw ProtobufUtil.getRemoteException(e);
4471 }
4472 }
4473
4474 @Override
4475 public void updateConfiguration() throws IOException {
4476 for (ServerName server : this.getClusterStatus().getServers()) {
4477 updateConfiguration(server);
4478 }
4479 }
4480
4481 @Override
4482 public int getMasterInfoPort() throws IOException {
4483
4484 ConnectionManager.HConnectionImplementation connection =
4485 (ConnectionManager.HConnectionImplementation)this.connection;
4486 ZooKeeperKeepAliveConnection zkw = connection.getKeepAliveZooKeeperWatcher();
4487 try {
4488 return MasterAddressTracker.getMasterInfoPort(zkw);
4489 } catch (KeeperException e) {
4490 throw new IOException("Failed to get master info port from MasterAddressTracker", e);
4491 }
4492 }
4493
4494 @Override
4495 public long getLastMajorCompactionTimestamp(final TableName tableName) throws IOException {
4496 return executeCallable(new MasterCallable<Long>(getConnection()) {
4497 @Override
4498 public Long call(int callTimeout) throws ServiceException {
4499 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4500 controller.setCallTimeout(callTimeout);
4501 MajorCompactionTimestampRequest req =
4502 MajorCompactionTimestampRequest.newBuilder()
4503 .setTableName(ProtobufUtil.toProtoTableName(tableName)).build();
4504 return master.getLastMajorCompactionTimestamp(controller, req).getCompactionTimestamp();
4505 }
4506 });
4507 }
4508
4509 @Override
4510 public long getLastMajorCompactionTimestampForRegion(final byte[] regionName) throws IOException {
4511 return executeCallable(new MasterCallable<Long>(getConnection()) {
4512 @Override
4513 public Long call(int callTimeout) throws ServiceException {
4514 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4515 controller.setCallTimeout(callTimeout);
4516 MajorCompactionTimestampForRegionRequest req =
4517 MajorCompactionTimestampForRegionRequest
4518 .newBuilder()
4519 .setRegion(
4520 RequestConverter
4521 .buildRegionSpecifier(RegionSpecifierType.REGION_NAME, regionName)).build();
4522 return master.getLastMajorCompactionTimestampForRegion(controller, req)
4523 .getCompactionTimestamp();
4524 }
4525 });
4526 }
4527
4528
4529
4530
4531
4532
4533 @InterfaceAudience.Private
4534 @InterfaceStability.Evolving
4535 protected static class ProcedureFuture<V> implements Future<V> {
4536 private ExecutionException exception = null;
4537 private boolean procResultFound = false;
4538 private boolean done = false;
4539 private boolean cancelled = false;
4540 private boolean waitForOpResult = false;
4541 private V result = null;
4542
4543 private final HBaseAdmin admin;
4544 private final Long procId;
4545
4546 public ProcedureFuture(final HBaseAdmin admin, final Long procId) {
4547 this.admin = admin;
4548 this.procId = procId;
4549 }
4550
4551 public ProcedureFuture(final HBaseAdmin admin, final Long procId,
4552 final boolean waitForOpResult) {
4553 this.admin = admin;
4554 this.procId = procId;
4555 this.waitForOpResult = waitForOpResult;
4556 }
4557
4558 @Override
4559 public boolean cancel(boolean mayInterruptIfRunning) {
4560 AbortProcedureRequest abortProcRequest = AbortProcedureRequest.newBuilder()
4561 .setProcId(procId).setMayInterruptIfRunning(mayInterruptIfRunning).build();
4562 try {
4563 cancelled = abortProcedureResult(abortProcRequest).getIsProcedureAborted();
4564 if (cancelled) {
4565 done = true;
4566 }
4567 } catch (IOException e) {
4568
4569
4570
4571 LOG.warn(
4572 "Cancelling the procedure with procId=" + procId + " throws exception " + e.getMessage(),
4573 e);
4574 cancelled = false;
4575 }
4576 return cancelled;
4577 }
4578
4579 @Override
4580 public boolean isCancelled() {
4581 return cancelled;
4582 }
4583
4584 protected AbortProcedureResponse abortProcedureResult(
4585 final AbortProcedureRequest request) throws IOException {
4586 return admin.executeCallable(new MasterCallable<AbortProcedureResponse>(
4587 admin.getConnection()) {
4588 @Override
4589 public AbortProcedureResponse call(int callTimeout) throws ServiceException {
4590 PayloadCarryingRpcController controller = admin.getRpcControllerFactory().newController();
4591 controller.setCallTimeout(callTimeout);
4592 return master.abortProcedure(controller, request);
4593 }
4594 });
4595 }
4596
4597 @Override
4598 public V get() throws InterruptedException, ExecutionException {
4599
4600 throw new UnsupportedOperationException();
4601 }
4602
4603 @Override
4604 public V get(long timeout, TimeUnit unit)
4605 throws InterruptedException, ExecutionException, TimeoutException {
4606 if (!done) {
4607 long deadlineTs = EnvironmentEdgeManager.currentTime() + unit.toMillis(timeout);
4608 try {
4609 try {
4610
4611 if (procId != null) {
4612 result = waitProcedureResult(procId, deadlineTs);
4613 }
4614
4615 if (!procResultFound || waitForOpResult) {
4616 result = waitOperationResult(deadlineTs);
4617 }
4618 result = postOperationResult(result, deadlineTs);
4619 done = true;
4620 } catch (IOException e) {
4621 result = postOpeartionFailure(e, deadlineTs);
4622 done = true;
4623 }
4624 } catch (IOException e) {
4625 exception = new ExecutionException(e);
4626 done = true;
4627 }
4628 }
4629 if (exception != null) {
4630 throw exception;
4631 }
4632 return result;
4633 }
4634
4635 @Override
4636 public boolean isDone() {
4637 return done;
4638 }
4639
4640 protected HBaseAdmin getAdmin() {
4641 return admin;
4642 }
4643
4644 private V waitProcedureResult(long procId, long deadlineTs)
4645 throws IOException, TimeoutException, InterruptedException {
4646 GetProcedureResultRequest request = GetProcedureResultRequest.newBuilder()
4647 .setProcId(procId)
4648 .build();
4649
4650 int tries = 0;
4651 IOException serviceEx = null;
4652 while (EnvironmentEdgeManager.currentTime() < deadlineTs) {
4653 GetProcedureResultResponse response = null;
4654 try {
4655
4656 response = getProcedureResult(request);
4657 } catch (IOException e) {
4658 serviceEx = unwrapException(e);
4659
4660
4661 LOG.warn("failed to get the procedure result procId=" + procId, serviceEx);
4662
4663
4664 if (serviceEx instanceof DoNotRetryIOException ||
4665 serviceEx instanceof NeedUnmanagedConnectionException) {
4666
4667
4668
4669
4670 LOG.warn("Proc-v2 is unsupported on this master: " + serviceEx.getMessage(), serviceEx);
4671 procResultFound = false;
4672 waitForOpResult = false;
4673 return null;
4674 }
4675 }
4676
4677
4678 if (response != null && response.getState() != GetProcedureResultResponse.State.RUNNING) {
4679 procResultFound = response.getState() != GetProcedureResultResponse.State.NOT_FOUND;
4680 return convertResult(response);
4681 }
4682
4683 try {
4684 Thread.sleep(getAdmin().getPauseTime(tries++));
4685 } catch (InterruptedException e) {
4686 throw new InterruptedException(
4687 "Interrupted while waiting for the result of proc " + procId);
4688 }
4689 }
4690 if (serviceEx != null) {
4691 throw serviceEx;
4692 } else {
4693 throw new TimeoutException("The procedure " + procId + " is still running");
4694 }
4695 }
4696
4697 private static IOException unwrapException(IOException e) {
4698 if (e instanceof RemoteException) {
4699 return ((RemoteException)e).unwrapRemoteException();
4700 }
4701 return e;
4702 }
4703
4704 protected GetProcedureResultResponse getProcedureResult(final GetProcedureResultRequest request)
4705 throws IOException {
4706 return admin.executeCallable(new MasterCallable<GetProcedureResultResponse>(
4707 admin.getConnection()) {
4708 @Override
4709 public GetProcedureResultResponse call(int callTimeout) throws ServiceException {
4710 return master.getProcedureResult(null, request);
4711 }
4712 });
4713 }
4714
4715
4716
4717
4718
4719
4720 protected V convertResult(final GetProcedureResultResponse response) throws IOException {
4721 if (response.hasException()) {
4722 throw ForeignExceptionUtil.toIOException(response.getException());
4723 }
4724 return null;
4725 }
4726
4727
4728
4729
4730
4731
4732
4733 protected V waitOperationResult(final long deadlineTs)
4734 throws IOException, TimeoutException {
4735 return null;
4736 }
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746 protected V postOperationResult(final V result, final long deadlineTs)
4747 throws IOException, TimeoutException {
4748 return result;
4749 }
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760 protected V postOpeartionFailure(final IOException exception, final long deadlineTs)
4761 throws IOException, TimeoutException {
4762 throw exception;
4763 }
4764
4765 protected interface WaitForStateCallable {
4766 boolean checkState(int tries) throws IOException;
4767 void throwInterruptedException() throws InterruptedIOException;
4768 void throwTimeoutException(long elapsed) throws TimeoutException;
4769 }
4770
4771 protected void waitForState(final long deadlineTs, final WaitForStateCallable callable)
4772 throws IOException, TimeoutException {
4773 int tries = 0;
4774 IOException serverEx = null;
4775 long startTime = EnvironmentEdgeManager.currentTime();
4776 while (EnvironmentEdgeManager.currentTime() < deadlineTs) {
4777 serverEx = null;
4778 try {
4779 if (callable.checkState(tries)) {
4780 return;
4781 }
4782 } catch (IOException e) {
4783 serverEx = e;
4784 }
4785 try {
4786 Thread.sleep(getAdmin().getPauseTime(tries++));
4787 } catch (InterruptedException e) {
4788 callable.throwInterruptedException();
4789 }
4790 }
4791 if (serverEx != null) {
4792 throw unwrapException(serverEx);
4793 } else {
4794 callable.throwTimeoutException(EnvironmentEdgeManager.currentTime() - startTime);
4795 }
4796 }
4797 }
4798
4799 @Override
4800 public List<SecurityCapability> getSecurityCapabilities() throws IOException {
4801 try {
4802 return executeCallable(new MasterCallable<List<SecurityCapability>>(getConnection()) {
4803 @Override
4804 public List<SecurityCapability> call(int callTimeout) throws ServiceException {
4805 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
4806 controller.setCallTimeout(callTimeout);
4807 SecurityCapabilitiesRequest req = SecurityCapabilitiesRequest.newBuilder().build();
4808 return ProtobufUtil.toSecurityCapabilityList(
4809 master.getSecurityCapabilities(controller, req).getCapabilitiesList());
4810 }
4811 });
4812 } catch (IOException e) {
4813 if (e instanceof RemoteException) {
4814 e = ((RemoteException)e).unwrapRemoteException();
4815 }
4816 throw e;
4817 }
4818 }
4819
4820 @Override
4821 public boolean[] setSplitOrMergeEnabled(final boolean enabled, final boolean synchronous,
4822 final MasterSwitchType... switchTypes)
4823 throws IOException {
4824 return executeCallable(new MasterCallable<boolean[]>(getConnection()) {
4825 @Override
4826 public boolean[] call(int callTimeout) throws ServiceException {
4827 MasterProtos.SetSplitOrMergeEnabledResponse response = master.setSplitOrMergeEnabled(null,
4828 RequestConverter.buildSetSplitOrMergeEnabledRequest(enabled, synchronous, switchTypes));
4829 boolean[] result = new boolean[switchTypes.length];
4830 int i = 0;
4831 for (Boolean prevValue : response.getPrevValueList()) {
4832 result[i++] = prevValue;
4833 }
4834 return result;
4835 }
4836 });
4837 }
4838
4839 @Override
4840 public boolean isSplitOrMergeEnabled(final MasterSwitchType switchType) throws IOException {
4841 return executeCallable(new MasterCallable<Boolean>(getConnection()) {
4842 @Override
4843 public Boolean call(int callTimeout) throws ServiceException {
4844 return master.isSplitOrMergeEnabled(null,
4845 RequestConverter.buildIsSplitOrMergeEnabledRequest(switchType)).getEnabled();
4846 }
4847 });
4848 }
4849
4850 private RpcControllerFactory getRpcControllerFactory() {
4851 return rpcControllerFactory;
4852 }
4853 }