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