package org.lilyproject.indexer.batchbuild.test;
import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Sets;
import com.ngdata.hbaseindexer.model.api.IndexerDefinition;
import com.ngdata.hbaseindexer.model.api.IndexerDefinitionBuilder;
import com.ngdata.hbaseindexer.model.api.IndexerModelEvent;
import com.ngdata.hbaseindexer.model.api.IndexerModelEventType;
import com.ngdata.hbaseindexer.model.api.IndexerModelListener;
import com.ngdata.hbaseindexer.model.api.IndexerUpdateException;
import com.ngdata.hbaseindexer.model.api.WriteableIndexerModel;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.lilyproject.lilyservertestfw.LilyProxy;
import org.lilyproject.repository.api.LRepository;
import org.lilyproject.repository.model.impl.RepositoryModelImpl;
import static org.junit.Assert.assertEquals;
import static org.lilyproject.indexer.batchbuild.test.IndexerIntegrationTestUtil.MINS15;
public class IndexAndRepoCreateDeleteIntegrationTest {
private static LilyProxy lilyProxy;
private static IndexerIntegrationTestUtil testUtil;
private RepositoryModelImpl model;
private HBaseAdmin hBaseAdmin;
private WriteableIndexerModel indexerModel;
@BeforeClass
public static void startLily() throws Exception {
lilyProxy = new LilyProxy(null,null,null,true);
testUtil = new IndexerIntegrationTestUtil(lilyProxy);
}
@AfterClass
public static void stopLily() throws Exception {
testUtil.stop();
}
@Before
public void setUp() throws Exception {
model = new RepositoryModelImpl(lilyProxy.getLilyServerProxy().getZooKeeper());
hBaseAdmin = new HBaseAdmin(lilyProxy.getHBaseProxy().getConf());
indexerModel = lilyProxy.getLilyServerProxy().getIndexerModel();
}
@Test
@Ignore("Since Lily 2.6 this is no longer true because the derefmaps should be managed by hbase-indexer")
public void testDeleteRepositoryRemovesTenantMaps() throws Exception {
model.delete(testUtil.secundaryRepo.getRepositoryName());
HTableDescriptor[] descriptors = hBaseAdmin.listTables();
System.out.println(Arrays.toString(descriptors));
waitForNoneOfTheseTablesExist(hBaseAdmin, "alternateRepo__record", "deref-backward-secundary",
"deref-forward-secundary");
//cleanup
deleteIndex("secundary");
}
/*
@Test(expected = IndexerUpdateException.class)
@Ignore //we no longer check on this
public void testChangeRepositoryForIndex() throws Exception {
LRepository firstNewRepo = testUtil.getAlternateTestRespository("repo1");
LRepository secondNewRepo = testUtil.getAlternateTestRespository("repo2");
testUtil.createIndex("testChRepo", "dummy", firstNewRepo);
String lock = indexerModel.lockIndexer("testChRepo");
try {
IndexerDefinition index = indexerModel.getIndexer("testChRepo");
ByteArrayInputStream is = new ByteArrayInputStream(index.getConfiguration());
IndexerConf indexerConf = new XmlIndexerConfReader().read(is);
indexerConf.getGlobalParams().put("repository", secondNewRepo.getRepositoryName());
ByteArrayOutputStream os = new ByteArrayOutputStream();
XmlIndexerConfWriter.writeConf(indexerConf, os);
indexerModel.updateIndexer(new IndexerDefinitionBuilder()
.startFrom(index)
.configuration(os.toByteArray())
.build(), lock);
} finally {
indexerModel.unlockIndexer(lock, true);
deleteIndex("testChRepo");
model.delete("repo1");
model.delete("repo2");
}
}
*/
@Test
public void testDropAndRecreateIndex() throws Exception {
try {
LRepository firstNewRepo = testUtil.getAlternateTestRespository("repo3");
LRepository secondNewRepo = testUtil.getAlternateTestRespository("repo4");
testUtil.createIndex("testBobbyTables", "dummyCORE", firstNewRepo);
deleteIndex("testBobbyTables");
testUtil.createIndex("testBobbyTables", "dummyCORE", secondNewRepo);
lilyProxy.getHBaseProxy().waitOnSepIdle(10000L);
checkOwner(hBaseAdmin, secondNewRepo.getRepositoryName(),
"deref-backward-testBobbyTables", "deref-forward-testBobbyTables");
} finally {
deleteIndex("testBobbyTables");
model.delete("repo3");
model.delete("repo4");
}
}
public void deleteIndex(final String indexName) throws Exception {
//set this up so we can wait for it later
final CountDownLatch latch = new CountDownLatch(1);
indexerModel.getIndexers(new IndexerModelListener() {
@Override
public void process(IndexerModelEvent event) {
if (indexName.equals(event.getIndexerName())
&& IndexerModelEventType.INDEXER_DELETED.equals(event.getType())) {
latch.countDown();
}
}
});
//request the delete
String lock = indexerModel.lockIndexer(indexName);
try {
indexerModel.updateIndexer(new IndexerDefinitionBuilder()
.startFrom(indexerModel.getIndexer(indexName))
.lifecycleState(IndexerDefinition.LifecycleState.DELETE_REQUESTED)
.build(), lock);
} finally {
indexerModel.unlockIndexer(lock, true);
}
//wait for delete to finish.
latch.await(MINS15, TimeUnit.MILLISECONDS);
}
public void waitForNoneOfTheseTablesExist(HBaseAdmin hBaseAdmin, String... tableNames) throws Exception {
long start = System.currentTimeMillis();
Set<String> leftOvers = checkTableExistence(hBaseAdmin, tableNames);
while (leftOvers.size() > 0) {
Thread.sleep(1000);
if (System.currentTimeMillis() - start > 1000 * 30)
throw new AssertionError("Waited too long for tables to get deleted: " + leftOvers);
leftOvers = checkTableExistence(hBaseAdmin, tableNames);
}
}
public void checkOwner(HBaseAdmin hBaseAdmin, String owner, String... tableNames) throws IOException {
for (String tableName : tableNames) {
HTableDescriptor descriptor = hBaseAdmin.getTableDescriptor(Bytes.toBytes(tableName));
String actualOwner = descriptor.getValue("lilyOwningRepository");
assertEquals(owner, actualOwner);
}
}
private Set<String> checkTableExistence(HBaseAdmin hBaseAdmin, String[] tableNames) throws IOException {
Set<String> names = Sets.newHashSet(tableNames);
Set<String> currenttables = Sets.newHashSet();
HTableDescriptor[] hTableDescriptors = hBaseAdmin.listTables();
for (HTableDescriptor hTableDescriptor : hTableDescriptors) {
currenttables.add(hTableDescriptor.getNameAsString());
}
return Sets.intersection(names, currenttables);
}
}