killbill-memoizeit

Details

diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/user/TestDefaultAnalyticsUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/api/user/TestDefaultAnalyticsUserApi.java
index 998e67a..783ef2c 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/user/TestDefaultAnalyticsUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/user/TestDefaultAnalyticsUserApi.java
@@ -59,7 +59,6 @@ import com.ning.billing.catalog.api.Product;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.mock.MockPlan;
-import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.callcontext.TenantContext;
 import com.ning.billing.util.clock.Clock;
@@ -82,7 +81,7 @@ public class TestDefaultAnalyticsUserApi extends AnalyticsTestSuiteWithEmbeddedD
     private BusinessOverdueStatusSqlDao overdueStatusSqlDao;
     private BusinessInvoicePaymentSqlDao invoicePaymentSqlDao;
 
-    @BeforeMethod(groups = "slow")
+    @BeforeMethod(groups = "mysql")
     public void setUp() throws Exception {
         final IDBI dbi = helper.getDBI();
         accountSqlDao = dbi.onDemand(BusinessAccountSqlDao.class);
@@ -108,7 +107,7 @@ public class TestDefaultAnalyticsUserApi extends AnalyticsTestSuiteWithEmbeddedD
                                                        new InternalCallContextFactory(dbi, clock));
     }
 
-    @Test(groups = "slow")
+    @Test(groups = "mysql")
     public void testAccountsCreatedOverTime() throws Exception {
         final BusinessAccountModelDao account = new BusinessAccountModelDao(UUID.randomUUID(), UUID.randomUUID().toString(), UUID.randomUUID().toString(), BigDecimal.ONE, clock.getUTCToday(),
                                                                             BigDecimal.TEN, "ERROR_NOT_ENOUGH_FUNDS", "CreditCard", "Visa", "FRANCE", "USD", clock.getUTCNow(), clock.getUTCNow());
@@ -121,7 +120,7 @@ public class TestDefaultAnalyticsUserApi extends AnalyticsTestSuiteWithEmbeddedD
         Assert.assertEquals(data.getValues().get(0), (double) 1);
     }
 
-    @Test(groups = "slow")
+    @Test(groups = "mysql")
     public void testSubscriptionsCreatedOverTime() throws Exception {
         final String productType = "subscription";
         final Product product = new MockProduct("platinum", productType, ProductCategory.BASE);
diff --git a/meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregator.java b/meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregator.java
index f39a547..505a114 100644
--- a/meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregator.java
+++ b/meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregator.java
@@ -295,6 +295,9 @@ public class TimelineAggregator {
 
                 @Override
                 public Void withHandle(final Handle handle) throws Exception {
+                    // MySQL needs special setup to make it stream the results. See:
+                    // http://javaquirks.blogspot.com/2007/12/mysql-streaming-result-set.html
+                    // http://stackoverflow.com/questions/2447324/streaming-large-result-sets-with-mysql
                     final Query<Map<String, Object>> query = handle.createQuery("getStreamingAggregationCandidates")
                                                                    .setFetchSize(Integer.MIN_VALUE)
                                                                    .bind("aggregationLevel", aggregationLevel)
diff --git a/meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.java b/meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.java
index d239d0a..e034a33 100644
--- a/meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.java
+++ b/meter/src/main/java/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.java
@@ -19,7 +19,6 @@ package com.ning.billing.meter.timeline.aggregator;
 import java.util.List;
 
 import org.skife.jdbi.v2.sqlobject.Bind;
-import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
 import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.UseStringTemplate3StatementLocator;
@@ -31,9 +30,6 @@ import com.ning.billing.util.callcontext.InternalTenantContextBinder;
 @UseStringTemplate3StatementLocator()
 public interface TimelineAggregatorSqlDao extends Transactional<TimelineAggregatorSqlDao> {
 
-    @SqlQuery
-    int getLastInsertedId();
-
     @SqlUpdate
     void makeTimelineChunkValid(@Bind("chunkId") final long chunkId,
                                 @InternalTenantContextBinder final InternalCallContext context);
diff --git a/meter/src/main/resources/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.sql.stg b/meter/src/main/resources/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.sql.stg
index bbb566a..418da2d 100644
--- a/meter/src/main/resources/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.sql.stg
+++ b/meter/src/main/resources/com/ning/billing/meter/timeline/aggregator/TimelineAggregatorSqlDao.sql.stg
@@ -42,10 +42,6 @@ and metric_record_id in (<metricIds>)
 ;
 >>
 
-getLastInsertedId() ::= <<
-select last_insert_id();
->>
-
 makeTimelineChunkValid() ::= <<
 update timeline_chunks
 set not_valid = 0
diff --git a/meter/src/test/java/com/ning/billing/meter/timeline/aggregator/TestTimelineAggregator.java b/meter/src/test/java/com/ning/billing/meter/timeline/aggregator/TestTimelineAggregator.java
index bb202dc..716a4e3 100644
--- a/meter/src/test/java/com/ning/billing/meter/timeline/aggregator/TestTimelineAggregator.java
+++ b/meter/src/test/java/com/ning/billing/meter/timeline/aggregator/TestTimelineAggregator.java
@@ -70,7 +70,7 @@ public class TestTimelineAggregator extends MeterTestSuiteWithEmbeddedDB {
     private Integer minHeapUsedKindId = null;
     private Integer maxHeapUsedKindId = null;
 
-    @BeforeMethod(groups = "slow")
+    @BeforeMethod(groups = "mysql")
     public void setUp() throws Exception {
         timelineDao = new DefaultTimelineDao(getDBI());
         final Properties properties = System.getProperties();
@@ -79,7 +79,7 @@ public class TestTimelineAggregator extends MeterTestSuiteWithEmbeddedDB {
         aggregator = new TimelineAggregator(getDBI(), timelineDao, timelineCoder, sampleCoder, config, internalCallContextFactory);
     }
 
-    @Test(groups = "slow")
+    @Test(groups = "mysql")
     public void testAggregation() throws Exception {
         // Create the host
         hostId = timelineDao.getOrAddSource(HOST_NAME, internalCallContext);

pom.xml 25(+23 -2)

diff --git a/pom.xml b/pom.xml
index 04afb96..78fbdd4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -564,7 +564,7 @@
                 <version>2.11</version>
                 <configuration>
                     <useManifestOnlyJar>false</useManifestOnlyJar>
-                    <groups>fast,slow</groups>
+                    <groups>fast,slow,mysql</groups>
                     <systemPropertyVariables>
                         <log4j.configuration>file:${project.basedir}/src/test/resources/log4j.xml</log4j.configuration>
                     </systemPropertyVariables>
@@ -597,7 +597,7 @@
     </build>
     <profiles>
         <profile>
-            <id>localtest</id>
+            <id>h2</id>
             <build>
                 <plugins>
                     <plugin>
@@ -606,6 +606,27 @@
                         <version>2.11</version>
                         <configuration>
                             <groups>fast,slow</groups>
+                            <excludedGroups>mysql</excludedGroups>
+                            <systemPropertyVariables>
+                                <com.ning.billing.dbi.test.h2>true</com.ning.billing.dbi.test.h2>
+                                <file.encoding>UTF-8</file.encoding>
+                                <user.timezone>GMT</user.timezone>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>localtest</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <version>2.11</version>
+                        <configuration>
+                            <groups>fast,slow,mysql</groups>
                             <useManifestOnlyJar>false</useManifestOnlyJar>
                             <systemPropertyVariables>
                                 <log4j.configuration>file:${project.basedir}/src/test/resources/log4j.xml
diff --git a/util/src/test/java/com/ning/billing/KillbillTestSuiteWithEmbeddedDB.java b/util/src/test/java/com/ning/billing/KillbillTestSuiteWithEmbeddedDB.java
index cde037c..20d2451 100644
--- a/util/src/test/java/com/ning/billing/KillbillTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/com/ning/billing/KillbillTestSuiteWithEmbeddedDB.java
@@ -55,14 +55,14 @@ public class KillbillTestSuiteWithEmbeddedDB extends KillbillTestSuite {
         return helper.getDBI();
     }
 
-    @BeforeSuite(groups = "slow")
+    @BeforeSuite(groups = {"slow", "mysql"})
     public void startMysqlBeforeTestSuite() throws IOException, ClassNotFoundException, SQLException, URISyntaxException {
         helper.start();
         helper.initDb();
         helper.cleanupAllTables();
     }
 
-    @BeforeMethod(groups = "slow")
+    @BeforeMethod(groups = {"slow", "mysql"})
     public void cleanupTablesBetweenMethods() {
         try {
             helper.cleanupAllTables();
@@ -70,7 +70,7 @@ public class KillbillTestSuiteWithEmbeddedDB extends KillbillTestSuite {
         }
     }
 
-    @AfterSuite(groups = "slow")
+    @AfterSuite(groups = {"slow", "mysql"})
     public void shutdownMysqlAfterTestSuite() throws IOException, ClassNotFoundException, SQLException, URISyntaxException {
         if (hasFailed()) {
             log.error("**********************************************************************************************");
diff --git a/util/src/test/java/com/ning/billing/util/globallocker/MockGlobalLocker.java b/util/src/test/java/com/ning/billing/util/globallocker/MockGlobalLocker.java
index 4466b1a..b9afb66 100644
--- a/util/src/test/java/com/ning/billing/util/globallocker/MockGlobalLocker.java
+++ b/util/src/test/java/com/ning/billing/util/globallocker/MockGlobalLocker.java
@@ -16,19 +16,60 @@
 
 package com.ning.billing.util.globallocker;
 
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 public class MockGlobalLocker implements GlobalLocker {
+
+    private final Map<String, AtomicBoolean> locks = new ConcurrentHashMap<String, AtomicBoolean>();
+
     @Override
     public GlobalLock lockWithNumberOfTries(final LockerType service,
-                                            final String lockKey, final int retry) {
+                                            final String lockKey,
+                                            final int retry) {
+        final String lockName = getLockName(service, lockKey);
+        int tries_left = retry;
+        while (tries_left-- > 0) {
+            final GlobalLock lock = lock(lockName);
+            if (lock != null) {
+                return lock;
+            }
+        }
+        throw new LockFailedException();
+    }
+
+    private synchronized GlobalLock lock(final String lockName) throws LockFailedException {
+        if (!isFree(lockName)) {
+            return null;
+        }
+
+        if (locks.get(lockName) == null) {
+            locks.put(lockName, new AtomicBoolean(true));
+        } else {
+            locks.get(lockName).set(true);
+        }
+
         return new GlobalLock() {
             @Override
             public void release() {
+                locks.get(lockName).set(false);
             }
         };
     }
 
     @Override
-    public Boolean isFree(final LockerType service, final String lockKey) {
-        return Boolean.TRUE;
+    public synchronized Boolean isFree(final LockerType service, final String lockKey) {
+        final String lockName = getLockName(service, lockKey);
+        return isFree(lockName);
+    }
+
+    private synchronized Boolean isFree(final String lockName) {
+        final AtomicBoolean lock = locks.get(lockName);
+        return lock == null || !lock.get();
+    }
+
+    private String getLockName(final LockerType service, final String lockKey) {
+        return String.format("%s-%s", service.toString(), lockKey);
     }
 }
diff --git a/util/src/test/java/com/ning/billing/util/globallocker/TestMysqlGlobalLocker.java b/util/src/test/java/com/ning/billing/util/globallocker/TestMysqlGlobalLocker.java
index a006e58..9f787d0 100644
--- a/util/src/test/java/com/ning/billing/util/globallocker/TestMysqlGlobalLocker.java
+++ b/util/src/test/java/com/ning/billing/util/globallocker/TestMysqlGlobalLocker.java
@@ -41,14 +41,14 @@ public class TestMysqlGlobalLocker extends UtilTestSuiteWithEmbeddedDB {
     @Inject
     private IDBI dbi;
 
-    @BeforeMethod(groups = "slow")
+    @BeforeMethod(groups = "mysql")
     public void setup() throws IOException {
         final String testDdl = IOUtils.toString(TestMysqlGlobalLocker.class.getResourceAsStream("/com/ning/billing/util/ddl_test.sql"));
         helper.initDb(testDdl);
     }
 
     // Used as a manual test to validate the simple DAO by stepping through that locking is done and release correctly
-    @Test(groups = "slow")
+    @Test(groups = "mysql")
     public void testSimpleLocking() {
         final String lockName = UUID.randomUUID().toString();