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
22 import java.io.Closeable;
23 import java.io.IOException;
24 import java.io.InterruptedIOException;
25 import java.net.SocketTimeoutException;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.concurrent.atomic.AtomicInteger;
32 import java.util.concurrent.atomic.AtomicReference;
33 import java.util.regex.Pattern;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.hadoop.conf.Configuration;
38 import org.apache.hadoop.hbase.Abortable;
39 import org.apache.hadoop.hbase.ClusterStatus;
40 import org.apache.hadoop.hbase.HBaseConfiguration;
41 import org.apache.hadoop.hbase.HBaseIOException;
42 import org.apache.hadoop.hbase.HColumnDescriptor;
43 import org.apache.hadoop.hbase.HConstants;
44 import org.apache.hadoop.hbase.HRegionInfo;
45 import org.apache.hadoop.hbase.HRegionLocation;
46 import org.apache.hadoop.hbase.HTableDescriptor;
47 import org.apache.hadoop.hbase.MasterNotRunningException;
48 import org.apache.hadoop.hbase.NamespaceDescriptor;
49 import org.apache.hadoop.hbase.NotServingRegionException;
50 import org.apache.hadoop.hbase.RegionException;
51 import org.apache.hadoop.hbase.ServerName;
52 import org.apache.hadoop.hbase.TableExistsException;
53 import org.apache.hadoop.hbase.TableName;
54 import org.apache.hadoop.hbase.TableNotDisabledException;
55 import org.apache.hadoop.hbase.TableNotEnabledException;
56 import org.apache.hadoop.hbase.TableNotFoundException;
57 import org.apache.hadoop.hbase.UnknownRegionException;
58 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
59 import org.apache.hadoop.hbase.catalog.CatalogTracker;
60 import org.apache.hadoop.hbase.catalog.MetaReader;
61 import org.apache.hadoop.hbase.classification.InterfaceAudience;
62 import org.apache.hadoop.hbase.classification.InterfaceStability;
63 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
64 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitorBase;
65 import org.apache.hadoop.hbase.client.security.SecurityCapability;
66 import org.apache.hadoop.hbase.exceptions.DeserializationException;
67 import org.apache.hadoop.hbase.exceptions.MergeRegionException;
68 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
69 import org.apache.hadoop.hbase.ipc.MasterCoprocessorRpcChannel;
70 import org.apache.hadoop.hbase.ipc.RegionServerCoprocessorRpcChannel;
71 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
72 import org.apache.hadoop.hbase.protobuf.RequestConverter;
73 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
74 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
75 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse;
76 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
77 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionRequest;
78 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
79 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse;
80 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse.CompactionState;
81 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterRequest;
82 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterResponse;
83 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
84 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
85 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
86 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ProcedureDescription;
87 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
88 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableSchema;
89 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AddColumnRequest;
90 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
91 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateNamespaceRequest;
92 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
93 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteColumnRequest;
94 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteNamespaceRequest;
95 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteSnapshotRequest;
96 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteTableRequest;
97 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DisableTableRequest;
98 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
99 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableTableRequest;
100 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ExecProcedureRequest;
101 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ExecProcedureResponse;
102 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetClusterStatusRequest;
103 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetCompletedSnapshotsRequest;
104 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest;
105 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
106 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusResponse;
107 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
108 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
109 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsProcedureDoneRequest;
110 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsProcedureDoneResponse;
111 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsRestoreSnapshotDoneRequest;
112 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsRestoreSnapshotDoneResponse;
113 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
114 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
115 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest;
116 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceRequest;
117 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListTableNamesByNamespaceRequest;
118 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyColumnRequest;
119 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyNamespaceRequest;
120 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyTableRequest;
121 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
122 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotRequest;
123 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RestoreSnapshotResponse;
124 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest;
125 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
126 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ShutdownRequest;
127 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotRequest;
128 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SnapshotResponse;
129 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.StopMasterRequest;
130 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.TruncateTableRequest;
131 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
132 import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
133 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
134 import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
135 import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
136 import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
137 import org.apache.hadoop.hbase.snapshot.UnknownSnapshotException;
138 import org.apache.hadoop.hbase.util.Addressing;
139 import org.apache.hadoop.hbase.util.Bytes;
140 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
141 import org.apache.hadoop.hbase.util.Pair;
142 import org.apache.hadoop.ipc.RemoteException;
143 import org.apache.hadoop.util.StringUtils;
144 import org.apache.zookeeper.KeeperException;
145
146 import com.google.common.annotations.VisibleForTesting;
147 import com.google.protobuf.ByteString;
148 import com.google.protobuf.ServiceException;
149
150
151
152
153
154
155
156
157
158
159 @InterfaceAudience.Public
160 @InterfaceStability.Evolving
161 public class HBaseAdmin implements Abortable, Closeable {
162 private static final Log LOG = LogFactory.getLog(HBaseAdmin.class);
163
164
165
166 private HConnection connection;
167
168 private volatile Configuration conf;
169 private final long pause;
170 private final int numRetries;
171
172
173
174 private final int retryLongerMultiplier;
175 private boolean aborted;
176 private boolean cleanupConnectionOnClose = false;
177 private boolean closed = false;
178
179 private RpcRetryingCallerFactory rpcCallerFactory;
180
181
182
183
184
185
186
187 public HBaseAdmin(Configuration c)
188 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
189
190
191 this(HConnectionManager.getConnection(new Configuration(c)));
192 this.cleanupConnectionOnClose = true;
193 }
194
195
196
197
198
199
200
201
202
203 public HBaseAdmin(HConnection connection)
204 throws MasterNotRunningException, ZooKeeperConnectionException {
205 this.conf = connection.getConfiguration();
206 this.connection = connection;
207
208 this.pause = this.conf.getLong(HConstants.HBASE_CLIENT_PAUSE,
209 HConstants.DEFAULT_HBASE_CLIENT_PAUSE);
210 this.numRetries = this.conf.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER,
211 HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER);
212 this.retryLongerMultiplier = this.conf.getInt(
213 "hbase.client.retries.longer.multiplier", 10);
214 this.rpcCallerFactory = RpcRetryingCallerFactory.instantiate(this.conf,
215 connection.getStatisticsTracker());
216 }
217
218
219
220
221
222
223
224
225 @VisibleForTesting
226 synchronized CatalogTracker getCatalogTracker()
227 throws ZooKeeperConnectionException, IOException {
228 boolean succeeded = false;
229 CatalogTracker ct = null;
230 try {
231 ct = new CatalogTracker(this.conf);
232 startCatalogTracker(ct);
233 succeeded = true;
234 } catch (InterruptedException e) {
235
236 throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
237 } finally {
238
239
240 if (!succeeded && ct != null) {
241 try {
242 ct.stop();
243 } catch (RuntimeException re) {
244 LOG.error("Failed to clean up HBase's internal catalog tracker after a failed initialization. " +
245 "We may have leaked network connections to ZooKeeper; they won't be cleaned up until " +
246 "the JVM exits. If you see a large number of stale connections to ZooKeeper this is likely " +
247 "the cause. The following exception details will be needed for assistance from the " +
248 "HBase community.", re);
249 }
250 ct = null;
251 }
252 }
253 return ct;
254 }
255
256 @VisibleForTesting
257 CatalogTracker startCatalogTracker(final CatalogTracker ct)
258 throws IOException, InterruptedException {
259 ct.start();
260 return ct;
261 }
262
263 @VisibleForTesting
264 void cleanupCatalogTracker(final CatalogTracker ct) {
265 ct.stop();
266 }
267
268 @Override
269 public void abort(String why, Throwable e) {
270
271 this.aborted = true;
272 throw new RuntimeException(why, e);
273 }
274
275 @Override
276 public boolean isAborted(){
277 return this.aborted;
278 }
279
280
281 public HConnection getConnection() {
282 return connection;
283 }
284
285
286
287
288
289
290 public boolean isMasterRunning()
291 throws MasterNotRunningException, ZooKeeperConnectionException {
292 return connection.isMasterRunning();
293 }
294
295
296
297
298
299
300 public boolean tableExists(final TableName tableName)
301 throws IOException {
302 boolean b = false;
303 CatalogTracker ct = getCatalogTracker();
304 try {
305 b = MetaReader.tableExists(ct, tableName);
306 } finally {
307 cleanupCatalogTracker(ct);
308 }
309 return b;
310 }
311
312 public boolean tableExists(final byte[] tableName)
313 throws IOException {
314 return tableExists(TableName.valueOf(tableName));
315 }
316
317 public boolean tableExists(final String tableName)
318 throws IOException {
319 return tableExists(TableName.valueOf(tableName));
320 }
321
322
323
324
325
326
327
328
329
330
331
332 public HTableDescriptor[] listTables() throws IOException {
333 return this.connection.listTables();
334 }
335
336
337
338
339
340
341
342
343
344 public HTableDescriptor[] listTables(Pattern pattern) throws IOException {
345 List<HTableDescriptor> matched = new LinkedList<HTableDescriptor>();
346 HTableDescriptor[] tables = listTables();
347 for (HTableDescriptor table : tables) {
348 if (pattern.matcher(table.getTableName().getNameAsString()).matches()) {
349 matched.add(table);
350 }
351 }
352 return matched.toArray(new HTableDescriptor[matched.size()]);
353 }
354
355
356
357
358
359
360
361
362
363 public HTableDescriptor[] listTables(String regex) throws IOException {
364 return listTables(Pattern.compile(regex));
365 }
366
367
368
369
370
371
372 @Deprecated
373 public String[] getTableNames() throws IOException {
374 return this.connection.getTableNames();
375 }
376
377
378
379
380
381
382
383 @Deprecated
384 public String[] getTableNames(Pattern pattern) throws IOException {
385 List<String> matched = new ArrayList<String>();
386 for (String name: this.connection.getTableNames()) {
387 if (pattern.matcher(name).matches()) {
388 matched.add(name);
389 }
390 }
391 return matched.toArray(new String[matched.size()]);
392 }
393
394
395
396
397
398
399
400 @Deprecated
401 public String[] getTableNames(String regex) throws IOException {
402 return getTableNames(Pattern.compile(regex));
403 }
404
405
406
407
408
409
410 public TableName[] listTableNames() throws IOException {
411 return this.connection.listTableNames();
412 }
413
414
415
416
417
418
419
420
421 public HTableDescriptor getTableDescriptor(final TableName tableName)
422 throws TableNotFoundException, IOException {
423 return this.connection.getHTableDescriptor(tableName);
424 }
425
426 public HTableDescriptor getTableDescriptor(final byte[] tableName)
427 throws TableNotFoundException, IOException {
428 return getTableDescriptor(TableName.valueOf(tableName));
429 }
430
431 private long getPauseTime(int tries) {
432 int triesCount = tries;
433 if (triesCount >= HConstants.RETRY_BACKOFF.length) {
434 triesCount = HConstants.RETRY_BACKOFF.length - 1;
435 }
436 return this.pause * HConstants.RETRY_BACKOFF[triesCount];
437 }
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452 public void createTable(HTableDescriptor desc)
453 throws IOException {
454 createTable(desc, null);
455 }
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481 public void createTable(HTableDescriptor desc, byte [] startKey,
482 byte [] endKey, int numRegions)
483 throws IOException {
484 if(numRegions < 3) {
485 throw new IllegalArgumentException("Must create at least three regions");
486 } else if(Bytes.compareTo(startKey, endKey) >= 0) {
487 throw new IllegalArgumentException("Start key must be smaller than end key");
488 }
489 if (numRegions == 3) {
490 createTable(desc, new byte[][]{startKey, endKey});
491 return;
492 }
493 byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
494 if(splitKeys == null || splitKeys.length != numRegions - 1) {
495 throw new IllegalArgumentException("Unable to split key range into enough regions");
496 }
497 createTable(desc, splitKeys);
498 }
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517 public void createTable(final HTableDescriptor desc, byte [][] splitKeys)
518 throws IOException {
519 try {
520 createTableAsync(desc, splitKeys);
521 } catch (SocketTimeoutException ste) {
522 LOG.warn("Creating " + desc.getTableName() + " took too long", ste);
523 }
524 int numRegs = splitKeys == null ? 1 : splitKeys.length + 1;
525 int prevRegCount = 0;
526 boolean doneWithMetaScan = false;
527 for (int tries = 0; tries < this.numRetries * this.retryLongerMultiplier;
528 ++tries) {
529 if (!doneWithMetaScan) {
530
531 final AtomicInteger actualRegCount = new AtomicInteger(0);
532 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
533 @Override
534 public boolean processRow(Result rowResult) throws IOException {
535 HRegionInfo info = HRegionInfo.getHRegionInfo(rowResult);
536 if (info == null) {
537 LOG.warn("No serialized HRegionInfo in " + rowResult);
538 return true;
539 }
540 if (!info.getTable().equals(desc.getTableName())) {
541 return false;
542 }
543 ServerName serverName = HRegionInfo.getServerName(rowResult);
544
545 if (!(info.isOffline() || info.isSplit()) && serverName != null
546 && serverName.getHostAndPort() != null) {
547 actualRegCount.incrementAndGet();
548 }
549 return true;
550 }
551 };
552 MetaScanner.metaScan(conf, connection, visitor, desc.getTableName());
553 if (actualRegCount.get() < numRegs) {
554 if (tries == this.numRetries * this.retryLongerMultiplier - 1) {
555 throw new RegionOfflineException("Only " + actualRegCount.get() +
556 " of " + numRegs + " regions are online; retries exhausted.");
557 }
558 try {
559 Thread.sleep(getPauseTime(tries));
560 } catch (InterruptedException e) {
561 throw new InterruptedIOException("Interrupted when opening" +
562 " regions; " + actualRegCount.get() + " of " + numRegs +
563 " regions processed so far");
564 }
565 if (actualRegCount.get() > prevRegCount) {
566 prevRegCount = actualRegCount.get();
567 tries = -1;
568 }
569 } else {
570 doneWithMetaScan = true;
571 tries = -1;
572 }
573 } else if (isTableEnabled(desc.getTableName())) {
574 return;
575 } else {
576 try {
577 Thread.sleep(getPauseTime(tries));
578 } catch (InterruptedException e) {
579 throw new InterruptedIOException("Interrupted when waiting" +
580 " for table to be enabled; meta scan was done");
581 }
582 }
583 }
584 throw new TableNotEnabledException(
585 "Retries exhausted while still waiting for table: "
586 + desc.getTableName() + " to be enabled");
587 }
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605 public void createTableAsync(
606 final HTableDescriptor desc, final byte [][] splitKeys)
607 throws IOException {
608 if(desc.getTableName() == null) {
609 throw new IllegalArgumentException("TableName cannot be null");
610 }
611 if(splitKeys != null && splitKeys.length > 0) {
612 Arrays.sort(splitKeys, Bytes.BYTES_COMPARATOR);
613
614 byte [] lastKey = null;
615 for(byte [] splitKey : splitKeys) {
616 if (Bytes.compareTo(splitKey, HConstants.EMPTY_BYTE_ARRAY) == 0) {
617 throw new IllegalArgumentException(
618 "Empty split key must not be passed in the split keys.");
619 }
620 if(lastKey != null && Bytes.equals(splitKey, lastKey)) {
621 throw new IllegalArgumentException("All split keys must be unique, " +
622 "found duplicate: " + Bytes.toStringBinary(splitKey) +
623 ", " + Bytes.toStringBinary(lastKey));
624 }
625 lastKey = splitKey;
626 }
627 }
628
629 executeCallable(new MasterCallable<Void>(getConnection()) {
630 @Override
631 public Void call() throws ServiceException {
632 CreateTableRequest request = RequestConverter.buildCreateTableRequest(desc, splitKeys);
633 master.createTable(null, request);
634 return null;
635 }
636 });
637 }
638
639 public void deleteTable(final String tableName) throws IOException {
640 deleteTable(TableName.valueOf(tableName));
641 }
642
643 public void deleteTable(final byte[] tableName) throws IOException {
644 deleteTable(TableName.valueOf(tableName));
645 }
646
647
648
649
650
651
652
653
654 public void deleteTable(final TableName tableName) throws IOException {
655 boolean tableExists = true;
656
657 executeCallable(new MasterCallable<Void>(getConnection()) {
658 @Override
659 public Void call() throws ServiceException {
660 DeleteTableRequest req = RequestConverter.buildDeleteTableRequest(tableName);
661 master.deleteTable(null,req);
662 return null;
663 }
664 });
665
666 int failures = 0;
667
668 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
669 try {
670 final AtomicInteger count = new AtomicInteger(0);
671 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
672 @Override
673 public boolean processRow(Result rowResult) throws IOException {
674 HRegionInfo info = HRegionInfo.getHRegionInfo(rowResult);
675 if (info == null) {
676 return true;
677 }
678 if (!info.getTable().equals(tableName)) {
679 return false;
680 }
681 count.incrementAndGet();
682 return true;
683 }
684 };
685 MetaScanner.metaScan(conf, connection, visitor, tableName);
686
687
688 if (count.get() == 0) {
689 tableExists = false;
690 GetTableDescriptorsResponse htds;
691 MasterKeepAliveConnection master = connection.getKeepAliveMasterService();
692 try {
693 GetTableDescriptorsRequest req =
694 RequestConverter.buildGetTableDescriptorsRequest(tableName);
695 htds = master.getTableDescriptors(null, req);
696 } catch (ServiceException se) {
697 throw ProtobufUtil.getRemoteException(se);
698 } finally {
699 master.close();
700 }
701 tableExists = !htds.getTableSchemaList().isEmpty();
702 if (!tableExists) {
703 break;
704 }
705 }
706 } catch (IOException ex) {
707 failures++;
708 if (failures == numRetries - 1) {
709 if (ex instanceof RemoteException) {
710 ex = ((RemoteException) ex).unwrapRemoteException();
711 }
712 throw ex;
713 }
714 }
715 try {
716 Thread.sleep(getPauseTime(tries));
717 } catch (InterruptedException e) {
718
719 }
720 }
721
722 if (tableExists) {
723 throw new IOException("Retries exhausted, it took too long to wait"+
724 " for the table " + tableName + " to be deleted.");
725 }
726
727 this.connection.clearRegionCache(tableName);
728 LOG.info("Deleted " + tableName);
729 }
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744 public HTableDescriptor[] deleteTables(String regex) throws IOException {
745 return deleteTables(Pattern.compile(regex));
746 }
747
748
749
750
751
752
753
754
755
756
757
758
759 public HTableDescriptor[] deleteTables(Pattern pattern) throws IOException {
760 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
761 for (HTableDescriptor table : listTables(pattern)) {
762 try {
763 deleteTable(table.getTableName());
764 } catch (IOException ex) {
765 LOG.info("Failed to delete table " + table.getTableName(), ex);
766 failed.add(table);
767 }
768 }
769 return failed.toArray(new HTableDescriptor[failed.size()]);
770 }
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786 public void enableTable(final TableName tableName)
787 throws IOException {
788 enableTableAsync(tableName);
789
790
791 waitUntilTableIsEnabled(tableName);
792
793 LOG.info("Enabled table " + tableName);
794 }
795
796 public void enableTable(final byte[] tableName)
797 throws IOException {
798 enableTable(TableName.valueOf(tableName));
799 }
800
801 public void enableTable(final String tableName)
802 throws IOException {
803 enableTable(TableName.valueOf(tableName));
804 }
805
806
807
808
809
810
811
812
813 private void waitUntilTableIsEnabled(final TableName tableName) throws IOException {
814 boolean enabled = false;
815 long start = EnvironmentEdgeManager.currentTimeMillis();
816 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
817 try {
818 enabled = isTableEnabled(tableName);
819 } catch (TableNotFoundException tnfe) {
820
821 enabled = false;
822 }
823 enabled = enabled && isTableAvailable(tableName);
824 if (enabled) {
825 break;
826 }
827 long sleep = getPauseTime(tries);
828 if (LOG.isDebugEnabled()) {
829 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
830 "enabled in " + tableName);
831 }
832 try {
833 Thread.sleep(sleep);
834 } catch (InterruptedException e) {
835
836
837 throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
838 }
839 }
840 if (!enabled) {
841 long msec = EnvironmentEdgeManager.currentTimeMillis() - start;
842 throw new IOException("Table '" + tableName +
843 "' not yet enabled, after " + msec + "ms.");
844 }
845 }
846
847
848
849
850
851
852
853
854
855
856
857 public void enableTableAsync(final TableName tableName)
858 throws IOException {
859 TableName.isLegalFullyQualifiedTableName(tableName.getName());
860 executeCallable(new MasterCallable<Void>(getConnection()) {
861 @Override
862 public Void call() throws ServiceException {
863 LOG.info("Started enable of " + tableName);
864 EnableTableRequest req = RequestConverter.buildEnableTableRequest(tableName);
865 master.enableTable(null,req);
866 return null;
867 }
868 });
869 }
870
871 public void enableTableAsync(final byte[] tableName)
872 throws IOException {
873 enableTable(TableName.valueOf(tableName));
874 }
875
876 public void enableTableAsync(final String tableName)
877 throws IOException {
878 enableTableAsync(TableName.valueOf(tableName));
879 }
880
881
882
883
884
885
886
887
888
889
890
891
892
893 public HTableDescriptor[] enableTables(String regex) throws IOException {
894 return enableTables(Pattern.compile(regex));
895 }
896
897
898
899
900
901
902
903
904
905
906
907 public HTableDescriptor[] enableTables(Pattern pattern) throws IOException {
908 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
909 for (HTableDescriptor table : listTables(pattern)) {
910 if (isTableDisabled(table.getTableName())) {
911 try {
912 enableTable(table.getTableName());
913 } catch (IOException ex) {
914 LOG.info("Failed to enable table " + table.getTableName(), ex);
915 failed.add(table);
916 }
917 }
918 }
919 return failed.toArray(new HTableDescriptor[failed.size()]);
920 }
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935 public void disableTableAsync(final TableName tableName) throws IOException {
936 TableName.isLegalFullyQualifiedTableName(tableName.getName());
937 executeCallable(new MasterCallable<Void>(getConnection()) {
938 @Override
939 public Void call() throws ServiceException {
940 LOG.info("Started disable of " + tableName);
941 DisableTableRequest req = RequestConverter.buildDisableTableRequest(tableName);
942 master.disableTable(null,req);
943 return null;
944 }
945 });
946 }
947
948 public void disableTableAsync(final byte[] tableName) throws IOException {
949 disableTableAsync(TableName.valueOf(tableName));
950 }
951
952 public void disableTableAsync(final String tableName) throws IOException {
953 disableTableAsync(TableName.valueOf(tableName));
954 }
955
956
957
958
959
960
961
962
963
964
965
966
967 public void disableTable(final TableName tableName)
968 throws IOException {
969 disableTableAsync(tableName);
970
971 boolean disabled = false;
972 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
973 disabled = isTableDisabled(tableName);
974 if (disabled) {
975 break;
976 }
977 long sleep = getPauseTime(tries);
978 if (LOG.isDebugEnabled()) {
979 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
980 "disabled in " + tableName);
981 }
982 try {
983 Thread.sleep(sleep);
984 } catch (InterruptedException e) {
985
986
987 throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
988 }
989 }
990 if (!disabled) {
991 throw new RegionException("Retries exhausted, it took too long to wait"+
992 " for the table " + tableName + " to be disabled.");
993 }
994 LOG.info("Disabled " + tableName);
995 }
996
997 public void disableTable(final byte[] tableName)
998 throws IOException {
999 disableTable(TableName.valueOf(tableName));
1000 }
1001
1002 public void disableTable(final String tableName)
1003 throws IOException {
1004 disableTable(TableName.valueOf(tableName));
1005 }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 public HTableDescriptor[] disableTables(String regex) throws IOException {
1021 return disableTables(Pattern.compile(regex));
1022 }
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035 public HTableDescriptor[] disableTables(Pattern pattern) throws IOException {
1036 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
1037 for (HTableDescriptor table : listTables(pattern)) {
1038 if (isTableEnabled(table.getTableName())) {
1039 try {
1040 disableTable(table.getTableName());
1041 } catch (IOException ex) {
1042 LOG.info("Failed to disable table " + table.getTableName(), ex);
1043 failed.add(table);
1044 }
1045 }
1046 }
1047 return failed.toArray(new HTableDescriptor[failed.size()]);
1048 }
1049
1050
1051
1052
1053
1054 private void checkTableExistence(TableName tableName) throws IOException {
1055 if (!tableExists(tableName)) {
1056 throw new TableNotFoundException(tableName);
1057 }
1058 }
1059
1060
1061
1062
1063
1064
1065 public boolean isTableEnabled(TableName tableName) throws IOException {
1066 checkTableExistence(tableName);
1067 return connection.isTableEnabled(tableName);
1068 }
1069
1070 public boolean isTableEnabled(byte[] tableName) throws IOException {
1071 return isTableEnabled(TableName.valueOf(tableName));
1072 }
1073
1074 public boolean isTableEnabled(String tableName) throws IOException {
1075 return isTableEnabled(TableName.valueOf(tableName));
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085 public boolean isTableDisabled(TableName tableName) throws IOException {
1086 checkTableExistence(tableName);
1087 return connection.isTableDisabled(tableName);
1088 }
1089
1090 public boolean isTableDisabled(byte[] tableName) throws IOException {
1091 return isTableDisabled(TableName.valueOf(tableName));
1092 }
1093
1094 public boolean isTableDisabled(String tableName) throws IOException {
1095 return isTableDisabled(TableName.valueOf(tableName));
1096 }
1097
1098
1099
1100
1101
1102
1103 public boolean isTableAvailable(TableName tableName) throws IOException {
1104 return connection.isTableAvailable(tableName);
1105 }
1106
1107 public boolean isTableAvailable(byte[] tableName) throws IOException {
1108 return isTableAvailable(TableName.valueOf(tableName));
1109 }
1110
1111 public boolean isTableAvailable(String tableName) throws IOException {
1112 return isTableAvailable(TableName.valueOf(tableName));
1113 }
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127 public boolean isTableAvailable(TableName tableName,
1128 byte[][] splitKeys) throws IOException {
1129 return connection.isTableAvailable(tableName, splitKeys);
1130 }
1131
1132 public boolean isTableAvailable(byte[] tableName,
1133 byte[][] splitKeys) throws IOException {
1134 return isTableAvailable(TableName.valueOf(tableName), splitKeys);
1135 }
1136
1137 public boolean isTableAvailable(String tableName,
1138 byte[][] splitKeys) throws IOException {
1139 return isTableAvailable(TableName.valueOf(tableName), splitKeys);
1140 }
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 public Pair<Integer, Integer> getAlterStatus(final TableName tableName)
1154 throws IOException {
1155 return executeCallable(new MasterCallable<Pair<Integer, Integer>>(getConnection()) {
1156 @Override
1157 public Pair<Integer, Integer> call() throws ServiceException {
1158 GetSchemaAlterStatusRequest req = RequestConverter
1159 .buildGetSchemaAlterStatusRequest(tableName);
1160 GetSchemaAlterStatusResponse ret = master.getSchemaAlterStatus(null, req);
1161 Pair<Integer, Integer> pair = new Pair<Integer, Integer>(Integer.valueOf(ret
1162 .getYetToUpdateRegions()), Integer.valueOf(ret.getTotalRegions()));
1163 return pair;
1164 }
1165 });
1166 }
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180 public Pair<Integer, Integer> getAlterStatus(final byte[] tableName)
1181 throws IOException {
1182 return getAlterStatus(TableName.valueOf(tableName));
1183 }
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193 public void addColumn(final byte[] tableName, HColumnDescriptor column)
1194 throws IOException {
1195 addColumn(TableName.valueOf(tableName), column);
1196 }
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207 public void addColumn(final String tableName, HColumnDescriptor column)
1208 throws IOException {
1209 addColumn(TableName.valueOf(tableName), column);
1210 }
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220 public void addColumn(final TableName tableName, final HColumnDescriptor column)
1221 throws IOException {
1222 executeCallable(new MasterCallable<Void>(getConnection()) {
1223 @Override
1224 public Void call() throws ServiceException {
1225 AddColumnRequest req = RequestConverter.buildAddColumnRequest(tableName, column);
1226 master.addColumn(null,req);
1227 return null;
1228 }
1229 });
1230 }
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240 public void deleteColumn(final byte[] tableName, final String columnName)
1241 throws IOException {
1242 deleteColumn(TableName.valueOf(tableName), Bytes.toBytes(columnName));
1243 }
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253 public void deleteColumn(final String tableName, final String columnName)
1254 throws IOException {
1255 deleteColumn(TableName.valueOf(tableName), Bytes.toBytes(columnName));
1256 }
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266 public void deleteColumn(final TableName tableName, final byte [] columnName)
1267 throws IOException {
1268 executeCallable(new MasterCallable<Void>(getConnection()) {
1269 @Override
1270 public Void call() throws ServiceException {
1271 DeleteColumnRequest req = RequestConverter.buildDeleteColumnRequest(tableName, columnName);
1272 master.deleteColumn(null,req);
1273 return null;
1274 }
1275 });
1276 }
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286 public void modifyColumn(final String tableName, HColumnDescriptor descriptor)
1287 throws IOException {
1288 modifyColumn(TableName.valueOf(tableName), descriptor);
1289 }
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 public void modifyColumn(final byte[] tableName, HColumnDescriptor descriptor)
1300 throws IOException {
1301 modifyColumn(TableName.valueOf(tableName), descriptor);
1302 }
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314 public void modifyColumn(final TableName tableName, final HColumnDescriptor descriptor)
1315 throws IOException {
1316 executeCallable(new MasterCallable<Void>(getConnection()) {
1317 @Override
1318 public Void call() throws ServiceException {
1319 ModifyColumnRequest req = RequestConverter.buildModifyColumnRequest(tableName, descriptor);
1320 master.modifyColumn(null,req);
1321 return null;
1322 }
1323 });
1324 }
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334 public void closeRegion(final String regionname, final String serverName)
1335 throws IOException {
1336 closeRegion(Bytes.toBytes(regionname), serverName);
1337 }
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349 public void closeRegion(final byte [] regionname, final String serverName)
1350 throws IOException {
1351 CatalogTracker ct = getCatalogTracker();
1352 try {
1353 if (serverName != null) {
1354 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, regionname);
1355 if (pair == null || pair.getFirst() == null) {
1356 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1357 } else {
1358 closeRegion(ServerName.valueOf(serverName), pair.getFirst());
1359 }
1360 } else {
1361 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, regionname);
1362 if (pair == null) {
1363 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1364 } else if (pair.getSecond() == null) {
1365 throw new NoServerForRegionException(Bytes.toStringBinary(regionname));
1366 } else {
1367 closeRegion(pair.getSecond(), pair.getFirst());
1368 }
1369 }
1370 } finally {
1371 cleanupCatalogTracker(ct);
1372 }
1373 }
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396 public boolean closeRegionWithEncodedRegionName(final String encodedRegionName,
1397 final String serverName) throws IOException {
1398 if (null == serverName || ("").equals(serverName.trim())) {
1399 throw new IllegalArgumentException(
1400 "The servername cannot be null or empty.");
1401 }
1402 ServerName sn = ServerName.valueOf(serverName);
1403 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1404
1405 CloseRegionRequest request =
1406 RequestConverter.buildCloseRegionRequest(sn, encodedRegionName, false);
1407 try {
1408 CloseRegionResponse response = admin.closeRegion(null, request);
1409 boolean isRegionClosed = response.getClosed();
1410 if (false == isRegionClosed) {
1411 LOG.error("Not able to close the region " + encodedRegionName + ".");
1412 }
1413 return isRegionClosed;
1414 } catch (ServiceException se) {
1415 throw ProtobufUtil.getRemoteException(se);
1416 }
1417 }
1418
1419
1420
1421
1422
1423
1424
1425
1426 public void closeRegion(final ServerName sn, final HRegionInfo hri)
1427 throws IOException {
1428 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1429
1430 ProtobufUtil.closeRegion(admin, sn, hri.getRegionName(), false);
1431 }
1432
1433
1434
1435
1436 public List<HRegionInfo> getOnlineRegions(
1437 final ServerName sn) throws IOException {
1438 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1439 return ProtobufUtil.getOnlineRegions(admin);
1440 }
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450 public void flush(final String tableNameOrRegionName)
1451 throws IOException, InterruptedException {
1452 flush(Bytes.toBytes(tableNameOrRegionName));
1453 }
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463 public void flush(final byte[] tableNameOrRegionName)
1464 throws IOException, InterruptedException {
1465 CatalogTracker ct = getCatalogTracker();
1466 try {
1467 Pair<HRegionInfo, ServerName> regionServerPair
1468 = getRegion(tableNameOrRegionName, ct);
1469 if (regionServerPair != null) {
1470 if (regionServerPair.getSecond() == null) {
1471 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1472 } else {
1473 flush(regionServerPair.getSecond(), regionServerPair.getFirst());
1474 }
1475 } else {
1476 final TableName tableName = checkTableExists(
1477 TableName.valueOf(tableNameOrRegionName), ct);
1478 List<Pair<HRegionInfo, ServerName>> pairs =
1479 MetaReader.getTableRegionsAndLocations(ct,
1480 tableName);
1481 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1482 if (pair.getFirst().isOffline()) continue;
1483 if (pair.getSecond() == null) continue;
1484 try {
1485 flush(pair.getSecond(), pair.getFirst());
1486 } catch (NotServingRegionException e) {
1487 if (LOG.isDebugEnabled()) {
1488 LOG.debug("Trying to flush " + pair.getFirst() + ": " +
1489 StringUtils.stringifyException(e));
1490 }
1491 }
1492 }
1493 }
1494 } finally {
1495 cleanupCatalogTracker(ct);
1496 }
1497 }
1498
1499 private void flush(final ServerName sn, final HRegionInfo hri)
1500 throws IOException {
1501 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1502 FlushRegionRequest request =
1503 RequestConverter.buildFlushRegionRequest(hri.getRegionName());
1504 try {
1505 admin.flushRegion(null, request);
1506 } catch (ServiceException se) {
1507 throw ProtobufUtil.getRemoteException(se);
1508 }
1509 }
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519 public void compact(final String tableNameOrRegionName)
1520 throws IOException, InterruptedException {
1521 compact(Bytes.toBytes(tableNameOrRegionName));
1522 }
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532 public void compact(final byte[] tableNameOrRegionName)
1533 throws IOException, InterruptedException {
1534 compact(tableNameOrRegionName, null, false);
1535 }
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546 public void compact(String tableOrRegionName, String columnFamily)
1547 throws IOException, InterruptedException {
1548 compact(Bytes.toBytes(tableOrRegionName), Bytes.toBytes(columnFamily));
1549 }
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560 public void compact(final byte[] tableNameOrRegionName, final byte[] columnFamily)
1561 throws IOException, InterruptedException {
1562 compact(tableNameOrRegionName, columnFamily, false);
1563 }
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573 public void majorCompact(final String tableNameOrRegionName)
1574 throws IOException, InterruptedException {
1575 majorCompact(Bytes.toBytes(tableNameOrRegionName));
1576 }
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586 public void majorCompact(final byte[] tableNameOrRegionName)
1587 throws IOException, InterruptedException {
1588 compact(tableNameOrRegionName, null, true);
1589 }
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600 public void majorCompact(final String tableNameOrRegionName,
1601 final String columnFamily) throws IOException, InterruptedException {
1602 majorCompact(Bytes.toBytes(tableNameOrRegionName),
1603 Bytes.toBytes(columnFamily));
1604 }
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615 public void majorCompact(final byte[] tableNameOrRegionName,
1616 final byte[] columnFamily) throws IOException, InterruptedException {
1617 compact(tableNameOrRegionName, columnFamily, true);
1618 }
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630 private void compact(final byte[] tableNameOrRegionName,
1631 final byte[] columnFamily,final boolean major)
1632 throws IOException, InterruptedException {
1633 CatalogTracker ct = getCatalogTracker();
1634 try {
1635 Pair<HRegionInfo, ServerName> regionServerPair
1636 = getRegion(tableNameOrRegionName, ct);
1637 if (regionServerPair != null) {
1638 if (regionServerPair.getSecond() == null) {
1639 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1640 } else {
1641 compact(regionServerPair.getSecond(), regionServerPair.getFirst(), major, columnFamily);
1642 }
1643 } else {
1644 final TableName tableName =
1645 checkTableExists(TableName.valueOf(tableNameOrRegionName), ct);
1646 List<Pair<HRegionInfo, ServerName>> pairs =
1647 MetaReader.getTableRegionsAndLocations(ct,
1648 tableName);
1649 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1650 if (pair.getFirst().isOffline()) continue;
1651 if (pair.getSecond() == null) continue;
1652 try {
1653 compact(pair.getSecond(), pair.getFirst(), major, columnFamily);
1654 } catch (NotServingRegionException e) {
1655 if (LOG.isDebugEnabled()) {
1656 LOG.debug("Trying to" + (major ? " major" : "") + " compact " +
1657 pair.getFirst() + ": " +
1658 StringUtils.stringifyException(e));
1659 }
1660 }
1661 }
1662 }
1663 } finally {
1664 cleanupCatalogTracker(ct);
1665 }
1666 }
1667
1668 private void compact(final ServerName sn, final HRegionInfo hri,
1669 final boolean major, final byte [] family)
1670 throws IOException {
1671 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
1672 CompactRegionRequest request =
1673 RequestConverter.buildCompactRegionRequest(hri.getRegionName(), major, family);
1674 try {
1675 admin.compactRegion(null, request);
1676 } catch (ServiceException se) {
1677 throw ProtobufUtil.getRemoteException(se);
1678 }
1679 }
1680
1681
1682
1683
1684
1685
1686
1687
1688 public void compactRegionServer(final ServerName sn, boolean major)
1689 throws IOException, InterruptedException {
1690 for (HRegionInfo region : getOnlineRegions(sn)) {
1691 compact(sn, region, major, null);
1692 }
1693 }
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710 public void move(final byte [] encodedRegionName, final byte [] destServerName)
1711 throws HBaseIOException, MasterNotRunningException, ZooKeeperConnectionException {
1712 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1713 try {
1714 MoveRegionRequest request =
1715 RequestConverter.buildMoveRegionRequest(encodedRegionName, destServerName);
1716 stub.moveRegion(null,request);
1717 } catch (ServiceException se) {
1718 IOException ioe = ProtobufUtil.getRemoteException(se);
1719 if (ioe instanceof HBaseIOException) {
1720 throw (HBaseIOException)ioe;
1721 }
1722 LOG.error("Unexpected exception: " + se + " from calling HMaster.moveRegion");
1723 } catch (DeserializationException de) {
1724 LOG.error("Could not parse destination server name: " + de);
1725 } finally {
1726 stub.close();
1727 }
1728 }
1729
1730
1731
1732
1733
1734
1735
1736
1737 public void assign(final byte[] regionName) throws MasterNotRunningException,
1738 ZooKeeperConnectionException, IOException {
1739 final byte[] toBeAssigned = getRegionName(regionName);
1740 executeCallable(new MasterCallable<Void>(getConnection()) {
1741 @Override
1742 public Void call() throws ServiceException {
1743 AssignRegionRequest request =
1744 RequestConverter.buildAssignRegionRequest(toBeAssigned);
1745 master.assignRegion(null,request);
1746 return null;
1747 }
1748 });
1749 }
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765 public void unassign(final byte [] regionName, final boolean force)
1766 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
1767 final byte[] toBeUnassigned = getRegionName(regionName);
1768 executeCallable(new MasterCallable<Void>(getConnection()) {
1769 @Override
1770 public Void call() throws ServiceException {
1771 UnassignRegionRequest request =
1772 RequestConverter.buildUnassignRegionRequest(toBeUnassigned, force);
1773 master.unassignRegion(null,request);
1774 return null;
1775 }
1776 });
1777 }
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791 public void offline(final byte [] regionName)
1792 throws IOException {
1793 MasterKeepAliveConnection master = connection.getKeepAliveMasterService();
1794 try {
1795 master.offlineRegion(null,RequestConverter.buildOfflineRegionRequest(regionName));
1796 } catch (ServiceException se) {
1797 throw ProtobufUtil.getRemoteException(se);
1798 } finally {
1799 master.close();
1800 }
1801 }
1802
1803
1804
1805
1806
1807
1808
1809 public boolean setBalancerRunning(final boolean on, final boolean synchronous)
1810 throws MasterNotRunningException, ZooKeeperConnectionException {
1811 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1812 try {
1813 SetBalancerRunningRequest req =
1814 RequestConverter.buildSetBalancerRunningRequest(on, synchronous);
1815 return stub.setBalancerRunning(null, req).getPrevBalanceValue();
1816 } catch (ServiceException se) {
1817 IOException ioe = ProtobufUtil.getRemoteException(se);
1818 if (ioe instanceof MasterNotRunningException) {
1819 throw (MasterNotRunningException)ioe;
1820 }
1821 if (ioe instanceof ZooKeeperConnectionException) {
1822 throw (ZooKeeperConnectionException)ioe;
1823 }
1824
1825
1826
1827 throw new MasterNotRunningException("Unexpected exception when calling balanceSwitch",se);
1828 } finally {
1829 stub.close();
1830 }
1831 }
1832
1833
1834
1835
1836
1837
1838
1839 public boolean balancer()
1840 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException {
1841 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1842 try {
1843 return stub.balance(null,RequestConverter.buildBalanceRequest()).getBalancerRan();
1844 } finally {
1845 stub.close();
1846 }
1847 }
1848
1849
1850
1851
1852
1853
1854
1855 public boolean isBalancerEnabled()
1856 throws ServiceException, MasterNotRunningException {
1857 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1858 try {
1859 return stub.isBalancerEnabled(null, RequestConverter.buildIsBalancerEnabledRequest())
1860 .getEnabled();
1861 } finally {
1862 stub.close();
1863 }
1864 }
1865
1866
1867
1868
1869
1870
1871
1872
1873 public boolean enableCatalogJanitor(boolean enable)
1874 throws ServiceException, MasterNotRunningException {
1875 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1876 try {
1877 return stub.enableCatalogJanitor(null,
1878 RequestConverter.buildEnableCatalogJanitorRequest(enable)).getPrevValue();
1879 } finally {
1880 stub.close();
1881 }
1882 }
1883
1884
1885
1886
1887
1888
1889
1890 public int runCatalogScan() throws ServiceException, MasterNotRunningException {
1891 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1892 try {
1893 return stub.runCatalogScan(null,
1894 RequestConverter.buildCatalogScanRequest()).getScanResult();
1895 } finally {
1896 stub.close();
1897 }
1898 }
1899
1900
1901
1902
1903
1904
1905 public boolean isCatalogJanitorEnabled() throws ServiceException, MasterNotRunningException {
1906 MasterKeepAliveConnection stub = connection.getKeepAliveMasterService();
1907 try {
1908 return stub.isCatalogJanitorEnabled(null,
1909 RequestConverter.buildIsCatalogJanitorEnabledRequest()).getValue();
1910 } finally {
1911 stub.close();
1912 }
1913 }
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923 public void mergeRegions(final byte[] encodedNameOfRegionA,
1924 final byte[] encodedNameOfRegionB, final boolean forcible)
1925 throws IOException {
1926 MasterKeepAliveConnection master = connection
1927 .getKeepAliveMasterService();
1928 try {
1929 DispatchMergingRegionsRequest request = RequestConverter
1930 .buildDispatchMergingRegionsRequest(encodedNameOfRegionA,
1931 encodedNameOfRegionB, forcible);
1932 master.dispatchMergingRegions(null, request);
1933 } catch (ServiceException se) {
1934 IOException ioe = ProtobufUtil.getRemoteException(se);
1935 if (ioe instanceof UnknownRegionException) {
1936 throw (UnknownRegionException) ioe;
1937 }
1938 if (ioe instanceof MergeRegionException) {
1939 throw (MergeRegionException) ioe;
1940 }
1941 LOG.error("Unexpected exception: " + se
1942 + " from calling HMaster.dispatchMergingRegions");
1943 } catch (DeserializationException de) {
1944 LOG.error("Could not parse destination server name: " + de);
1945 } finally {
1946 master.close();
1947 }
1948 }
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958 public void split(final String tableNameOrRegionName)
1959 throws IOException, InterruptedException {
1960 split(Bytes.toBytes(tableNameOrRegionName));
1961 }
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971 public void split(final byte[] tableNameOrRegionName)
1972 throws IOException, InterruptedException {
1973 split(tableNameOrRegionName, null);
1974 }
1975
1976 public void split(final String tableNameOrRegionName,
1977 final String splitPoint) throws IOException, InterruptedException {
1978 split(Bytes.toBytes(tableNameOrRegionName), Bytes.toBytes(splitPoint));
1979 }
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990 public void split(final byte[] tableNameOrRegionName,
1991 final byte [] splitPoint) throws IOException, InterruptedException {
1992 CatalogTracker ct = getCatalogTracker();
1993 try {
1994 Pair<HRegionInfo, ServerName> regionServerPair
1995 = getRegion(tableNameOrRegionName, ct);
1996 if (regionServerPair != null) {
1997 if (regionServerPair.getSecond() == null) {
1998 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1999 } else {
2000 split(regionServerPair.getSecond(), regionServerPair.getFirst(), splitPoint);
2001 }
2002 } else {
2003 final TableName tableName =
2004 checkTableExists(TableName.valueOf(tableNameOrRegionName), ct);
2005 List<Pair<HRegionInfo, ServerName>> pairs =
2006 MetaReader.getTableRegionsAndLocations(ct,
2007 tableName);
2008 for (Pair<HRegionInfo, ServerName> pair: pairs) {
2009
2010 if (pair.getSecond() == null) continue;
2011 HRegionInfo r = pair.getFirst();
2012
2013 if (r.isSplitParent()) continue;
2014
2015 if (splitPoint != null && !r.containsRow(splitPoint)) continue;
2016
2017 split(pair.getSecond(), pair.getFirst(), splitPoint);
2018 }
2019 }
2020 } finally {
2021 cleanupCatalogTracker(ct);
2022 }
2023 }
2024
2025 private void split(final ServerName sn, final HRegionInfo hri,
2026 byte[] splitPoint) throws IOException {
2027 if (hri.getStartKey() != null && splitPoint != null &&
2028 Bytes.compareTo(hri.getStartKey(), splitPoint) == 0) {
2029 throw new IOException("should not give a splitkey which equals to startkey!");
2030 }
2031 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2032 ProtobufUtil.split(admin, hri, splitPoint);
2033 }
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044 public void modifyTable(final TableName tableName, final HTableDescriptor htd)
2045 throws IOException {
2046 if (!tableName.equals(htd.getTableName())) {
2047 throw new IllegalArgumentException("the specified table name '" + tableName +
2048 "' doesn't match with the HTD one: " + htd.getTableName());
2049 }
2050
2051 executeCallable(new MasterCallable<Void>(getConnection()) {
2052 @Override
2053 public Void call() throws ServiceException {
2054 ModifyTableRequest request = RequestConverter.buildModifyTableRequest(tableName, htd);
2055 master.modifyTable(null, request);
2056 return null;
2057 }
2058 });
2059 }
2060
2061 public void modifyTable(final byte[] tableName, final HTableDescriptor htd)
2062 throws IOException {
2063 modifyTable(TableName.valueOf(tableName), htd);
2064 }
2065
2066 public void modifyTable(final String tableName, final HTableDescriptor htd)
2067 throws IOException {
2068 modifyTable(TableName.valueOf(tableName), htd);
2069 }
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080 Pair<HRegionInfo, ServerName> getRegion(final byte[] tableNameOrRegionName,
2081 final CatalogTracker ct) throws IOException {
2082 if (tableNameOrRegionName == null) {
2083 throw new IllegalArgumentException("Pass a table name or region name");
2084 }
2085 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, tableNameOrRegionName);
2086 if (pair == null) {
2087 final AtomicReference<Pair<HRegionInfo, ServerName>> result =
2088 new AtomicReference<Pair<HRegionInfo, ServerName>>(null);
2089 final String encodedName = Bytes.toString(tableNameOrRegionName);
2090 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
2091 @Override
2092 public boolean processRow(Result data) throws IOException {
2093 HRegionInfo info = HRegionInfo.getHRegionInfo(data);
2094 if (info == null) {
2095 LOG.warn("No serialized HRegionInfo in " + data);
2096 return true;
2097 }
2098 if (!encodedName.equals(info.getEncodedName())) return true;
2099 ServerName sn = HRegionInfo.getServerName(data);
2100 result.set(new Pair<HRegionInfo, ServerName>(info, sn));
2101 return false;
2102 }
2103 };
2104
2105 MetaScanner.metaScan(conf, connection, visitor, null);
2106 pair = result.get();
2107 }
2108 return pair;
2109 }
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119 private byte[] getRegionName(
2120 final byte[] regionNameOrEncodedRegionName) throws IOException {
2121 if (Bytes.equals(regionNameOrEncodedRegionName,
2122 HRegionInfo.FIRST_META_REGIONINFO.getRegionName())
2123 || Bytes.equals(regionNameOrEncodedRegionName,
2124 HRegionInfo.FIRST_META_REGIONINFO.getEncodedNameAsBytes())) {
2125 return HRegionInfo.FIRST_META_REGIONINFO.getRegionName();
2126 }
2127 CatalogTracker ct = getCatalogTracker();
2128 byte[] tmp = regionNameOrEncodedRegionName;
2129 try {
2130 Pair<HRegionInfo, ServerName> regionServerPair
2131 = getRegion(regionNameOrEncodedRegionName, ct);
2132 if (regionServerPair != null && regionServerPair.getFirst() != null) {
2133 tmp = regionServerPair.getFirst().getRegionName();
2134 }
2135 } finally {
2136 cleanupCatalogTracker(ct);
2137 }
2138 return tmp;
2139 }
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150 private TableName checkTableExists(
2151 final TableName tableName, CatalogTracker ct)
2152 throws IOException {
2153 if (!MetaReader.tableExists(ct, tableName)) {
2154 throw new TableNotFoundException(tableName);
2155 }
2156 return tableName;
2157 }
2158
2159
2160
2161
2162
2163 public synchronized void shutdown() throws IOException {
2164 executeCallable(new MasterCallable<Void>(getConnection()) {
2165 @Override
2166 public Void call() throws ServiceException {
2167 master.shutdown(null,ShutdownRequest.newBuilder().build());
2168 return null;
2169 }
2170 });
2171 }
2172
2173
2174
2175
2176
2177
2178
2179 public synchronized void stopMaster() throws IOException {
2180 executeCallable(new MasterCallable<Void>(getConnection()) {
2181 @Override
2182 public Void call() throws ServiceException {
2183 master.stopMaster(null,StopMasterRequest.newBuilder().build());
2184 return null;
2185 }
2186 });
2187 }
2188
2189
2190
2191
2192
2193
2194
2195 public synchronized void stopRegionServer(final String hostnamePort)
2196 throws IOException {
2197 String hostname = Addressing.parseHostname(hostnamePort);
2198 int port = Addressing.parsePort(hostnamePort);
2199 AdminService.BlockingInterface admin =
2200 this.connection.getAdmin(ServerName.valueOf(hostname, port, 0));
2201 StopServerRequest request = RequestConverter.buildStopServerRequest(
2202 "Called by admin client " + this.connection.toString());
2203 try {
2204 admin.stopServer(null, request);
2205 } catch (ServiceException se) {
2206 throw ProtobufUtil.getRemoteException(se);
2207 }
2208 }
2209
2210
2211
2212
2213
2214
2215 public ClusterStatus getClusterStatus() throws IOException {
2216 return executeCallable(new MasterCallable<ClusterStatus>(getConnection()) {
2217 @Override
2218 public ClusterStatus call() throws ServiceException {
2219 GetClusterStatusRequest req = RequestConverter.buildGetClusterStatusRequest();
2220 return ClusterStatus.convert(master.getClusterStatus(null,req).getClusterStatus());
2221 }
2222 });
2223 }
2224
2225 private HRegionLocation getFirstMetaServerForTable(final TableName tableName)
2226 throws IOException {
2227 return connection.locateRegion(TableName.META_TABLE_NAME,
2228 HRegionInfo.createRegionName(tableName, null, HConstants.NINES, false));
2229 }
2230
2231
2232
2233
2234 public Configuration getConfiguration() {
2235 return this.conf;
2236 }
2237
2238
2239
2240
2241
2242
2243 public void createNamespace(final NamespaceDescriptor descriptor) throws IOException {
2244 executeCallable(new MasterCallable<Void>(getConnection()) {
2245 @Override
2246 public Void call() throws Exception {
2247 master.createNamespace(null,
2248 CreateNamespaceRequest.newBuilder()
2249 .setNamespaceDescriptor(ProtobufUtil
2250 .toProtoNamespaceDescriptor(descriptor)).build());
2251 return null;
2252 }
2253 });
2254 }
2255
2256
2257
2258
2259
2260
2261 public void modifyNamespace(final NamespaceDescriptor descriptor) throws IOException {
2262 executeCallable(new MasterCallable<Void>(getConnection()) {
2263 @Override
2264 public Void call() throws Exception {
2265 master.modifyNamespace(null, ModifyNamespaceRequest.newBuilder().
2266 setNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(descriptor)).build());
2267 return null;
2268 }
2269 });
2270 }
2271
2272
2273
2274
2275
2276
2277 public void deleteNamespace(final String name) throws IOException {
2278 executeCallable(new MasterCallable<Void>(getConnection()) {
2279 @Override
2280 public Void call() throws Exception {
2281 master.deleteNamespace(null, DeleteNamespaceRequest.newBuilder().
2282 setNamespaceName(name).build());
2283 return null;
2284 }
2285 });
2286 }
2287
2288
2289
2290
2291
2292
2293
2294 public NamespaceDescriptor getNamespaceDescriptor(final String name) throws IOException {
2295 return
2296 executeCallable(new MasterCallable<NamespaceDescriptor>(getConnection()) {
2297 @Override
2298 public NamespaceDescriptor call() throws Exception {
2299 return ProtobufUtil.toNamespaceDescriptor(
2300 master.getNamespaceDescriptor(null, GetNamespaceDescriptorRequest.newBuilder().
2301 setNamespaceName(name).build()).getNamespaceDescriptor());
2302 }
2303 });
2304 }
2305
2306
2307
2308
2309
2310
2311 public NamespaceDescriptor[] listNamespaceDescriptors() throws IOException {
2312 return
2313 executeCallable(new MasterCallable<NamespaceDescriptor[]>(getConnection()) {
2314 @Override
2315 public NamespaceDescriptor[] call() throws Exception {
2316 List<HBaseProtos.NamespaceDescriptor> list =
2317 master.listNamespaceDescriptors(null, ListNamespaceDescriptorsRequest.newBuilder().
2318 build()).getNamespaceDescriptorList();
2319 NamespaceDescriptor[] res = new NamespaceDescriptor[list.size()];
2320 for(int i = 0; i < list.size(); i++) {
2321 res[i] = ProtobufUtil.toNamespaceDescriptor(list.get(i));
2322 }
2323 return res;
2324 }
2325 });
2326 }
2327
2328
2329
2330
2331
2332
2333
2334 public HTableDescriptor[] listTableDescriptorsByNamespace(final String name) throws IOException {
2335 return
2336 executeCallable(new MasterCallable<HTableDescriptor[]>(getConnection()) {
2337 @Override
2338 public HTableDescriptor[] call() throws Exception {
2339 List<TableSchema> list =
2340 master.listTableDescriptorsByNamespace(null, ListTableDescriptorsByNamespaceRequest.
2341 newBuilder().setNamespaceName(name).build()).getTableSchemaList();
2342 HTableDescriptor[] res = new HTableDescriptor[list.size()];
2343 for(int i=0; i < list.size(); i++) {
2344
2345 res[i] = HTableDescriptor.convert(list.get(i));
2346 }
2347 return res;
2348 }
2349 });
2350 }
2351
2352
2353
2354
2355
2356
2357
2358 public TableName[] listTableNamesByNamespace(final String name) throws IOException {
2359 return
2360 executeCallable(new MasterCallable<TableName[]>(getConnection()) {
2361 @Override
2362 public TableName[] call() throws Exception {
2363 List<HBaseProtos.TableName> tableNames =
2364 master.listTableNamesByNamespace(null, ListTableNamesByNamespaceRequest.
2365 newBuilder().setNamespaceName(name).build())
2366 .getTableNameList();
2367 TableName[] result = new TableName[tableNames.size()];
2368 for (int i = 0; i < tableNames.size(); i++) {
2369 result[i] = ProtobufUtil.toTableName(tableNames.get(i));
2370 }
2371 return result;
2372 }
2373 });
2374 }
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384 public static void checkHBaseAvailable(Configuration conf)
2385 throws MasterNotRunningException, ZooKeeperConnectionException, ServiceException, IOException {
2386 Configuration copyOfConf = HBaseConfiguration.create(conf);
2387
2388
2389 copyOfConf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
2390 copyOfConf.setInt("zookeeper.recovery.retry", 0);
2391
2392 HConnectionManager.HConnectionImplementation connection
2393 = (HConnectionManager.HConnectionImplementation)
2394 HConnectionManager.getConnection(copyOfConf);
2395
2396 try {
2397
2398
2399
2400 ZooKeeperKeepAliveConnection zkw = null;
2401 try {
2402 zkw = connection.getKeepAliveZooKeeperWatcher();
2403 zkw.getRecoverableZooKeeper().getZooKeeper().exists(
2404 zkw.baseZNode, false);
2405
2406 } catch (IOException e) {
2407 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2408 } catch (InterruptedException e) {
2409 throw (InterruptedIOException)
2410 new InterruptedIOException("Can't connect to ZooKeeper").initCause(e);
2411 } catch (KeeperException e) {
2412 throw new ZooKeeperConnectionException("Can't connect to ZooKeeper", e);
2413 } finally {
2414 if (zkw != null) {
2415 zkw.close();
2416 }
2417 }
2418
2419
2420 connection.isMasterRunning();
2421
2422 } finally {
2423 connection.close();
2424 }
2425 }
2426
2427
2428
2429
2430
2431
2432
2433
2434 public List<HRegionInfo> getTableRegions(final TableName tableName)
2435 throws IOException {
2436 CatalogTracker ct = getCatalogTracker();
2437 List<HRegionInfo> Regions = null;
2438 try {
2439 Regions = MetaReader.getTableRegions(ct, tableName, true);
2440 } finally {
2441 cleanupCatalogTracker(ct);
2442 }
2443 return Regions;
2444 }
2445
2446 public List<HRegionInfo> getTableRegions(final byte[] tableName)
2447 throws IOException {
2448 return getTableRegions(TableName.valueOf(tableName));
2449 }
2450
2451 @Override
2452 public synchronized void close() throws IOException {
2453 if (cleanupConnectionOnClose && this.connection != null && !this.closed) {
2454 this.connection.close();
2455 this.closed = true;
2456 }
2457 }
2458
2459
2460
2461
2462
2463
2464
2465 public HTableDescriptor[] getTableDescriptorsByTableName(List<TableName> tableNames)
2466 throws IOException {
2467 return this.connection.getHTableDescriptorsByTableName(tableNames);
2468 }
2469
2470
2471
2472
2473
2474
2475
2476 public HTableDescriptor[] getTableDescriptors(List<String> names)
2477 throws IOException {
2478 List<TableName> tableNames = new ArrayList<TableName>(names.size());
2479 for(String name : names) {
2480 tableNames.add(TableName.valueOf(name));
2481 }
2482 return getTableDescriptorsByTableName(tableNames);
2483 }
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498 public synchronized byte[][] rollHLogWriter(String serverName)
2499 throws IOException, FailedLogCloseException {
2500 ServerName sn = ServerName.valueOf(serverName);
2501 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2502 RollWALWriterRequest request = RequestConverter.buildRollWALWriterRequest();
2503 try {
2504 RollWALWriterResponse response = admin.rollWALWriter(null, request);
2505 int regionCount = response.getRegionToFlushCount();
2506 byte[][] regionsToFlush = new byte[regionCount][];
2507 for (int i = 0; i < regionCount; i++) {
2508 ByteString region = response.getRegionToFlush(i);
2509 regionsToFlush[i] = region.toByteArray();
2510 }
2511 return regionsToFlush;
2512 } catch (ServiceException se) {
2513 throw ProtobufUtil.getRemoteException(se);
2514 }
2515 }
2516
2517 public String[] getMasterCoprocessors() {
2518 try {
2519 return getClusterStatus().getMasterCoprocessors();
2520 } catch (IOException e) {
2521 LOG.error("Could not getClusterStatus()",e);
2522 return null;
2523 }
2524 }
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535 public CompactionState getCompactionState(final String tableNameOrRegionName)
2536 throws IOException, InterruptedException {
2537 return getCompactionState(Bytes.toBytes(tableNameOrRegionName));
2538 }
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549 public CompactionState getCompactionState(final byte[] tableNameOrRegionName)
2550 throws IOException, InterruptedException {
2551 CompactionState state = CompactionState.NONE;
2552 CatalogTracker ct = getCatalogTracker();
2553 try {
2554 Pair<HRegionInfo, ServerName> regionServerPair
2555 = getRegion(tableNameOrRegionName, ct);
2556 if (regionServerPair != null) {
2557 if (regionServerPair.getSecond() == null) {
2558 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
2559 } else {
2560 ServerName sn = regionServerPair.getSecond();
2561 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2562 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
2563 regionServerPair.getFirst().getRegionName(), true);
2564 GetRegionInfoResponse response = admin.getRegionInfo(null, request);
2565 return response.getCompactionState();
2566 }
2567 } else {
2568 final TableName tableName =
2569 checkTableExists(TableName.valueOf(tableNameOrRegionName), ct);
2570 List<Pair<HRegionInfo, ServerName>> pairs =
2571 MetaReader.getTableRegionsAndLocations(ct, tableName);
2572 for (Pair<HRegionInfo, ServerName> pair: pairs) {
2573 if (pair.getFirst().isOffline()) continue;
2574 if (pair.getSecond() == null) continue;
2575 try {
2576 ServerName sn = pair.getSecond();
2577 AdminService.BlockingInterface admin = this.connection.getAdmin(sn);
2578 GetRegionInfoRequest request = RequestConverter.buildGetRegionInfoRequest(
2579 pair.getFirst().getRegionName(), true);
2580 GetRegionInfoResponse response = admin.getRegionInfo(null, request);
2581 switch (response.getCompactionState()) {
2582 case MAJOR_AND_MINOR:
2583 return CompactionState.MAJOR_AND_MINOR;
2584 case MAJOR:
2585 if (state == CompactionState.MINOR) {
2586 return CompactionState.MAJOR_AND_MINOR;
2587 }
2588 state = CompactionState.MAJOR;
2589 break;
2590 case MINOR:
2591 if (state == CompactionState.MAJOR) {
2592 return CompactionState.MAJOR_AND_MINOR;
2593 }
2594 state = CompactionState.MINOR;
2595 break;
2596 case NONE:
2597 default:
2598 }
2599 } catch (NotServingRegionException e) {
2600 if (LOG.isDebugEnabled()) {
2601 LOG.debug("Trying to get compaction state of " +
2602 pair.getFirst() + ": " +
2603 StringUtils.stringifyException(e));
2604 }
2605 } catch (RemoteException e) {
2606 if (e.getMessage().indexOf(NotServingRegionException.class.getName()) >= 0) {
2607 if (LOG.isDebugEnabled()) {
2608 LOG.debug("Trying to get compaction state of " + pair.getFirst() + ": "
2609 + StringUtils.stringifyException(e));
2610 }
2611 } else {
2612 throw e;
2613 }
2614 }
2615 }
2616 }
2617 } catch (ServiceException se) {
2618 throw ProtobufUtil.getRemoteException(se);
2619 } finally {
2620 cleanupCatalogTracker(ct);
2621 }
2622 return state;
2623 }
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641 public void snapshot(final String snapshotName,
2642 final TableName tableName) throws IOException,
2643 SnapshotCreationException, IllegalArgumentException {
2644 snapshot(snapshotName, tableName, SnapshotDescription.Type.FLUSH);
2645 }
2646
2647 public void snapshot(final String snapshotName,
2648 final String tableName) throws IOException,
2649 SnapshotCreationException, IllegalArgumentException {
2650 snapshot(snapshotName, TableName.valueOf(tableName),
2651 SnapshotDescription.Type.FLUSH);
2652 }
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669 public void snapshot(final byte[] snapshotName, final byte[] tableName,
2670 final SnapshotDescription.Type flushType) throws
2671 IOException, SnapshotCreationException, IllegalArgumentException {
2672 snapshot(Bytes.toString(snapshotName), Bytes.toString(tableName), flushType);
2673 }
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690 public void snapshot(final byte[] snapshotName,
2691 final TableName tableName) throws IOException,
2692 SnapshotCreationException, IllegalArgumentException {
2693 snapshot(Bytes.toString(snapshotName), tableName, SnapshotDescription.Type.FLUSH);
2694 }
2695
2696 public void snapshot(final byte[] snapshotName,
2697 final byte[] tableName) throws IOException,
2698 SnapshotCreationException, IllegalArgumentException {
2699 snapshot(Bytes.toString(snapshotName), TableName.valueOf(tableName),
2700 SnapshotDescription.Type.FLUSH);
2701 }
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721 public void snapshot(final String snapshotName,
2722 final TableName tableName,
2723 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
2724 IllegalArgumentException {
2725 SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
2726 builder.setTable(tableName.getNameAsString());
2727 builder.setName(snapshotName);
2728 builder.setType(type);
2729 snapshot(builder.build());
2730 }
2731
2732 public void snapshot(final String snapshotName,
2733 final String tableName,
2734 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
2735 IllegalArgumentException {
2736 snapshot(snapshotName, TableName.valueOf(tableName), type);
2737 }
2738
2739 public void snapshot(final String snapshotName,
2740 final byte[] tableName,
2741 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
2742 IllegalArgumentException {
2743 snapshot(snapshotName, TableName.valueOf(tableName), type);
2744 }
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767 public void snapshot(SnapshotDescription snapshot) throws IOException, SnapshotCreationException,
2768 IllegalArgumentException {
2769
2770 SnapshotResponse response = takeSnapshotAsync(snapshot);
2771 final IsSnapshotDoneRequest request = IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot)
2772 .build();
2773 IsSnapshotDoneResponse done = null;
2774 long start = EnvironmentEdgeManager.currentTimeMillis();
2775 long max = response.getExpectedTimeout();
2776 long maxPauseTime = max / this.numRetries;
2777 int tries = 0;
2778 LOG.debug("Waiting a max of " + max + " ms for snapshot '" +
2779 ClientSnapshotDescriptionUtils.toString(snapshot) + "'' to complete. (max " +
2780 maxPauseTime + " ms per retry)");
2781 while (tries == 0
2782 || ((EnvironmentEdgeManager.currentTimeMillis() - start) < max && !done.getDone())) {
2783 try {
2784
2785 long sleep = getPauseTime(tries++);
2786 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
2787 LOG.debug("(#" + tries + ") Sleeping: " + sleep +
2788 "ms while waiting for snapshot completion.");
2789 Thread.sleep(sleep);
2790
2791 } catch (InterruptedException e) {
2792 LOG.debug("Interrupted while waiting for snapshot " + snapshot + " to complete");
2793 Thread.currentThread().interrupt();
2794 }
2795 LOG.debug("Getting current status of snapshot from master...");
2796 done = executeCallable(new MasterCallable<IsSnapshotDoneResponse>(getConnection()) {
2797 @Override
2798 public IsSnapshotDoneResponse call() throws ServiceException {
2799 return master.isSnapshotDone(null, request);
2800 }
2801 });
2802 };
2803 if (!done.getDone()) {
2804 throw new SnapshotCreationException("Snapshot '" + snapshot.getName()
2805 + "' wasn't completed in expectedTime:" + max + " ms", snapshot);
2806 }
2807 }
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819 public SnapshotResponse takeSnapshotAsync(SnapshotDescription snapshot) throws IOException,
2820 SnapshotCreationException {
2821 ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
2822 final SnapshotRequest request = SnapshotRequest.newBuilder().setSnapshot(snapshot)
2823 .build();
2824
2825 return executeCallable(new MasterCallable<SnapshotResponse>(getConnection()) {
2826 @Override
2827 public SnapshotResponse call() throws ServiceException {
2828 return master.snapshot(null, request);
2829 }
2830 });
2831 }
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853 public boolean isSnapshotFinished(final SnapshotDescription snapshot)
2854 throws IOException, HBaseSnapshotException, UnknownSnapshotException {
2855
2856 return executeCallable(new MasterCallable<IsSnapshotDoneResponse>(getConnection()) {
2857 @Override
2858 public IsSnapshotDoneResponse call() throws ServiceException {
2859 return master.isSnapshotDone(null,
2860 IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot).build());
2861 }
2862 }).getDone();
2863 }
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878 public void restoreSnapshot(final byte[] snapshotName)
2879 throws IOException, RestoreSnapshotException {
2880 restoreSnapshot(Bytes.toString(snapshotName));
2881 }
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896 public void restoreSnapshot(final String snapshotName)
2897 throws IOException, RestoreSnapshotException {
2898 boolean takeFailSafeSnapshot =
2899 conf.getBoolean("hbase.snapshot.restore.take.failsafe.snapshot", false);
2900 restoreSnapshot(snapshotName, takeFailSafeSnapshot);
2901 }
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919 public void restoreSnapshot(final byte[] snapshotName, final boolean takeFailSafeSnapshot)
2920 throws IOException, RestoreSnapshotException {
2921 restoreSnapshot(Bytes.toString(snapshotName), takeFailSafeSnapshot);
2922 }
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940 public void restoreSnapshot(final String snapshotName, boolean takeFailSafeSnapshot)
2941 throws IOException, RestoreSnapshotException {
2942 TableName tableName = null;
2943 for (SnapshotDescription snapshotInfo: listSnapshots()) {
2944 if (snapshotInfo.getName().equals(snapshotName)) {
2945 tableName = TableName.valueOf(snapshotInfo.getTable());
2946 break;
2947 }
2948 }
2949
2950 if (tableName == null) {
2951 throw new RestoreSnapshotException(
2952 "Unable to find the table name for snapshot=" + snapshotName);
2953 }
2954
2955
2956 if (!tableExists(tableName)) {
2957 try {
2958 cloneSnapshot(snapshotName, tableName);
2959 } catch (InterruptedException e) {
2960 throw new InterruptedIOException("Interrupted when restoring a nonexistent table: " +
2961 e.getMessage());
2962 }
2963 return;
2964 }
2965
2966
2967 if (!isTableDisabled(tableName)) {
2968 throw new TableNotDisabledException(tableName);
2969 }
2970
2971
2972 String failSafeSnapshotSnapshotName = null;
2973 if (takeFailSafeSnapshot) {
2974 failSafeSnapshotSnapshotName = conf.get("hbase.snapshot.restore.failsafe.name",
2975 "hbase-failsafe-{snapshot.name}-{restore.timestamp}");
2976 failSafeSnapshotSnapshotName = failSafeSnapshotSnapshotName
2977 .replace("{snapshot.name}", snapshotName)
2978 .replace("{table.name}", tableName.toString().replace(TableName.NAMESPACE_DELIM, '.'))
2979 .replace("{restore.timestamp}", String.valueOf(EnvironmentEdgeManager.currentTimeMillis()));
2980 LOG.info("Taking restore-failsafe snapshot: " + failSafeSnapshotSnapshotName);
2981 snapshot(failSafeSnapshotSnapshotName, tableName);
2982 }
2983
2984 try {
2985
2986 internalRestoreSnapshot(snapshotName, tableName);
2987 } catch (IOException e) {
2988
2989
2990 if (takeFailSafeSnapshot) {
2991 try {
2992 internalRestoreSnapshot(failSafeSnapshotSnapshotName, tableName);
2993 String msg = "Restore snapshot=" + snapshotName +
2994 " failed. Rollback to snapshot=" + failSafeSnapshotSnapshotName + " succeeded.";
2995 LOG.error(msg, e);
2996 throw new RestoreSnapshotException(msg, e);
2997 } catch (IOException ex) {
2998 String msg = "Failed to restore and rollback to snapshot=" + failSafeSnapshotSnapshotName;
2999 LOG.error(msg, ex);
3000 throw new RestoreSnapshotException(msg, e);
3001 }
3002 } else {
3003 throw new RestoreSnapshotException("Failed to restore snapshot=" + snapshotName, e);
3004 }
3005 }
3006
3007
3008 if (takeFailSafeSnapshot) {
3009 try {
3010 LOG.info("Deleting restore-failsafe snapshot: " + failSafeSnapshotSnapshotName);
3011 deleteSnapshot(failSafeSnapshotSnapshotName);
3012 } catch (IOException e) {
3013 LOG.error("Unable to remove the failsafe snapshot: " + failSafeSnapshotSnapshotName, e);
3014 }
3015 }
3016 }
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028 public void cloneSnapshot(final byte[] snapshotName, final byte[] tableName)
3029 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
3030 cloneSnapshot(Bytes.toString(snapshotName), TableName.valueOf(tableName));
3031 }
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043 public void cloneSnapshot(final byte[] snapshotName, final TableName tableName)
3044 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
3045 cloneSnapshot(Bytes.toString(snapshotName), tableName);
3046 }
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060 public void cloneSnapshot(final String snapshotName, final String tableName)
3061 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
3062 cloneSnapshot(snapshotName, TableName.valueOf(tableName));
3063 }
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075 public void cloneSnapshot(final String snapshotName, final TableName tableName)
3076 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
3077 if (tableExists(tableName)) {
3078 throw new TableExistsException(tableName);
3079 }
3080 internalRestoreSnapshot(snapshotName, tableName);
3081 waitUntilTableIsEnabled(tableName);
3082 }
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093 public void execProcedure(String signature, String instance,
3094 Map<String, String> props) throws IOException {
3095 ProcedureDescription.Builder builder = ProcedureDescription.newBuilder();
3096 builder.setSignature(signature).setInstance(instance);
3097 for (String key : props.keySet()) {
3098 NameStringPair pair = NameStringPair.newBuilder().setName(key)
3099 .setValue(props.get(key)).build();
3100 builder.addConfiguration(pair);
3101 }
3102
3103 final ExecProcedureRequest request = ExecProcedureRequest.newBuilder()
3104 .setProcedure(builder.build()).build();
3105
3106 ExecProcedureResponse response = executeCallable(new MasterCallable<ExecProcedureResponse>(
3107 getConnection()) {
3108 @Override
3109 public ExecProcedureResponse call() throws ServiceException {
3110 return master.execProcedure(null, request);
3111 }
3112 });
3113
3114 long start = EnvironmentEdgeManager.currentTimeMillis();
3115 long max = response.getExpectedTimeout();
3116 long maxPauseTime = max / this.numRetries;
3117 int tries = 0;
3118 LOG.debug("Waiting a max of " + max + " ms for procedure '" +
3119 signature + " : " + instance + "'' to complete. (max " + maxPauseTime + " ms per retry)");
3120 boolean done = false;
3121 while (tries == 0
3122 || ((EnvironmentEdgeManager.currentTimeMillis() - start) < max && !done)) {
3123 try {
3124
3125 long sleep = getPauseTime(tries++);
3126 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
3127 LOG.debug("(#" + tries + ") Sleeping: " + sleep +
3128 "ms while waiting for procedure completion.");
3129 Thread.sleep(sleep);
3130
3131 } catch (InterruptedException e) {
3132 LOG.debug("Interrupted while waiting for procedure " + signature + " to complete");
3133 Thread.currentThread().interrupt();
3134 }
3135 LOG.debug("Getting current status of procedure from master...");
3136 done = isProcedureFinished(signature, instance, props);
3137 }
3138 if (!done) {
3139 throw new IOException("Procedure '" + signature + " : " + instance
3140 + "' wasn't completed in expectedTime:" + max + " ms");
3141 }
3142 }
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161 public boolean isProcedureFinished(String signature, String instance, Map<String, String> props)
3162 throws IOException {
3163 final ProcedureDescription.Builder builder = ProcedureDescription.newBuilder();
3164 builder.setSignature(signature).setInstance(instance);
3165 for (String key : props.keySet()) {
3166 NameStringPair pair = NameStringPair.newBuilder().setName(key)
3167 .setValue(props.get(key)).build();
3168 builder.addConfiguration(pair);
3169 }
3170 final ProcedureDescription desc = builder.build();
3171 return executeCallable(
3172 new MasterCallable<IsProcedureDoneResponse>(getConnection()) {
3173 @Override
3174 public IsProcedureDoneResponse call() throws ServiceException {
3175 return master.isProcedureDone(null, IsProcedureDoneRequest
3176 .newBuilder().setProcedure(desc).build());
3177 }
3178 }).getDone();
3179 }
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191 private void internalRestoreSnapshot(final String snapshotName, final TableName
3192 tableName)
3193 throws IOException, RestoreSnapshotException {
3194 SnapshotDescription snapshot = SnapshotDescription.newBuilder()
3195 .setName(snapshotName).setTable(tableName.getNameAsString()).build();
3196
3197
3198 internalRestoreSnapshotAsync(snapshot);
3199
3200 final IsRestoreSnapshotDoneRequest request = IsRestoreSnapshotDoneRequest.newBuilder()
3201 .setSnapshot(snapshot).build();
3202 IsRestoreSnapshotDoneResponse done = IsRestoreSnapshotDoneResponse.newBuilder()
3203 .setDone(false).buildPartial();
3204 final long maxPauseTime = 5000;
3205 int tries = 0;
3206 while (!done.getDone()) {
3207 try {
3208
3209 long sleep = getPauseTime(tries++);
3210 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
3211 LOG.debug(tries + ") Sleeping: " + sleep + " ms while we wait for snapshot restore to complete.");
3212 Thread.sleep(sleep);
3213 } catch (InterruptedException e) {
3214 LOG.debug("Interrupted while waiting for snapshot " + snapshot + " restore to complete");
3215 Thread.currentThread().interrupt();
3216 }
3217 LOG.debug("Getting current status of snapshot restore from master...");
3218 done = executeCallable(new MasterCallable<IsRestoreSnapshotDoneResponse>(
3219 getConnection()) {
3220 @Override
3221 public IsRestoreSnapshotDoneResponse call() throws ServiceException {
3222 return master.isRestoreSnapshotDone(null, request);
3223 }
3224 });
3225 }
3226 if (!done.getDone()) {
3227 throw new RestoreSnapshotException("Snapshot '" + snapshot.getName() + "' wasn't restored.");
3228 }
3229 }
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241 private RestoreSnapshotResponse internalRestoreSnapshotAsync(final SnapshotDescription snapshot)
3242 throws IOException, RestoreSnapshotException {
3243 ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
3244
3245 final RestoreSnapshotRequest request = RestoreSnapshotRequest.newBuilder().setSnapshot(snapshot)
3246 .build();
3247
3248
3249 return executeCallable(new MasterCallable<RestoreSnapshotResponse>(getConnection()) {
3250 @Override
3251 public RestoreSnapshotResponse call() throws ServiceException {
3252 return master.restoreSnapshot(null, request);
3253 }
3254 });
3255 }
3256
3257
3258
3259
3260
3261
3262 public List<SnapshotDescription> listSnapshots() throws IOException {
3263 return executeCallable(new MasterCallable<List<SnapshotDescription>>(getConnection()) {
3264 @Override
3265 public List<SnapshotDescription> call() throws ServiceException {
3266 return master.getCompletedSnapshots(null, GetCompletedSnapshotsRequest.newBuilder().build())
3267 .getSnapshotsList();
3268 }
3269 });
3270 }
3271
3272
3273
3274
3275
3276
3277
3278
3279 public List<SnapshotDescription> listSnapshots(String regex) throws IOException {
3280 return listSnapshots(Pattern.compile(regex));
3281 }
3282
3283
3284
3285
3286
3287
3288
3289
3290 public List<SnapshotDescription> listSnapshots(Pattern pattern) throws IOException {
3291 List<SnapshotDescription> matched = new LinkedList<SnapshotDescription>();
3292 List<SnapshotDescription> snapshots = listSnapshots();
3293 for (SnapshotDescription snapshot : snapshots) {
3294 if (pattern.matcher(snapshot.getName()).matches()) {
3295 matched.add(snapshot);
3296 }
3297 }
3298 return matched;
3299 }
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309 public List<SnapshotDescription> listTableSnapshots(String tableNameRegex,
3310 String snapshotNameRegex) throws IOException {
3311 return listTableSnapshots(Pattern.compile(tableNameRegex), Pattern.compile(snapshotNameRegex));
3312 }
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322 public List<SnapshotDescription> listTableSnapshots(Pattern tableNamePattern,
3323 Pattern snapshotNamePattern) throws IOException {
3324 String[] tableNames = getTableNames(tableNamePattern);
3325
3326 List<SnapshotDescription> tableSnapshots = new LinkedList<SnapshotDescription>();
3327 List<SnapshotDescription> snapshots = listSnapshots(snapshotNamePattern);
3328
3329 List<String> listOfTableNames = Arrays.asList(tableNames);
3330 for (SnapshotDescription snapshot : snapshots) {
3331 if (listOfTableNames.contains(snapshot.getTable())) {
3332 tableSnapshots.add(snapshot);
3333 }
3334 }
3335 return tableSnapshots;
3336 }
3337
3338
3339
3340
3341
3342
3343 public void deleteSnapshot(final byte[] snapshotName) throws IOException {
3344 deleteSnapshot(Bytes.toString(snapshotName));
3345 }
3346
3347
3348
3349
3350
3351
3352 public void deleteSnapshot(final String snapshotName) throws IOException {
3353
3354 TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(snapshotName));
3355
3356 executeCallable(new MasterCallable<Void>(getConnection()) {
3357 @Override
3358 public Void call() throws ServiceException {
3359 master.deleteSnapshot(null,
3360 DeleteSnapshotRequest.newBuilder().
3361 setSnapshot(SnapshotDescription.newBuilder().setName(snapshotName).build()).build());
3362 return null;
3363 }
3364 });
3365 }
3366
3367
3368
3369
3370
3371
3372 public void deleteSnapshots(final String regex) throws IOException {
3373 deleteSnapshots(Pattern.compile(regex));
3374 }
3375
3376
3377
3378
3379
3380
3381 public void deleteSnapshots(final Pattern pattern) throws IOException {
3382 List<SnapshotDescription> snapshots = listSnapshots(pattern);
3383 for (final SnapshotDescription snapshot : snapshots) {
3384 try {
3385 internalDeleteSnapshot(snapshot);
3386 } catch (IOException ex) {
3387 LOG.info(
3388 "Failed to delete snapshot " + snapshot.getName() + " for table " + snapshot.getTable(),
3389 ex);
3390 }
3391 }
3392 }
3393
3394
3395
3396
3397
3398
3399
3400
3401 public void deleteTableSnapshots(String tableNameRegex, String snapshotNameRegex)
3402 throws IOException {
3403 deleteTableSnapshots(Pattern.compile(tableNameRegex), Pattern.compile(snapshotNameRegex));
3404 }
3405
3406
3407
3408
3409
3410
3411
3412
3413 public void deleteTableSnapshots(Pattern tableNamePattern, Pattern snapshotNamePattern)
3414 throws IOException {
3415 List<SnapshotDescription> snapshots = listTableSnapshots(tableNamePattern, snapshotNamePattern);
3416 for (SnapshotDescription snapshot : snapshots) {
3417 try {
3418 internalDeleteSnapshot(snapshot);
3419 LOG.debug("Successfully deleted snapshot: " + snapshot.getName());
3420 } catch (IOException e) {
3421 LOG.error("Failed to delete snapshot: " + snapshot.getName(), e);
3422 }
3423 }
3424 }
3425
3426 private void internalDeleteSnapshot(final SnapshotDescription snapshot) throws IOException {
3427 executeCallable(new MasterCallable<Void>(getConnection()) {
3428 @Override
3429 public Void call() throws ServiceException {
3430 this.master.deleteSnapshot(null, DeleteSnapshotRequest.newBuilder().setSnapshot(snapshot)
3431 .build());
3432 return null;
3433 }
3434 });
3435 }
3436
3437
3438
3439
3440
3441
3442 abstract static class MasterCallable<V> implements RetryingCallable<V>, Closeable {
3443 protected HConnection connection;
3444 protected MasterKeepAliveConnection master;
3445
3446 public MasterCallable(final HConnection connection) {
3447 this.connection = connection;
3448 }
3449
3450 @Override
3451 public void prepare(boolean reload) throws IOException {
3452 this.master = this.connection.getKeepAliveMasterService();
3453 }
3454
3455 @Override
3456 public void close() throws IOException {
3457
3458 if (this.master != null) this.master.close();
3459 }
3460
3461 @Override
3462 public void throwable(Throwable t, boolean retrying) {
3463 }
3464
3465 @Override
3466 public String getExceptionMessageAdditionalDetail() {
3467 return "";
3468 }
3469
3470 @Override
3471 public long sleep(long pause, int tries) {
3472 return ConnectionUtils.getPauseTime(pause, tries);
3473 }
3474 }
3475
3476 private <V> V executeCallable(MasterCallable<V> callable) throws IOException {
3477 RpcRetryingCaller<V> caller = rpcCallerFactory.newCaller();
3478 try {
3479 return caller.callWithRetries(callable);
3480 } finally {
3481 callable.close();
3482 }
3483 }
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506 public CoprocessorRpcChannel coprocessorService() {
3507 return new MasterCoprocessorRpcChannel(connection);
3508 }
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532 public CoprocessorRpcChannel coprocessorService(ServerName sn) {
3533 return new RegionServerCoprocessorRpcChannel(connection, sn);
3534 }
3535
3536
3537
3538
3539
3540
3541
3542 public void truncateTable(final TableName tableName, final boolean preserveSplits)
3543 throws IOException {
3544 executeCallable(new MasterCallable<Void>(getConnection()) {
3545 @Override
3546 public Void call() throws ServiceException {
3547 LOG.info("Started truncate of " + tableName);
3548 TruncateTableRequest req = RequestConverter.buildTruncateTableRequest(
3549 tableName, preserveSplits);
3550 master.truncateTable(null, req);
3551 return null;
3552 }
3553 });
3554 }
3555
3556
3557
3558
3559
3560
3561 public List<SecurityCapability> getSecurityCapabilities() throws IOException {
3562 try {
3563 return executeCallable(new MasterCallable<List<SecurityCapability>>(getConnection()) {
3564 @Override
3565 public List<SecurityCapability> call() throws ServiceException {
3566 SecurityCapabilitiesRequest req = SecurityCapabilitiesRequest.newBuilder().build();
3567 return ProtobufUtil.toSecurityCapabilityList(
3568 master.getSecurityCapabilities(null, req).getCapabilitiesList());
3569 }
3570 });
3571 } catch (IOException e) {
3572 if (e instanceof RemoteException) {
3573 e = ((RemoteException)e).unwrapRemoteException();
3574 }
3575 throw e;
3576 }
3577 }
3578 }