package com.bagri.server.hazelcast.store;
import static com.bagri.core.Constants.*;
import static com.bagri.core.server.api.CacheConstants.CN_XDM_TRANSACTION;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bagri.core.api.BagriException;
import com.bagri.core.api.TransactionIsolation;
import com.bagri.core.query.AxisType;
import com.bagri.core.query.Comparison;
import com.bagri.core.query.ExpressionContainer;
import com.bagri.core.query.PathBuilder;
import com.bagri.core.server.api.ModelManagement;
import com.bagri.core.server.api.QueryManagement;
import com.bagri.core.server.api.SchemaRepository;
import com.bagri.core.system.Library;
import com.bagri.core.system.Module;
import com.bagri.core.system.Schema;
import com.bagri.core.test.BagriManagementTest;
import com.bagri.server.hazelcast.impl.PopulationManagementImpl;
import com.bagri.server.hazelcast.impl.SchemaRepositoryImpl;
import com.bagri.server.hazelcast.impl.TransactionManagementImpl;
import com.bagri.server.hazelcast.store.TransactionCacheStore;
import com.bagri.support.util.PropUtils;
import com.hazelcast.core.HazelcastInstance;
public class TransactionCacheStoreTest extends BagriManagementTest {
private static ClassPathXmlApplicationContext context;
//private static String txFileName;
private TransactionCacheStore txStore;
private Properties tmProps;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
sampleRoot = "..\\..\\etc\\samples\\tpox\\";
System.setProperty("hz.log.level", "info");
//System.setProperty("bdb.log.level", "trace");
System.setProperty(pn_node_instance, "0");
System.setProperty("logback.configurationFile", "hz-logging.xml");
System.setProperty(pn_config_properties_file, "store.properties");
System.setProperty(pn_config_path, "src\\test\\resources");
context = new ClassPathXmlApplicationContext("spring/cache-test-context.xml");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
// wait for document store..?
Thread.sleep(5000);
//Assert.assertTrue("expected to delete tx log from " + txFileName, Files.deleteIfExists(Paths.get(txFileName)));
// delete all stored securities?
context.close();
}
@Before
public void setUp() throws Exception {
xRepo = context.getBean(SchemaRepositoryImpl.class);
SchemaRepositoryImpl xdmRepo = (SchemaRepositoryImpl) xRepo;
Schema schema = xdmRepo.getSchema();
if (schema == null) {
schema = new Schema(1, new java.util.Date(), "test", "test", "test schema", true, null);
Properties props = PropUtils.propsFromFile("src/test/resources/store.properties");
schema.setProperties(props);
xdmRepo.setSchema(schema);
((TransactionManagementImpl) xdmRepo.getTxManagement()).adjustTxCounter(0);
xdmRepo.setDataFormats(getBasicDataFormats());
xdmRepo.setLibraries(new ArrayList<Library>());
xdmRepo.setModules(new ArrayList<Module>());
PopulationManagementImpl pm = (PopulationManagementImpl) context.getBean(HazelcastInstance.class).getUserContext().get(ctx_popService);
txStore = (TransactionCacheStore) pm.getMapStore(CN_XDM_TRANSACTION);
tmProps = new Properties();
tmProps.setProperty(pn_client_txTimeout, "50");
}
}
@After
public void tearDown() throws Exception {
removeDocumentsTest();
//SchemaRepositoryImpl xdmRepo = (SchemaRepositoryImpl) xRepo;
//Schema schema = xdmRepo.getSchema();
//String dataPath = schema.getProperty(pn_schema_store_data_path);
//String nodeNum = System.getProperty(pn_node_instance);
//txFileName = FileUtils.buildStoreFileName(dataPath, nodeNum, "txlog");
}
private ModelManagement getModelManagement() {
return ((SchemaRepository) xRepo).getModelManagement();
}
public Collection<String> getSecurity(String symbol) throws Exception {
String prefix = "http://tpox-benchmark.com/security";
int docType = 0; //getModelManagement().getDocumentType("/" + prefix + ":Security");
PathBuilder path = new PathBuilder().
addPathSegment(AxisType.CHILD, prefix, "Security").
addPathSegment(AxisType.CHILD, prefix, "Symbol").
addPathSegment(AxisType.CHILD, null, "text()");
ExpressionContainer ec = new ExpressionContainer();
ec.addExpression(docType, Comparison.EQ, path, "$sym", symbol);
Map<String, Object> params = new HashMap<>();
params.put(":sec", "/" + prefix + ":Security");
return ((QueryManagement) getQueryManagement()).getContent(ec, ":sec", params);
}
@Test
public void bulkTransactionTest() throws Exception {
int oldCount = txStore.getStoredCount();
int loops = 10;
int thCount = 5;
final CountDownLatch cdl = new CountDownLatch(thCount);
for (int i=1; i <= thCount; i++) {
Thread th = new Thread(new TransactionTest(i % 2 == 0, loops, cdl));
Thread.sleep(10);
th.start();
}
cdl.await();
int newCount = txStore.getStoredCount();
int expCount = oldCount; // + (loops*(thCount/2)); why is new == old??
assertTrue("expected " + expCount + " but got " + newCount + " transactions", newCount == expCount);
}
@Override
protected Properties getDocumentProperties() {
return tmProps;
}
private class TransactionTest implements Runnable {
private int loops;
private boolean rollback;
private CountDownLatch counter;
TransactionTest(boolean rollback, int loops, CountDownLatch counter) {
this.rollback = rollback;
this.counter = counter;
this.loops = loops;
}
@Override
public void run() {
long txId = 0;
try {
//for (int i=0; i < loops; i++) {
int i = 0;
while (i < loops) {
txId = xRepo.getTxManagement().beginTransaction(); //TransactionIsolation.repeatableRead);
try {
//storeSecurityTest();
uris.add(updateDocumentTest("security1500.xml", sampleRoot + getFileName("security1500.xml")).getUri());
uris.add(updateDocumentTest("security5621.xml", sampleRoot + getFileName("security5621.xml")).getUri());
uris.add(updateDocumentTest("security9012.xml", sampleRoot + getFileName("security9012.xml")).getUri());
} catch (BagriException ex) {
if (ex.getErrorCode() == BagriException.ecTransTimeout) {
xRepo.getTxManagement().rollbackTransaction(txId);
Thread.sleep(100);
continue;
}
throw ex;
}
Collection<String> sec = getSecurity("VFINX");
assertNotNull("Got null VFINX", sec);
assertTrue("Got empty VFINX", sec.size() > 0);
sec = getSecurity("IBM");
assertNotNull("Got null IBM", sec);
assertTrue("Got empty IBM", sec.size() > 0);
sec = getSecurity("PTTAX");
assertNotNull("Got null PTTAX", sec);
assertTrue("Got empty PTTAX", sec.size() > 0);
if (rollback) {
xRepo.getTxManagement().rollbackTransaction(txId);
} else {
xRepo.getTxManagement().commitTransaction(txId);
}
// wait till it is flushed to store
Thread.sleep(2000);
i++;
}
} catch (Throwable ex) {
counter.countDown();
try {
xRepo.getTxManagement().rollbackTransaction(txId);
} catch (BagriException e) {
e.printStackTrace();
}
assertTrue("Unexpected exception: " + ex.getMessage(), false);
}
counter.countDown();
}
}
}