1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.client;
21
22 import java.io.Closeable;
23 import java.io.IOException;
24 import java.io.InterruptedIOException;
25 import java.lang.reflect.Proxy;
26 import java.lang.reflect.UndeclaredThrowableException;
27 import java.net.SocketTimeoutException;
28 import java.util.Arrays;
29 import java.util.LinkedList;
30 import java.util.List;
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.HColumnDescriptor;
42 import org.apache.hadoop.hbase.HConstants;
43 import org.apache.hadoop.hbase.HRegionInfo;
44 import org.apache.hadoop.hbase.HRegionLocation;
45 import org.apache.hadoop.hbase.HTableDescriptor;
46 import org.apache.hadoop.hbase.MasterNotRunningException;
47 import org.apache.hadoop.hbase.NotServingRegionException;
48 import org.apache.hadoop.hbase.RegionException;
49 import org.apache.hadoop.hbase.RemoteExceptionHandler;
50 import org.apache.hadoop.hbase.ServerName;
51 import org.apache.hadoop.hbase.TableExistsException;
52 import org.apache.hadoop.hbase.TableNotEnabledException;
53 import org.apache.hadoop.hbase.TableNotFoundException;
54 import org.apache.hadoop.hbase.UnknownRegionException;
55 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
56 import org.apache.hadoop.hbase.catalog.CatalogTracker;
57 import org.apache.hadoop.hbase.catalog.MetaReader;
58 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor;
59 import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitorBase;
60 import org.apache.hadoop.hbase.ipc.CoprocessorProtocol;
61 import org.apache.hadoop.hbase.ipc.HMasterInterface;
62 import org.apache.hadoop.hbase.ipc.HRegionInterface;
63 import org.apache.hadoop.hbase.ipc.MasterExecRPCInvoker;
64 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
65 import org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest.CompactionState;
66 import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
67 import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
68 import org.apache.hadoop.hbase.snapshot.HSnapshotDescription;
69 import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
70 import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
71 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
72 import org.apache.hadoop.hbase.snapshot.UnknownSnapshotException;
73 import org.apache.hadoop.hbase.util.Addressing;
74 import org.apache.hadoop.hbase.util.Bytes;
75 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
76 import org.apache.hadoop.hbase.util.Pair;
77 import org.apache.hadoop.ipc.RemoteException;
78 import org.apache.hadoop.util.StringUtils;
79
80 import com.google.protobuf.ServiceException;
81
82
83
84
85
86
87
88
89
90
91 public class HBaseAdmin implements Abortable, Closeable {
92 private final Log LOG = LogFactory.getLog(this.getClass().getName());
93
94 private HConnection connection;
95 private volatile Configuration conf;
96 private final long pause;
97 private final int numRetries;
98
99
100
101 private final int retryLongerMultiplier;
102 private boolean aborted;
103
104 private static volatile boolean synchronousBalanceSwitchSupported = true;
105
106
107
108
109
110
111
112
113 public HBaseAdmin(Configuration c)
114 throws MasterNotRunningException, ZooKeeperConnectionException {
115 this.conf = HBaseConfiguration.create(c);
116 this.connection = HConnectionManager.getConnection(this.conf);
117 this.pause = this.conf.getLong("hbase.client.pause", 1000);
118 this.numRetries = this.conf.getInt("hbase.client.retries.number", 10);
119 this.retryLongerMultiplier = this.conf.getInt(
120 "hbase.client.retries.longer.multiplier", 10);
121
122 int tries = 0;
123 while ( true ){
124 try {
125
126 this.connection.getMaster();
127 return;
128
129 } catch (MasterNotRunningException mnre) {
130 HConnectionManager.deleteStaleConnection(this.connection);
131 this.connection = HConnectionManager.getConnection(this.conf);
132 }
133
134 tries++;
135 if (tries >= numRetries) {
136
137 HConnectionManager.deleteStaleConnection(this.connection);
138 throw new MasterNotRunningException("Retried " + numRetries + " times");
139 }
140
141 try {
142 Thread.sleep(getPauseTime(tries));
143 } catch (InterruptedException e) {
144 Thread.currentThread().interrupt();
145
146 HConnectionManager.deleteStaleConnection(this.connection);
147 throw new MasterNotRunningException(
148 "Interrupted after "+tries+" tries");
149 }
150 }
151 }
152
153
154
155
156
157
158
159
160
161
162
163 public HBaseAdmin(HConnection connection)
164 throws MasterNotRunningException, ZooKeeperConnectionException {
165 this.conf = connection.getConfiguration();
166 this.connection = connection;
167
168 this.pause = this.conf.getLong("hbase.client.pause", 1000);
169 this.numRetries = this.conf.getInt("hbase.client.retries.number", 10);
170 this.retryLongerMultiplier = this.conf.getInt(
171 "hbase.client.retries.longer.multiplier", 10);
172
173 this.connection.getMaster();
174 }
175
176
177
178
179
180
181
182
183 private synchronized CatalogTracker getCatalogTracker()
184 throws ZooKeeperConnectionException, IOException {
185 CatalogTracker ct = null;
186 try {
187 ct = new CatalogTracker(this.conf);
188 ct.start();
189 } catch (InterruptedException e) {
190
191 Thread.currentThread().interrupt();
192 throw new IOException("Interrupted", e);
193 }
194 return ct;
195 }
196
197 private void cleanupCatalogTracker(final CatalogTracker ct) {
198 ct.stop();
199 }
200
201 @Override
202 public void abort(String why, Throwable e) {
203
204 this.aborted = true;
205 throw new RuntimeException(why, e);
206 }
207
208 @Override
209 public boolean isAborted(){
210 return this.aborted;
211 }
212
213
214 public HConnection getConnection() {
215 return connection;
216 }
217
218
219
220
221
222
223
224
225
226 @Deprecated
227 public HMasterInterface getMaster()
228 throws MasterNotRunningException, ZooKeeperConnectionException {
229 return this.connection.getMaster();
230 }
231
232
233
234
235 public boolean isMasterRunning()
236 throws MasterNotRunningException, ZooKeeperConnectionException {
237 return this.connection.isMasterRunning();
238 }
239
240
241
242
243
244
245 public boolean tableExists(final String tableName)
246 throws IOException {
247 boolean b = false;
248 CatalogTracker ct = getCatalogTracker();
249 try {
250 b = MetaReader.tableExists(ct, tableName);
251 } finally {
252 cleanupCatalogTracker(ct);
253 }
254 return b;
255 }
256
257
258
259
260
261
262 public boolean tableExists(final byte [] tableName)
263 throws IOException {
264 return tableExists(Bytes.toString(tableName));
265 }
266
267
268
269
270
271
272
273
274
275
276
277 public HTableDescriptor[] listTables() throws IOException {
278 return this.connection.listTables();
279 }
280
281
282
283
284
285
286
287
288
289 public HTableDescriptor[] listTables(Pattern pattern) throws IOException {
290 List<HTableDescriptor> matched = new LinkedList<HTableDescriptor>();
291 HTableDescriptor[] tables = listTables();
292 for (HTableDescriptor table : tables) {
293 if (pattern.matcher(table.getNameAsString()).matches()) {
294 matched.add(table);
295 }
296 }
297 return matched.toArray(new HTableDescriptor[matched.size()]);
298 }
299
300
301
302
303
304
305
306
307
308 public HTableDescriptor[] listTables(String regex) throws IOException {
309 return listTables(Pattern.compile(regex));
310 }
311
312
313
314
315
316
317
318
319
320 public HTableDescriptor getTableDescriptor(final byte [] tableName)
321 throws TableNotFoundException, IOException {
322 return this.connection.getHTableDescriptor(tableName);
323 }
324
325 private long getPauseTime(int tries) {
326 int triesCount = tries;
327 if (triesCount >= HConstants.RETRY_BACKOFF.length) {
328 triesCount = HConstants.RETRY_BACKOFF.length - 1;
329 }
330 return this.pause * HConstants.RETRY_BACKOFF[triesCount];
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346 public void createTable(HTableDescriptor desc)
347 throws IOException {
348 createTable(desc, null);
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375 public void createTable(HTableDescriptor desc, byte [] startKey,
376 byte [] endKey, int numRegions)
377 throws IOException {
378 HTableDescriptor.isLegalTableName(desc.getName());
379 if(numRegions < 3) {
380 throw new IllegalArgumentException("Must create at least three regions");
381 } else if(Bytes.compareTo(startKey, endKey) >= 0) {
382 throw new IllegalArgumentException("Start key must be smaller than end key");
383 }
384 if (numRegions == 3) {
385 createTable(desc, new byte[][] { startKey, endKey });
386 return;
387 }
388 byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
389 if(splitKeys == null || splitKeys.length != numRegions - 1) {
390 throw new IllegalArgumentException("Unable to split key range into enough regions");
391 }
392 createTable(desc, splitKeys);
393 }
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412 public void createTable(final HTableDescriptor desc, byte [][] splitKeys)
413 throws IOException {
414 HTableDescriptor.isLegalTableName(desc.getName());
415 try {
416 createTableAsync(desc, splitKeys);
417 } catch (SocketTimeoutException ste) {
418 LOG.warn("Creating " + desc.getNameAsString() + " took too long", ste);
419 }
420 int numRegs = splitKeys == null ? 1 : splitKeys.length + 1;
421 int prevRegCount = 0;
422 boolean doneWithMetaScan = false;
423 for (int tries = 0; tries < this.numRetries * this.retryLongerMultiplier;
424 ++tries) {
425 if (!doneWithMetaScan) {
426
427 final AtomicInteger actualRegCount = new AtomicInteger(0);
428 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
429 @Override
430 public boolean processRow(Result rowResult) throws IOException {
431 if (rowResult == null || rowResult.size() <= 0) {
432 return true;
433 }
434 HRegionInfo info = MetaReader.parseHRegionInfoFromCatalogResult(
435 rowResult, HConstants.REGIONINFO_QUALIFIER);
436 if (info == null) {
437 LOG.warn("No serialized HRegionInfo in " + rowResult);
438 return true;
439 }
440 if (!(Bytes.equals(info.getTableName(), desc.getName()))) {
441 return false;
442 }
443 String hostAndPort = null;
444 byte [] value = rowResult.getValue(HConstants.CATALOG_FAMILY,
445 HConstants.SERVER_QUALIFIER);
446
447 if (value != null && value.length > 0) {
448 hostAndPort = Bytes.toString(value);
449 }
450 if (!(info.isOffline() || info.isSplit()) && hostAndPort != null) {
451 actualRegCount.incrementAndGet();
452 }
453 return true;
454 }
455 };
456 MetaScanner.metaScan(conf, visitor, desc.getName());
457 if (actualRegCount.get() != numRegs) {
458 if (tries == this.numRetries * this.retryLongerMultiplier - 1) {
459 throw new RegionOfflineException("Only " + actualRegCount.get() +
460 " of " + numRegs + " regions are online; retries exhausted.");
461 }
462 try {
463 Thread.sleep(getPauseTime(tries));
464 } catch (InterruptedException e) {
465 throw new InterruptedIOException("Interrupted when opening" +
466 " regions; " + actualRegCount.get() + " of " + numRegs +
467 " regions processed so far");
468 }
469 if (actualRegCount.get() > prevRegCount) {
470 prevRegCount = actualRegCount.get();
471 tries = -1;
472 }
473 } else {
474 doneWithMetaScan = true;
475 tries = -1;
476 }
477 } else if (isTableEnabled(desc.getName())) {
478 return;
479 } else {
480 try {
481 Thread.sleep(getPauseTime(tries));
482 } catch (InterruptedException e) {
483 throw new InterruptedIOException("Interrupted when waiting" +
484 " for table to be enabled; meta scan was done");
485 }
486 }
487 }
488 throw new TableNotEnabledException(
489 "Retries exhausted while still waiting for table: "
490 + desc.getNameAsString() + " to be enabled");
491 }
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509 public void createTableAsync(HTableDescriptor desc, byte [][] splitKeys)
510 throws IOException {
511 HTableDescriptor.isLegalTableName(desc.getName());
512 if(splitKeys != null && splitKeys.length > 0) {
513 Arrays.sort(splitKeys, Bytes.BYTES_COMPARATOR);
514
515 byte [] lastKey = null;
516 for(byte [] splitKey : splitKeys) {
517 if (Bytes.compareTo(splitKey, HConstants.EMPTY_BYTE_ARRAY) == 0) {
518 throw new IllegalArgumentException(
519 "Empty split key must not be passed in the split keys.");
520 }
521 if(lastKey != null && Bytes.equals(splitKey, lastKey)) {
522 throw new IllegalArgumentException("All split keys must be unique, " +
523 "found duplicate: " + Bytes.toStringBinary(splitKey) +
524 ", " + Bytes.toStringBinary(lastKey));
525 }
526 lastKey = splitKey;
527 }
528 }
529 try {
530 getMaster().createTable(desc, splitKeys);
531 } catch (RemoteException e) {
532 throw e.unwrapRemoteException();
533 }
534 }
535
536
537
538
539
540
541
542
543 public void deleteTable(final String tableName) throws IOException {
544 deleteTable(Bytes.toBytes(tableName));
545 }
546
547
548
549
550
551
552
553
554 public void deleteTable(final byte [] tableName) throws IOException {
555 isMasterRunning();
556 HTableDescriptor.isLegalTableName(tableName);
557 HRegionLocation firstMetaServer = getFirstMetaServerForTable(tableName);
558 boolean tableExists = true;
559 try {
560 getMaster().deleteTable(tableName);
561 } catch (RemoteException e) {
562 throw RemoteExceptionHandler.decodeRemoteException(e);
563 }
564
565 HRegionInterface server =
566 connection.getHRegionConnection(firstMetaServer.getHostname(), firstMetaServer.getPort());
567 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
568 long scannerId = -1L;
569 try {
570
571 Scan scan = MetaReader.getScanForTableName(tableName);
572 scan.addColumn(HConstants.CATALOG_FAMILY,
573 HConstants.REGIONINFO_QUALIFIER);
574 scannerId = server.openScanner(
575 firstMetaServer.getRegionInfo().getRegionName(), scan);
576
577 Result values = server.next(scannerId);
578
579
580
581 if (values == null) {
582 tableExists = false;
583 HTableDescriptor[] htds = getMaster().getHTableDescriptors();
584 if (htds != null && htds.length > 0) {
585 for (HTableDescriptor htd: htds) {
586 if (Bytes.equals(tableName, htd.getName())) {
587 tableExists = true;
588 break;
589 }
590 }
591 }
592 if (!tableExists) {
593 break;
594 }
595 }
596 } catch (IOException ex) {
597 if(tries == numRetries - 1) {
598 if (ex instanceof RemoteException) {
599 ex = RemoteExceptionHandler.decodeRemoteException((RemoteException) ex);
600 }
601 throw ex;
602 }
603 } finally {
604 if (scannerId != -1L) {
605 try {
606 server.close(scannerId);
607 } catch (Exception ex) {
608 LOG.warn(ex);
609 }
610 }
611 }
612 try {
613 Thread.sleep(getPauseTime(tries));
614 } catch (InterruptedException e) {
615
616 }
617 }
618
619 if (tableExists) {
620 throw new IOException("Retries exhausted, it took too long to wait"+
621 " for the table " + Bytes.toString(tableName) + " to be deleted.");
622 }
623
624 this.connection.clearRegionCache(tableName);
625 LOG.info("Deleted " + Bytes.toString(tableName));
626 }
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641 public HTableDescriptor[] deleteTables(String regex) throws IOException {
642 return deleteTables(Pattern.compile(regex));
643 }
644
645
646
647
648
649
650
651
652
653
654
655
656 public HTableDescriptor[] deleteTables(Pattern pattern) throws IOException {
657 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
658 for (HTableDescriptor table : listTables(pattern)) {
659 try {
660 deleteTable(table.getName());
661 } catch (IOException ex) {
662 LOG.info("Failed to delete table " + table.getNameAsString(), ex);
663 failed.add(table);
664 }
665 }
666 return failed.toArray(new HTableDescriptor[failed.size()]);
667 }
668
669
670 public void enableTable(final String tableName)
671 throws IOException {
672 enableTable(Bytes.toBytes(tableName));
673 }
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688 public void enableTable(final byte [] tableName)
689 throws IOException {
690 enableTableAsync(tableName);
691
692
693 waitUntilTableIsEnabled(tableName);
694
695 LOG.info("Enabled table " + Bytes.toString(tableName));
696 }
697
698
699
700
701
702
703
704
705 private void waitUntilTableIsEnabled(final byte[] tableName) throws IOException {
706 boolean enabled = false;
707 long start = EnvironmentEdgeManager.currentTimeMillis();
708 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
709 enabled = isTableEnabled(tableName) && isTableAvailable(tableName);
710 if (enabled) {
711 break;
712 }
713 long sleep = getPauseTime(tries);
714 if (LOG.isDebugEnabled()) {
715 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
716 "enabled in " + Bytes.toString(tableName));
717 }
718 try {
719 Thread.sleep(sleep);
720 } catch (InterruptedException e) {
721 Thread.currentThread().interrupt();
722
723
724 throw new IOException("Interrupted", e);
725 }
726 }
727 if (!enabled) {
728 long msec = EnvironmentEdgeManager.currentTimeMillis() - start;
729 throw new IOException("Table '" + Bytes.toString(tableName) +
730 "' not yet enabled, after " + msec + "ms.");
731 }
732 }
733
734 public void enableTableAsync(final String tableName)
735 throws IOException {
736 enableTableAsync(Bytes.toBytes(tableName));
737 }
738
739
740
741
742
743
744
745
746
747
748
749 public void enableTableAsync(final byte [] tableName)
750 throws IOException {
751 HTableDescriptor.isLegalTableName(tableName);
752 isMasterRunning();
753 try {
754 getMaster().enableTable(tableName);
755 } catch (RemoteException e) {
756 throw e.unwrapRemoteException();
757 }
758 LOG.info("Started enable of " + Bytes.toString(tableName));
759 }
760
761
762
763
764
765
766
767
768
769
770
771
772
773 public HTableDescriptor[] enableTables(String regex) throws IOException {
774 return enableTables(Pattern.compile(regex));
775 }
776
777
778
779
780
781
782
783
784
785
786
787 public HTableDescriptor[] enableTables(Pattern pattern) throws IOException {
788 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
789 for (HTableDescriptor table : listTables(pattern)) {
790 if (isTableDisabled(table.getName())) {
791 try {
792 enableTable(table.getName());
793 } catch (IOException ex) {
794 LOG.info("Failed to enable table " + table.getNameAsString(), ex);
795 failed.add(table);
796 }
797 }
798 }
799 return failed.toArray(new HTableDescriptor[failed.size()]);
800 }
801
802 public void disableTableAsync(final String tableName) throws IOException {
803 disableTableAsync(Bytes.toBytes(tableName));
804 }
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819 public void disableTableAsync(final byte [] tableName) throws IOException {
820 HTableDescriptor.isLegalTableName(tableName);
821 isMasterRunning();
822 try {
823 getMaster().disableTable(tableName);
824 } catch (RemoteException e) {
825 throw e.unwrapRemoteException();
826 }
827 LOG.info("Started disable of " + Bytes.toString(tableName));
828 }
829
830 public void disableTable(final String tableName)
831 throws IOException {
832 disableTable(Bytes.toBytes(tableName));
833 }
834
835
836
837
838
839
840
841
842
843
844
845
846 public void disableTable(final byte [] tableName)
847 throws IOException {
848 disableTableAsync(tableName);
849
850 boolean disabled = false;
851 for (int tries = 0; tries < (this.numRetries * this.retryLongerMultiplier); tries++) {
852 disabled = isTableDisabled(tableName);
853 if (disabled) {
854 break;
855 }
856 long sleep = getPauseTime(tries);
857 if (LOG.isDebugEnabled()) {
858 LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
859 "disabled in " + Bytes.toString(tableName));
860 }
861 try {
862 Thread.sleep(sleep);
863 } catch (InterruptedException e) {
864
865
866 Thread.currentThread().interrupt();
867 throw new IOException("Interrupted", e);
868 }
869 }
870 if (!disabled) {
871 throw new RegionException("Retries exhausted, it took too long to wait"+
872 " for the table " + Bytes.toString(tableName) + " to be disabled.");
873 }
874 LOG.info("Disabled " + Bytes.toString(tableName));
875 }
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890 public HTableDescriptor[] disableTables(String regex) throws IOException {
891 return disableTables(Pattern.compile(regex));
892 }
893
894
895
896
897
898
899
900
901
902
903
904
905 public HTableDescriptor[] disableTables(Pattern pattern) throws IOException {
906 List<HTableDescriptor> failed = new LinkedList<HTableDescriptor>();
907 for (HTableDescriptor table : listTables(pattern)) {
908 if (isTableEnabled(table.getName())) {
909 try {
910 disableTable(table.getName());
911 } catch (IOException ex) {
912 LOG.info("Failed to disable table " + table.getNameAsString(), ex);
913 failed.add(table);
914 }
915 }
916 }
917 return failed.toArray(new HTableDescriptor[failed.size()]);
918 }
919
920
921
922
923
924
925 public boolean isTableEnabled(String tableName) throws IOException {
926 return isTableEnabled(Bytes.toBytes(tableName));
927 }
928
929
930
931
932
933 public boolean isTableEnabled(byte[] tableName) throws IOException {
934 if (!HTableDescriptor.isMetaTable(tableName)) {
935 HTableDescriptor.isLegalTableName(tableName);
936 }
937 if(!tableExists(tableName)){
938 throw new TableNotFoundException(Bytes.toString(tableName));
939 }
940 return connection.isTableEnabled(tableName);
941 }
942
943
944
945
946
947
948 public boolean isTableDisabled(final String tableName) throws IOException {
949 return isTableDisabled(Bytes.toBytes(tableName));
950 }
951
952
953
954
955
956
957 public boolean isTableDisabled(byte[] tableName) throws IOException {
958 if (!HTableDescriptor.isMetaTable(tableName)) {
959 HTableDescriptor.isLegalTableName(tableName);
960 }
961 return connection.isTableDisabled(tableName);
962 }
963
964
965
966
967
968
969 public boolean isTableAvailable(byte[] tableName) throws IOException {
970 return connection.isTableAvailable(tableName);
971 }
972
973
974
975
976
977
978 public boolean isTableAvailable(String tableName) throws IOException {
979 return connection.isTableAvailable(Bytes.toBytes(tableName));
980 }
981
982
983
984
985
986
987
988
989
990
991
992
993
994 public Pair<Integer, Integer> getAlterStatus(final byte[] tableName)
995 throws IOException {
996 HTableDescriptor.isLegalTableName(tableName);
997 try {
998 return getMaster().getAlterStatus(tableName);
999 } catch (RemoteException e) {
1000 throw RemoteExceptionHandler.decodeRemoteException(e);
1001 }
1002 }
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012 public void addColumn(final String tableName, HColumnDescriptor column)
1013 throws IOException {
1014 addColumn(Bytes.toBytes(tableName), column);
1015 }
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025 public void addColumn(final byte [] tableName, HColumnDescriptor column)
1026 throws IOException {
1027 HTableDescriptor.isLegalTableName(tableName);
1028 try {
1029 getMaster().addColumn(tableName, column);
1030 } catch (RemoteException e) {
1031 throw RemoteExceptionHandler.decodeRemoteException(e);
1032 }
1033 }
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043 public void deleteColumn(final String tableName, final String columnName)
1044 throws IOException {
1045 deleteColumn(Bytes.toBytes(tableName), Bytes.toBytes(columnName));
1046 }
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 public void deleteColumn(final byte [] tableName, final byte [] columnName)
1057 throws IOException {
1058 try {
1059 getMaster().deleteColumn(tableName, columnName);
1060 } catch (RemoteException e) {
1061 throw RemoteExceptionHandler.decodeRemoteException(e);
1062 }
1063 }
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 public void modifyColumn(final String tableName, HColumnDescriptor descriptor)
1074 throws IOException {
1075 modifyColumn(Bytes.toBytes(tableName), descriptor);
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086 public void modifyColumn(final byte [] tableName, HColumnDescriptor descriptor)
1087 throws IOException {
1088 try {
1089 getMaster().modifyColumn(tableName, descriptor);
1090 } catch (RemoteException re) {
1091
1092
1093
1094 throw RemoteExceptionHandler.decodeRemoteException(re);
1095 }
1096 }
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106 public void closeRegion(final String regionname, final String serverName)
1107 throws IOException {
1108 closeRegion(Bytes.toBytes(regionname), serverName);
1109 }
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121 public void closeRegion(final byte [] regionname, final String serverName)
1122 throws IOException {
1123 CatalogTracker ct = getCatalogTracker();
1124 try {
1125 if (serverName != null) {
1126 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, regionname);
1127 if (pair == null || pair.getFirst() == null) {
1128 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1129 } else {
1130 closeRegion(new ServerName(serverName), pair.getFirst());
1131 }
1132 } else {
1133 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, regionname);
1134 if (pair == null) {
1135 throw new UnknownRegionException(Bytes.toStringBinary(regionname));
1136 } else if (pair.getSecond() == null) {
1137 throw new NoServerForRegionException(Bytes.toStringBinary(regionname));
1138 } else {
1139 closeRegion(pair.getSecond(), pair.getFirst());
1140 }
1141 }
1142 } finally {
1143 cleanupCatalogTracker(ct);
1144 }
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 public boolean closeRegionWithEncodedRegionName(final String encodedRegionName,
1169 final String serverName) throws IOException {
1170 byte[] encodedRegionNameInBytes = Bytes.toBytes(encodedRegionName);
1171 if (null == serverName || ("").equals(serverName.trim())) {
1172 throw new IllegalArgumentException(
1173 "The servername cannot be null or empty.");
1174 }
1175 ServerName sn = new ServerName(serverName);
1176 HRegionInterface rs = this.connection.getHRegionConnection(
1177 sn.getHostname(), sn.getPort());
1178
1179 boolean isRegionClosed = rs.closeRegion(encodedRegionNameInBytes, false);
1180 if (false == isRegionClosed) {
1181 LOG.error("Not able to close the region " + encodedRegionName + ".");
1182 }
1183 return isRegionClosed;
1184 }
1185
1186
1187
1188
1189
1190
1191
1192
1193 public void closeRegion(final ServerName sn, final HRegionInfo hri)
1194 throws IOException {
1195 HRegionInterface rs =
1196 this.connection.getHRegionConnection(sn.getHostname(), sn.getPort());
1197
1198 rs.closeRegion(hri, false);
1199 }
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209 public void flush(final String tableNameOrRegionName)
1210 throws IOException, InterruptedException {
1211 flush(Bytes.toBytes(tableNameOrRegionName));
1212 }
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222 public void flush(final byte [] tableNameOrRegionName)
1223 throws IOException, InterruptedException {
1224 CatalogTracker ct = getCatalogTracker();
1225 try {
1226 Pair<HRegionInfo, ServerName> regionServerPair
1227 = getRegion(tableNameOrRegionName, ct);
1228 if (regionServerPair != null) {
1229 if (regionServerPair.getSecond() == null) {
1230 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1231 } else {
1232 flush(regionServerPair.getSecond(), regionServerPair.getFirst());
1233 }
1234 } else {
1235 final String tableName = tableNameString(tableNameOrRegionName, ct);
1236 List<Pair<HRegionInfo, ServerName>> pairs =
1237 MetaReader.getTableRegionsAndLocations(ct,
1238 tableName);
1239 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1240 if (pair.getFirst().isOffline()) continue;
1241 if (pair.getSecond() == null) continue;
1242 try {
1243 flush(pair.getSecond(), pair.getFirst());
1244 } catch (NotServingRegionException e) {
1245 if (LOG.isDebugEnabled()) {
1246 LOG.debug("Trying to flush " + pair.getFirst() + ": " +
1247 StringUtils.stringifyException(e));
1248 }
1249 }
1250 }
1251 }
1252 } finally {
1253 cleanupCatalogTracker(ct);
1254 }
1255 }
1256
1257 private void flush(final ServerName sn, final HRegionInfo hri)
1258 throws IOException {
1259 HRegionInterface rs =
1260 this.connection.getHRegionConnection(sn.getHostname(), sn.getPort());
1261 rs.flushRegion(hri);
1262 }
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 public void compact(final String tableNameOrRegionName)
1273 throws IOException, InterruptedException {
1274 compact(Bytes.toBytes(tableNameOrRegionName));
1275 }
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285 public void compact(final byte [] tableNameOrRegionName)
1286 throws IOException, InterruptedException {
1287 compact(tableNameOrRegionName, null, false);
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 public void compact(String tableOrRegionName, String columnFamily)
1300 throws IOException, InterruptedException {
1301 compact(Bytes.toBytes(tableOrRegionName), Bytes.toBytes(columnFamily));
1302 }
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 public void compact(final byte [] tableNameOrRegionName, final byte[] columnFamily)
1314 throws IOException, InterruptedException {
1315 compact(tableNameOrRegionName, columnFamily, false);
1316 }
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326 public void majorCompact(final String tableNameOrRegionName)
1327 throws IOException, InterruptedException {
1328 majorCompact(Bytes.toBytes(tableNameOrRegionName));
1329 }
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339 public void majorCompact(final byte [] tableNameOrRegionName)
1340 throws IOException, InterruptedException {
1341 compact(tableNameOrRegionName, null, true);
1342 }
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353 public void majorCompact(final String tableNameOrRegionName,
1354 final String columnFamily) throws IOException, InterruptedException {
1355 majorCompact(Bytes.toBytes(tableNameOrRegionName),
1356 Bytes.toBytes(columnFamily));
1357 }
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368 public void majorCompact(final byte [] tableNameOrRegionName,
1369 final byte[] columnFamily) throws IOException, InterruptedException {
1370 compact(tableNameOrRegionName, columnFamily, true);
1371 }
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383 private void compact(final byte [] tableNameOrRegionName,
1384 final byte[] columnFamily, final boolean major)
1385 throws IOException, InterruptedException {
1386 CatalogTracker ct = getCatalogTracker();
1387 try {
1388 Pair<HRegionInfo, ServerName> regionServerPair
1389 = getRegion(tableNameOrRegionName, ct);
1390 if (regionServerPair != null) {
1391 if (regionServerPair.getSecond() == null) {
1392 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1393 } else {
1394 compact(regionServerPair.getSecond(), regionServerPair.getFirst(), major, columnFamily);
1395 }
1396 } else {
1397 final String tableName = tableNameString(tableNameOrRegionName, ct);
1398 List<Pair<HRegionInfo, ServerName>> pairs =
1399 MetaReader.getTableRegionsAndLocations(ct,
1400 tableName);
1401 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1402 if (pair.getFirst().isOffline()) continue;
1403 if (pair.getSecond() == null) continue;
1404 try {
1405 compact(pair.getSecond(), pair.getFirst(), major, columnFamily);
1406 } catch (NotServingRegionException e) {
1407 if (LOG.isDebugEnabled()) {
1408 LOG.debug("Trying to" + (major ? " major" : "") + " compact " +
1409 pair.getFirst() + ": " +
1410 StringUtils.stringifyException(e));
1411 }
1412 }
1413 }
1414 }
1415 } finally {
1416 cleanupCatalogTracker(ct);
1417 }
1418 }
1419
1420 private void compact(final ServerName sn, final HRegionInfo hri,
1421 final boolean major, final byte [] family)
1422 throws IOException {
1423 HRegionInterface rs =
1424 this.connection.getHRegionConnection(sn.getHostname(), sn.getPort());
1425 if (family != null) {
1426 try {
1427 rs.compactRegion(hri, major, family);
1428 } catch (IOException ioe) {
1429 String notFoundMsg = "java.lang.NoSuchMethodException: org.apache.hadoop.hbase.ipc.HRegionInterface."
1430 + "compactRegion(org.apache.hadoop.hbase.HRegionInfo, boolean, [B)";
1431 if (ioe.getMessage().contains(notFoundMsg)) {
1432 throw new IOException("per-column family compaction not supported on this version "
1433 + "of the HBase server. You may still compact at the table or region level by "
1434 + "omitting the column family name. Alternatively, you can upgrade the HBase server");
1435 }
1436 throw ioe;
1437 }
1438 } else {
1439 rs.compactRegion(hri, major);
1440 }
1441 }
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458 public void move(final byte [] encodedRegionName, final byte [] destServerName)
1459 throws UnknownRegionException, MasterNotRunningException, ZooKeeperConnectionException {
1460 getMaster().move(encodedRegionName, destServerName);
1461 }
1462
1463
1464
1465
1466
1467
1468
1469
1470 public void assign(final byte[] regionName) throws MasterNotRunningException,
1471 ZooKeeperConnectionException, IOException {
1472 getMaster().assign(regionName);
1473 }
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489 public void unassign(final byte [] regionName, final boolean force)
1490 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
1491 getMaster().unassign(regionName, force);
1492 }
1493
1494
1495
1496
1497
1498
1499
1500 @Deprecated
1501 public boolean balanceSwitch(final boolean b)
1502 throws MasterNotRunningException, ZooKeeperConnectionException {
1503 return getMaster().balanceSwitch(b);
1504 }
1505
1506
1507
1508
1509
1510
1511
1512 public boolean setBalancerRunning(final boolean on, final boolean synchronous)
1513 throws MasterNotRunningException, ZooKeeperConnectionException {
1514 if (synchronous && synchronousBalanceSwitchSupported) {
1515 try {
1516 return getMaster().synchronousBalanceSwitch(on);
1517 } catch (UndeclaredThrowableException ute) {
1518 String error = ute.getCause().getMessage();
1519 if (error != null && error.matches(
1520 "(?s).+NoSuchMethodException:.+synchronousBalanceSwitch.+")) {
1521 LOG.info("HMaster doesn't support synchronousBalanceSwitch");
1522 synchronousBalanceSwitchSupported = false;
1523 } else {
1524 throw ute;
1525 }
1526 }
1527 }
1528 return balanceSwitch(on);
1529 }
1530
1531
1532
1533
1534
1535
1536
1537 public boolean balancer()
1538 throws MasterNotRunningException, ZooKeeperConnectionException {
1539 return getMaster().balance();
1540 }
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550 public void split(final String tableNameOrRegionName)
1551 throws IOException, InterruptedException {
1552 split(Bytes.toBytes(tableNameOrRegionName));
1553 }
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563 public void split(final byte [] tableNameOrRegionName)
1564 throws IOException, InterruptedException {
1565 split(tableNameOrRegionName, null);
1566 }
1567
1568 public void split(final String tableNameOrRegionName,
1569 final String splitPoint) throws IOException, InterruptedException {
1570 split(Bytes.toBytes(tableNameOrRegionName), Bytes.toBytes(splitPoint));
1571 }
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582 public void split(final byte [] tableNameOrRegionName,
1583 final byte [] splitPoint) throws IOException, InterruptedException {
1584 CatalogTracker ct = getCatalogTracker();
1585 try {
1586 Pair<HRegionInfo, ServerName> regionServerPair
1587 = getRegion(tableNameOrRegionName, ct);
1588 if (regionServerPair != null) {
1589 if (regionServerPair.getSecond() == null) {
1590 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1591 } else {
1592 split(regionServerPair.getSecond(), regionServerPair.getFirst(), splitPoint);
1593 }
1594 } else {
1595 final String tableName = tableNameString(tableNameOrRegionName, ct);
1596 List<Pair<HRegionInfo, ServerName>> pairs =
1597 MetaReader.getTableRegionsAndLocations(ct,
1598 tableName);
1599 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1600
1601 if (pair.getSecond() == null) continue;
1602 HRegionInfo r = pair.getFirst();
1603
1604 if (r.isSplitParent()) continue;
1605
1606 if (splitPoint != null && !r.containsRow(splitPoint)) continue;
1607
1608 split(pair.getSecond(), pair.getFirst(), splitPoint);
1609 }
1610 }
1611 } finally {
1612 cleanupCatalogTracker(ct);
1613 }
1614 }
1615
1616 private void split(final ServerName sn, final HRegionInfo hri,
1617 byte[] splitPoint) throws IOException {
1618 HRegionInterface rs =
1619 this.connection.getHRegionConnection(sn.getHostname(), sn.getPort());
1620 rs.splitRegion(hri, splitPoint);
1621 }
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632 public void modifyTable(final byte [] tableName, HTableDescriptor htd)
1633 throws IOException {
1634 try {
1635 getMaster().modifyTable(tableName, htd);
1636 } catch (RemoteException re) {
1637
1638
1639
1640 throw RemoteExceptionHandler.decodeRemoteException(re);
1641 }
1642 }
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653 Pair<HRegionInfo, ServerName> getRegion(final byte[] tableNameOrRegionName,
1654 final CatalogTracker ct) throws IOException {
1655 if (tableNameOrRegionName == null) {
1656 throw new IllegalArgumentException("Pass a table name or region name");
1657 }
1658 Pair<HRegionInfo, ServerName> pair = MetaReader.getRegion(ct, tableNameOrRegionName);
1659 if (pair == null) {
1660 final AtomicReference<Pair<HRegionInfo, ServerName>> result =
1661 new AtomicReference<Pair<HRegionInfo, ServerName>>(null);
1662 final String encodedName = Bytes.toString(tableNameOrRegionName);
1663 MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
1664 @Override
1665 public boolean processRow(Result data) throws IOException {
1666 if (data == null || data.size() <= 0) {
1667 return true;
1668 }
1669 HRegionInfo info = MetaReader.parseHRegionInfoFromCatalogResult(
1670 data, HConstants.REGIONINFO_QUALIFIER);
1671 if (info == null) {
1672 LOG.warn("No serialized HRegionInfo in " + data);
1673 return true;
1674 }
1675 if (!encodedName.equals(info.getEncodedName())) return true;
1676 ServerName sn = MetaReader.getServerNameFromCatalogResult(data);
1677 result.set(new Pair<HRegionInfo, ServerName>(info, sn));
1678 return false;
1679 }
1680 };
1681
1682 MetaScanner.metaScan(conf, visitor);
1683 pair = result.get();
1684 }
1685 return pair;
1686 }
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697 private String tableNameString(final byte[] tableNameBytes, CatalogTracker ct)
1698 throws IOException {
1699 String tableNameString = Bytes.toString(tableNameBytes);
1700 if (!MetaReader.tableExists(ct, tableNameString)) {
1701 throw new TableNotFoundException(tableNameString);
1702 }
1703 return tableNameString;
1704 }
1705
1706
1707
1708
1709
1710 public synchronized void shutdown() throws IOException {
1711 isMasterRunning();
1712 try {
1713 getMaster().shutdown();
1714 } catch (RemoteException e) {
1715 throw RemoteExceptionHandler.decodeRemoteException(e);
1716 }
1717 }
1718
1719
1720
1721
1722
1723
1724
1725 public synchronized void stopMaster() throws IOException {
1726 isMasterRunning();
1727 try {
1728 getMaster().stopMaster();
1729 } catch (RemoteException e) {
1730 throw RemoteExceptionHandler.decodeRemoteException(e);
1731 }
1732 }
1733
1734
1735
1736
1737
1738
1739
1740 public synchronized void stopRegionServer(final String hostnamePort)
1741 throws IOException {
1742 String hostname = Addressing.parseHostname(hostnamePort);
1743 int port = Addressing.parsePort(hostnamePort);
1744 HRegionInterface rs =
1745 this.connection.getHRegionConnection(hostname, port);
1746 rs.stop("Called by admin client " + this.connection.toString());
1747 }
1748
1749
1750
1751
1752
1753 public ClusterStatus getClusterStatus() throws IOException {
1754 return getMaster().getClusterStatus();
1755 }
1756
1757 private HRegionLocation getFirstMetaServerForTable(final byte [] tableName)
1758 throws IOException {
1759 return connection.locateRegion(HConstants.META_TABLE_NAME,
1760 HRegionInfo.createRegionName(tableName, null, HConstants.NINES, false));
1761 }
1762
1763
1764
1765
1766 public Configuration getConfiguration() {
1767 return this.conf;
1768 }
1769
1770
1771
1772
1773
1774
1775
1776
1777 public static void checkHBaseAvailable(Configuration conf)
1778 throws MasterNotRunningException, ZooKeeperConnectionException {
1779 Configuration copyOfConf = HBaseConfiguration.create(conf);
1780 copyOfConf.setInt("hbase.client.retries.number", 1);
1781 HBaseAdmin admin = new HBaseAdmin(copyOfConf);
1782 try {
1783 admin.close();
1784 } catch (IOException ioe) {
1785 admin.LOG.info("Failed to close connection", ioe);
1786 }
1787 }
1788
1789
1790
1791
1792
1793
1794
1795
1796 public List<HRegionInfo> getTableRegions(final byte[] tableName)
1797 throws IOException {
1798 CatalogTracker ct = getCatalogTracker();
1799 List<HRegionInfo> Regions = null;
1800 try {
1801 Regions = MetaReader.getTableRegions(ct, tableName, true);
1802 } finally {
1803 cleanupCatalogTracker(ct);
1804 }
1805 return Regions;
1806 }
1807
1808 public void close() throws IOException {
1809 if (this.connection != null) {
1810 this.connection.close();
1811 }
1812 }
1813
1814
1815
1816
1817
1818
1819
1820 public HTableDescriptor[] getTableDescriptors(List<String> tableNames)
1821 throws IOException {
1822 return this.connection.getHTableDescriptors(tableNames);
1823 }
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838 public synchronized byte[][] rollHLogWriter(String serverName)
1839 throws IOException, FailedLogCloseException {
1840 ServerName sn = new ServerName(serverName);
1841 HRegionInterface rs = this.connection.getHRegionConnection(
1842 sn.getHostname(), sn.getPort());
1843 return rs.rollHLogWriter();
1844 }
1845
1846 public String[] getMasterCoprocessors() {
1847 try {
1848 return getClusterStatus().getMasterCoprocessors();
1849 } catch (IOException e) {
1850 LOG.error("Could not getClusterStatus()",e);
1851 return null;
1852 }
1853 }
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864 public CompactionState getCompactionState(final String tableNameOrRegionName)
1865 throws IOException, InterruptedException {
1866 return getCompactionState(Bytes.toBytes(tableNameOrRegionName));
1867 }
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 public CompactionState getCompactionState(final byte [] tableNameOrRegionName)
1879 throws IOException, InterruptedException {
1880 CompactionState state = CompactionState.NONE;
1881 CatalogTracker ct = getCatalogTracker();
1882 try {
1883 Pair<HRegionInfo, ServerName> regionServerPair
1884 = getRegion(tableNameOrRegionName, ct);
1885 if (regionServerPair != null) {
1886 if (regionServerPair.getSecond() == null) {
1887 throw new NoServerForRegionException(Bytes.toStringBinary(tableNameOrRegionName));
1888 } else {
1889 ServerName sn = regionServerPair.getSecond();
1890 HRegionInterface rs =
1891 this.connection.getHRegionConnection(sn.getHostname(), sn.getPort());
1892 return CompactionState.valueOf(
1893 rs.getCompactionState(regionServerPair.getFirst().getRegionName()));
1894 }
1895 } else {
1896 final String tableName = tableNameString(tableNameOrRegionName, ct);
1897 List<Pair<HRegionInfo, ServerName>> pairs =
1898 MetaReader.getTableRegionsAndLocations(ct, tableName);
1899 for (Pair<HRegionInfo, ServerName> pair: pairs) {
1900 if (pair.getFirst().isOffline()) continue;
1901 if (pair.getSecond() == null) continue;
1902 try {
1903 ServerName sn = pair.getSecond();
1904 HRegionInterface rs =
1905 this.connection.getHRegionConnection(sn.getHostname(), sn.getPort());
1906 switch (CompactionState.valueOf(
1907 rs.getCompactionState(pair.getFirst().getRegionName()))) {
1908 case MAJOR_AND_MINOR:
1909 return CompactionState.MAJOR_AND_MINOR;
1910 case MAJOR:
1911 if (state == CompactionState.MINOR) {
1912 return CompactionState.MAJOR_AND_MINOR;
1913 }
1914 state = CompactionState.MAJOR;
1915 break;
1916 case MINOR:
1917 if (state == CompactionState.MAJOR) {
1918 return CompactionState.MAJOR_AND_MINOR;
1919 }
1920 state = CompactionState.MINOR;
1921 break;
1922 case NONE:
1923 default:
1924 }
1925 } catch (NotServingRegionException e) {
1926 if (LOG.isDebugEnabled()) {
1927 LOG.debug("Trying to get compaction state of " +
1928 pair.getFirst() + ": " +
1929 StringUtils.stringifyException(e));
1930 }
1931 }
1932 }
1933 }
1934 } finally {
1935 cleanupCatalogTracker(ct);
1936 }
1937 return state;
1938 }
1939
1940
1941
1942
1943
1944
1945
1946
1947 public <T extends CoprocessorProtocol> T coprocessorProxy(
1948 Class<T> protocol) {
1949 return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(),
1950 new Class[]{protocol},
1951 new MasterExecRPCInvoker(conf,
1952 connection,
1953 protocol));
1954 }
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972 public void snapshot(final String snapshotName, final String tableName) throws IOException,
1973 SnapshotCreationException, IllegalArgumentException {
1974 snapshot(snapshotName, tableName, SnapshotDescription.Type.FLUSH);
1975 }
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993 public void snapshot(final byte[] snapshotName, final byte[] tableName) throws IOException,
1994 SnapshotCreationException, IllegalArgumentException {
1995 snapshot(Bytes.toString(snapshotName), Bytes.toString(tableName));
1996 }
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016 public void snapshot(final String snapshotName, final String tableName,
2017 SnapshotDescription.Type type) throws IOException, SnapshotCreationException,
2018 IllegalArgumentException {
2019 SnapshotDescription.Builder builder = SnapshotDescription.newBuilder();
2020 builder.setTable(tableName);
2021 builder.setName(snapshotName);
2022 builder.setType(type);
2023 snapshot(builder.build());
2024 }
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047 public void snapshot(SnapshotDescription snapshot) throws IOException, SnapshotCreationException,
2048 IllegalArgumentException {
2049 HSnapshotDescription snapshotWritable = new HSnapshotDescription(snapshot);
2050
2051 try {
2052
2053 long max = takeSnapshotAsync(snapshot);
2054 long start = EnvironmentEdgeManager.currentTimeMillis();
2055 long maxPauseTime = max / this.numRetries;
2056 boolean done = false;
2057 int tries = 0;
2058 LOG.debug("Waiting a max of " + max + " ms for snapshot '" +
2059 SnapshotDescriptionUtils.toString(snapshot) + "' to complete. (max " +
2060 maxPauseTime + " ms per retry)");
2061 while (tries == 0 || (EnvironmentEdgeManager.currentTimeMillis() - start) < max && !done) {
2062 try {
2063
2064 long sleep = getPauseTime(tries++);
2065 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
2066 LOG.debug("(#" + tries + ") Sleeping: " + sleep +
2067 "ms while waiting for snapshot completion.");
2068 Thread.sleep(sleep);
2069
2070 } catch (InterruptedException e) {
2071 LOG.debug("Interrupted while waiting for snapshot " + snapshot + " to complete");
2072 Thread.currentThread().interrupt();
2073 }
2074 LOG.debug("Getting current status of snapshot from master...");
2075 done = getMaster().isSnapshotDone(snapshotWritable);
2076 }
2077
2078 if (!done) {
2079 throw new SnapshotCreationException("Snapshot '" + snapshot.getName()
2080 + "' wasn't completed in expectedTime:" + max + " ms", snapshot);
2081 }
2082 } catch (RemoteException e) {
2083 throw RemoteExceptionHandler.decodeRemoteException(e);
2084 }
2085 }
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097 public long takeSnapshotAsync(SnapshotDescription snapshot) throws IOException,
2098 SnapshotCreationException {
2099 SnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
2100 HSnapshotDescription snapshotWritable = new HSnapshotDescription(snapshot);
2101 return getMaster().snapshot(snapshotWritable);
2102 }
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124 public boolean isSnapshotFinished(final SnapshotDescription snapshot)
2125 throws IOException, HBaseSnapshotException, UnknownSnapshotException {
2126 try {
2127 return getMaster().isSnapshotDone(new HSnapshotDescription(snapshot));
2128 } catch (RemoteException e) {
2129 throw RemoteExceptionHandler.decodeRemoteException(e);
2130 }
2131 }
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143 public void restoreSnapshot(final byte[] snapshotName)
2144 throws IOException, RestoreSnapshotException {
2145 restoreSnapshot(Bytes.toString(snapshotName));
2146 }
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158 public void restoreSnapshot(final String snapshotName)
2159 throws IOException, RestoreSnapshotException {
2160 String rollbackSnapshot = snapshotName + "-" + EnvironmentEdgeManager.currentTimeMillis();
2161
2162 String tableName = null;
2163 for (SnapshotDescription snapshotInfo: listSnapshots()) {
2164 if (snapshotInfo.getName().equals(snapshotName)) {
2165 tableName = snapshotInfo.getTable();
2166 break;
2167 }
2168 }
2169
2170 if (tableName == null) {
2171 throw new RestoreSnapshotException(
2172 "Unable to find the table name for snapshot=" + snapshotName);
2173 }
2174
2175
2176 snapshot(rollbackSnapshot, tableName);
2177
2178
2179 try {
2180 internalRestoreSnapshot(snapshotName, tableName);
2181 } catch (IOException e) {
2182
2183 try {
2184 String msg = "Restore snapshot=" + snapshotName +
2185 " failed. Rollback to snapshot=" + rollbackSnapshot + " succeeded.";
2186 LOG.error(msg, e);
2187 internalRestoreSnapshot(rollbackSnapshot, tableName);
2188 throw new RestoreSnapshotException(msg, e);
2189 } catch (IOException ex) {
2190 String msg = "Failed to restore and rollback to snapshot=" + rollbackSnapshot;
2191 LOG.error(msg, ex);
2192 throw new RestoreSnapshotException(msg, ex);
2193 }
2194 }
2195 }
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207 public void cloneSnapshot(final byte[] snapshotName, final byte[] tableName)
2208 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
2209 cloneSnapshot(Bytes.toString(snapshotName), Bytes.toString(tableName));
2210 }
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222 public void cloneSnapshot(final String snapshotName, final String tableName)
2223 throws IOException, TableExistsException, RestoreSnapshotException, InterruptedException {
2224 if (tableExists(tableName)) {
2225 throw new TableExistsException("Table '" + tableName + " already exists");
2226 }
2227 internalRestoreSnapshot(snapshotName, tableName);
2228 waitUntilTableIsEnabled(Bytes.toBytes(tableName));
2229 }
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241 private void internalRestoreSnapshot(final String snapshotName, final String tableName)
2242 throws IOException, RestoreSnapshotException {
2243 HSnapshotDescription snapshot = new HSnapshotDescription(
2244 SnapshotDescription.newBuilder().setName(snapshotName).setTable(tableName).build());
2245
2246 try {
2247
2248 getMaster().restoreSnapshot(snapshot);
2249
2250 final long maxPauseTime = 5000;
2251 boolean done = false;
2252 int tries = 0;
2253 while (!done) {
2254 try {
2255
2256 long sleep = getPauseTime(tries++);
2257 sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
2258 LOG.debug(tries + ") Sleeping: " + sleep + " ms while we wait for snapshot restore to complete.");
2259 Thread.sleep(sleep);
2260 } catch (InterruptedException e) {
2261 LOG.debug("Interrupted while waiting for snapshot " + snapshot + " restore to complete");
2262 Thread.currentThread().interrupt();
2263 }
2264 LOG.debug("Getting current status of snapshot restore from master...");
2265 done = getMaster().isRestoreSnapshotDone(snapshot);
2266 }
2267 if (!done) {
2268 throw new RestoreSnapshotException("Snapshot '" + snapshot.getName() + "' wasn't restored.");
2269 }
2270 } catch (RemoteException e) {
2271 throw RemoteExceptionHandler.decodeRemoteException(e);
2272 }
2273 }
2274
2275
2276
2277
2278
2279
2280 public List<SnapshotDescription> listSnapshots() throws IOException {
2281 List<SnapshotDescription> snapshots = new LinkedList<SnapshotDescription>();
2282 try {
2283 for (HSnapshotDescription snapshot: getMaster().getCompletedSnapshots()) {
2284 snapshots.add(snapshot.getProto());
2285 }
2286 } catch (RemoteException e) {
2287 throw RemoteExceptionHandler.decodeRemoteException(e);
2288 }
2289 return snapshots;
2290 }
2291
2292
2293
2294
2295
2296
2297 public void deleteSnapshot(final byte[] snapshotName) throws IOException {
2298
2299 HTableDescriptor.isLegalTableName(snapshotName);
2300
2301 SnapshotDescription snapshot = SnapshotDescription.newBuilder()
2302 .setName(Bytes.toString(snapshotName)).build();
2303 try {
2304 getMaster().deleteSnapshot(new HSnapshotDescription(snapshot));
2305 } catch (RemoteException e) {
2306 throw RemoteExceptionHandler.decodeRemoteException(e);
2307 }
2308 }
2309
2310
2311
2312
2313
2314
2315 public void deleteSnapshot(final String snapshotName) throws IOException {
2316 deleteSnapshot(Bytes.toBytes(snapshotName));
2317 }
2318 }