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