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