001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.rsgroup;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertTrue;
022
023import java.io.ByteArrayInputStream;
024import java.io.Closeable;
025import java.io.IOException;
026import java.util.ArrayList;
027import java.util.EnumSet;
028import java.util.List;
029import java.util.Map;
030import java.util.Set;
031import java.util.SortedSet;
032import java.util.concurrent.Future;
033import java.util.regex.Pattern;
034import org.apache.hadoop.conf.Configuration;
035import org.apache.hadoop.hbase.CacheEvictionStats;
036import org.apache.hadoop.hbase.ClusterMetrics;
037import org.apache.hadoop.hbase.ClusterMetrics.Option;
038import org.apache.hadoop.hbase.NamespaceDescriptor;
039import org.apache.hadoop.hbase.NamespaceNotFoundException;
040import org.apache.hadoop.hbase.RegionMetrics;
041import org.apache.hadoop.hbase.ServerName;
042import org.apache.hadoop.hbase.TableExistsException;
043import org.apache.hadoop.hbase.TableName;
044import org.apache.hadoop.hbase.TableNotFoundException;
045import org.apache.hadoop.hbase.client.Admin;
046import org.apache.hadoop.hbase.client.BalanceRequest;
047import org.apache.hadoop.hbase.client.BalanceResponse;
048import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
049import org.apache.hadoop.hbase.client.CompactType;
050import org.apache.hadoop.hbase.client.CompactionState;
051import org.apache.hadoop.hbase.client.Connection;
052import org.apache.hadoop.hbase.client.ConnectionFactory;
053import org.apache.hadoop.hbase.client.LogEntry;
054import org.apache.hadoop.hbase.client.NormalizeTableFilterParams;
055import org.apache.hadoop.hbase.client.RegionInfo;
056import org.apache.hadoop.hbase.client.Result;
057import org.apache.hadoop.hbase.client.ResultScanner;
058import org.apache.hadoop.hbase.client.Scan;
059import org.apache.hadoop.hbase.client.ServerType;
060import org.apache.hadoop.hbase.client.SnapshotDescription;
061import org.apache.hadoop.hbase.client.Table;
062import org.apache.hadoop.hbase.client.TableDescriptor;
063import org.apache.hadoop.hbase.client.replication.TableCFs;
064import org.apache.hadoop.hbase.client.security.SecurityCapability;
065import org.apache.hadoop.hbase.exceptions.DeserializationException;
066import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
067import org.apache.hadoop.hbase.net.Address;
068import org.apache.hadoop.hbase.quotas.QuotaFilter;
069import org.apache.hadoop.hbase.quotas.QuotaSettings;
070import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshotView;
071import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
072import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
073import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
074import org.apache.hadoop.hbase.replication.SyncReplicationState;
075import org.apache.hadoop.hbase.security.access.GetUserPermissionsRequest;
076import org.apache.hadoop.hbase.security.access.Permission;
077import org.apache.hadoop.hbase.security.access.UserPermission;
078import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
079import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
080import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
081import org.apache.hadoop.hbase.snapshot.UnknownSnapshotException;
082import org.apache.hadoop.hbase.util.Pair;
083import org.apache.hadoop.hbase.zookeeper.ZKUtil;
084import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
085import org.apache.hadoop.hbase.zookeeper.ZNodePaths;
086import org.apache.yetus.audience.InterfaceAudience;
087import org.apache.zookeeper.KeeperException;
088
089import org.apache.hbase.thirdparty.com.google.common.collect.Maps;
090import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
091
092import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
093import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupProtos;
094
095@InterfaceAudience.Private
096public class VerifyingRSGroupAdmin implements Admin, Closeable {
097
098  private final Connection conn;
099
100  private final Admin admin;
101
102  private final ZKWatcher zkw;
103
104  public VerifyingRSGroupAdmin(Configuration conf) throws IOException {
105    conn = ConnectionFactory.createConnection(conf);
106    admin = conn.getAdmin();
107    zkw = new ZKWatcher(conf, this.getClass().getSimpleName(), null);
108  }
109
110  public int getOperationTimeout() {
111    return admin.getOperationTimeout();
112  }
113
114  public int getSyncWaitTimeout() {
115    return admin.getSyncWaitTimeout();
116  }
117
118  public void abort(String why, Throwable e) {
119    admin.abort(why, e);
120  }
121
122  public boolean isAborted() {
123    return admin.isAborted();
124  }
125
126  public Connection getConnection() {
127    return admin.getConnection();
128  }
129
130  public boolean tableExists(TableName tableName) throws IOException {
131    return admin.tableExists(tableName);
132  }
133
134  public List<TableDescriptor> listTableDescriptors() throws IOException {
135    return admin.listTableDescriptors();
136  }
137
138  public List<TableDescriptor> listTableDescriptors(boolean includeSysTables) throws IOException {
139    return admin.listTableDescriptors(includeSysTables);
140  }
141
142  public List<TableDescriptor> listTableDescriptors(Pattern pattern, boolean includeSysTables)
143    throws IOException {
144    return admin.listTableDescriptors(pattern, includeSysTables);
145  }
146
147  @Override
148  public List<TableDescriptor> listTableDescriptorsByState(boolean isEnabled) throws IOException {
149    return admin.listTableDescriptorsByState(isEnabled);
150  }
151
152  public TableName[] listTableNames() throws IOException {
153    return admin.listTableNames();
154  }
155
156  public TableName[] listTableNames(Pattern pattern, boolean includeSysTables) throws IOException {
157    return admin.listTableNames(pattern, includeSysTables);
158  }
159
160  @Override
161  public List<TableName> listTableNamesByState(boolean isEnabled) throws IOException {
162    return admin.listTableNamesByState(isEnabled);
163  }
164
165  public TableDescriptor getDescriptor(TableName tableName)
166    throws TableNotFoundException, IOException {
167    return admin.getDescriptor(tableName);
168  }
169
170  public void createTable(TableDescriptor desc, byte[] startKey, byte[] endKey, int numRegions)
171    throws IOException {
172    admin.createTable(desc, startKey, endKey, numRegions);
173  }
174
175  public Future<Void> createTableAsync(TableDescriptor desc) throws IOException {
176    return admin.createTableAsync(desc);
177  }
178
179  public Future<Void> createTableAsync(TableDescriptor desc, byte[][] splitKeys)
180    throws IOException {
181    return admin.createTableAsync(desc, splitKeys);
182  }
183
184  public Future<Void> deleteTableAsync(TableName tableName) throws IOException {
185    return admin.deleteTableAsync(tableName);
186  }
187
188  public Future<Void> truncateTableAsync(TableName tableName, boolean preserveSplits)
189    throws IOException {
190    return admin.truncateTableAsync(tableName, preserveSplits);
191  }
192
193  public Future<Void> enableTableAsync(TableName tableName) throws IOException {
194    return admin.enableTableAsync(tableName);
195  }
196
197  public Future<Void> disableTableAsync(TableName tableName) throws IOException {
198    return admin.disableTableAsync(tableName);
199  }
200
201  public boolean isTableEnabled(TableName tableName) throws IOException {
202    return admin.isTableEnabled(tableName);
203  }
204
205  public boolean isTableDisabled(TableName tableName) throws IOException {
206    return admin.isTableDisabled(tableName);
207  }
208
209  public boolean isTableAvailable(TableName tableName) throws IOException {
210    return admin.isTableAvailable(tableName);
211  }
212
213  public Future<Void> addColumnFamilyAsync(TableName tableName, ColumnFamilyDescriptor columnFamily)
214    throws IOException {
215    return admin.addColumnFamilyAsync(tableName, columnFamily);
216  }
217
218  public Future<Void> deleteColumnFamilyAsync(TableName tableName, byte[] columnFamily)
219    throws IOException {
220    return admin.deleteColumnFamilyAsync(tableName, columnFamily);
221  }
222
223  public Future<Void> modifyColumnFamilyAsync(TableName tableName,
224    ColumnFamilyDescriptor columnFamily) throws IOException {
225    return admin.modifyColumnFamilyAsync(tableName, columnFamily);
226  }
227
228  public List<RegionInfo> getRegions(ServerName serverName) throws IOException {
229    return admin.getRegions(serverName);
230  }
231
232  public void flush(TableName tableName) throws IOException {
233    admin.flush(tableName);
234  }
235
236  public void flush(TableName tableName, byte[] columnFamily) throws IOException {
237    admin.flush(tableName, columnFamily);
238  }
239
240  public void flush(TableName tableName, List<byte[]> columnFamilies) throws IOException {
241    admin.flush(tableName, columnFamilies);
242  }
243
244  public void flushRegion(byte[] regionName) throws IOException {
245    admin.flushRegion(regionName);
246  }
247
248  public void flushRegion(byte[] regionName, byte[] columnFamily) throws IOException {
249    admin.flushRegion(regionName, columnFamily);
250  }
251
252  public void flushRegionServer(ServerName serverName) throws IOException {
253    admin.flushRegionServer(serverName);
254  }
255
256  public void compact(TableName tableName) throws IOException {
257    admin.compact(tableName);
258  }
259
260  public void compactRegion(byte[] regionName) throws IOException {
261    admin.compactRegion(regionName);
262  }
263
264  public void compact(TableName tableName, byte[] columnFamily) throws IOException {
265    admin.compact(tableName, columnFamily);
266  }
267
268  public void compactRegion(byte[] regionName, byte[] columnFamily) throws IOException {
269    admin.compactRegion(regionName, columnFamily);
270  }
271
272  public void compact(TableName tableName, CompactType compactType)
273    throws IOException, InterruptedException {
274    admin.compact(tableName, compactType);
275  }
276
277  public void compact(TableName tableName, byte[] columnFamily, CompactType compactType)
278    throws IOException, InterruptedException {
279    admin.compact(tableName, columnFamily, compactType);
280  }
281
282  public void majorCompact(TableName tableName) throws IOException {
283    admin.majorCompact(tableName);
284  }
285
286  public void majorCompactRegion(byte[] regionName) throws IOException {
287    admin.majorCompactRegion(regionName);
288  }
289
290  public void majorCompact(TableName tableName, byte[] columnFamily) throws IOException {
291    admin.majorCompact(tableName, columnFamily);
292  }
293
294  public void majorCompactRegion(byte[] regionName, byte[] columnFamily) throws IOException {
295    admin.majorCompactRegion(regionName, columnFamily);
296  }
297
298  public void majorCompact(TableName tableName, CompactType compactType)
299    throws IOException, InterruptedException {
300    admin.majorCompact(tableName, compactType);
301  }
302
303  public void majorCompact(TableName tableName, byte[] columnFamily, CompactType compactType)
304    throws IOException, InterruptedException {
305    admin.majorCompact(tableName, columnFamily, compactType);
306  }
307
308  public Map<ServerName, Boolean> compactionSwitch(boolean switchState,
309    List<String> serverNamesList) throws IOException {
310    return admin.compactionSwitch(switchState, serverNamesList);
311  }
312
313  public void compactRegionServer(ServerName serverName) throws IOException {
314    admin.compactRegionServer(serverName);
315  }
316
317  public void majorCompactRegionServer(ServerName serverName) throws IOException {
318    admin.majorCompactRegionServer(serverName);
319  }
320
321  public void move(byte[] encodedRegionName) throws IOException {
322    admin.move(encodedRegionName);
323  }
324
325  public void move(byte[] encodedRegionName, ServerName destServerName) throws IOException {
326    admin.move(encodedRegionName, destServerName);
327  }
328
329  public void assign(byte[] regionName) throws IOException {
330    admin.assign(regionName);
331  }
332
333  public void unassign(byte[] regionName) throws IOException {
334    admin.unassign(regionName);
335  }
336
337  public void offline(byte[] regionName) throws IOException {
338    admin.offline(regionName);
339  }
340
341  public boolean balancerSwitch(boolean onOrOff, boolean synchronous) throws IOException {
342    return admin.balancerSwitch(onOrOff, synchronous);
343  }
344
345  public BalanceResponse balance(BalanceRequest request) throws IOException {
346    return admin.balance(request);
347  }
348
349  public boolean isBalancerEnabled() throws IOException {
350    return admin.isBalancerEnabled();
351  }
352
353  public CacheEvictionStats clearBlockCache(TableName tableName) throws IOException {
354    return admin.clearBlockCache(tableName);
355  }
356
357  @Override
358  public boolean normalize(NormalizeTableFilterParams ntfp) throws IOException {
359    return admin.normalize(ntfp);
360  }
361
362  public boolean isNormalizerEnabled() throws IOException {
363    return admin.isNormalizerEnabled();
364  }
365
366  public boolean normalizerSwitch(boolean on) throws IOException {
367    return admin.normalizerSwitch(on);
368  }
369
370  public boolean catalogJanitorSwitch(boolean onOrOff) throws IOException {
371    return admin.catalogJanitorSwitch(onOrOff);
372  }
373
374  public int runCatalogJanitor() throws IOException {
375    return admin.runCatalogJanitor();
376  }
377
378  public boolean isCatalogJanitorEnabled() throws IOException {
379    return admin.isCatalogJanitorEnabled();
380  }
381
382  public boolean cleanerChoreSwitch(boolean onOrOff) throws IOException {
383    return admin.cleanerChoreSwitch(onOrOff);
384  }
385
386  public boolean runCleanerChore() throws IOException {
387    return admin.runCleanerChore();
388  }
389
390  public boolean isCleanerChoreEnabled() throws IOException {
391    return admin.isCleanerChoreEnabled();
392  }
393
394  public Future<Void> mergeRegionsAsync(byte[][] nameofRegionsToMerge, boolean forcible)
395    throws IOException {
396    return admin.mergeRegionsAsync(nameofRegionsToMerge, forcible);
397  }
398
399  public void split(TableName tableName) throws IOException {
400    admin.split(tableName);
401  }
402
403  public void split(TableName tableName, byte[] splitPoint) throws IOException {
404    admin.split(tableName, splitPoint);
405  }
406
407  public Future<Void> splitRegionAsync(byte[] regionName) throws IOException {
408    return admin.splitRegionAsync(regionName);
409  }
410
411  public Future<Void> splitRegionAsync(byte[] regionName, byte[] splitPoint) throws IOException {
412    return admin.splitRegionAsync(regionName, splitPoint);
413  }
414
415  @Override
416  public void truncateRegion(byte[] regionName) throws IOException {
417    admin.truncateRegion(regionName);
418  }
419
420  @Override
421  public Future<Void> truncateRegionAsync(byte[] regionName) throws IOException {
422    return admin.truncateRegionAsync(regionName);
423  }
424
425  public Future<Void> modifyTableAsync(TableDescriptor td) throws IOException {
426    return modifyTableAsync(td, true);
427  }
428
429  public Future<Void> modifyTableAsync(TableDescriptor td, boolean reopenRegions)
430    throws IOException {
431    return admin.modifyTableAsync(td, reopenRegions);
432  }
433
434  public void shutdown() throws IOException {
435    admin.shutdown();
436  }
437
438  public void stopMaster() throws IOException {
439    admin.stopMaster();
440  }
441
442  public boolean isMasterInMaintenanceMode() throws IOException {
443    return admin.isMasterInMaintenanceMode();
444  }
445
446  public void stopRegionServer(String hostnamePort) throws IOException {
447    admin.stopRegionServer(hostnamePort);
448  }
449
450  public ClusterMetrics getClusterMetrics(EnumSet<Option> options) throws IOException {
451    return admin.getClusterMetrics(options);
452  }
453
454  public List<RegionMetrics> getRegionMetrics(ServerName serverName) throws IOException {
455    return admin.getRegionMetrics(serverName);
456  }
457
458  public List<RegionMetrics> getRegionMetrics(ServerName serverName, TableName tableName)
459    throws IOException {
460    return admin.getRegionMetrics(serverName, tableName);
461  }
462
463  public Configuration getConfiguration() {
464    return admin.getConfiguration();
465  }
466
467  public Future<Void> createNamespaceAsync(NamespaceDescriptor descriptor) throws IOException {
468    return admin.createNamespaceAsync(descriptor);
469  }
470
471  public Future<Void> modifyNamespaceAsync(NamespaceDescriptor descriptor) throws IOException {
472    return admin.modifyNamespaceAsync(descriptor);
473  }
474
475  public Future<Void> deleteNamespaceAsync(String name) throws IOException {
476    return admin.deleteNamespaceAsync(name);
477  }
478
479  public NamespaceDescriptor getNamespaceDescriptor(String name)
480    throws NamespaceNotFoundException, IOException {
481    return admin.getNamespaceDescriptor(name);
482  }
483
484  public String[] listNamespaces() throws IOException {
485    return admin.listNamespaces();
486  }
487
488  public NamespaceDescriptor[] listNamespaceDescriptors() throws IOException {
489    return admin.listNamespaceDescriptors();
490  }
491
492  public List<TableDescriptor> listTableDescriptorsByNamespace(byte[] name) throws IOException {
493    return admin.listTableDescriptorsByNamespace(name);
494  }
495
496  public TableName[] listTableNamesByNamespace(String name) throws IOException {
497    return admin.listTableNamesByNamespace(name);
498  }
499
500  public List<RegionInfo> getRegions(TableName tableName) throws IOException {
501    return admin.getRegions(tableName);
502  }
503
504  public void close() {
505    admin.close();
506  }
507
508  public List<TableDescriptor> listTableDescriptors(List<TableName> tableNames) throws IOException {
509    return admin.listTableDescriptors(tableNames);
510  }
511
512  public Future<Boolean> abortProcedureAsync(long procId, boolean mayInterruptIfRunning)
513    throws IOException {
514    return admin.abortProcedureAsync(procId, mayInterruptIfRunning);
515  }
516
517  public String getProcedures() throws IOException {
518    return admin.getProcedures();
519  }
520
521  public String getLocks() throws IOException {
522    return admin.getLocks();
523  }
524
525  public void rollWALWriter(ServerName serverName) throws IOException, FailedLogCloseException {
526    admin.rollWALWriter(serverName);
527  }
528
529  @Override
530  public Map<ServerName, Long> rollAllWALWriters() throws IOException {
531    return admin.rollAllWALWriters();
532  }
533
534  public CompactionState getCompactionState(TableName tableName) throws IOException {
535    return admin.getCompactionState(tableName);
536  }
537
538  public CompactionState getCompactionState(TableName tableName, CompactType compactType)
539    throws IOException {
540    return admin.getCompactionState(tableName, compactType);
541  }
542
543  public CompactionState getCompactionStateForRegion(byte[] regionName) throws IOException {
544    return admin.getCompactionStateForRegion(regionName);
545  }
546
547  public long getLastMajorCompactionTimestamp(TableName tableName) throws IOException {
548    return admin.getLastMajorCompactionTimestamp(tableName);
549  }
550
551  public long getLastMajorCompactionTimestampForRegion(byte[] regionName) throws IOException {
552    return admin.getLastMajorCompactionTimestampForRegion(regionName);
553  }
554
555  public void snapshot(SnapshotDescription snapshot)
556    throws IOException, SnapshotCreationException, IllegalArgumentException {
557    admin.snapshot(snapshot);
558  }
559
560  public Future<Void> snapshotAsync(SnapshotDescription snapshot)
561    throws IOException, SnapshotCreationException {
562    return admin.snapshotAsync(snapshot);
563  }
564
565  public boolean isSnapshotFinished(SnapshotDescription snapshot)
566    throws IOException, HBaseSnapshotException, UnknownSnapshotException {
567    return admin.isSnapshotFinished(snapshot);
568  }
569
570  public void restoreSnapshot(String snapshotName) throws IOException, RestoreSnapshotException {
571    admin.restoreSnapshot(snapshotName);
572  }
573
574  public void restoreSnapshot(String snapshotName, boolean takeFailSafeSnapshot, boolean restoreAcl)
575    throws IOException, RestoreSnapshotException {
576    admin.restoreSnapshot(snapshotName, takeFailSafeSnapshot, restoreAcl);
577  }
578
579  public Future<Void> cloneSnapshotAsync(String snapshotName, TableName tableName,
580    boolean restoreAcl, String customSFT)
581    throws IOException, TableExistsException, RestoreSnapshotException {
582    return admin.cloneSnapshotAsync(snapshotName, tableName, restoreAcl, customSFT);
583  }
584
585  public void execProcedure(String signature, String instance, Map<String, String> props)
586    throws IOException {
587    admin.execProcedure(signature, instance, props);
588  }
589
590  public byte[] execProcedureWithReturn(String signature, String instance,
591    Map<String, String> props) throws IOException {
592    return admin.execProcedureWithReturn(signature, instance, props);
593  }
594
595  public boolean isProcedureFinished(String signature, String instance, Map<String, String> props)
596    throws IOException {
597    return admin.isProcedureFinished(signature, instance, props);
598  }
599
600  public List<SnapshotDescription> listSnapshots() throws IOException {
601    return admin.listSnapshots();
602  }
603
604  public List<SnapshotDescription> listSnapshots(Pattern pattern) throws IOException {
605    return admin.listSnapshots(pattern);
606  }
607
608  public List<SnapshotDescription> listTableSnapshots(Pattern tableNamePattern,
609    Pattern snapshotNamePattern) throws IOException {
610    return admin.listTableSnapshots(tableNamePattern, snapshotNamePattern);
611  }
612
613  public void deleteSnapshot(String snapshotName) throws IOException {
614    admin.deleteSnapshot(snapshotName);
615  }
616
617  public void deleteSnapshots(Pattern pattern) throws IOException {
618    admin.deleteSnapshots(pattern);
619  }
620
621  public void deleteTableSnapshots(Pattern tableNamePattern, Pattern snapshotNamePattern)
622    throws IOException {
623    admin.deleteTableSnapshots(tableNamePattern, snapshotNamePattern);
624  }
625
626  public void setQuota(QuotaSettings quota) throws IOException {
627    admin.setQuota(quota);
628  }
629
630  public List<QuotaSettings> getQuota(QuotaFilter filter) throws IOException {
631    return admin.getQuota(filter);
632  }
633
634  public CoprocessorRpcChannel coprocessorService() {
635    return admin.coprocessorService();
636  }
637
638  public CoprocessorRpcChannel coprocessorService(ServerName serverName) {
639    return admin.coprocessorService(serverName);
640  }
641
642  public void updateConfiguration(ServerName server) throws IOException {
643    admin.updateConfiguration(server);
644  }
645
646  public void updateConfiguration() throws IOException {
647    admin.updateConfiguration();
648  }
649
650  public void updateConfiguration(String groupName) throws IOException {
651    admin.updateConfiguration(groupName);
652  }
653
654  public List<SecurityCapability> getSecurityCapabilities() throws IOException {
655    return admin.getSecurityCapabilities();
656  }
657
658  public boolean splitSwitch(boolean enabled, boolean synchronous) throws IOException {
659    return admin.splitSwitch(enabled, synchronous);
660  }
661
662  public boolean mergeSwitch(boolean enabled, boolean synchronous) throws IOException {
663    return admin.mergeSwitch(enabled, synchronous);
664  }
665
666  public boolean isSplitEnabled() throws IOException {
667    return admin.isSplitEnabled();
668  }
669
670  public boolean isMergeEnabled() throws IOException {
671    return admin.isMergeEnabled();
672  }
673
674  public Future<Void> addReplicationPeerAsync(String peerId, ReplicationPeerConfig peerConfig,
675    boolean enabled) throws IOException {
676    return admin.addReplicationPeerAsync(peerId, peerConfig, enabled);
677  }
678
679  public Future<Void> removeReplicationPeerAsync(String peerId) throws IOException {
680    return admin.removeReplicationPeerAsync(peerId);
681  }
682
683  public Future<Void> enableReplicationPeerAsync(String peerId) throws IOException {
684    return admin.enableReplicationPeerAsync(peerId);
685  }
686
687  public Future<Void> disableReplicationPeerAsync(String peerId) throws IOException {
688    return admin.disableReplicationPeerAsync(peerId);
689  }
690
691  public ReplicationPeerConfig getReplicationPeerConfig(String peerId) throws IOException {
692    return admin.getReplicationPeerConfig(peerId);
693  }
694
695  public Future<Void> updateReplicationPeerConfigAsync(String peerId,
696    ReplicationPeerConfig peerConfig) throws IOException {
697    return admin.updateReplicationPeerConfigAsync(peerId, peerConfig);
698  }
699
700  public List<ReplicationPeerDescription> listReplicationPeers() throws IOException {
701    return admin.listReplicationPeers();
702  }
703
704  public List<ReplicationPeerDescription> listReplicationPeers(Pattern pattern) throws IOException {
705    return admin.listReplicationPeers(pattern);
706  }
707
708  public Future<Void> transitReplicationPeerSyncReplicationStateAsync(String peerId,
709    SyncReplicationState state) throws IOException {
710    return admin.transitReplicationPeerSyncReplicationStateAsync(peerId, state);
711  }
712
713  @Override
714  public boolean isReplicationPeerEnabled(String peerId) throws IOException {
715    return admin.isReplicationPeerEnabled(peerId);
716  }
717
718  public void decommissionRegionServers(List<ServerName> servers, boolean offload)
719    throws IOException {
720    admin.decommissionRegionServers(servers, offload);
721  }
722
723  public List<ServerName> listDecommissionedRegionServers() throws IOException {
724    return admin.listDecommissionedRegionServers();
725  }
726
727  public void recommissionRegionServer(ServerName server, List<byte[]> encodedRegionNames)
728    throws IOException {
729    admin.recommissionRegionServer(server, encodedRegionNames);
730  }
731
732  public List<TableCFs> listReplicatedTableCFs() throws IOException {
733    return admin.listReplicatedTableCFs();
734  }
735
736  public void enableTableReplication(TableName tableName) throws IOException {
737    admin.enableTableReplication(tableName);
738  }
739
740  public void disableTableReplication(TableName tableName) throws IOException {
741    admin.disableTableReplication(tableName);
742  }
743
744  public void clearCompactionQueues(ServerName serverName, Set<String> queues)
745    throws IOException, InterruptedException {
746    admin.clearCompactionQueues(serverName, queues);
747  }
748
749  public List<ServerName> clearDeadServers(List<ServerName> servers) throws IOException {
750    return admin.clearDeadServers(servers);
751  }
752
753  public void cloneTableSchema(TableName tableName, TableName newTableName, boolean preserveSplits)
754    throws IOException {
755    admin.cloneTableSchema(tableName, newTableName, preserveSplits);
756  }
757
758  public boolean switchRpcThrottle(boolean enable) throws IOException {
759    return admin.switchRpcThrottle(enable);
760  }
761
762  public boolean isRpcThrottleEnabled() throws IOException {
763    return admin.isRpcThrottleEnabled();
764  }
765
766  public boolean exceedThrottleQuotaSwitch(boolean enable) throws IOException {
767    return admin.exceedThrottleQuotaSwitch(enable);
768  }
769
770  public Map<TableName, Long> getSpaceQuotaTableSizes() throws IOException {
771    return admin.getSpaceQuotaTableSizes();
772  }
773
774  public Map<TableName, ? extends SpaceQuotaSnapshotView>
775    getRegionServerSpaceQuotaSnapshots(ServerName serverName) throws IOException {
776    return admin.getRegionServerSpaceQuotaSnapshots(serverName);
777  }
778
779  public SpaceQuotaSnapshotView getCurrentSpaceQuotaSnapshot(String namespace) throws IOException {
780    return admin.getCurrentSpaceQuotaSnapshot(namespace);
781  }
782
783  public SpaceQuotaSnapshotView getCurrentSpaceQuotaSnapshot(TableName tableName)
784    throws IOException {
785    return admin.getCurrentSpaceQuotaSnapshot(tableName);
786  }
787
788  public void grant(UserPermission userPermission, boolean mergeExistingPermissions)
789    throws IOException {
790    admin.grant(userPermission, mergeExistingPermissions);
791  }
792
793  public void revoke(UserPermission userPermission) throws IOException {
794    admin.revoke(userPermission);
795  }
796
797  public List<UserPermission>
798    getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest) throws IOException {
799    return admin.getUserPermissions(getUserPermissionsRequest);
800  }
801
802  public List<Boolean> hasUserPermissions(String userName, List<Permission> permissions)
803    throws IOException {
804    return admin.hasUserPermissions(userName, permissions);
805  }
806
807  public boolean snapshotCleanupSwitch(boolean on, boolean synchronous) throws IOException {
808    return admin.snapshotCleanupSwitch(on, synchronous);
809  }
810
811  public boolean isSnapshotCleanupEnabled() throws IOException {
812    return admin.isSnapshotCleanupEnabled();
813  }
814
815  public void addRSGroup(String groupName) throws IOException {
816    admin.addRSGroup(groupName);
817    verify();
818  }
819
820  public RSGroupInfo getRSGroup(String groupName) throws IOException {
821    return admin.getRSGroup(groupName);
822  }
823
824  public RSGroupInfo getRSGroup(Address hostPort) throws IOException {
825    return admin.getRSGroup(hostPort);
826  }
827
828  public RSGroupInfo getRSGroup(TableName tableName) throws IOException {
829    return admin.getRSGroup(tableName);
830  }
831
832  public List<RSGroupInfo> listRSGroups() throws IOException {
833    return admin.listRSGroups();
834  }
835
836  @Override
837  public List<TableName> listTablesInRSGroup(String groupName) throws IOException {
838    return admin.listTablesInRSGroup(groupName);
839  }
840
841  @Override
842  public Pair<List<String>, List<TableName>>
843    getConfiguredNamespacesAndTablesInRSGroup(String groupName) throws IOException {
844    return admin.getConfiguredNamespacesAndTablesInRSGroup(groupName);
845  }
846
847  public void removeRSGroup(String groupName) throws IOException {
848    admin.removeRSGroup(groupName);
849    verify();
850  }
851
852  public void removeServersFromRSGroup(Set<Address> servers) throws IOException {
853    admin.removeServersFromRSGroup(servers);
854    verify();
855  }
856
857  public void moveServersToRSGroup(Set<Address> servers, String targetGroup) throws IOException {
858    admin.moveServersToRSGroup(servers, targetGroup);
859    verify();
860  }
861
862  public void setRSGroup(Set<TableName> tables, String groupName) throws IOException {
863    admin.setRSGroup(tables, groupName);
864    verify();
865  }
866
867  public BalanceResponse balanceRSGroup(String groupName, BalanceRequest request)
868    throws IOException {
869    return admin.balanceRSGroup(groupName, request);
870  }
871
872  @Override
873  public void renameRSGroup(String oldName, String newName) throws IOException {
874    admin.renameRSGroup(oldName, newName);
875    verify();
876  }
877
878  @Override
879  public void updateRSGroupConfig(String groupName, Map<String, String> configuration)
880    throws IOException {
881    admin.updateRSGroupConfig(groupName, configuration);
882    verify();
883  }
884
885  @Override
886  public List<LogEntry> getLogEntries(Set<ServerName> serverNames, String logType,
887    ServerType serverType, int limit, Map<String, Object> filterParams) throws IOException {
888    return admin.getLogEntries(serverNames, logType, serverType, limit, filterParams);
889  }
890
891  private void verify() throws IOException {
892    Map<String, RSGroupInfo> groupMap = Maps.newHashMap();
893    Set<RSGroupInfo> zList = Sets.newHashSet();
894    List<TableDescriptor> tds = new ArrayList<>();
895    try (Admin admin = conn.getAdmin()) {
896      tds.addAll(admin.listTableDescriptors());
897      tds.addAll(admin.listTableDescriptorsByNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME));
898    }
899    SortedSet<Address> lives = Sets.newTreeSet();
900    for (ServerName sn : conn.getAdmin().getClusterMetrics().getLiveServerMetrics().keySet()) {
901      lives.add(sn.getAddress());
902    }
903    for (ServerName sn : conn.getAdmin().listDecommissionedRegionServers()) {
904      lives.remove(sn.getAddress());
905    }
906    try (Table table = conn.getTable(RSGroupInfoManagerImpl.RSGROUP_TABLE_NAME);
907      ResultScanner scanner = table.getScanner(new Scan())) {
908      for (;;) {
909        Result result = scanner.next();
910        if (result == null) {
911          break;
912        }
913        RSGroupProtos.RSGroupInfo proto = RSGroupProtos.RSGroupInfo.parseFrom(result.getValue(
914          RSGroupInfoManagerImpl.META_FAMILY_BYTES, RSGroupInfoManagerImpl.META_QUALIFIER_BYTES));
915        RSGroupInfo rsGroupInfo = ProtobufUtil.toGroupInfo(proto);
916        groupMap.put(proto.getName(), RSGroupUtil.fillTables(rsGroupInfo, tds));
917        for (Address address : rsGroupInfo.getServers()) {
918          lives.remove(address);
919        }
920      }
921    }
922    SortedSet<TableName> tables = Sets.newTreeSet();
923    for (TableDescriptor td : conn.getAdmin().listTableDescriptors(Pattern.compile(".*"), true)) {
924      String groupName = td.getRegionServerGroup().orElse(RSGroupInfo.DEFAULT_GROUP);
925      if (groupName.equals(RSGroupInfo.DEFAULT_GROUP)) {
926        tables.add(td.getTableName());
927      }
928    }
929
930    groupMap.put(RSGroupInfo.DEFAULT_GROUP,
931      new RSGroupInfo(RSGroupInfo.DEFAULT_GROUP, lives, tables));
932    assertEquals(Sets.newHashSet(groupMap.values()), Sets.newHashSet(admin.listRSGroups()));
933    try {
934      String groupBasePath = ZNodePaths.joinZNode(zkw.getZNodePaths().baseZNode, "rsgroup");
935      for (String znode : ZKUtil.listChildrenNoWatch(zkw, groupBasePath)) {
936        byte[] data = ZKUtil.getData(zkw, ZNodePaths.joinZNode(groupBasePath, znode));
937        if (data.length > 0) {
938          ProtobufUtil.expectPBMagicPrefix(data);
939          ByteArrayInputStream bis =
940            new ByteArrayInputStream(data, ProtobufUtil.lengthOfPBMagic(), data.length);
941          RSGroupInfo rsGroupInfo =
942            ProtobufUtil.toGroupInfo(RSGroupProtos.RSGroupInfo.parseFrom(bis));
943          zList.add(RSGroupUtil.fillTables(rsGroupInfo, tds));
944        }
945      }
946      groupMap.remove(RSGroupInfo.DEFAULT_GROUP);
947      assertEquals(zList.size(), groupMap.size());
948      for (RSGroupInfo rsGroupInfo : zList) {
949        assertTrue(groupMap.get(rsGroupInfo.getName()).equals(rsGroupInfo));
950      }
951    } catch (KeeperException e) {
952      throw new IOException("ZK verification failed", e);
953    } catch (DeserializationException e) {
954      throw new IOException("ZK verification failed", e);
955    } catch (InterruptedException e) {
956      throw new IOException("ZK verification failed", e);
957    }
958  }
959
960  @Override
961  public List<Boolean> clearSlowLogResponses(Set<ServerName> serverNames) throws IOException {
962    return admin.clearSlowLogResponses(serverNames);
963  }
964
965  @Override
966  public Future<Void> modifyColumnFamilyStoreFileTrackerAsync(TableName tableName, byte[] family,
967    String dstSFT) throws IOException {
968    return admin.modifyColumnFamilyStoreFileTrackerAsync(tableName, family, dstSFT);
969  }
970
971  @Override
972  public Future<Void> modifyTableStoreFileTrackerAsync(TableName tableName, String dstSFT)
973    throws IOException {
974    return admin.modifyTableStoreFileTrackerAsync(tableName, dstSFT);
975  }
976
977  @Override
978  public void flushMasterStore() throws IOException {
979    admin.flushMasterStore();
980  }
981
982  @Override
983  public List<String> getCachedFilesList(ServerName serverName) throws IOException {
984    return admin.getCachedFilesList(serverName);
985  }
986
987  @Override
988  public boolean replicationPeerModificationSwitch(boolean on, boolean drainProcedures)
989    throws IOException {
990    return admin.replicationPeerModificationSwitch(on, drainProcedures);
991  }
992
993  @Override
994  public boolean isReplicationPeerModificationEnabled() throws IOException {
995    return admin.isReplicationPeerModificationEnabled();
996  }
997}