package org.csc.phynixx.connection;
/*
* #%L
* phynixx-connection
* %%
* Copyright (C) 2014 csc
* %%
* Licensed 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.
* #L%
*/
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.csc.phynixx.common.TestUtils;
import org.csc.phynixx.common.TmpDirectory;
import org.csc.phynixx.common.exceptions.DelegatedRuntimeException;
import org.csc.phynixx.common.logger.IPhynixxLogger;
import org.csc.phynixx.common.logger.PhynixxLogManager;
import org.csc.phynixx.connection.loggersystem.IPhynixxLoggerSystemStrategy;
import org.csc.phynixx.connection.loggersystem.LoggerPerTransactionStrategy;
import org.csc.phynixx.loggersystem.logger.IDataLoggerFactory;
import org.csc.phynixx.loggersystem.logger.channellogger.FileChannelDataLoggerFactory;
import org.csc.phynixx.phynixx.testconnection.*;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MTPooledConnectionIT extends TestCase {
private IPhynixxLogger logger = PhynixxLogManager.getLogger(this.getClass());
private PooledPhynixxManagedConnectionFactory<ITestConnection> factory = null;
private static final int CONNECTION_POOL_SIZE = 20;
private TmpDirectory tmpDir = null;
protected void setUp() throws Exception {
// configuring the log-system (e.g. log4j)
TestUtils.configureLogging();
this.tmpDir = new TmpDirectory("howllogger");
// clears all existing file in dem tmp directory
this.tmpDir.clear();
GenericObjectPoolConfig cfg = new GenericObjectPoolConfig();
cfg.setMaxTotal(CONNECTION_POOL_SIZE);
this.factory = new PooledPhynixxManagedConnectionFactory(new TestConnectionFactory(), cfg);
this.factory.setSynchronizeConnection(true);
IDataLoggerFactory loggerFactory = new FileChannelDataLoggerFactory("pool", this.tmpDir.getDirectory());
LoggerPerTransactionStrategy strategy = new LoggerPerTransactionStrategy(loggerFactory);
this.factory.setLoggerSystemStrategy(strategy);
}
protected void tearDown() throws Exception {
TestConnectionStatusManager.clear();
this.factory.close();
// delete all tmp files ...
this.tmpDir.delete();
this.factory = null;
}
private static interface IActOnConnection {
Object doWork(ITestConnection con);
}
private static List<Exception> exceptions = Collections.synchronizedList(new ArrayList());
private class Caller implements Callable<Object> {
private IActOnConnection actOnConnection = null;
private int repeats= 1;
private long msecsDelay= -1;
public Caller(IActOnConnection actOnConnection) {
this(actOnConnection,1);
}
public Caller(IActOnConnection actOnConnection, int repeats) {
this.actOnConnection = actOnConnection;
this.repeats= repeats;
}
public Object call() {
ITestConnection con = null;
Object conId=null;
try {
for (int i = 0; i < repeats; i++)
{
try {
con = MTPooledConnectionIT.this.factory.getConnection();
conId= con.getConnectionId();
if(msecsDelay > 0) {
Thread.currentThread().sleep(msecsDelay);
}
try {
this.actOnConnection.doWork(con);
} catch (ActionInterruptedException e) {
} catch (DelegatedRuntimeException e) {
if (!(e.getRootCause() instanceof ActionInterruptedException)) {
throw e;
}
}
} finally {
if (con != null) {
//con.close();
}
}
}
} catch (Throwable ex) {
ex.printStackTrace();
exceptions.add(new DelegatedRuntimeException("Thread " + Thread.currentThread(), ex));
}
return conId;
}
}
private void startRunners(IActOnConnection actOnConnection, int numThreads) throws Exception {
exceptions.clear();
ExecutorService executorService= Executors.newFixedThreadPool(numThreads);
for (int i = 0; i < numThreads; i++) {
Callable<Object> task = new Caller(actOnConnection);
executorService.submit(task);
}
executorService.shutdown();
// 10 seconds per execution
boolean inTime= executorService.awaitTermination(10000*CONNECTION_POOL_SIZE, TimeUnit.SECONDS);
if(!inTime) {
if(!executorService.isShutdown()) {
List<Runnable> runnables = executorService.shutdownNow();
}
throw new IllegalStateException("Execution was stopped after "+10*CONNECTION_POOL_SIZE +" seconds");
}
if (exceptions.size() > 0) {
for (int i = 0; i < exceptions.size(); i++) {
Exception ex = (Exception) exceptions.get(i);
ex.printStackTrace();
}
throw new IllegalStateException("Error occurred",exceptions.get(0));
}
}
public void testGoodCase() throws Exception {
IActOnConnection actOnConnection = new IActOnConnection() {
public Object doWork(ITestConnection con) {
try {
con.act(5);
con.act(7);
con.rollback();
} finally {
con.close();
}
return con.getConnectionId();
}
};
this.startRunners(actOnConnection,CONNECTION_POOL_SIZE*2);
// nothing has to be recoverd ...
}
public void testInterruptedRollback() throws Exception {
final int[] counter = new int[1];
IActOnConnection actOnConnection = new IActOnConnection() {
public Object doWork(ITestConnection con) {
Object conId=con.getConnectionId();
try {
con.act(5);
con.setInterruptFlag(TestInterruptionPoint.ACT);
con.act(7);
con.rollback();
} finally {
con.close();
return conId;
}
}
};
this.startRunners(actOnConnection, CONNECTION_POOL_SIZE*2);
this.factory.close();
PhynixxRecovery<ITestConnection> recovery= new PhynixxRecovery<ITestConnection>(new TestConnectionFactory());
IPhynixxLoggerSystemStrategy<ITestConnection> loggerStrategy= this.factory.getLoggerSystemStrategy();
loggerStrategy.close();
recovery.setLoggerSystemStrategy(loggerStrategy);
recovery.recover(null);
// TestStatusStack statusStack= TestConnectionStatusManager.getStatusStack(con.)
}
private Properties loadHowlConfig() throws Exception {
Properties howlprop = new Properties();
howlprop.put("listConfig", "false");
howlprop.put("bufferSize", "32");
howlprop.put("minBuffers", "1");
howlprop.put("maxBuffers", "1");
howlprop.put("maxBlocksPerFile", "100");
howlprop.put("logFileDir", this.tmpDir.getDirectory().getAbsolutePath());
howlprop.put("logFileName", "test1");
howlprop.put("maxLogFiles", "2");
return howlprop;
}
}