killbill-developers
Changes
account/pom.xml 50(+0 -50)
account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java 14(+10 -4)
account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java 16(+12 -4)
api/pom.xml 50(+0 -50)
catalog/pom.xml 46(+0 -46)
docker-compose.yml 10(+2 -8)
entitlement/pom.xml 50(+0 -50)
entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java 6(+4 -2)
invoice/pom.xml 50(+0 -50)
jaxrs/pom.xml 50(+0 -50)
junction/pom.xml 50(+0 -50)
overdue/pom.xml 46(+0 -46)
overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java 38(+22 -16)
payment/pom.xml 50(+0 -50)
payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java 77(+42 -35)
pom.xml 4(+2 -2)
profiles/killbill/pom.xml 46(+0 -46)
profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java 23(+17 -6)
profiles/killpay/pom.xml 46(+0 -46)
subscription/pom.xml 50(+0 -50)
subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java 14(+9 -5)
subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java 9(+8 -1)
tenant/pom.xml 50(+0 -50)
util/pom.xml 51(+5 -46)
Details
account/pom.xml 50(+0 -50)
diff --git a/account/pom.xml b/account/pom.xml
index f9f6da0..eec798b 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -191,54 +191,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
diff --git a/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java b/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java
index e6d0a05..5a21243 100644
--- a/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java
+++ b/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultAccountInternalApi.java
@@ -53,6 +53,9 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultAccountInternalApi extends DefaultAccountApiBase implements AccountInternalApi {
private final ImmutableAccountInternalApi immutableAccountInternalApi;
@@ -98,8 +101,8 @@ public class DefaultAccountInternalApi extends DefaultAccountApiBase implements
final MutableAccountData mutableAccountData = currentAccount.toMutableAccountData();
mutableAccountData.setBillCycleDayLocal(bcd);
final AccountModelDao accountToUpdate = new AccountModelDao(currentAccount.getId(), mutableAccountData);
- // bcdCacheController.remove(currentAccount.getId());
- // bcdCacheController.putIfAbsent(currentAccount.getId(), new Integer(bcd));
+ CacheControllerDispatcher.bcdCacheController.invalidate(currentAccount.getId());
+ CacheControllerDispatcher.bcdCacheController.put(currentAccount.getId(), new Integer(bcd));
accountDao.update(accountToUpdate, true, context);
}
@@ -108,8 +111,11 @@ public class DefaultAccountInternalApi extends DefaultAccountApiBase implements
// final CacheLoaderArgument arg = createBCDCacheLoaderArgument(context);
Preconditions.checkNotNull(context.getAccountRecordId(), "Context missing accountRecordId");
final ImmutableAccountData account = immutableAccountInternalApi.getImmutableAccountDataByRecordId(context.getAccountRecordId(), context);
- // final Integer result = bcdCacheController.get(account.getId(), arg);
- final Integer result = accountDao.getAccountBCD(account.getId(), context);
+ Integer result = null;
+ try {
+ result = CacheControllerDispatcher.bcdCacheController.get(account.getId());
+ } catch (KeyNotFoundException ex) {
+ }
return result != null ? result : DefaultMutableAccountData.DEFAULT_BILLING_CYCLE_DAY_LOCAL;
}
diff --git a/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java b/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java
index 6adb006..4dded2e 100644
--- a/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java
+++ b/account/src/main/java/org/killbill/billing/account/api/svcs/DefaultImmutableAccountInternalApi.java
@@ -48,12 +48,14 @@ import com.google.inject.Inject;
import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
public class DefaultImmutableAccountInternalApi implements ImmutableAccountInternalApi {
private final EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao;
private final NonEntityDao nonEntityDao;
// private final CacheController<Long, ImmutableAccountData> accountCacheController;
- // private final CacheController<String, Long> recordIdCacheController;
+ // private final CacheController<String, Long> CacheControllerDispatcher.recordIdCacheController;
@Inject
public DefaultImmutableAccountInternalApi(final IDBI dbi,
@@ -66,21 +68,27 @@ public class DefaultImmutableAccountInternalApi implements ImmutableAccountInter
nonEntityDao, null);
this.nonEntityDao = nonEntityDao;
// this.accountCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_IMMUTABLE);
- // this.recordIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID);
+ // this.CacheControllerDispatcher.recordIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID);
}
@Override
public ImmutableAccountData getImmutableAccountDataById(final UUID accountId, final InternalTenantContext context) throws AccountApiException {
- final Long recordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, null);
+ final Long recordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, CacheControllerDispatcher.recordIdCacheController);
return getImmutableAccountDataByRecordId(recordId, context);
}
@Override
- public ImmutableAccountData getImmutableAccountDataByRecordId(final Long recordId, final InternalTenantContext context) throws AccountApiException {
+ public ImmutableAccountData getImmutableAccountDataByRecordId(final Long recordId, final InternalTenantContext context) {//throws AccountApiException {
+return CacheControllerDispatcher.accountImmutableCacheController.computeIfAbsent(recordId, () -> {
// final CacheLoaderArgument arg = createImmutableAccountCacheLoaderArgument(context);
// return accountCacheController.get(recordId, arg);
+ try {
final Account account = getAccountByRecordIdInternal(recordId, context);
return account != null ? new DefaultImmutableAccountData(account) : null;
+ } catch (Exception ex){
+ throw new RuntimeException(ex);
+ }
+}, 20000);
}
// private CacheLoaderArgument createImmutableAccountCacheLoaderArgument(final InternalTenantContext context) {
diff --git a/account/src/main/java/org/killbill/billing/account/api/user/DefaultAccountApiBase.java b/account/src/main/java/org/killbill/billing/account/api/user/DefaultAccountApiBase.java
index 881d737..fd9c3f4 100644
--- a/account/src/main/java/org/killbill/billing/account/api/user/DefaultAccountApiBase.java
+++ b/account/src/main/java/org/killbill/billing/account/api/user/DefaultAccountApiBase.java
@@ -34,9 +34,12 @@ import org.killbill.billing.callcontext.InternalTenantContext;
// import org.killbill.billing.util.cache.CacheControllerDispatcher;
import org.killbill.billing.util.dao.NonEntityDao;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
public class DefaultAccountApiBase {
private final AccountDao accountDao;
+
// private final CacheController<Long, ImmutableAccountData> accountCacheController;
// private final CacheController<String, Long> recordIdCacheController;
private final NonEntityDao nonEntityDao;
@@ -50,12 +53,12 @@ public class DefaultAccountApiBase {
}
protected Account getAccountById(final UUID accountId, final InternalTenantContext context) throws AccountApiException {
- final Long recordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, null);
+ final Long recordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, CacheControllerDispatcher.recordIdCacheController);
final Account account = getAccountByRecordIdInternal(recordId, context);
if (account == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, accountId);
}
- // accountCacheController.putIfAbsent(recordId, new DefaultImmutableAccountData(account));
+ CacheControllerDispatcher.accountCacheController.put(recordId, new DefaultImmutableAccountData(account));
return account;
}
@@ -65,8 +68,8 @@ public class DefaultAccountApiBase {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_KEY, key);
}
final Account account = new DefaultAccount(accountModelDao);
- final Long recordId = nonEntityDao.retrieveRecordIdFromObject(account.getId(), ObjectType.ACCOUNT, null);
- // accountCacheController.putIfAbsent(recordId, new DefaultImmutableAccountData(account));
+ final Long recordId = nonEntityDao.retrieveRecordIdFromObject(account.getId(), ObjectType.ACCOUNT, CacheControllerDispatcher.recordIdCacheController);
+ CacheControllerDispatcher.accountCacheController.put(recordId, new DefaultImmutableAccountData(account));
return account;
}
diff --git a/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java b/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
index 1ab81f5..715f5fd 100644
--- a/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
+++ b/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
@@ -68,6 +68,8 @@ import com.google.inject.Inject;
import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
public class DefaultAccountDao extends EntityDaoBase<AccountModelDao, Account, AccountApiException> implements AccountDao {
private static final Logger log = LoggerFactory.getLogger(DefaultAccountDao.class);
@@ -105,7 +107,7 @@ public class DefaultAccountDao extends EntityDaoBase<AccountModelDao, Account, A
// Populate the caches only after the transaction has been committed, in case of rollbacks
// transactionalSqlDao.populateCaches(refreshedEntity);
// Eagerly populate the account-immutable cache as well
- // accountImmutableCacheController.putIfAbsent(refreshedEntity.getRecordId(), new DefaultImmutableAccountData(refreshedEntity));
+ CacheControllerDispatcher.accountImmutableCacheController.put(refreshedEntity.getRecordId(), new DefaultImmutableAccountData(refreshedEntity));
}
@Override
api/pom.xml 50(+0 -50)
diff --git a/api/pom.xml b/api/pom.xml
index a4164e5..af00cce 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -65,54 +65,4 @@
<artifactId>config-magic</artifactId>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
catalog/pom.xml 46(+0 -46)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index 335e287..2b1772c 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -188,52 +188,6 @@
<build>
<plugins>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultCatalogCache.java b/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultCatalogCache.java
index c895dcc..ba54bf7 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultCatalogCache.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultCatalogCache.java
@@ -52,10 +52,14 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultCatalogCache implements CatalogCache {
private final Logger logger = LoggerFactory.getLogger(DefaultCatalogCache.class);
+public static MultiCache<Long, DefaultVersionedCatalog> cacheController = new MultiCache<>("DefaultCatalogCache.cacheController");
+
// private final CacheController<Long, DefaultVersionedCatalog> cacheController;
private final VersionedCatalogLoader loader;
// private final CacheLoaderArgument cacheLoaderArgumentWithTemplateFiltering;
@@ -116,8 +120,10 @@ public class DefaultCatalogCache implements CatalogCache {
// The cache loader might choke on some bad xml -- unlikely since we check its validity prior storing it,
// but to be on the safe side;;
try {
- DefaultVersionedCatalog tenantCatalog = null; // cacheController.get(tenantContext.getTenantRecordId(),
- // filterTemplateCatalog ? cacheLoaderArgumentWithTemplateFiltering : cacheLoaderArgument);
+ DefaultVersionedCatalog tenantCatalog = null;
+ try {
+ tenantCatalog = cacheController.get(tenantContext.getTenantRecordId());
+ } catch (KeyNotFoundException ex) {}
// It means we are using a default catalog in a multi-tenant deployment, that does not really match a real use case, but we want to support it
// for test purpose.
if (useDefaultCatalog && tenantCatalog == null) {
@@ -126,7 +132,7 @@ public class DefaultCatalogCache implements CatalogCache {
final StandaloneCatalogWithPriceOverride curWithOverride = new StandaloneCatalogWithPriceOverride(cur, priceOverride, tenantContext.getTenantRecordId(), internalCallContextFactory);
tenantCatalog.add(curWithOverride);
}
- // cacheController.putIfAbsent(tenantContext.getTenantRecordId(), tenantCatalog);
+ cacheController.put(tenantContext.getTenantRecordId(), tenantCatalog);
}
if (tenantCatalog != null) {
@@ -141,9 +147,9 @@ public class DefaultCatalogCache implements CatalogCache {
@Override
public void clearCatalog(final InternalTenantContext tenantContext) {
- // if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId())) {
- // cacheController.remove(tenantContext.getTenantRecordId());
- // }
+ if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId())) {
+ cacheController.invalidate(tenantContext.getTenantRecordId());
+ }
}
private DefaultVersionedCatalog getCatalogFromPlugins(final InternalTenantContext internalTenantContext) throws CatalogApiException {
@@ -163,14 +169,17 @@ public class DefaultCatalogCache implements CatalogCache {
// A null latestCatalogUpdatedDate bypasses caching, by fetching full catalog from plugin below (compatibility mode with 0.18.x or non optimized plugin api mode)
// final boolean cacheable = latestCatalogUpdatedDate != null;
// if (cacheable) {
- // final DefaultVersionedCatalog tenantCatalog = cacheController.get(internalTenantContext.getTenantRecordId(), cacheLoaderArgument);
- // if (tenantCatalog != null) {
- // initializeCatalog(tenantCatalog);
- // if (tenantCatalog.getEffectiveDate().compareTo(latestCatalogUpdatedDate.toDate()) == 0) {
+ DefaultVersionedCatalog tenantCatalog = null;
+ try {
+ tenantCatalog = cacheController.get(internalTenantContext.getTenantRecordId());
+ } catch (KeyNotFoundException ex){}
+ if (tenantCatalog != null) {
+ initializeCatalog(tenantCatalog);
+ if (tenantCatalog.getEffectiveDate().compareTo(latestCatalogUpdatedDate.toDate()) == 0) {
// // Current cached version matches the one from the plugin
- // return tenantCatalog;
- // }
- // }
+ return tenantCatalog;
+ }
+ }
// }
final VersionedPluginCatalog pluginCatalog = plugin.getVersionedPluginCatalog(ImmutableList.<PluginProperty>of(), tenantContext);
@@ -184,9 +193,9 @@ public class DefaultCatalogCache implements CatalogCache {
final DefaultVersionedCatalog resolvedPluginCatalog = versionedCatalogMapper.toVersionedCatalog(pluginCatalog, internalTenantContext);
// Always clear the cache for safety
- // cacheController.remove(internalTenantContext.getTenantRecordId());
+ cacheController.invalidate(internalTenantContext.getTenantRecordId());
// if (cacheable) {
- // cacheController.putIfAbsent(internalTenantContext.getTenantRecordId(), resolvedPluginCatalog);
+ cacheController.put(internalTenantContext.getTenantRecordId(), resolvedPluginCatalog);
// }
return resolvedPluginCatalog;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java b/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java
index f75deb6..9888f3c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java
@@ -56,11 +56,15 @@ import org.killbill.billing.catalog.override.DefaultPriceOverride;
// import org.killbill.billing.util.cache.CacheLoaderArgument;
// import org.killbill.billing.util.cache.OverriddenPlanCacheLoader.LoaderCallback;
+import br.ufrgs.inf.prosoft.cache.*;
+
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
public class DefaultOverriddenPlanCache implements OverriddenPlanCache {
+public static MultiCache<String, Plan> cacheController = new MultiCache<>("DefaultOverriddenPlanCache.cacheController");
+
// private final CacheController<String, Plan> cacheController;
// private final LoaderCallback loaderCallback;
private final CatalogOverrideDao overrideDao;
@@ -86,6 +90,7 @@ public class DefaultOverriddenPlanCache implements OverriddenPlanCache {
// final CacheLoaderArgument argument = new CacheLoaderArgument(irrelevant, args, context);
// final DefaultPlan defaultPlan = (DefaultPlan) cacheController.get(planName, argument);
+return (DefaultPlan) cacheController.computeIfAbsent(planName, () -> {
DefaultPlan defaultPlan = null;
try {
defaultPlan = (DefaultPlan) loadOverriddenPlan(planName, (StandaloneCatalog) catalog, context);
@@ -93,11 +98,12 @@ public class DefaultOverriddenPlanCache implements OverriddenPlanCache {
} catch(CatalogApiException ex){
}
return defaultPlan;
+}, 20000);
}
@Override
public void addDryRunPlan(final String planName, final Plan plan) {
- // cacheController.putIfAbsent(planName, plan);
+ cacheController.put(planName, plan);
}
private DefaultPlan loadOverriddenPlan(final String planName, final StandaloneCatalog catalog, final InternalTenantContext context) throws CatalogApiException {
docker-compose.yml 10(+2 -8)
diff --git a/docker-compose.yml b/docker-compose.yml
index cba3982..8ed42e3 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -17,14 +17,8 @@ services:
- KILLBILL_DAO_USER=root
- KILLBILL_DAO_PASSWORD=killbill
- JAVA_OPTS=${JAVA_OPTS:-"-Xms4096m -Xmx6124m"}
- - TRACER_ENABLE=${TRACER_ENABLE:-true}
- - TRACER_MINIMUM_EXECUTION_TIME=${TRACER_MINIMUM_EXECUTION_TIME:-1}
- - TRACER_SERIALISE_INTERNALS=false
- - TRACER_VERBOSE=true
- - TRACER_TRACES=/caching-approaches-comparison/applications/traces/killbill
- - TRACER_IGNORED_PACKAGES=/caching-approaches-comparison/applications/uncached/killbill/ignored
- - TRACER_WHITELIST=/caching-approaches-comparison/applications/uncached/killbill/whitelist
- - TRACER_LOG=/caching-approaches-comparison/applications/output/killbill-tracer.log
+ - CACHE_EVENTS=${CACHE_EVENTS:-/caching-approaches-comparison/applications/output/killbill-developers-cache}
+ - CACHE_REGISTER_SIZE=false
volumes:
- application:/application
- /root/.m2:/root/.m2
entitlement/pom.xml 50(+0 -50)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index bc36b0d..fce0269 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -214,54 +214,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
index bb26552..9eb3648 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
@@ -78,6 +78,8 @@ import com.google.common.collect.Ordering;
import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
public class DefaultBlockingStateDao extends EntityDaoBase<BlockingStateModelDao, BlockingState, EntitlementApiException> implements BlockingStateDao {
private static final Logger log = LoggerFactory.getLogger(DefaultBlockingStateDao.class);
@@ -279,13 +281,13 @@ public class DefaultBlockingStateDao extends EntityDaoBase<BlockingStateModelDao
final List<BlockingState> bundleBlockingStates;
final List<BlockingState> subscriptionBlockingStates;
if (type == BlockingStateType.SUBSCRIPTION) {
- final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, null, handle);
+ final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController, handle);
final List<BlockingState> allBlockingStatesForAccount = getBlockingAllUpToForAccountRecordId(sqlDao, upToDate, context);
accountBlockingStates = filterBlockingStates(allBlockingStatesForAccount, accountId, BlockingStateType.ACCOUNT);
bundleBlockingStates = filterBlockingStates(allBlockingStatesForAccount, bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE);
subscriptionBlockingStates = filterBlockingStates(allBlockingStatesForAccount, blockableId, BlockingStateType.SUBSCRIPTION);
} else if (type == BlockingStateType.SUBSCRIPTION_BUNDLE) {
- final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, null, handle);
+ final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController, handle);
final List<BlockingState> allBlockingStatesForAccount = getBlockingAllUpToForAccountRecordId(sqlDao, upToDate, context);
accountBlockingStates = filterBlockingStates(allBlockingStatesForAccount, accountId, BlockingStateType.ACCOUNT);
bundleBlockingStates = filterBlockingStates(allBlockingStatesForAccount, blockableId, BlockingStateType.SUBSCRIPTION_BUNDLE);
invoice/pom.xml 50(+0 -50)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index 37e9f4d..45a3262 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -232,54 +232,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
jaxrs/pom.xml 50(+0 -50)
diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index e3bc326..4a269ca 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -201,54 +201,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
index 72d84a6..db60e6d 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
@@ -104,6 +104,8 @@ import io.swagger.annotations.ApiResponses;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
@Singleton
@Path(JaxrsResource.ADMIN_PATH)
@Api(value = JaxrsResource.ADMIN_PATH, description = "Admin operations (will require special privileges)", tags="Admin")
@@ -361,15 +363,15 @@ public class AdminResource extends JaxRsResourceBase {
// clear account-record-id cache by accountId (note: String!)
// final CacheController<String, Long> accountRecordIdCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_RECORD_ID);
- // accountRecordIdCacheController.remove(accountId.toString());
+ CacheControllerDispatcher.accountRecordIdCacheController.invalidate(accountId.toString());
// clear account-immutable cache by account record id
// final CacheController<Long, ImmutableAccountData> accountImmutableCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_IMMUTABLE);
- // accountImmutableCacheController.remove(accountRecordId);
+ CacheControllerDispatcher.accountImmutableCacheController.invalidate(accountRecordId);
// clear account-bcd cache by accountId (note: UUID!)
// final CacheController<UUID, Integer> accountBCDCacheController = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_BCD);
- // accountBCDCacheController.remove(accountId);
+ CacheControllerDispatcher.bcdCacheController.invalidate(accountId);
return Response.status(Status.NO_CONTENT).build();
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
index 4ab1e3d..2d442dc 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -117,6 +117,8 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import br.ufrgs.inf.prosoft.cache.*;
+
public abstract class JaxRsResourceBase implements JaxrsResource {
static final Logger log = LoggerFactory.getLogger(JaxRsResourceBase.class);
@@ -201,14 +203,18 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
protected Response createTagResponse(final UUID accountId, final List<Tag> tags, final AuditMode auditMode, final TenantContext context) throws TagDefinitionApiException {
final AccountAuditLogsForObjectType tagsAuditLogs = auditUserApi.getAccountAuditLogs(accountId, ObjectType.TAG, auditMode.getLevel(), context);
+MultiCache<UUID, TagDefinition> createTagResponse = new MultiCache<>("JaxRsResourceBase.createTagResponse");
+
// final Map<UUID, TagDefinition> tagDefinitionsCache = new HashMap<UUID, TagDefinition>();
final Collection<TagJson> result = new LinkedList<TagJson>();
for (final Tag tag : tags) {
- // if (tagDefinitionsCache.get(tag.getTagDefinitionId()) == null) {
- // tagDefinitionsCache.put(tag.getTagDefinitionId(), tagUserApi.getTagDefinition(tag.getTagDefinitionId(), context));
- // }
- // final TagDefinition tagDefinition = tagDefinitionsCache.get(tag.getTagDefinitionId());
- final TagDefinition tagDefinition = tagUserApi.getTagDefinition(tag.getTagDefinitionId(), context);
+ if (!createTagResponse.containsKey(tag.getTagDefinitionId())) {
+ createTagResponse.put(tag.getTagDefinitionId(), tagUserApi.getTagDefinition(tag.getTagDefinitionId(), context));
+ }
+ TagDefinition tagDefinition = null;
+ try {
+ tagDefinition = createTagResponse.get(tag.getTagDefinitionId());
+ } catch (KeyNotFoundException ex){}
final List<AuditLog> auditLogs = tagsAuditLogs.getAuditLogs(tag.getId());
result.add(new TagJson(tag, tagDefinition, auditLogs));
junction/pom.xml 50(+0 -50)
diff --git a/junction/pom.xml b/junction/pom.xml
index afeb9d9..134d3d7 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -206,54 +206,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
overdue/pom.xml 46(+0 -46)
diff --git a/overdue/pom.xml b/overdue/pom.xml
index d343e45..445b503 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -206,52 +206,6 @@
<build>
<plugins>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java b/overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java
index 8da8069..f4d4b7d 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/caching/DefaultOverdueConfigCache.java
@@ -42,10 +42,14 @@ import org.slf4j.LoggerFactory;
import org.killbill.billing.tenant.api.TenantInternalApi;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultOverdueConfigCache implements OverdueConfigCache {
private static final Logger log = LoggerFactory.getLogger(DefaultOverdueConfigCache.class);
+public static MultiCache<Long, OverdueConfig> cacheController = new MultiCache<>("DefaultOverdueConfig.cacheController");
+
// private final CacheController<Long, OverdueConfig> cacheController;
// private final CacheLoaderArgument cacheLoaderArgument;
@@ -103,19 +107,21 @@ public class DefaultOverdueConfigCache implements OverdueConfigCache {
// The cache loader might choke on some bad xml -- unlikely since we check its validity prior storing it,
// but to be on the safe side;;
try {
- final OverdueConfig overdueConfig;// = cacheController.get(tenantContext.getTenantRecordId(), cacheLoaderArgument);
-
- final String overdueXML = tenantApi.getTenantOverdueConfig(tenantContext);
- if (overdueXML == null) {
- throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ");
- }
-
- final InputStream overdueConfigStream = new ByteArrayInputStream(overdueXML.getBytes());
- try {
- overdueConfig = XMLLoader.getObjectFromStream(overdueConfigStream, DefaultOverdueConfig.class);
- } catch (final Exception e) {
- throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ", e);
- }
+ final OverdueConfig overdueConfig = cacheController.computeIfAbsent(tenantContext.getTenantRecordId(), () -> {
+ final String overdueXML = tenantApi.getTenantOverdueConfig(tenantContext);
+ if (overdueXML == null) {
+ // throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ");
+ throw new RuntimeException();
+ }
+
+ final InputStream overdueConfigStream = new ByteArrayInputStream(overdueXML.getBytes());
+ try {
+ return XMLLoader.getObjectFromStream(overdueConfigStream, DefaultOverdueConfig.class);
+ } catch (final Exception e) {
+ // throw new OverdueApiException(ErrorCode.OVERDUE_INVALID_FOR_TENANT, "Problem encountered loading overdue config ", e);
+ throw new RuntimeException(e);
+ }
+ });
return (overdueConfig != null) ? overdueConfig : defaultOverdueConfig;
} catch (final IllegalStateException e) {
@@ -125,9 +131,9 @@ public class DefaultOverdueConfigCache implements OverdueConfigCache {
@Override
public void clearOverdueConfig(final InternalTenantContext tenantContext) {
- // if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId())) {
- // cacheController.remove(tenantContext.getTenantRecordId());
- // }
+ if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId())) {
+ cacheController.invalidate(tenantContext.getTenantRecordId());
+ }
}
// private CacheLoaderArgument initializeCacheLoaderArgument() {
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java b/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
index 35e5f2e..5ac4a63 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/listener/OverdueListener.java
@@ -61,6 +61,9 @@ import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Inject;
+import org.killbill.billing.util.cache.*;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
public class OverdueListener {
private static final Logger log = LoggerFactory.getLogger(OverdueListener.class);
@@ -97,7 +100,7 @@ public class OverdueListener {
final InternalCallContext internalCallContext = createCallContext(event.getUserToken(), event.getSearchKey1(), event.getSearchKey2());
insertBusEventIntoNotificationQueue(event.getObjectId(), OverdueAsyncBusNotificationAction.CLEAR, internalCallContext);
} else if (event.getTagDefinition().getName().equals(ControlTagType.WRITTEN_OFF.toString()) && event.getObjectType() == ObjectType.INVOICE) {
- final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, null);
+ final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController);
insertBusEventIntoNotificationQueue(accountId, event);
}
}
@@ -108,7 +111,7 @@ public class OverdueListener {
if (event.getTagDefinition().getName().equals(ControlTagType.OVERDUE_ENFORCEMENT_OFF.toString()) && event.getObjectType() == ObjectType.ACCOUNT) {
insertBusEventIntoNotificationQueue(event.getObjectId(), event);
} else if (event.getTagDefinition().getName().equals(ControlTagType.WRITTEN_OFF.toString()) && event.getObjectType() == ObjectType.INVOICE) {
- final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, null);
+ final UUID accountId = nonEntityDao.retrieveIdFromObject(event.getSearchKey1(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController);
insertBusEventIntoNotificationQueue(accountId, event);
}
}
payment/pom.xml 50(+0 -50)
diff --git a/payment/pom.xml b/payment/pom.xml
index 4e8f48d..1277f2c 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -249,54 +249,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
diff --git a/payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java b/payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java
index 12e47c9..0215d08 100644
--- a/payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java
+++ b/payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java
@@ -35,7 +35,7 @@ import org.killbill.billing.tenant.api.TenantInternalApi;
import org.killbill.billing.tenant.api.TenantKV.TenantKey;
// import org.killbill.billing.util.cache.Cachable.CacheType;
// import org.killbill.billing.util.cache.CacheController;
-// import org.killbill.billing.util.cache.CacheControllerDispatcher;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
// import org.killbill.billing.util.cache.CacheLoaderArgument;
// import org.killbill.billing.util.cache.TenantStateMachineConfigCacheLoader.LoaderCallback;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
@@ -45,10 +45,14 @@ import org.slf4j.LoggerFactory;
import com.google.common.io.Resources;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultStateMachineConfigCache implements StateMachineConfigCache {
private static final Logger logger = LoggerFactory.getLogger(DefaultStateMachineConfigCache.class);
+public static MultiCache<String, StateMachineConfig> cacheController = new MultiCache<>("DefaultStateMachineConfigCache.cacheController");
+
// private final CacheController<String, StateMachineConfig> cacheController;
// private final LoaderCallback loaderCallback;
@@ -97,62 +101,65 @@ public class DefaultStateMachineConfigCache implements StateMachineConfigCache {
return defaultPaymentStateMachineConfig;
}
- // final String pluginConfigKey = getCacheKeyName(pluginName, tenantContext);
+ final String pluginConfigKey = getCacheKeyName(pluginName, tenantContext);
// final CacheLoaderArgument cacheLoaderArgument = createCacheLoaderArgument(pluginName);
- try {
- StateMachineConfig pluginPaymentStateMachineConfig = null;// = cacheController.get(pluginConfigKey, cacheLoaderArgument);
-
-final String tenantRecordId = String.valueOf(tenantContext.getTenantRecordId());
-final InternalTenantContext internalTenantContext = new InternalTenantContext(Long.valueOf(tenantRecordId));
-final String stateMachineConfigXML = tenantApi.getPluginPaymentStateMachineConfig(pluginName, internalTenantContext);
-try {
-if (stateMachineConfigXML == null) {
- throw new Exception();
-}
+return cacheController.computeIfAbsent(pluginConfigKey, () -> {
+ try {
+ final String tenantRecordId = String.valueOf(tenantContext.getTenantRecordId());
- logger.info("Loading config state machine cache for pluginName='{}', tenantRecordId='{}'", pluginName, tenantContext.getTenantRecordId());
- final InputStream stream = new ByteArrayInputStream(stateMachineConfigXML.getBytes());
- pluginPaymentStateMachineConfig = XMLLoader.getObjectFromStream(stream, DefaultStateMachineConfig.class);
-// } catch (final PaymentApiException e) {
-// throw new IllegalStateException(String.format("Failed to de-serialize state machine config for tenantRecordId='%s'", internalTenantContext.getTenantRecordId()), e);
-// }
- } catch (final Exception e) {
- // TODO 0.17 proper error code
- throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine config");
- }
+ final InternalTenantContext internalTenantContext = new InternalTenantContext(Long.valueOf(tenantRecordId));
+ final String stateMachineConfigXML = tenantApi.getPluginPaymentStateMachineConfig(pluginName, internalTenantContext);
+
+ if (stateMachineConfigXML == null) {
+ throw new RuntimeException();
+ }
+ StateMachineConfig pluginPaymentStateMachineConfig = null;
+ try {
+ logger.info("Loading config state machine cache for pluginName='{}', tenantRecordId='{}'", pluginName, tenantContext.getTenantRecordId());
+ final InputStream stream = new ByteArrayInputStream(stateMachineConfigXML.getBytes());
+ pluginPaymentStateMachineConfig = XMLLoader.getObjectFromStream(stream, DefaultStateMachineConfig.class);
+ // } catch (final PaymentApiException e) {
+ // throw new IllegalStateException(String.format("Failed to de-serialize state machine config for tenantRecordId='%s'", internalTenantContext.getTenantRecordId()), e);
+ // }
+ } catch (final Exception e) {
+ // TODO 0.17 proper error code
+ // throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine config");
+ throw new RuntimeException(e);
+ }
// It means we are using the default state machine config in a multi-tenant deployment
if (pluginPaymentStateMachineConfig == null) {
pluginPaymentStateMachineConfig = defaultPaymentStateMachineConfig;
- // cacheController.putIfAbsent(pluginConfigKey, pluginPaymentStateMachineConfig);
}
((DefaultStateMachineConfig)pluginPaymentStateMachineConfig).initialize(defaultPaymentStateMachineConfig);
return pluginPaymentStateMachineConfig;
} catch (final IllegalStateException e) {
// TODO 0.17 proper error code
- throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine");
+ // throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, "Invalid payment state machine");
+ throw new RuntimeException(e);
}
+});
}
// See also DefaultTenantUserApi - we use the same conventions as the main XML cache (so we can re-use the invalidation code)
- // private String getCacheKeyName(final String pluginName, final InternalTenantContext internalContext) {
- // final StringBuilder tenantKey = new StringBuilder(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_.toString());
- // tenantKey.append(pluginName);
- // tenantKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
- // tenantKey.append(internalContext.getTenantRecordId());
- // return tenantKey.toString();
- // }
+ private String getCacheKeyName(final String pluginName, final InternalTenantContext internalContext) {
+ final StringBuilder tenantKey = new StringBuilder(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_.toString());
+ tenantKey.append(pluginName);
+ tenantKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
+ tenantKey.append(internalContext.getTenantRecordId());
+ return tenantKey.toString();
+ }
@Override
public void clearPaymentStateMachineConfig(final String pluginName, final InternalTenantContext tenantContext) {
- // if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId()) && cacheController != null) {
- // final String key = getCacheKeyName(pluginName, tenantContext);
- // cacheController.remove(key);
- // }
+ if (!InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(tenantContext.getTenantRecordId()) && cacheController != null) {
+ final String key = getCacheKeyName(pluginName, tenantContext);
+ cacheController.invalidate(key);
+ }
}
// private CacheLoaderArgument createCacheLoaderArgument(final String pluginName) {
pom.xml 4(+2 -2)
diff --git a/pom.xml b/pom.xml
index 036d73e..7068082 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,8 +49,8 @@
</modules>
<dependencies>
<dependency>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
+ <groupId>br.ufrgs.inf.prosoft.cache</groupId>
+ <artifactId>Cache</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
profiles/killbill/pom.xml 46(+0 -46)
diff --git a/profiles/killbill/pom.xml b/profiles/killbill/pom.xml
index e58a90c..5ac48b3 100644
--- a/profiles/killbill/pom.xml
+++ b/profiles/killbill/pom.xml
@@ -471,52 +471,6 @@
</resources>
<plugins>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java b/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
index 2e40851..5cf6470 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
@@ -36,6 +36,8 @@ import org.apache.shiro.util.ByteSource;
import org.killbill.billing.util.config.definition.SecurityConfig;
import org.killbill.billing.util.security.shiro.KillbillCredentialsMatcher;
+import br.ufrgs.inf.prosoft.cache.*;
+
/**
* @see {shiro.ini}
*/
@@ -92,8 +94,11 @@ public class KillbillJdbcTenantRealm extends JdbcRealm {
private static final long serialVersionUID = 4498655519894503985L;
private byte[] bytes;
- private String cachedHex;
- private String cachedBase64;
+ // private String cachedHex;
+ // private String cachedBase64;
+private GetterCache<String> cachedHex = new GetterCache<>("KillbillJdbcTenantRealm.cachedHex");
+private GetterCache<String> cachedBase64 = new GetterCache<>("KillbillJdbcTenantRealm.cachedBase64");
+
// For deserialization
public SerializableSimpleByteSource() {}
@@ -109,18 +114,24 @@ public class KillbillJdbcTenantRealm extends JdbcRealm {
@Override
public String toHex() {
+ return cachedHex.computeIfAbsent(() -> {
// if (this.cachedHex == null) {
- this.cachedHex = Hex.encodeToString(getBytes());
+ // this.cachedHex = Hex.encodeToString(getBytes());
+ return Hex.encodeToString(getBytes());
// }
- return this.cachedHex;
+ // return this.cachedHex;
+ });
}
@Override
public String toBase64() {
+ return cachedBase64.computeIfAbsent(() -> {
// if (this.cachedBase64 == null) {
- this.cachedBase64 = Base64.encodeToString(getBytes());
+ // this.cachedBase64 = Base64.encodeToString(getBytes());
+ return Base64.encodeToString(getBytes());
// }
- return this.cachedBase64;
+ // return this.cachedBase64;
+ });
}
@Override
profiles/killpay/pom.xml 46(+0 -46)
diff --git a/profiles/killpay/pom.xml b/profiles/killpay/pom.xml
index fab2ff6..2b4cdda 100644
--- a/profiles/killpay/pom.xml
+++ b/profiles/killpay/pom.xml
@@ -190,52 +190,6 @@
<build>
<plugins>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
subscription/pom.xml 50(+0 -50)
diff --git a/subscription/pom.xml b/subscription/pom.xml
index d46a8d6..f6ed771 100644
--- a/subscription/pom.xml
+++ b/subscription/pom.xml
@@ -202,54 +202,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
index 5e2441d..c543078 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
@@ -60,6 +60,8 @@ import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class SubscriptionApiBase {
protected final SubscriptionDao dao;
@@ -259,6 +261,9 @@ public class SubscriptionApiBase {
}
}
+
+public static MultiCache<UUID, UUID> accountIdCacheController = new MultiCache<>("SubscriptionApiBase.accountIdCacheController");
+
protected SubscriptionBaseBundle createBundleForAccount(final UUID accountId,
final String bundleKey,
final boolean renameCancelledBundleIfExist,
@@ -272,7 +277,7 @@ public class SubscriptionApiBase {
}
final SubscriptionBaseBundle subscriptionBundle = dao.createSubscriptionBundle(bundle, catalog, renameCancelledBundleIfExist, context);
- // accountIdCacheController.putIfAbsent(bundle.getId(), accountId);
+ accountIdCacheController.put(bundle.getId(), accountId);
return subscriptionBundle;
}
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java
index 1d6a38e..39b8eb3 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionBaseCreateApi.java
@@ -57,10 +57,14 @@ import org.killbill.clock.Clock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultSubscriptionBaseCreateApi extends SubscriptionApiBase {
private static final Logger log = LoggerFactory.getLogger(DefaultSubscriptionBaseCreateApi.class);
+public static MultiCache<UUID, UUID> bundleIdCacheController = new MultiCache<>("DefaultSubscriptionBaseCreateApi.bundleIdCacheController");
+
DefaultSubscriptionBaseCreateApi(final SubscriptionDao dao, final SubscriptionBaseApiService apiService, final Clock clock) {
super(dao, apiService, clock);
}
@@ -93,11 +97,11 @@ public class DefaultSubscriptionBaseCreateApi extends SubscriptionApiBase {
callContext);
// Populate the caches
- // for (final SubscriptionBaseWithAddOns subscriptionBaseWithAO : subscriptionBaseWithAddOns) {
- // for (final SubscriptionBase subscriptionBase : subscriptionBaseWithAO.getSubscriptionBaseList()) {
- // bundleIdCacheController.putIfAbsent(subscriptionBase.getId(), subscriptionBaseWithAO.getBundle().getId());
- // }
- // }
+ for (final SubscriptionBaseWithAddOns subscriptionBaseWithAO : subscriptionBaseWithAddOns) {
+ for (final SubscriptionBase subscriptionBase : subscriptionBaseWithAO.getSubscriptionBaseList()) {
+ bundleIdCacheController.put(subscriptionBase.getId(), subscriptionBaseWithAO.getBundle().getId());
+ }
+ }
return subscriptionBaseWithAddOns;
}
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index db7324a..98e82fc 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -94,6 +94,9 @@ import com.google.inject.Inject;
import static org.killbill.billing.util.entity.dao.DefaultPaginationHelper.getEntityPaginationNoException;
+import br.ufrgs.inf.prosoft.cache.*;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
public class DefaultSubscriptionInternalApi extends DefaultSubscriptionBaseCreateApi implements SubscriptionBaseInternalApi {
private static final Logger log = LoggerFactory.getLogger(DefaultSubscriptionInternalApi.class);
@@ -458,6 +461,7 @@ public class DefaultSubscriptionInternalApi extends DefaultSubscriptionBaseCreat
public UUID getAccountIdFromBundleId(final UUID bundleId, final InternalTenantContext context) throws SubscriptionBaseApiException {
// final CacheLoaderArgument arg = createAccountIdFromBundleIdCacheLoaderArgument(context);
// return accountIdCacheController.get(bundleId, arg);
+ return CacheControllerDispatcher.accountIdCacheController.computeIfAbsent(bundleId, () -> {
final SubscriptionBaseBundle bundle;
try {
bundle = getBundleFromId(bundleId, context);
@@ -466,13 +470,16 @@ public class DefaultSubscriptionInternalApi extends DefaultSubscriptionBaseCreat
return null;
}
return bundle.getAccountId();
+ });
}
@Override
public UUID getBundleIdFromSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) throws SubscriptionBaseApiException {
// final CacheLoaderArgument arg = createBundleIdFromSubscriptionIdCacheLoaderArgument(context);
// return bundleIdCacheController.get(subscriptionId, arg);
- return dao.getBundleIdFromSubscriptionId(subscriptionId, context);
+ return CacheControllerDispatcher.bundleIdCacheController.computeIfAbsent(subscriptionId, () -> {
+ return dao.getBundleIdFromSubscriptionId(subscriptionId, context);
+ });
}
@Override
tenant/pom.xml 50(+0 -50)
diff --git a/tenant/pom.xml b/tenant/pom.xml
index 93eab11..46646cb 100644
--- a/tenant/pom.xml
+++ b/tenant/pom.xml
@@ -183,54 +183,4 @@
<scope>test</scope>
</dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
</project>
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
index d15a8ab..b393344 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
@@ -39,7 +39,7 @@ import org.killbill.billing.tenant.dao.TenantKVModelDao;
import org.killbill.billing.tenant.dao.TenantModelDao;
// import org.killbill.billing.util.cache.Cachable.CacheType;
// import org.killbill.billing.util.cache.CacheController;
-// import org.killbill.billing.util.cache.CacheControllerDispatcher;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
// import org.killbill.billing.util.cache.CacheLoaderArgument;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
@@ -52,6 +52,8 @@ import com.google.inject.Inject;
import org.killbill.billing.tenant.api.TenantInternalApi;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultTenantUserApi implements TenantUserApi {
//
@@ -62,18 +64,20 @@ public class DefaultTenantUserApi implements TenantUserApi {
//
// CACHED_TENANT_KEY is not exposed in the API and is hardcoded here since this is really a implementation choice.
//
- // public static final Iterable<TenantKey> CACHED_TENANT_KEY = ImmutableList.<TenantKey>builder()
- // .add(TenantKey.CATALOG_TRANSLATION_)
- // .add(TenantKey.INVOICE_MP_TEMPLATE)
- // .add(TenantKey.INVOICE_TEMPLATE)
- // .add(TenantKey.INVOICE_TRANSLATION_)
- // .add(TenantKey.PLUGIN_CONFIG_)
- // .add(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_)
- // .add(TenantKey.PUSH_NOTIFICATION_CB).build();
+ public static final Iterable<TenantKey> CACHED_TENANT_KEY = ImmutableList.<TenantKey>builder()
+ .add(TenantKey.CATALOG_TRANSLATION_)
+ .add(TenantKey.INVOICE_MP_TEMPLATE)
+ .add(TenantKey.INVOICE_TEMPLATE)
+ .add(TenantKey.INVOICE_TRANSLATION_)
+ .add(TenantKey.PLUGIN_CONFIG_)
+ .add(TenantKey.PLUGIN_PAYMENT_STATE_MACHINE_)
+ .add(TenantKey.PUSH_NOTIFICATION_CB).build();
private final TenantDao tenantDao;
private final InternalCallContextFactory internalCallContextFactory;
+public static MultiCache<String, List<String>> tenantKVCache = new MultiCache<>("DefaultTenantUserApi.tenantKVCache");
// private final CacheController<String, String> tenantKVCache;
+public static MultiCache<String, Tenant> tenantCache = new MultiCache<>("DefaultTenantUserApi.tenantCache");
// private final CacheController<String, Tenant> tenantCache;
private final TenantInternalApi tenantApi;
@@ -119,18 +123,21 @@ public class DefaultTenantUserApi implements TenantUserApi {
@Override
public Tenant getTenantByApiKey(final String key) throws TenantApiException {
- Tenant tenant = null; //tenantCache.get(key, new CacheLoaderArgument(ObjectType.TENANT));
-
- try {
- tenant = tenantApi.getTenantByApiKey(key);
- } catch (final TenantApiException e) {
- throw new IllegalStateException("TenantCacheLoader cannot find value for key " + key);
- }
+ return tenantCache.computeIfAbsent(key, () -> {
+ Tenant tenant = null;
+ try {
+ tenant = tenantApi.getTenantByApiKey(key);
+ } catch (final TenantApiException e) {
+ // throw new IllegalStateException("TenantCacheLoader cannot find value for key " + key);
+ throw new RuntimeException(e);
+ }
- if (tenant == null) {
- throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_API_KEY, key);
- }
- return tenant;
+ if (tenant == null) {
+ // throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_API_KEY, key);
+ throw new RuntimeException();
+ }
+ return tenant;
+ });
}
@Override
@@ -146,38 +153,38 @@ public class DefaultTenantUserApi implements TenantUserApi {
@Override
public List<String> getTenantValuesForKey(final String key, final TenantContext context) throws TenantApiException {
final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context);
- // if (!isCachedInTenantKVCache(key)) {
+ if (!isCachedInTenantKVCache(key)) {
return tenantDao.getTenantValueForKey(key, internalContext);
- // } else {
- // return getCachedTenantValuesForKey(key, internalContext);
- // }
+ } else {
+ return getCachedTenantValuesForKey(key, internalContext);
+ }
}
@Override
public void addTenantKeyValue(final String key, final String value, final CallContext context) throws TenantApiException {
// Invalidate tenantKVCache after we store (to avoid race conditions). Multi-node invalidation will follow the TenantBroadcast pattern
final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContextWithoutAccountRecordId(context);
- // final String tenantKey = getCacheKeyName(key, internalContext);
+ final String tenantKey = getCacheKeyName(key, internalContext);
tenantDao.addTenantKeyValue(key, value, isSingleValueKey(key), internalContext);
- // tenantKVCache.remove(tenantKey);
+ tenantKVCache.invalidate(tenantKey);
}
@Override
public void updateTenantKeyValue(final String key, final String value, final CallContext context) throws TenantApiException {
// Invalidate tenantKVCache after we store (to avoid race conditions). Multi-node invalidation will follow the TenantBroadcast pattern
final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContextWithoutAccountRecordId(context);
- // final String tenantKey = getCacheKeyName(key, internalContext);
+ final String tenantKey = getCacheKeyName(key, internalContext);
tenantDao.updateTenantLastKeyValue(key, value, internalContext);
- // tenantKVCache.remove(tenantKey);
+ tenantKVCache.invalidate(tenantKey);
}
@Override
public void deleteTenantKey(final String key, final CallContext context) throws TenantApiException {
// Invalidate tenantKVCache after we delete (to avoid race conditions). Multi-node invalidation will follow the TenantBroadcast pattern
final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContextWithoutAccountRecordId(context);
- // final String tenantKey = getCacheKeyName(key, internalContext);
+ final String tenantKey = getCacheKeyName(key, internalContext);
tenantDao.deleteTenantKey(key, internalContext);
- // tenantKVCache.remove(tenantKey);
+ tenantKVCache.invalidate(tenantKey);
}
@Override
@@ -195,23 +202,25 @@ public class DefaultTenantUserApi implements TenantUserApi {
}
- // private List<String> getCachedTenantValuesForKey(final String key, final InternalTenantContext internalContext) {
- // final String tenantKey = getCacheKeyName(key, internalContext);
- // final Object cachedTenantValues = tenantKVCache.get(tenantKey, new CacheLoaderArgument(ObjectType.TENANT_KVS));
- // if (cachedTenantValues == null) {
- // return ImmutableList.<String>of();
- // } else {
- // // Current, we only cache single-value keys
- // return ImmutableList.<String>of((String) cachedTenantValues);
- // }
- // }
-
- // private String getCacheKeyName(final String key, final InternalTenantContext internalContext) {
- // final StringBuilder tenantKey = new StringBuilder(key);
- // tenantKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
- // tenantKey.append(internalContext.getTenantRecordId());
- // return tenantKey.toString();
- // }
+ private List<String> getCachedTenantValuesForKey(final String key, final InternalTenantContext internalContext) {
+ final String tenantKey = getCacheKeyName(key, internalContext);
+ final Object cachedTenantValues = tenantKVCache.computeIfAbsent(tenantKey, () -> {
+ return tenantDao.getTenantValueForKey(tenantKey, internalContext);
+ });
+ if (cachedTenantValues == null) {
+ return ImmutableList.<String>of();
+ } else {
+ // Current, we only cache single-value keys
+ return ImmutableList.<String>of((String) cachedTenantValues);
+ }
+ }
+
+ private String getCacheKeyName(final String key, final InternalTenantContext internalContext) {
+ final StringBuilder tenantKey = new StringBuilder(key);
+ tenantKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
+ tenantKey.append(internalContext.getTenantRecordId());
+ return tenantKey.toString();
+ }
private boolean isSingleValueKey(final String key) {
return Iterables.tryFind(ImmutableList.copyOf(TenantKey.values()), new Predicate<TenantKey>() {
@@ -222,12 +231,12 @@ public class DefaultTenantUserApi implements TenantUserApi {
}).orNull() != null;
}
- // private boolean isCachedInTenantKVCache(final String key) {
- // return Iterables.tryFind(CACHED_TENANT_KEY, new Predicate<TenantKey>() {
- // @Override
- // public boolean apply(final TenantKey input) {
- // return key.startsWith(input.toString());
- // }
- // }).orNull() != null;
- // }
+ private boolean isCachedInTenantKVCache(final String key) {
+ return Iterables.tryFind(CACHED_TENANT_KEY, new Predicate<TenantKey>() {
+ @Override
+ public boolean apply(final TenantKey input) {
+ return key.startsWith(input.toString());
+ }
+ }).orNull() != null;
+ }
}
util/pom.xml 51(+5 -46)
diff --git a/util/pom.xml b/util/pom.xml
index 6b2334b..fd71597 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -29,6 +29,11 @@
<name>killbill-util</name>
<dependencies>
<dependency>
+ <groupId>br.ufrgs.inf.prosoft.cache</groupId>
+ <artifactId>Cache</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<scope>provided</scope>
@@ -325,52 +330,6 @@
<build>
<plugins>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>aspectj-maven-plugin</artifactId>
- <version>1.11</version>
- <configuration>
- <showWeaveInfo>false</showWeaveInfo>
- <complianceLevel>1.8</complianceLevel>
- <source>1.8</source>
- <target>1.8</target>
- <Xlint>ignore</Xlint>
- <encoding>UTF-8</encoding>
- <verbose>false</verbose>
- <forceAjcCompile>true</forceAjcCompile>
- <sources/>
- <weaveDirectories>
- <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
- </weaveDirectories>
- <aspectLibraries>
- <aspectLibrary>
- <groupId>br.ufrgs.inf.prosoft.applicationtracer</groupId>
- <artifactId>ApplicationTracer</artifactId>
- </aspectLibrary>
- </aspectLibraries>
- </configuration>
- <executions>
- <execution>
- <phase>process-classes</phase>
- <goals>
- <goal>compile</goal>
- <goal>test-compile</goal>
- </goals>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.1</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjtools</artifactId>
- <version>1.9.1</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
diff --git a/util/src/main/java/org/killbill/billing/util/audit/dao/DefaultAuditDao.java b/util/src/main/java/org/killbill/billing/util/audit/dao/DefaultAuditDao.java
index 782e4e0..99e369a 100644
--- a/util/src/main/java/org/killbill/billing/util/audit/dao/DefaultAuditDao.java
+++ b/util/src/main/java/org/killbill/billing/util/audit/dao/DefaultAuditDao.java
@@ -61,6 +61,8 @@ import com.google.common.collect.Lists;
import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultAuditDao implements AuditDao {
private final DBRouter<NonEntitySqlDao> dbRouter;
@@ -110,6 +112,10 @@ public class DefaultAuditDao implements AuditDao {
}
private Iterator<AuditLog> buildAuditLogsFromModelDao(final Iterator<AuditLogModelDao> auditLogsForAccountRecordId, final InternalTenantContext tenantContext) {
+
+MultiCache<TableName, Map<Long, UUID>> recordIdIdsCache = new MultiCache<>("DefaultAuditDao.recordIdIdsCache");
+MultiCache<TableName, Map<Long, UUID>> historyRecordIdIdsCache = new MultiCache<>("DefaultAuditDao.historyRecordIdIdsCache");
+
// final Map<TableName, Map<Long, UUID>> recordIdIdsCache = new HashMap<TableName, Map<Long, UUID>>();
// final Map<TableName, Map<Long, UUID>> historyRecordIdIdsCache = new HashMap<TableName, Map<Long, UUID>>();
return Iterators.<AuditLogModelDao, AuditLog>transform(auditLogsForAccountRecordId,
@@ -122,48 +128,49 @@ public class DefaultAuditDao implements AuditDao {
final NonEntitySqlDao nonEntitySqlDao = dbRouter.onDemand(true);
final ObjectType objectType;
- final UUID auditedEntityId;
+ UUID auditedEntityId = null;
if (originalTableNameForHistoryTableName != null) {
// input point to a history entry
objectType = originalTableNameForHistoryTableName.getObjectType();
Iterable<RecordIdIdMappings> mappings = null;
- // if (historyRecordIdIdsCache.get(originalTableNameForHistoryTableName) == null) {
+
+ if (!historyRecordIdIdsCache.containsKey(originalTableNameForHistoryTableName)) {
if (TableName.ACCOUNT.equals(originalTableNameForHistoryTableName)) {
mappings = nonEntitySqlDao.getHistoryRecordIdIdMappingsForAccountsTable(originalTableNameForHistoryTableName.getTableName(),
input.getTableName().getTableName(),
tenantContext);
- // historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+ historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
} else if (TableName.TAG_DEFINITIONS.equals(originalTableNameForHistoryTableName)) {
mappings = nonEntitySqlDao.getHistoryRecordIdIdMappingsForTablesWithoutAccountRecordId(originalTableNameForHistoryTableName.getTableName(),
input.getTableName().getTableName(),
tenantContext);
- // historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+ historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
} else {
mappings = nonEntitySqlDao.getHistoryRecordIdIdMappings(originalTableNameForHistoryTableName.getTableName(),
input.getTableName().getTableName(),
tenantContext);
- // historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
+ historyRecordIdIdsCache.put(originalTableNameForHistoryTableName, RecordIdIdMappings.toMap(mappings));
}
- // }
- Map<Long, UUID> tomapping = RecordIdIdMappings.toMap(mappings);
+ }
+
+try {
+ auditedEntityId = historyRecordIdIdsCache.get(originalTableNameForHistoryTableName).get(input.getTargetRecordId());
+} catch (KeyNotFoundException ex) {}
- // auditedEntityId = historyRecordIdIdsCache.get(originalTableNameForHistoryTableName).get(input.getTargetRecordId());
- auditedEntityId = tomapping.get(input.getTargetRecordId());
} else {
objectType = input.getTableName().getObjectType();
- // if (recordIdIdsCache.get(input.getTableName()) == null) {
+ if (!recordIdIdsCache.containsKey(input.getTableName())) {
final Iterable<RecordIdIdMappings> mappings = nonEntitySqlDao.getRecordIdIdMappings(input.getTableName().getTableName(),
tenantContext);
- // recordIdIdsCache.put(input.getTableName(), RecordIdIdMappings.toMap(mappings));
- // }
- Map<Long, UUID> tomapping = RecordIdIdMappings.toMap(mappings);
-
- // auditedEntityId = recordIdIdsCache.get(input.getTableName()).get(input.getTargetRecordId());
- auditedEntityId = tomapping.get(input.getTargetRecordId());
+ recordIdIdsCache.put(input.getTableName(), RecordIdIdMappings.toMap(mappings));
+ }
+try{
+ auditedEntityId = recordIdIdsCache.get(input.getTableName()).get(input.getTargetRecordId());
+} catch (KeyNotFoundException ex) {}
}
return new DefaultAuditLog(input, objectType, auditedEntityId);
@@ -190,6 +197,8 @@ Iterable<RecordIdIdMappings> mappings = null;
}
}
+public static MultiCache<Parameters, List<AuditLogWithHistory>> getAuditLogsWithHistoryForId = new MultiCache<>("DefaultAuditDao.getAuditLogsWithHistoryForId");
+
@Override
public List<AuditLogWithHistory> getAuditLogsWithHistoryForId(final HistorySqlDao transactional, final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) {
final TableName historyTableName = tableName.getHistoryTableName();
@@ -203,6 +212,8 @@ Iterable<RecordIdIdMappings> mappings = null;
final Long targetRecordId = dbRouter.onDemand(true).getRecordIdFromObject(objectId.toString(), tableName.getTableName());
final List<EntityHistoryModelDao> objectHistory = transactional.getHistoryForTargetRecordId(true, targetRecordId, context);
+ return getAuditLogsWithHistoryForId.computeIfAbsent(new Parameters(historyTableName.name(), historyTableName.getTableName().toLowerCase(), targetRecordId), () -> {
+
return ImmutableList.<AuditLogWithHistory>copyOf(Collections2.transform(entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
historyTableName.getTableName().toLowerCase(),
targetRecordId,
@@ -223,6 +234,7 @@ Iterable<RecordIdIdMappings> mappings = null;
return new DefaultAuditLogWithHistory((historyEntity == null ? null : historyEntity.getEntity()), inputAuditLog, tableName.getObjectType(), objectId);
}
}));
+ });
}
});
}
@@ -236,6 +248,8 @@ Iterable<RecordIdIdMappings> mappings = null;
}
}
+public static MultiCache<Parameters, List<AuditLogModelDao>> getAuditLogsViaHistoryForTargetRecordId = new MultiCache<>("DefaultAuditDao.getAuditLogsViaHistoryForTargetRecordId");
+
private List<AuditLog> doGetAuditLogsViaHistoryForId(final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) {
final TableName historyTableName = tableName.getHistoryTableName();
if (historyTableName == null) {
@@ -246,23 +260,32 @@ Iterable<RecordIdIdMappings> mappings = null;
final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<AuditLog>>() {
@Override
public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
- final List<AuditLogModelDao> auditLogsViaHistoryForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
- historyTableName.getTableName().toLowerCase(),
- targetRecordId,
- context);
+ final List<AuditLogModelDao> auditLogsViaHistoryForTargetRecordId =
+ getAuditLogsViaHistoryForTargetRecordId.computeIfAbsent(new Parameters(historyTableName.name(), historyTableName.getTableName().toLowerCase(), targetRecordId), () -> {
+
+ return entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
+ historyTableName.getTableName().toLowerCase(),
+ targetRecordId,
+ context);
+ });
return buildAuditLogsFromModelDao(auditLogsViaHistoryForTargetRecordId, tableName.getObjectType(), objectId);
}
});
return filterAuditLogs(auditLevel, allAuditLogs);
}
+public static MultiCache<Parameters, List<AuditLogModelDao>> getAuditLogsForTargetRecordId = new MultiCache<>("DefaultAuditDao.getAuditLogsForTargetRecordId");
+
private List<AuditLog> getAuditLogsForRecordId(final TableName tableName, final UUID auditedEntityId, final Long targetRecordId, final AuditLevel auditLevel, final InternalTenantContext context) {
final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(true, new EntitySqlDaoTransactionWrapper<List<AuditLog>>() {
@Override
public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
- final List<AuditLogModelDao> auditLogsForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsForTargetRecordId(tableName.name(),
+ final List<AuditLogModelDao> auditLogsForTargetRecordId =
+ getAuditLogsForTargetRecordId.computeIfAbsent(new Parameters(tableName.name(), targetRecordId), () -> {
+ return entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsForTargetRecordId(tableName.name(),
targetRecordId,
context);
+ });
return buildAuditLogsFromModelDao(auditLogsForTargetRecordId, tableName.getObjectType(), auditedEntityId);
}
});
diff --git a/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java b/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
index 7105f81..0d34afe 100644
--- a/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
+++ b/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
@@ -30,12 +30,15 @@ import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultAccountAuditLogs implements AccountAuditLogs {
private final UUID accountId;
private final AuditLevel auditLevel;
private final List<AuditLog> accountAuditLogs;
+private MultiCache<ObjectType, DefaultAccountAuditLogsForObjectType> auditLogsCache = new MultiCache<>("DefaultAccountAuditLogs.auditLogsCache");
// private final Map<ObjectType, DefaultAccountAuditLogsForObjectType> auditLogsCache = new HashMap<ObjectType, DefaultAccountAuditLogsForObjectType>();
public DefaultAccountAuditLogs(final UUID accountId) {
@@ -126,12 +129,15 @@ public class DefaultAccountAuditLogs implements AccountAuditLogs {
@Override
public AccountAuditLogsForObjectType getAuditLogs(final ObjectType objectType) {
- // if (auditLogsCache.get(objectType) == null) {
- // auditLogsCache.put(objectType, new DefaultAccountAuditLogsForObjectType(auditLevel, new ObjectTypeFilter(objectType, accountAuditLogs.iterator())));
- // }
-return new DefaultAccountAuditLogsForObjectType(auditLevel, new ObjectTypeFilter(objectType, accountAuditLogs.iterator()));
+ if (!auditLogsCache.containsKey(objectType)) {
+ auditLogsCache.put(objectType, new DefaultAccountAuditLogsForObjectType(auditLevel, new ObjectTypeFilter(objectType, accountAuditLogs.iterator())));
+ }
// Should never be null
- // return auditLogsCache.get(objectType);
+ try {
+ return auditLogsCache.get(objectType);
+ } catch (KeyNotFoundException ex) {
+ return null;
+ }
}
@Override
diff --git a/util/src/main/java/org/killbill/billing/util/bcd/BillCycleDayCalculator.java b/util/src/main/java/org/killbill/billing/util/bcd/BillCycleDayCalculator.java
index ce6656c..3b7f927 100644
--- a/util/src/main/java/org/killbill/billing/util/bcd/BillCycleDayCalculator.java
+++ b/util/src/main/java/org/killbill/billing/util/bcd/BillCycleDayCalculator.java
@@ -33,6 +33,8 @@ import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
public abstract class BillCycleDayCalculator {
private static final Logger log = LoggerFactory.getLogger(BillCycleDayCalculator.class);
@@ -87,14 +89,9 @@ public abstract class BillCycleDayCalculator {
private static int calculateOrRetrieveBcdFromSubscription(
// @Nullable final Map<UUID, Integer> bcdCache,
final SubscriptionBase subscription, final InternalTenantContext internalTenantContext) {
- Integer result;// = bcdCache != null ? bcdCache.get(subscription.getId()) : null;
- // if (result == null) {
- result = calculateBcdFromSubscription(subscription, internalTenantContext);
- // if (bcdCache != null) {
- // bcdCache.put(subscription.getId(), result);
- // }
- // }
- return result;
+ return CacheControllerDispatcher.bcdCacheController.computeIfAbsent(subscription.getId(), () -> {
+ return calculateBcdFromSubscription(subscription, internalTenantContext);
+ });
}
private static int calculateBcdFromSubscription(final SubscriptionBase subscription, final InternalTenantContext internalTenantContext) {
diff --git a/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcher.java b/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcher.java
index 0ba2e61..8ca96f8 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcher.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcher.java
@@ -14,7 +14,7 @@
* under the License.
*/
-// package org.killbill.billing.util.cache;
+package org.killbill.billing.util.cache;
// import java.util.HashMap;
// import java.util.Map;
@@ -25,12 +25,29 @@
// import org.slf4j.Logger;
// import org.slf4j.LoggerFactory;
+import br.ufrgs.inf.prosoft.cache.*;
+import java.util.UUID;
+import java.util.List;
+import org.killbill.billing.account.api.ImmutableAccountData;
+
// // Kill Bill generic cache dispatcher
-// public class CacheControllerDispatcher {
+public class CacheControllerDispatcher {
// private static final Logger logger = LoggerFactory.getLogger(CacheControllerDispatcher.class);
-// public static final String CACHE_KEY_SEPARATOR = "::";
+ public static final String CACHE_KEY_SEPARATOR = "::";
+
+public static MultiCache<String, Long> accountRecordIdCacheController = new MultiCache<>("CacheControllerDispatcher.accountRecordIdCacheController");
+public static MultiCache<String, Long> tenantRecordIdCacheController = new MultiCache<>("CacheControllerDispatcher.tenantRecordIdCacheController");
+public static MultiCache<String, Long> recordIdCacheController = new MultiCache<>("CacheControllerDispatcher.recordIdCacheController");
+public static MultiCache<String, List> auditLogViaHistory = new MultiCache<>("CacheControllerDispatcher.auditLogViaHistory");
+public static MultiCache<String, UUID> objectIdCacheController = new MultiCache<>("CacheControllerDispatcher.objectIdCacheController");
+public static MultiCache<String, List> auditLog = new MultiCache<>("CacheControllerDispatcher.auditLog");
+public static MultiCache<UUID, Integer> bcdCacheController = new MultiCache<>("CacheControllerDispatcher.bcdCacheController");
+public static MultiCache<Long, ImmutableAccountData> accountCacheController = new MultiCache<>("CacheControllerDispatcher.accountCacheController");
+public static MultiCache<Long, ImmutableAccountData> accountImmutableCacheController = new MultiCache<>("CacheControllerDispatcher.accountImmutableCacheController");
+public static MultiCache<UUID, UUID> accountIdCacheController = new MultiCache<>("CacheControllerDispatcher.accountIdCacheController");
+public static MultiCache<UUID, UUID> bundleIdCacheController = new MultiCache<>("CacheControllerDispatcher.bundleIdCacheController");
// private final Map<CacheType, CacheController<Object, Object>> caches;
@@ -58,4 +75,4 @@
// private static <K, V> CacheController<K, V> cast(final CacheController<?, ?> cache) {
// return (CacheController<K, V>) cache;
// }
-// }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/callcontext/InternalCallContextFactory.java b/util/src/main/java/org/killbill/billing/util/callcontext/InternalCallContextFactory.java
index ed15ba1..d97e8f0 100644
--- a/util/src/main/java/org/killbill/billing/util/callcontext/InternalCallContextFactory.java
+++ b/util/src/main/java/org/killbill/billing/util/callcontext/InternalCallContextFactory.java
@@ -43,6 +43,8 @@ import org.slf4j.MDC;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
// Internal contexts almost always expect accountRecordId and tenantRecordId to be populated
public class InternalCallContextFactory {
@@ -61,6 +63,7 @@ public class InternalCallContextFactory {
// private final CacheController<String, Long> accountRecordIdCacheController;
// private final CacheController<String, Long> tenantRecordIdCacheController;
+
@Inject
public InternalCallContextFactory(@Nullable final ImmutableAccountInternalApi accountInternalApi,
final Clock clock,
@@ -346,7 +349,7 @@ public class InternalCallContextFactory {
public UUID getAccountId(final UUID objectId, final ObjectType objectType, final TenantContext context) {
final Long accountRecordId = getAccountRecordIdSafe(objectId, objectType, context);
if (accountRecordId != null) {
- return nonEntityDao.retrieveIdFromObject(accountRecordId, ObjectType.ACCOUNT, null);
+ return nonEntityDao.retrieveIdFromObject(accountRecordId, ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController);
} else {
return null;
}
@@ -356,7 +359,7 @@ public class InternalCallContextFactory {
public Long getRecordIdFromObject(final UUID objectId, final ObjectType objectType, final TenantContext context) {
try {
if (objectBelongsToTheRightTenant(objectId, objectType, context)) {
- return nonEntityDao.retrieveRecordIdFromObject(objectId, objectType, null);
+ return nonEntityDao.retrieveRecordIdFromObject(objectId, objectType, CacheControllerDispatcher.recordIdCacheController);
} else {
return null;
}
@@ -397,11 +400,11 @@ public class InternalCallContextFactory {
}
private UUID getTenantIdSafe(final InternalTenantContext context) {
- return nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT, null);
+ return nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT, CacheControllerDispatcher.objectIdCacheController);
}
private UUID getAccountIdSafe(final InternalTenantContext context) {
- return context.getAccountRecordId() != null ? nonEntityDao.retrieveIdFromObject(context.getAccountRecordId(), ObjectType.ACCOUNT, null) : null;
+ return context.getAccountRecordId() != null ? nonEntityDao.retrieveIdFromObject(context.getAccountRecordId(), ObjectType.ACCOUNT, CacheControllerDispatcher.objectIdCacheController) : null;
}
//
@@ -429,11 +432,11 @@ public class InternalCallContextFactory {
//
private Long getAccountRecordIdUnsafe(final UUID objectId, final ObjectType objectType) {
- return nonEntityDao.retrieveAccountRecordIdFromObject(objectId, objectType, null);
+ return nonEntityDao.retrieveAccountRecordIdFromObject(objectId, objectType, CacheControllerDispatcher.tenantRecordIdCacheController);
}
private Long getTenantRecordIdUnsafe(final UUID objectId, final ObjectType objectType) {
- return nonEntityDao.retrieveTenantRecordIdFromObject(objectId, objectType, null);
+ return nonEntityDao.retrieveTenantRecordIdFromObject(objectId, objectType, CacheControllerDispatcher.tenantRecordIdCacheController);
}
public static final class ObjectDoesNotExist extends IllegalStateException {
diff --git a/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java b/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
index 0cd2544..8fd9b7a 100644
--- a/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
+++ b/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
@@ -32,8 +32,12 @@ import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import br.ufrgs.inf.prosoft.cache.*;
+
public abstract class MultiTenantConfigBase {
+MultiCache<String, Method> methodsCache = new MultiCache<>("MultiTenantConfigBase.methodsCache");
+
// private final Map<String, Method> methodsCache = new HashMap<String, Method>();
// protected final CacheConfig cacheConfig;
@@ -116,22 +120,13 @@ public abstract class MultiTenantConfigBase {
}
protected Method getConfigStaticMethod(final String methodName) {
- // Method method = methodsCache.get(methodName);
- Method method = null;
- // if (method == null) {
- // synchronized (methodsCache) {
- // method = methodsCache.get(methodName);
- // if (method == null) {
- try {
- method = getConfigClass().getMethod(methodName, InternalTenantContext.class);
- // methodsCache.put(methodName, method);
- } catch (final NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
- // }
- // }
- // }
- return method;
+ return methodsCache.computeIfAbsent(methodName, () -> {
+ try {
+ return getConfigClass().getMethod(methodName, InternalTenantContext.class);
+ } catch (final NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ });
}
protected abstract Class<? extends KillbillConfig> getConfigClass();
diff --git a/util/src/main/java/org/killbill/billing/util/dao/DefaultNonEntityDao.java b/util/src/main/java/org/killbill/billing/util/dao/DefaultNonEntityDao.java
index 7ebb1c4..b7a90e4 100644
--- a/util/src/main/java/org/killbill/billing/util/dao/DefaultNonEntityDao.java
+++ b/util/src/main/java/org/killbill/billing/util/dao/DefaultNonEntityDao.java
@@ -41,25 +41,27 @@ import com.google.common.base.Preconditions;
import static org.killbill.billing.util.glue.IDBISetup.MAIN_RO_IDBI_NAMED;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class DefaultNonEntityDao implements NonEntityDao {
private final DBRouter<NonEntitySqlDao> dbRouter;
- private final WithCaching<String, Long> withCachingObjectId;
- private final WithCaching<String, UUID> withCachingRecordId;
+ // private final WithCaching<String, Long> withCachingObjectId;
+ // private final WithCaching<String, UUID> withCachingRecordId;
@Inject
public DefaultNonEntityDao(final IDBI dbi, @Named(MAIN_RO_IDBI_NAMED) final IDBI roDbi) {
this.dbRouter = new DBRouter<NonEntitySqlDao>(dbi, roDbi, NonEntitySqlDao.class);
- this.withCachingObjectId = new WithCaching<String, Long>();
- this.withCachingRecordId = new WithCaching<String, UUID>();
+ // this.withCachingObjectId = new WithCaching<String, Long>();
+ // this.withCachingRecordId = new WithCaching<String, UUID>();
}
@Override
- public Long retrieveRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache) {
+ public Long retrieveRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache) {
return retrieveRecordIdFromObjectInTransaction(objectId, objectType, cache, null);
}
- public Long retrieveRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle) {
+ public Long retrieveRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle) {
if (objectId == null) {
return null;
}
@@ -67,29 +69,33 @@ public class DefaultNonEntityDao implements NonEntityDao {
final TableName tableName = TableName.fromObjectType(objectType);
Preconditions.checkNotNull(tableName, "%s is not a valid ObjectType", objectType);
- return withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
- @Override
- public Long doRetrieve(final ObjectType objectType) {
+ // return withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
+ // @Override
+ // public Long doRetrieve(final ObjectType objectType) {
+ return cache.computeIfAbsent(objectId.toString(), () -> {
final NonEntitySqlDao inTransactionNonEntitySqlDao = handle == null ? dbRouter.onDemand(true) : SqlObjectBuilder.attach(handle, NonEntitySqlDao.class);
return inTransactionNonEntitySqlDao.getRecordIdFromObject(objectId.toString(), tableName.getTableName());
- }
- }, objectId.toString(), objectType, tableName, cache);
+ });
+ // }
+ // }, objectId.toString(), objectType, tableName, cache);
}
@Override
- public Long retrieveAccountRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache) {
+ public Long retrieveAccountRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache) {
return retrieveAccountRecordIdFromObjectInTransaction(objectId, objectType, cache, null);
}
@Override
- public Long retrieveAccountRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle) {
+ public Long retrieveAccountRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle) {
final TableName tableName = TableName.fromObjectType(objectType);
Preconditions.checkNotNull(tableName, "%s is not a valid ObjectType", objectType);
final String objectIdOrNull = objectId != null ? objectId.toString() : null;
- return withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
- @Override
- public Long doRetrieve(final ObjectType objectType) {
+ return cache.computeIfAbsent(objectIdOrNull, () -> {
+
+ // withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
+ // @Override
+ // public Long doRetrieve(final ObjectType objectType) {
final NonEntitySqlDao inTransactionNonEntitySqlDao = handle == null ? dbRouter.onDemand(true) : SqlObjectBuilder.attach(handle, NonEntitySqlDao.class);
switch (tableName) {
@@ -104,24 +110,26 @@ public class DefaultNonEntityDao implements NonEntityDao {
default:
return inTransactionNonEntitySqlDao.getAccountRecordIdFromObjectOtherThanAccount(objectIdOrNull, tableName.getTableName());
}
- }
- }, objectIdOrNull, objectType, tableName, cache);
+ });
+ // }
+ // }, objectIdOrNull, objectType, tableName, cache);
}
@Override
- public Long retrieveTenantRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache) {
+ public Long retrieveTenantRecordIdFromObject(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache) {
return retrieveTenantRecordIdFromObjectInTransaction(objectId, objectType, cache, null);
}
@Override
- public Long retrieveTenantRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle) {
+ public Long retrieveTenantRecordIdFromObjectInTransaction(@Nullable final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle) {
final TableName tableName = TableName.fromObjectType(objectType);
Preconditions.checkNotNull(tableName, "%s is not a valid ObjectType", objectType);
final String objectIdOrNull = objectId != null ? objectId.toString() : null;
- return withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
- @Override
- public Long doRetrieve(final ObjectType objectType) {
+ return cache.computeIfAbsent(objectIdOrNull, () -> {
+ // withCachingObjectId.withCaching(new OperationRetrieval<Long>() {
+ // @Override
+ // public Long doRetrieve(final ObjectType objectType) {
final NonEntitySqlDao inTransactionNonEntitySqlDao = handle == null ? dbRouter.onDemand(true) : SqlObjectBuilder.attach(handle, NonEntitySqlDao.class);
switch (tableName) {
@@ -133,17 +141,18 @@ public class DefaultNonEntityDao implements NonEntityDao {
return inTransactionNonEntitySqlDao.getTenantRecordIdFromObjectOtherThanTenant(objectIdOrNull, tableName.getTableName());
}
- }
- }, objectIdOrNull, objectType, tableName, cache);
+ // }
+ });
+ // }, objectIdOrNull, objectType, tableName, cache);
}
@Override
- public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType, @Nullable final Object cache) {
+ public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType, @Nullable final Cache<String, UUID> cache) {
return retrieveIdFromObjectInTransaction(recordId, objectType, cache, null);
}
@Override
- public UUID retrieveIdFromObjectInTransaction(final Long recordId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle) {
+ public UUID retrieveIdFromObjectInTransaction(final Long recordId, final ObjectType objectType, @Nullable final Cache<String, UUID> cache, @Nullable final Handle handle) {
if (objectType == ObjectType.TENANT && InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID.equals(recordId)) {
return null;
}
@@ -151,13 +160,15 @@ public class DefaultNonEntityDao implements NonEntityDao {
final TableName tableName = TableName.fromObjectType(objectType);
Preconditions.checkNotNull(tableName, "%s is not a valid ObjectType", objectType);
- return withCachingRecordId.withCaching(new OperationRetrieval<UUID>() {
- @Override
- public UUID doRetrieve(final ObjectType objectType) {
+ return cache.computeIfAbsent(String.valueOf(recordId), () -> {
+ // withCachingRecordId.withCaching(new OperationRetrieval<UUID>() {
+ // @Override
+ // public UUID doRetrieve(final ObjectType objectType) {
final NonEntitySqlDao inTransactionNonEntitySqlDao = handle == null ? dbRouter.onDemand(true) : SqlObjectBuilder.attach(handle, NonEntitySqlDao.class);
return inTransactionNonEntitySqlDao.getIdFromObject(recordId, tableName.getTableName());
- }
- }, String.valueOf(recordId), objectType, tableName, cache);
+ // }
+ // }, String.valueOf(recordId), objectType, tableName, cache);
+ });
}
@Override
@@ -171,34 +182,34 @@ public class DefaultNonEntityDao implements NonEntityDao {
return dbRouter.onDemand(true).getHistoryTargetRecordId(recordId, tableName.getTableName());
}
- private interface OperationRetrieval<TypeOut> {
+ // private interface OperationRetrieval<TypeOut> {
- public TypeOut doRetrieve(final ObjectType objectType);
- }
+ // public TypeOut doRetrieve(final ObjectType objectType);
+ // }
// 'cache' will be null for the CacheLoader classes -- or if cache is not configured.
- private class WithCaching<TypeIn, TypeOut> {
+ // private class WithCaching<TypeIn, TypeOut> {
- private TypeOut withCaching(final OperationRetrieval<TypeOut> op, @Nullable final TypeIn objectOrRecordId, final ObjectType objectType, final TableName tableName, @Nullable final Object cache) {
+ // private TypeOut withCaching(final OperationRetrieval<TypeOut> op, @Nullable final TypeIn objectOrRecordId, final ObjectType objectType, final TableName tableName, @Nullable final Cache<TypeIn, TypeOut> cache) {
- final Profiling<TypeOut, RuntimeException> prof = new Profiling<TypeOut, RuntimeException>();
- if (objectOrRecordId == null) {
- return null;
- }
+ // final Profiling<TypeOut, RuntimeException> prof = new Profiling<TypeOut, RuntimeException>();
+ // if (objectOrRecordId == null) {
+ // return null;
+ // }
// if (cache != null) {
- // final TypeIn key = (cache.getCacheType().isKeyPrefixedWithTableName()) ?
- // (TypeIn) (tableName + CacheControllerDispatcher.CACHE_KEY_SEPARATOR + objectOrRecordId.toString()) :
- // objectOrRecordId;
- // return cache.get(key, new CacheLoaderArgument(objectType));
+ // final TypeIn key = //(cache.getCacheType().isKeyPrefixedWithTableName()) ?
+ // (TypeIn) (tableName + CacheControllerDispatcher.CACHE_KEY_SEPARATOR + objectOrRecordId.toString());// :
+ // // objectOrRecordId;
+ // return cache.get(key);
// }
- final TypeOut result;
- result = prof.executeWithProfiling(ProfilingFeatureType.DAO_DETAILS, "NonEntityDao (type = " + objectType + ") cache miss", new WithProfilingCallback<TypeOut, RuntimeException>() {
- @Override
- public TypeOut execute() throws RuntimeException {
- return op.doRetrieve(objectType);
- }
- });
- return result;
- }
- }
+ // final TypeOut result;
+ // result = prof.executeWithProfiling(ProfilingFeatureType.DAO_DETAILS, "NonEntityDao (type = " + objectType + ") cache miss", new WithProfilingCallback<TypeOut, RuntimeException>() {
+ // @Override
+ // public TypeOut execute() throws RuntimeException {
+ // return op.doRetrieve(objectType);
+ // }
+ // });
+ // return result;
+ // }
+ // }
}
diff --git a/util/src/main/java/org/killbill/billing/util/dao/NonEntityDao.java b/util/src/main/java/org/killbill/billing/util/dao/NonEntityDao.java
index 19142be..b646efe 100644
--- a/util/src/main/java/org/killbill/billing/util/dao/NonEntityDao.java
+++ b/util/src/main/java/org/killbill/billing/util/dao/NonEntityDao.java
@@ -26,24 +26,26 @@ import org.killbill.billing.ObjectType;
// import org.killbill.billing.util.cache.CacheController;
import org.skife.jdbi.v2.Handle;
+import br.ufrgs.inf.prosoft.cache.*;
+
// This should only be used for internal operations (trusted code, not API), because the context will not be validated!
public interface NonEntityDao {
- public Long retrieveRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Object cache);
+ public Long retrieveRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache);
- public Long retrieveRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle);
+ public Long retrieveRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle);
- public Long retrieveAccountRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Object cache);
+ public Long retrieveAccountRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache);
- public Long retrieveAccountRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle);
+ public Long retrieveAccountRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle);
- public Long retrieveTenantRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Object cache);
+ public Long retrieveTenantRecordIdFromObject(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache);
- public Long retrieveTenantRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle);
+ public Long retrieveTenantRecordIdFromObjectInTransaction(final UUID objectId, final ObjectType objectType, @Nullable final Cache<String, Long> cache, @Nullable final Handle handle);
- public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType, @Nullable final Object cache);
+ public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType, @Nullable final Cache<String, UUID> cache);
- public UUID retrieveIdFromObjectInTransaction(final Long recordId, final ObjectType objectType, @Nullable final Object cache, @Nullable final Handle handle);
+ public UUID retrieveIdFromObjectInTransaction(final Long recordId, final ObjectType objectType, @Nullable final Cache<String, UUID> cache, @Nullable final Handle handle);
// This retrieves from the history table the latest record for which targetId matches the one we are passing
public Long retrieveLastHistoryRecordIdFromTransaction(final Long targetRecordId, final TableName tableName, final NonEntitySqlDao transactional);
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
index 1154593..aea6772 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
@@ -75,6 +75,8 @@ import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
+import org.killbill.billing.util.cache.CacheControllerDispatcher;
+
/**
* Wraps an instance of EntitySqlDao, performing extra work around each method (Sql query)
*
@@ -212,9 +214,9 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>,
// the object after it was created, which means this method is (by pattern) first called right after object creation and contains all the goodies we care
// about (record_id, account_record_id, object_id, tenant_record_id)
//
- // if (result != null && method.getName().equals("getById")) {
- // populateCacheOnGetByIdInvocation((M) result);
- // }
+ if (result != null && method.getName().equals("getById")) {
+ populateCacheOnGetByIdInvocation((M) result);
+ }
return result;
}
});
@@ -371,33 +373,30 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>,
}
}
- // private void populateCacheOnGetByIdInvocation(final M model) {
- // populateCaches(cacheControllerDispatcher, model);
- // }
-
- // public static void populateCaches(final CacheControllerDispatcher cacheControllerDispatcher, final EntityModelDao model) {
- // final CacheController<String, Long> cacheRecordId = cacheControllerDispatcher.getCacheController(CacheType.RECORD_ID);
- // cacheRecordId.putIfAbsent(getKey(model.getId().toString(), CacheType.RECORD_ID, model.getTableName()), model.getRecordId());
-
- // final CacheController<String, UUID> cacheObjectId = cacheControllerDispatcher.getCacheController(CacheType.OBJECT_ID);
- // cacheObjectId.putIfAbsent(getKey(model.getRecordId().toString(), CacheType.OBJECT_ID, model.getTableName()), model.getId());
+ private void populateCacheOnGetByIdInvocation(final M model) {
+ populateCaches(//cacheControllerDispatcher,
+ model);
+ }
- // if (model.getTenantRecordId() != null) {
- // final CacheController<String, Long> cacheTenantRecordId = cacheControllerDispatcher.getCacheController(CacheType.TENANT_RECORD_ID);
- // cacheTenantRecordId.putIfAbsent(getKey(model.getId().toString(), CacheType.TENANT_RECORD_ID, model.getTableName()), model.getTenantRecordId());
- // }
+ public static void populateCaches(
+ //final CacheControllerDispatcher cacheControllerDispatcher,
+ final EntityModelDao model) {
+ CacheControllerDispatcher.recordIdCacheController.put(getKey(model.getId().toString(), "CacheType.RECORD_ID", model.getTableName()), model.getRecordId());
+ CacheControllerDispatcher.objectIdCacheController.put(getKey(model.getRecordId().toString(), "CacheType.OBJECT_ID", model.getTableName()), model.getId());
+ if (model.getTenantRecordId() != null) {
+ CacheControllerDispatcher.tenantRecordIdCacheController.put(getKey(model.getId().toString(), "CacheType.TENANT_RECORD_ID", model.getTableName()), model.getTenantRecordId());
+ }
- // if (model.getAccountRecordId() != null) {
- // final CacheController<String, Long> cacheAccountRecordId = cacheControllerDispatcher.getCacheController(CacheType.ACCOUNT_RECORD_ID);
- // cacheAccountRecordId.putIfAbsent(getKey(model.getId().toString(), CacheType.ACCOUNT_RECORD_ID, model.getTableName()), model.getAccountRecordId());
- // }
- // }
+ if (model.getAccountRecordId() != null) {
+ CacheControllerDispatcher.accountRecordIdCacheController.put(getKey(model.getId().toString(), "CacheType.ACCOUNT_RECORD_ID", model.getTableName()), model.getAccountRecordId());
+ }
+ }
- // private static String getKey(final String rawKey, final CacheType cacheType, final TableName tableName) {
- // return cacheType.isKeyPrefixedWithTableName() ?
- // tableName + CacheControllerDispatcher.CACHE_KEY_SEPARATOR + rawKey :
- // rawKey;
- // }
+ private static String getKey(final String rawKey, final String cacheType, final TableName tableName) {
+ return //cacheType.isKeyPrefixedWithTableName() ?
+ tableName + CacheControllerDispatcher.CACHE_KEY_SEPARATOR + rawKey ;//:
+ //rawKey;
+ }
private M updateHistoryAndAudit(final String entityId, @Nullable final M deletedEntity, final ChangeType changeType, final InternalCallContext context) throws Throwable {
final Object reHydratedEntity = prof.executeWithProfiling(ProfilingFeatureType.DAO_DETAILS, getProfilingId("history/audit", null), new WithProfilingCallback<Object, Throwable>() {
@@ -528,35 +527,29 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>,
// We need to invalidate the caches. There is a small window of doom here where caches will be stale.
// TODO Knowledge on how the key is constructed is also in AuditSqlDao
- // if (tableName.getHistoryTableName() != null) {
- // final CacheController<String, List> cacheController = cacheControllerDispatcher.getCacheController(CacheType.AUDIT_LOG_VIA_HISTORY);
- // if (cacheController != null) {
- // final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName.getHistoryTableName(), 1, tableName.getHistoryTableName(), 2, entityRecordId));
- // cacheController.remove(key);
- // }
- // } else {
- // final CacheController<String, List> cacheController = cacheControllerDispatcher.getCacheController(CacheType.AUDIT_LOG);
- // if (cacheController != null) {
- // final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName, 1, entityRecordId));
- // cacheController.remove(key);
- // }
- // }
+ if (tableName.getHistoryTableName() != null) {
+ final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName.getHistoryTableName(), 1, tableName.getHistoryTableName(), 2, entityRecordId));
+ CacheControllerDispatcher.auditLogViaHistory.invalidate(key);
+ } else {
+ final String key = buildCacheKey(ImmutableMap.<Integer, Object>of(0, tableName, 1, entityRecordId));
+ CacheControllerDispatcher.auditLog.invalidate(key);
+ }
}
- // private String buildCacheKey(final Map<Integer, Object> keyPieces) {
- // final StringBuilder cacheKey = new StringBuilder();
- // for (int i = 0; i < keyPieces.size(); i++) {
- // // To normalize the arguments and avoid casing issues, we make all pieces of the key uppercase.
- // // Since the database engine may be case insensitive and we use arguments of the SQL method call
- // // to build the key, the key has to be case insensitive as well.
- // final String str = String.valueOf(keyPieces.get(i)).toUpperCase();
- // cacheKey.append(str);
- // if (i < keyPieces.size() - 1) {
- // cacheKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
- // }
- // }
- // return cacheKey.toString();
- // }
+ private String buildCacheKey(final Map<Integer, Object> keyPieces) {
+ final StringBuilder cacheKey = new StringBuilder();
+ for (int i = 0; i < keyPieces.size(); i++) {
+ // To normalize the arguments and avoid casing issues, we make all pieces of the key uppercase.
+ // Since the database engine may be case insensitive and we use arguments of the SQL method call
+ // to build the key, the key has to be case insensitive as well.
+ final String str = String.valueOf(keyPieces.get(i)).toUpperCase();
+ cacheKey.append(str);
+ if (i < keyPieces.size() - 1) {
+ cacheKey.append(CacheControllerDispatcher.CACHE_KEY_SEPARATOR);
+ }
+ }
+ return cacheKey.toString();
+ }
private String getProfilingId(@Nullable final String prefix, @Nullable final Method method) {
final StringBuilder stringBuilder = new StringBuilder().append(sqlDaoClass.getSimpleName());
diff --git a/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java b/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
index dc8a72f..a72d353 100644
--- a/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
+++ b/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
@@ -25,6 +25,8 @@ import java.util.WeakHashMap;
import org.apache.shiro.aop.AnnotationResolver;
import org.apache.shiro.aop.MethodInvocation;
+import br.ufrgs.inf.prosoft.cache.*;
+
public class AnnotationHierarchicalResolver implements AnnotationResolver {
private final Map<String, Annotation> methodToAnnotation = new HashMap<String, Annotation>();
@@ -122,9 +124,12 @@ public class AnnotationHierarchicalResolver implements AnnotationResolver {
return annotation;
}
+
+public static MultiCache<Class<?>, Boolean> isInterfaceWithAnnotatedMethods = new MultiCache<>("AnnotationHierarchicalResolver.isInterfaceWithAnnotatedMethods");
// private static final Map<Class<?>, Boolean> annotatedInterfaceCache = new WeakHashMap<Class<?>, Boolean>();
private static boolean isInterfaceWithAnnotatedMethods(final Class<?> iface) {
+return isInterfaceWithAnnotatedMethods.computeIfAbsent(iface, () -> {
// synchronized (annotatedInterfaceCache) {
// final Boolean flag = annotatedInterfaceCache.get(iface);
// if (flag != null) {
@@ -139,6 +144,7 @@ public class AnnotationHierarchicalResolver implements AnnotationResolver {
}
// annotatedInterfaceCache.put(iface, found);
return found;
+}, 20000);
}
// }
}