From 92f5d42e48332a0f4c556f33324d39a543ee9da3 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Fri, 13 Nov 2015 10:43:18 +0000 Subject: [PATCH] Recoded the code redesign. Recoded the function which retrieve the AccountingPersistenceBackend class to use. git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/accounting/accounting-lib@120270 82a268e6-3cf1-43bd-a215-b396298e98cf --- .../AccountingPersistenceBackend.java | 8 +- .../AccountingPersistenceBackendFactory.java | 147 ++++++++++-------- .../AccountingPersistenceBackendTest.java | 12 +- 3 files changed, 94 insertions(+), 73 deletions(-) diff --git a/src/main/java/org/gcube/accounting/persistence/AccountingPersistenceBackend.java b/src/main/java/org/gcube/accounting/persistence/AccountingPersistenceBackend.java index e18213a..e542a68 100644 --- a/src/main/java/org/gcube/accounting/persistence/AccountingPersistenceBackend.java +++ b/src/main/java/org/gcube/accounting/persistence/AccountingPersistenceBackend.java @@ -47,6 +47,13 @@ public abstract class AccountingPersistenceBackend { this.fallback = fallback; } + /** + * @return the aggregationScheduler + */ + public AggregationScheduler getAggregationScheduler() { + return aggregationScheduler; + } + /** * @param aggregationScheduler the aggregationScheduler to set */ @@ -156,7 +163,6 @@ public abstract class AccountingPersistenceBackend { } - public abstract void close() throws Exception; } diff --git a/src/main/java/org/gcube/accounting/persistence/AccountingPersistenceBackendFactory.java b/src/main/java/org/gcube/accounting/persistence/AccountingPersistenceBackendFactory.java index fd43b25..5004bd2 100644 --- a/src/main/java/org/gcube/accounting/persistence/AccountingPersistenceBackendFactory.java +++ b/src/main/java/org/gcube/accounting/persistence/AccountingPersistenceBackendFactory.java @@ -34,7 +34,7 @@ public abstract class AccountingPersistenceBackendFactory { public static final long FALLBACK_RETRY_TIME = 1000*60*10; // 10 min - private static Map fallbackLastCheck; + protected static Map fallbackLastCheck; static { persistencePersistenceBackends = new HashMap(); @@ -62,86 +62,99 @@ public abstract class AccountingPersistenceBackendFactory { } } + protected static AccountingPersistenceBackend discoverAccountingPersistenceBackend(String scope){ + ServiceLoader serviceLoader = ServiceLoader.load(AccountingPersistenceBackend.class); + for (AccountingPersistenceBackend foundPersistence : serviceLoader) { + if(foundPersistence instanceof FallbackPersistence){ + continue; + } + try { + String foundPersistenceClassName = foundPersistence.getClass().getSimpleName(); + logger.debug("Testing {}", foundPersistenceClassName); + AccountingPersistenceConfiguration configuration = new AccountingPersistenceConfiguration(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()); + */ + logger.debug("{} will be used.", foundPersistenceClassName); + foundPersistence.setAggregationScheduler(AggregationScheduler.newInstance()); + return foundPersistence; + } catch (Exception e) { + logger.error(String.format("%s not initialized correctly. It will not be used. Trying the next one if any.", foundPersistence.getClass().getSimpleName()), e); + } + } + return null; + }; + + protected static FallbackPersistence createFallback(String scope){ + File fallbackFile = null; + if(scope!=null){ + ScopeBean bean = new ScopeBean(scope); + /* if(bean.is(Type.VRE)){ bean = bean.enclosingScope(); } */ + String name = bean.name(); + fallbackFile = new File(fallbackLocation, String.format("%s.%s", name, ACCOUTING_FALLBACK_FILENAME)); + }else{ + fallbackFile = new File(fallbackLocation, ACCOUTING_FALLBACK_FILENAME); + } + FallbackPersistence fallbackPersistence = new FallbackPersistence(fallbackFile); + fallbackPersistence.setAggregationScheduler(AggregationScheduler.newInstance()); + return fallbackPersistence; + } + + protected static synchronized AccountingPersistenceBackend getPersistenceBackend() { String scope = ScopeProvider.instance.get(); if(scope==null){ logger.error("No Scope available. FallbackPersistence will be used"); - File fallbackFile = new File(fallbackLocation, ACCOUTING_FALLBACK_FILENAME); - return new FallbackPersistence(fallbackFile); + return createFallback(null); } - AccountingPersistenceBackend persistence = persistencePersistenceBackends.get(scope); - if(persistence!=null && persistence instanceof FallbackPersistence && fallbackLastCheck.get(scope)!=null){ - long now = Calendar.getInstance().getTimeInMillis(); - Long lastCheckTimestamp = fallbackLastCheck.get(scope); - if(lastCheckTimestamp <= (now + FALLBACK_RETRY_TIME)){ - // Setting persistence to null so that the - // AccountingPersistenceBackend is rechecked - logger.debug("The {} for scope {} is {}. Is time to rediscover if there is another possibility.", - AccountingPersistenceBackend.class.getSimpleName(), scope, persistence.getClass().getSimpleName()); - persistence = null; - - } - } - if(persistence==null){ - - ScopeBean bean = new ScopeBean(scope); - /* - if(bean.is(Type.VRE)){ - bean = bean.enclosingScope(); - } - */ - String name = bean.name(); + persistence = discoverAccountingPersistenceBackend(scope); - File fallbackFile = new File(fallbackLocation, String.format("%s.%s", name, ACCOUTING_FALLBACK_FILENAME)); - FallbackPersistence fallbackPersistence = new FallbackPersistence(fallbackFile); - try { - ServiceLoader serviceLoader = ServiceLoader.load(AccountingPersistenceBackend.class); - for (AccountingPersistenceBackend foundPersistence : serviceLoader) { - if(foundPersistence instanceof FallbackPersistence){ - continue; - } - try { - String foundPersistenceClassName = foundPersistence.getClass().getSimpleName(); - logger.debug("Testing {}", foundPersistenceClassName); - AccountingPersistenceConfiguration configuration = new AccountingPersistenceConfiguration(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; - logger.debug("{} will be used.", foundPersistenceClassName); - break; - } catch (Exception e) { - logger.error(String.format("%s not initialized correctly. It will not be used. Trying the next one if any.", foundPersistence.getClass().getSimpleName()), e); - } - } - - if(persistence==null){ - logger.error("Unable to instatiate a {}. {} will be used.", AccountingPersistenceBackend.class.getSimpleName(), FallbackPersistence.class.getSimpleName()); - persistence = fallbackPersistence; - } - - } catch(Exception e){ - //logger.error("Unable to instance a Persistence Implementation. Using fallback as default", e); - logger.error("Unable to instantiate a {}. {} will be used.", AccountingPersistenceBackend.class.getSimpleName(), FallbackPersistence.class.getSimpleName(), e); - persistence = fallbackPersistence; - } - - persistence.setAggregationScheduler(AggregationScheduler.newInstance()); - persistence.setFallback(fallbackPersistence); - if(persistence instanceof FallbackPersistence){ + if(persistence==null){ + logger.warn("Unable to find a usable {}. {} will be used.", AccountingPersistenceBackend.class.getSimpleName(), FallbackPersistence.class.getSimpleName()); long now = Calendar.getInstance().getTimeInMillis(); fallbackLastCheck.put(scope, now); + persistence = createFallback(scope); } + persistencePersistenceBackends.put(scope, persistence); + + } else { + if(persistence instanceof FallbackPersistence && fallbackLastCheck.get(scope)!=null){ + long now = Calendar.getInstance().getTimeInMillis(); + Long lastCheckTimestamp = fallbackLastCheck.get(scope); + if(lastCheckTimestamp <= (now + FALLBACK_RETRY_TIME)){ + // Setting persistence to null so that the + // AccountingPersistenceBackend is rechecked + logger.debug("The {} for scope {} is {}. Is time to rediscover if there is another possibility.", + AccountingPersistenceBackend.class.getSimpleName(), scope, persistence.getClass().getSimpleName()); + + AccountingPersistenceBackend discoveredPersistenceBackend = discoverAccountingPersistenceBackend(scope); + if(discoveredPersistenceBackend!=null){ + discoveredPersistenceBackend.setAggregationScheduler(persistence.getAggregationScheduler()); + fallbackLastCheck.remove(scope); + persistencePersistenceBackends.put(scope, discoveredPersistenceBackend); + try { + persistence.close(); + } catch (Exception e) { + logger.error("Error closing {} for scope {} which has been substituted with {}.", + persistence.getClass().getSimpleName(), scope, + discoveredPersistenceBackend.getClass().getSimpleName(), e); + } + persistence = discoveredPersistenceBackend; + }else{ + fallbackLastCheck.put(scope, now); + } + } + } } return persistence; diff --git a/src/test/java/org/gcube/accounting/persistence/AccountingPersistenceBackendTest.java b/src/test/java/org/gcube/accounting/persistence/AccountingPersistenceBackendTest.java index a2351ff..dba0290 100644 --- a/src/test/java/org/gcube/accounting/persistence/AccountingPersistenceBackendTest.java +++ b/src/test/java/org/gcube/accounting/persistence/AccountingPersistenceBackendTest.java @@ -103,8 +103,9 @@ public class AccountingPersistenceBackendTest { @Test public void testScopeRecheck() throws Exception { ScopeProvider.instance.set("/fakeScope"); - AccountingPersistenceBackend first = AccountingPersistenceBackendFactory.getPersistenceBackend(); - logger.debug("First {} : {}", AccountingPersistenceBackend.class.getSimpleName(), first); + AccountingPersistenceBackendFactory.getPersistenceBackend(); + Long firstCheck = AccountingPersistenceBackendFactory.fallbackLastCheck.get(ScopeProvider.instance.get()); + logger.debug("First Check Time {}", firstCheck); long startTime = Calendar.getInstance().getTimeInMillis(); long endTime = startTime; @@ -113,10 +114,11 @@ public class AccountingPersistenceBackendTest { endTime = Calendar.getInstance().getTimeInMillis(); } - AccountingPersistenceBackend second = AccountingPersistenceBackendFactory.getPersistenceBackend(); - logger.debug("Second {} : {}", AccountingPersistenceBackend.class.getSimpleName(), second); + AccountingPersistenceBackendFactory.getPersistenceBackend(); + Long secondCheck = AccountingPersistenceBackendFactory.fallbackLastCheck.get(ScopeProvider.instance.get()); + logger.debug("Second Check Time {}", secondCheck); - Assert.assertNotEquals(first, second); + Assert.assertNotEquals(firstCheck, secondCheck); } }