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