/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.rsgroup;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.net.Address;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.RSGroupProtos;
import org.apache.hadoop.hbase.zookeeper.ZKUtil;
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
import org.apache.zookeeper.KeeperException;
import org.junit.Assert;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@InterfaceAudience.Private
public class VerifyingRSGroupAdminClient implements RSGroupAdmin {
private Table table;
private ZooKeeperWatcher zkw;
private RSGroupAdmin wrapped;
public VerifyingRSGroupAdminClient(RSGroupAdmin RSGroupAdmin, Configuration conf)
throws IOException {
wrapped = RSGroupAdmin;
table = ConnectionFactory.createConnection(conf).getTable(RSGroupInfoManager.RSGROUP_TABLE_NAME);
zkw = new ZooKeeperWatcher(conf, this.getClass().getSimpleName(), null);
}
@Override
public void addRSGroup(String groupName) throws IOException {
wrapped.addRSGroup(groupName);
verify();
}
@Override
public RSGroupInfo getRSGroupInfo(String groupName) throws IOException {
return wrapped.getRSGroupInfo(groupName);
}
@Override
public RSGroupInfo getRSGroupInfoOfTable(TableName tableName) throws IOException {
return wrapped.getRSGroupInfoOfTable(tableName);
}
@Override
public void moveServers(Set<Address> servers, String targetGroup) throws IOException {
wrapped.moveServers(servers, targetGroup);
verify();
}
@Override
public void moveTables(Set<TableName> tables, String targetGroup) throws IOException {
wrapped.moveTables(tables, targetGroup);
verify();
}
@Override
public void removeRSGroup(String name) throws IOException {
wrapped.removeRSGroup(name);
verify();
}
@Override
public boolean balanceRSGroup(String groupName) throws IOException {
return wrapped.balanceRSGroup(groupName);
}
@Override
public List<RSGroupInfo> listRSGroups() throws IOException {
return wrapped.listRSGroups();
}
@Override
public RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException {
return wrapped.getRSGroupOfServer(hostPort);
}
@Override
public void moveServersAndTables(Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
wrapped.moveServersAndTables(servers, tables, targetGroup);
verify();
}
public void verify() throws IOException {
Map<String, RSGroupInfo> groupMap = Maps.newHashMap();
Set<RSGroupInfo> zList = Sets.newHashSet();
for (Result result : table.getScanner(new Scan())) {
RSGroupProtos.RSGroupInfo proto =
RSGroupProtos.RSGroupInfo.parseFrom(
result.getValue(
RSGroupInfoManager.META_FAMILY_BYTES,
RSGroupInfoManager.META_QUALIFIER_BYTES));
groupMap.put(proto.getName(), RSGroupProtobufUtil.toGroupInfo(proto));
}
Assert.assertEquals(Sets.newHashSet(groupMap.values()),
Sets.newHashSet(wrapped.listRSGroups()));
try {
String groupBasePath = ZKUtil.joinZNode(zkw.znodePaths.baseZNode, "rsgroup");
for(String znode: ZKUtil.listChildrenNoWatch(zkw, groupBasePath)) {
byte[] data = ZKUtil.getData(zkw, ZKUtil.joinZNode(groupBasePath, znode));
if(data.length > 0) {
ProtobufUtil.expectPBMagicPrefix(data);
ByteArrayInputStream bis = new ByteArrayInputStream(
data, ProtobufUtil.lengthOfPBMagic(), data.length);
zList.add(RSGroupProtobufUtil.toGroupInfo(RSGroupProtos.RSGroupInfo.parseFrom(bis)));
}
}
Assert.assertEquals(zList.size(), groupMap.size());
for(RSGroupInfo RSGroupInfo : zList) {
Assert.assertTrue(groupMap.get(RSGroupInfo.getName()).equals(RSGroupInfo));
}
} catch (KeeperException e) {
throw new IOException("ZK verification failed", e);
} catch (DeserializationException e) {
throw new IOException("ZK verification failed", e);
} catch (InterruptedException e) {
throw new IOException("ZK verification failed", e);
}
}
}