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