refs #200: Create accouting-lib library

https://support.d4science.org/issues/200
Fixing tests

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/accounting/accounting-lib@117029 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Luca Frosini 2015-07-06 13:33:54 +00:00
parent 317b72c11a
commit fbf99786bb
11 changed files with 168 additions and 177 deletions

View File

@ -3,6 +3,7 @@ package org.gcube.accounting.messaging;
import org.gcube.accounting.datamodel.RawUsageRecord;
import org.gcube.accounting.exception.InvalidValueException;
import org.gcube.accounting.persistence.Persistence;
import org.gcube.accounting.persistence.PersistenceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -22,7 +23,7 @@ public class ResourceAccounting {
@Deprecated
public ResourceAccounting() {
persistence = Persistence.getInstance();
persistence = PersistenceFactory.getPersistence();
}
@Deprecated

View File

@ -9,6 +9,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import org.gcube.accounting.aggregation.scheduler.AggregationScheduler;
import org.gcube.accounting.datamodel.UsageRecord;
/**
@ -19,7 +20,7 @@ public class FallbackPersistence extends Persistence {
private File accountingFallbackFile;
protected FallbackPersistence(File accountingFallbackFile) {
super();
super(null, AggregationScheduler.getInstance());
this.accountingFallbackFile = accountingFallbackFile;
}

View File

@ -3,8 +3,6 @@
*/
package org.gcube.accounting.persistence;
import java.io.File;
import java.util.ServiceLoader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -22,97 +20,38 @@ public abstract class Persistence {
private static final Logger logger = LoggerFactory.getLogger(Persistence.class);
private static final String ACCOUTING_FALLBACK_FILENAME = "accountingFallback.log";
/**
* The singleton instance of persistence
*/
protected static Persistence persistence;
protected static FallbackPersistence fallback;
protected static AggregationScheduler aggregationScheduler;
private static File file(File file) throws IllegalArgumentException {
if (file.isDirectory())
throw new IllegalArgumentException(file.getAbsolutePath() + " cannot be used in write mode because it's folder");
//create folder structure it does not exist
if (!file.getParentFile().exists())
file.getParentFile().mkdirs();
return file;
}
public synchronized static void setFallbackLocation(String path){
if(fallback == null){
if(path==null){
path = ".";
}
File file = file(new File(path, ACCOUTING_FALLBACK_FILENAME));
fallback = new FallbackPersistence(file);
}
}
protected static void init() {
setFallbackLocation(null);
try {
ServiceLoader<Persistence> serviceLoader = ServiceLoader.load(Persistence.class);
for (Persistence foundPersistence : serviceLoader) {
if(foundPersistence.getClass().isInstance(FallbackPersistence.class)){
continue;
}
try {
String foundPersistenceClassName = foundPersistence.getClass().getSimpleName();
logger.debug("Testing {}", foundPersistenceClassName);
String scope = null; // TODO
PersistenceConfiguration configuration = PersistenceConfiguration.getPersistenceConfiguration(scope, foundPersistenceClassName);
foundPersistence.prepareConnection(configuration);
/*
* Uncomment the following line of code if you want to try
* to create a test UsageRecord before setting the
* foundPersistence as default
*
* foundPersistence.accountWithFallback(TestUsageRecord.createTestServiceUsageRecord());
*/
persistence = foundPersistence;
break;
} catch (Exception e) {
logger.debug(String.format("%s not initialized correctly. It will not be used", foundPersistence.getClass().getSimpleName()));
}
}
if(persistence==null){
persistence = fallback;
}
} catch(Exception e){
logger.error("Unable to instance a Persistence Implementation. Using fallback as default",
e.getCause());
persistence = fallback;
}
aggregationScheduler = AggregationScheduler.getInstance();
}
protected FallbackPersistence fallback;
protected AggregationScheduler aggregationScheduler;
/**
* Pool for thread execution
*/
private ExecutorService pool;
protected Persistence(){
this.pool = Executors.newCachedThreadPool();
}
protected Persistence(FallbackPersistence fallback, AggregationScheduler aggregationScheduler){
this.fallback = fallback;
this.aggregationScheduler = aggregationScheduler;
this.pool = Executors.newCachedThreadPool();
}
/**
* @return the singleton instance of persistence
* @throws Exception if fails
* @param fallback the fallback to set
*/
public static Persistence getInstance() {
if(persistence==null){
init();
}
return persistence;
protected void setFallback(FallbackPersistence fallback) {
this.fallback = fallback;
}
protected Persistence() {
pool = Executors.newCachedThreadPool();
/**
* @param aggregationScheduler the aggregationScheduler to set
*/
protected void setAggregationScheduler(AggregationScheduler aggregationScheduler) {
this.aggregationScheduler = aggregationScheduler;
}
/**
* Prepare the connection to persistence.
* This method must be used by implementation class to open
@ -141,11 +80,11 @@ public abstract class Persistence {
protected abstract void reallyAccount(UsageRecord usageRecords) throws Exception;
private void accountWithFallback(UsageRecord... usageRecords) {
String persistenceName = getInstance().getClass().getSimpleName();
String persistenceName = this.getClass().getSimpleName();
for(UsageRecord usageRecord : usageRecords){
try {
//logger.debug("Going to account {} using {}", usageRecord, persistenceName);
persistence.reallyAccount(usageRecord);
this.reallyAccount(usageRecord);
logger.debug("{} accounted succesfully from {}.", usageRecord.toString(), persistenceName);
} catch (Exception e) {
String fallabackPersistenceName = fallback.getClass().getSimpleName();
@ -169,6 +108,7 @@ public abstract class Persistence {
usageRecord.validate();
}
if(aggregate){
final Persistence persistence = this;
aggregationScheduler.aggregate(usageRecord, new PersistenceExecutor(){
@Override
@ -178,7 +118,7 @@ public abstract class Persistence {
});
}else{
persistence.accountWithFallback(usageRecord);
this.accountWithFallback(usageRecord);
}
} catch (InvalidValueException e) {
@ -209,6 +149,7 @@ public abstract class Persistence {
}
public void flush() throws Exception {
final Persistence persistence = this;
aggregationScheduler.flush(new PersistenceExecutor(){
@Override

View File

@ -116,10 +116,10 @@ public class PersistenceConfiguration {
}
private static String decrypt(String encrypted, Key... key) throws Exception {
return StringEncrypter.getEncrypter().decrypt(encrypted, key);
return StringEncrypter.getEncrypter().decrypt(encrypted);
}
private static PersistenceConfiguration createPersistenceConfiguration(ServiceEndpoint serviceEndpoint, Key... key) throws Exception{
protected static PersistenceConfiguration createPersistenceConfiguration(ServiceEndpoint serviceEndpoint) throws Exception{
PersistenceConfiguration persistenceConfiguration = new PersistenceConfiguration();
Group<AccessPoint> accessPoints = serviceEndpoint.profile().accessPoints();
for(AccessPoint accessPoint : accessPoints){
@ -127,7 +127,7 @@ public class PersistenceConfiguration {
persistenceConfiguration.username = accessPoint.username();
String encryptedPassword = accessPoint.password();
String password = decrypt(encryptedPassword, key);
String password = decrypt(encryptedPassword);
persistenceConfiguration.password = password;
persistenceConfiguration.propertyMap = accessPoint.propertyMap();
@ -142,9 +142,9 @@ public class PersistenceConfiguration {
* @return
* @throws Exception
*/
protected static PersistenceConfiguration getPersistenceConfiguration(String scope, String persistenceClassName, Key... key) throws Exception {
public static PersistenceConfiguration getPersistenceConfiguration(String scope, String persistenceClassName) throws Exception {
ServiceEndpoint serviceEndpoint = getServiceEndpoint(scope, persistenceClassName);
return createPersistenceConfiguration(serviceEndpoint, key);
return createPersistenceConfiguration(serviceEndpoint);
}
}

View File

@ -0,0 +1,108 @@
/**
*
*/
package org.gcube.accounting.persistence;
import java.io.File;
import java.util.ServiceLoader;
import org.gcube.accounting.aggregation.scheduler.AggregationScheduler;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR) http://www.lucafrosini.com/
*
*/
public abstract class PersistenceFactory {
private static final Logger logger = LoggerFactory.getLogger(PersistenceFactory.class);
public final static String HOME_SYSTEM_PROPERTY = "user.home";
private static final String ACCOUTING_FALLBACK_FILENAME = "accountingFallback.log";
private static String fallbackLocation;
private static File file(File file) throws IllegalArgumentException {
if(!file.isDirectory()){
file = file.getParentFile();
}
//create folder structure if not exist
if (!file.exists())
file.mkdirs();
return file;
}
public synchronized static void setFallbackLocation(String path){
if(fallbackLocation == null){
if(path==null){
path = System.getProperty(HOME_SYSTEM_PROPERTY);
}
file(new File(path));
fallbackLocation = path;
}
}
public synchronized static Persistence getPersistence(){
Persistence persistence = null;
String scope = ScopeProvider.instance.get();
String name = "";
if(scope!=null){
ScopeBean bean = new ScopeBean(scope);
if(bean.is(Type.VRE)){
bean = bean.enclosingScope();
}
name = bean.name();
}
String separator = name.compareTo("")==0 ? "" : ".";
File fallbackFile = new File(fallbackLocation, String.format("%s%s%s", name, separator ,ACCOUTING_FALLBACK_FILENAME));
FallbackPersistence fallbackPersistence = new FallbackPersistence(fallbackFile);
try {
ServiceLoader<Persistence> serviceLoader = ServiceLoader.load(Persistence.class);
for (Persistence foundPersistence : serviceLoader) {
if(foundPersistence.getClass().isInstance(FallbackPersistence.class)){
continue;
}
try {
String foundPersistenceClassName = foundPersistence.getClass().getSimpleName();
logger.debug("Testing {}", foundPersistenceClassName);
PersistenceConfiguration configuration = PersistenceConfiguration.getPersistenceConfiguration(scope, foundPersistenceClassName);
foundPersistence.prepareConnection(configuration);
/*
* Uncomment the following line of code if you want to try
* to create a test UsageRecord before setting the
* foundPersistence as default
*
* foundPersistence.accountWithFallback(TestUsageRecord.createTestServiceUsageRecord());
*/
persistence = foundPersistence;
break;
} catch (Exception e) {
logger.debug(String.format("%s not initialized correctly. It will not be used", foundPersistence.getClass().getSimpleName()));
}
}
if(persistence==null){
persistence = fallbackPersistence;
}
} catch(Exception e){
logger.error("Unable to instance a Persistence Implementation. Using fallback as default",
e.getCause());
persistence = fallbackPersistence;
}
persistence.setAggregationScheduler(AggregationScheduler.getInstance());
persistence.setFallback(fallbackPersistence);
return persistence;
}
}

View File

@ -5,7 +5,6 @@ package org.gcube.accounting.persistence;
import java.io.StringWriter;
import java.net.URL;
import java.security.Key;
import java.util.Arrays;
import java.util.List;
@ -56,7 +55,7 @@ public class PersistenceConfigurationTest {
public static final String FAKE_PASSWORD = "fakepassword";
public static final String[] SCOPES = new String[]{"/gcube", "/gcube/devsec"};
public static final String GCUBE_SCOPE = SCOPES[1];
public static final String GCUBE_SCOPE = SCOPES[0];
public static final String GCUBE_DEVSEC_SCOPE = SCOPES[1];
public static final String DB_NAME_PROPERTY_NAME = "dbName";
@ -198,9 +197,7 @@ public class PersistenceConfigurationTest {
}
try {
String keyName = "devsec.gcubekey";
Key key = SymmetricKey.getKey(System.getProperty(PersistenceTest.HOME_SYSTEM_PROPERTY)+ "/" + keyName);
PersistenceConfiguration persitenceConfiguration = PersistenceConfiguration.getPersistenceConfiguration(GCUBE_DEVSEC_SCOPE, COUCHDB_CLASS_NAME, key);
PersistenceConfiguration persitenceConfiguration = PersistenceConfiguration.getPersistenceConfiguration(GCUBE_DEVSEC_SCOPE, COUCHDB_CLASS_NAME);
if(createResource){
Assert.assertTrue(persitenceConfiguration.getUri().toURL().equals(new URL(RUNNING_ON)));
Assert.assertTrue(persitenceConfiguration.getUsername().compareTo(FAKE_USERNAME)==0);

View File

@ -15,16 +15,23 @@ import org.junit.Test;
*/
public class PersistenceTest {
protected final static String HOME_SYSTEM_PROPERTY = "user.home";
public static Persistence getPersistence(){
Persistence.setFallbackLocation(System.getProperty(HOME_SYSTEM_PROPERTY));
return Persistence.getInstance();
PersistenceFactory.setFallbackLocation(null);
return PersistenceFactory.getPersistence();
}
@Test
public void test() throws Exception {
getPersistence();
public void singleTest() throws Exception {
final Persistence persistence = getPersistence();
StressTestUtility.stressTest(new TestOperation() {
@Override
public void operate(int i) {
SingleUsageRecord usageRecord = TestUsageRecord.createTestServiceUsageRecord();
persistence.validateAccountAggregate(usageRecord, true, false);
}
}, 1);
persistence.flush();
}
@Test

View File

@ -1,69 +0,0 @@
package org.gcube.accounting.persistence;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import javax.crypto.spec.SecretKeySpec;
final class SymmetricKey {
private static Key key;
private static String keyAlgorithm = "AES";
//private constructor
private SymmetricKey() {}
/**
* Gets the key for encryption/decryption
* @return the key
* @throws InvalidKeyException if the key is not available or is invalid
*/
public static Key getKey(String keyPath) throws InvalidKeyException {
if (key == null) load(keyPath);
return key;
}
/**
* Loads the key from the classpaht
* @throws InvalidKeyException if the key is not available or is invalid
*/
private static void load(String keyPath) throws InvalidKeyException {
byte[] rawKey;
String keyFileName=null;
try {
InputStream is = new FileInputStream(new File(keyPath));
rawKey = getBytesFromStream(is);
} catch (Exception e) {
System.out.println("Unable to load the Key "+keyFileName+" from the classpath");
e.printStackTrace();
throw new InvalidKeyException("Unable to load the Key "+keyFileName+" from the classpath");
}
try {
key = new SecretKeySpec(rawKey, 0, rawKey.length, keyAlgorithm);
}catch (Exception e) {
e.printStackTrace();
throw new InvalidKeyException();
}
}
private static byte[] getBytesFromStream(InputStream is) throws IOException {
byte[] rawKey;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
rawKey= buffer.toByteArray();
return rawKey;
}
}

View File

@ -18,19 +18,22 @@ public class StressTestUtility {
private static final Logger logger = LoggerFactory.getLogger(StressTestUtility.class);
protected final static int NUMBER_OF_RECORDS = 3000;
protected final static int DEFAULT_NUMBER_OF_RECORDS = 3000;
public static void stressTest(TestOperation operation) throws Exception {
stressTest(operation, DEFAULT_NUMBER_OF_RECORDS);
}
public static void stressTest(TestOperation operation, int runs) throws Exception {
Calendar startTestTime = new GregorianCalendar();
for(int i=0; i< NUMBER_OF_RECORDS; i++){
for(int i=0; i< runs; i++){
operation.operate(i);
}
Calendar stopTestTime = new GregorianCalendar();
double startMillis = startTestTime.getTimeInMillis();
double stopMillis = stopTestTime.getTimeInMillis();
double duration = stopMillis - startMillis;
double average = (duration/NUMBER_OF_RECORDS);
double average = (duration/runs);
logger.debug("Duration (in millisec) : " + duration);
logger.debug("Average (in millisec) : " + average);
}

View File

@ -0,0 +1 @@
6 4Z<34>/U<><55> C<><43>ߘ

View File

@ -0,0 +1 @@
6 4Z<34>/U<><55> C<><43>ߘ