This is an automated email from the ASF dual-hosted git repository.

dlmarion pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo.git


The following commit(s) were added to refs/heads/main by this push:
     new 30a74e2400 Execute Caffeine tasks in current Thread for tests (#2691)
30a74e2400 is described below

commit 30a74e24008e6015d56443cebb348d257ba6420d
Author: Dave Marion <dlmar...@apache.org>
AuthorDate: Wed May 11 12:09:26 2022 -0400

    Execute Caffeine tasks in current Thread for tests (#2691)
    
    * Execute Caffeine tasks in current Thread for tests
    
    As described at https://github.com/ben-manes/caffeine/wiki/Testing, Caffeine
    delegates maintenance tasks (eviction, refreshes, etc.) to background 
threads
    to take advantage of batching. This change implements the suggestion at
    https://github.com/ben-manes/caffeine/issues/455#issuecomment-689398669 to
    run all of the maintenance tasks in the current Thread for testing. Using
    Cache.cleanup as suggested in the wiki page did not appear to work, but this
    approach allows us to remove all of the calls to Thread.sleep in the tests.
---
 .../conf/store/impl/PropCacheCaffeineImpl.java     | 23 +++++------
 .../server/conf/store/impl/ZooPropStore.java       |  9 +----
 .../conf/store/impl/PropCacheCaffeineImplTest.java |  6 +--
 .../server/conf/store/impl/ZooPropLoaderTest.java  | 47 +++++++---------------
 .../accumulo/test/conf/store/ZooBasedConfigIT.java |  2 -
 5 files changed, 28 insertions(+), 59 deletions(-)

diff --git 
a/server/base/src/main/java/org/apache/accumulo/server/conf/store/impl/PropCacheCaffeineImpl.java
 
b/server/base/src/main/java/org/apache/accumulo/server/conf/store/impl/PropCacheCaffeineImpl.java
index d1664b8fcb..6433a51a4c 100644
--- 
a/server/base/src/main/java/org/apache/accumulo/server/conf/store/impl/PropCacheCaffeineImpl.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/conf/store/impl/PropCacheCaffeineImpl.java
@@ -35,7 +35,6 @@ import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.LoadingCache;
 import com.github.benmanes.caffeine.cache.RemovalCause;
 import com.github.benmanes.caffeine.cache.Ticker;
-import com.google.common.annotations.VisibleForTesting;
 
 public class PropCacheCaffeineImpl implements PropCache {
 
@@ -51,11 +50,15 @@ public class PropCacheCaffeineImpl implements PropCache {
   private final LoadingCache<PropCacheKey<?>,VersionedProperties> cache;
 
   private PropCacheCaffeineImpl(final 
CacheLoader<PropCacheKey<?>,VersionedProperties> cacheLoader,
-      final PropStoreMetrics metrics, final Ticker ticker) {
+      final PropStoreMetrics metrics, final Ticker ticker, boolean 
runTasksInline) {
     this.metrics = metrics;
     var builder = Caffeine.newBuilder().refreshAfterWrite(REFRESH_MIN, 
BASE_TIME_UNITS)
-        .expireAfterAccess(EXPIRE_MIN, 
BASE_TIME_UNITS).evictionListener(this::evictionNotifier)
-        .executor(executor);
+        .expireAfterAccess(EXPIRE_MIN, 
BASE_TIME_UNITS).evictionListener(this::evictionNotifier);
+    if (runTasksInline) {
+      builder = builder.executor(Runnable::run);
+    } else {
+      builder = builder.executor(executor);
+    }
     if (ticker != null) {
       builder = builder.ticker(ticker);
     }
@@ -95,12 +98,6 @@ public class PropCacheCaffeineImpl implements PropCache {
     cache.invalidateAll();
   }
 
-  /** for testing - force Caffeine housekeeping to run. */
-  @VisibleForTesting
-  void cleanUp() {
-    cache.cleanUp();
-  }
-
   /**
    * Retrieve the version properties if present in the cache, otherwise return 
null. This prevents
    * caching the properties and should be used when properties will be updated 
and then committed to
@@ -122,6 +119,7 @@ public class PropCacheCaffeineImpl implements PropCache {
     private final PropStoreMetrics metrics;
     private final ZooPropLoader zooPropLoader;
     private Ticker ticker = null;
+    private boolean runTasksInline = false;
 
     public Builder(final ZooPropLoader zooPropLoader, final PropStoreMetrics 
metrics) {
       Objects.requireNonNull(zooPropLoader, "A PropStoreChangeMonitor must be 
provided");
@@ -130,11 +128,12 @@ public class PropCacheCaffeineImpl implements PropCache {
     }
 
     public PropCacheCaffeineImpl build() {
-      return new PropCacheCaffeineImpl(zooPropLoader, metrics, ticker);
+      return new PropCacheCaffeineImpl(zooPropLoader, metrics, ticker, 
runTasksInline);
     }
 
-    public Builder withTicker(final Ticker ticker) {
+    public Builder forTests(final Ticker ticker) {
       this.ticker = ticker;
+      this.runTasksInline = true;
       return this;
     }
   }
diff --git 
a/server/base/src/main/java/org/apache/accumulo/server/conf/store/impl/ZooPropStore.java
 
b/server/base/src/main/java/org/apache/accumulo/server/conf/store/impl/ZooPropStore.java
index 7c522e0e2f..f8449f0497 100644
--- 
a/server/base/src/main/java/org/apache/accumulo/server/conf/store/impl/ZooPropStore.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/conf/store/impl/ZooPropStore.java
@@ -46,7 +46,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.github.benmanes.caffeine.cache.Ticker;
-import com.google.common.annotations.VisibleForTesting;
 
 public class ZooPropStore implements PropStore, PropChangeListener {
 
@@ -103,7 +102,7 @@ public class ZooPropStore implements PropStore, 
PropChangeListener {
       this.cache = new PropCacheCaffeineImpl.Builder(propLoader, 
cacheMetrics).build();
     } else {
       this.cache =
-          new PropCacheCaffeineImpl.Builder(propLoader, 
cacheMetrics).withTicker(ticker).build();
+          new PropCacheCaffeineImpl.Builder(propLoader, 
cacheMetrics).forTests(ticker).build();
     }
 
     MetricsUtil.initializeProducers(cacheMetrics);
@@ -355,12 +354,6 @@ public class ZooPropStore implements PropStore, 
PropChangeListener {
     cache.removeAll();
   }
 
-  /** for testing - force Caffeine housekeeping to run. */
-  @VisibleForTesting
-  public void cleanUp() {
-    ((PropCacheCaffeineImpl) cache).cleanUp();
-  }
-
   /**
    * Read and decode property node from ZooKeeper.
    *
diff --git 
a/server/base/src/test/java/org/apache/accumulo/server/conf/store/impl/PropCacheCaffeineImplTest.java
 
b/server/base/src/test/java/org/apache/accumulo/server/conf/store/impl/PropCacheCaffeineImplTest.java
index d6a766e7d3..6b6b2858ae 100644
--- 
a/server/base/src/test/java/org/apache/accumulo/server/conf/store/impl/PropCacheCaffeineImplTest.java
+++ 
b/server/base/src/test/java/org/apache/accumulo/server/conf/store/impl/PropCacheCaffeineImplTest.java
@@ -87,8 +87,7 @@ public class PropCacheCaffeineImplTest {
 
     expect(context.getInstanceID()).andReturn(instanceId).anyTimes();
 
-    cache =
-        new PropCacheCaffeineImpl.Builder(zooPropLoader, 
cacheMetrics).withTicker(ticker).build();
+    cache = new PropCacheCaffeineImpl.Builder(zooPropLoader, 
cacheMetrics).forTests(ticker).build();
 
   }
 
@@ -175,11 +174,9 @@ public class PropCacheCaffeineImplTest {
     assertNotNull(cache.get(tablePropKey)); // will call load and place into 
cache
 
     ticker.advance(30, TimeUnit.MINUTES);
-    cache.cleanUp();
     assertNotNull(cache.get(tablePropKey)); // will async check stat and then 
reload
   }
 
-  @SuppressWarnings({"rawtypes"})
   @Test
   public void expireTest() {
     expect(zooPropLoader.load(eq(tablePropKey))).andReturn(vProps).times(2);
@@ -188,7 +185,6 @@ public class PropCacheCaffeineImplTest {
     assertNotNull(cache.get(tablePropKey)); // will call load
 
     ticker.advance(90, TimeUnit.MINUTES);
-    cache.cleanUp();
     assertNotNull(cache.get(tablePropKey)); // expired - will call load.
   }
 
diff --git 
a/server/base/src/test/java/org/apache/accumulo/server/conf/store/impl/ZooPropLoaderTest.java
 
b/server/base/src/test/java/org/apache/accumulo/server/conf/store/impl/ZooPropLoaderTest.java
index 84a809bd1c..ba376dc22d 100644
--- 
a/server/base/src/test/java/org/apache/accumulo/server/conf/store/impl/ZooPropLoaderTest.java
+++ 
b/server/base/src/test/java/org/apache/accumulo/server/conf/store/impl/ZooPropLoaderTest.java
@@ -148,7 +148,7 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // load into cache
     assertNotNull(cache.get(propCacheKey));
@@ -186,7 +186,7 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     assertNull(cache.get(propCacheKey));
 
@@ -215,13 +215,12 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // load cache
     assertNotNull(cache.get(propCacheKey));
 
     ticker.advance(70, TimeUnit.MINUTES);
-    cache.cleanUp();
 
     assertNotNull(cache.get(propCacheKey));
 
@@ -267,26 +266,21 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // prime cache
     assertNotNull(cache.get(propCacheKey));
 
     ticker.advance(5, TimeUnit.MINUTES);
-    cache.cleanUp();
 
     // read cached value
     assertNotNull(cache.get(propCacheKey));
 
     // advance so refresh called.
     ticker.advance(20, TimeUnit.MINUTES);
-    cache.cleanUp();
 
     assertNotNull(cache.get(propCacheKey));
 
-    // yield so async thread completes.
-    Thread.sleep(250);
-
     assertNull(cache.get(propCacheKey));
   }
 
@@ -296,7 +290,7 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     assertNull(cache.getWithoutCaching(propCacheKey));
 
@@ -320,14 +314,13 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // load into cache
     assertNotNull(cache.get(sysPropKey));
     assertNotNull(cache.get(tablePropKey));
 
     cache.remove(tablePropKey);
-    cache.cleanUp();
 
     // verify retrieved from cache without loading.
     assertNotNull(cache.getWithoutCaching(sysPropKey));
@@ -352,14 +345,13 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // load into cache
     assertNotNull(cache.get(sysPropKey));
     assertNotNull(cache.get(tablePropKey));
 
     cache.removeAll();
-    cache.cleanUp();
 
     // verify retrieved from cache without loading.
     assertNull(cache.getWithoutCaching(sysPropKey));
@@ -371,7 +363,7 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // load into cache
     assertNull(cache.getWithoutCaching(propCacheKey));
@@ -406,7 +398,7 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // load cache
     log.debug("received: {}", cache.get(propCacheKey));
@@ -419,14 +411,10 @@ public class ZooPropLoaderTest {
 
     assertNotNull(cache.get(propCacheKey));
 
-    Thread.sleep(100);
-
     ticker.advance(REFRESH_MIN + 1, TimeUnit.MINUTES);
 
     assertNotNull(cache.get(propCacheKey));
 
-    Thread.sleep(100);
-
     ticker.advance(1, TimeUnit.MINUTES);
 
     assertNotNull(cache.get(propCacheKey));
@@ -490,10 +478,12 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // prime cache
-    assertNotNull(cache.get(propCacheKey));
+    var origProps = cache.get(propCacheKey);
+    assertNotNull(origProps);
+    assertEquals("7G", 
origProps.asMap().get(Property.TABLE_SPLIT_THRESHOLD.getKey()));
 
     ticker.advance(REFRESH_MIN + 1, TimeUnit.MINUTES);
     // first call after refresh return original and schedules update
@@ -501,15 +491,11 @@ public class ZooPropLoaderTest {
     assertNotNull(originalProps);
     
assertNotNull(originalProps.asMap().get(Property.TABLE_SPLIT_THRESHOLD.getKey()));
 
-    // allow refresh thread to run
-    Thread.sleep(50);
-
     // refresh should have loaded updated value;
     var updatedProps = cache.get(propCacheKey);
     log.debug("Updated props: {}", updatedProps == null ? "null" : 
updatedProps.print(true));
 
     assertNotNull(updatedProps);
-    Thread.sleep(250);
 
     assertEquals("12G", 
updatedProps.asMap().get(Property.TABLE_SPLIT_THRESHOLD.getKey()));
   }
@@ -558,19 +544,17 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics, mockProps);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // prime cache
     cache.get(propCacheKey);
 
     ticker.advance(30, TimeUnit.MINUTES);
-    cache.cleanUp();
 
     VersionedProperties vPropsRead = cache.get(propCacheKey);
 
     assertNotNull(vPropsRead);
 
-    Thread.sleep(250);
     cache.get(propCacheKey);
 
     verify(mockProps);
@@ -619,7 +603,7 @@ public class ZooPropLoaderTest {
     replay(context, zrw, propStoreWatcher, cacheMetrics);
 
     PropCacheCaffeineImpl cache =
-        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).withTicker(ticker).build();
+        new PropCacheCaffeineImpl.Builder(loader, 
cacheMetrics).forTests(ticker).build();
 
     // load cache
     log.debug("received: {}", cache.get(propCacheKey));
@@ -628,7 +612,6 @@ public class ZooPropLoaderTest {
 
     assertNotNull(cache.get(propCacheKey)); // returns current and queues 
async refresh
 
-    Thread.sleep(150);
     assertNull(cache.get(propCacheKey)); // on exception, the loader should 
return null
 
   }
diff --git 
a/test/src/main/java/org/apache/accumulo/test/conf/store/ZooBasedConfigIT.java 
b/test/src/main/java/org/apache/accumulo/test/conf/store/ZooBasedConfigIT.java
index 34a32333ec..a6ab8fe8a4 100644
--- 
a/test/src/main/java/org/apache/accumulo/test/conf/store/ZooBasedConfigIT.java
+++ 
b/test/src/main/java/org/apache/accumulo/test/conf/store/ZooBasedConfigIT.java
@@ -281,8 +281,6 @@ public class ZooBasedConfigIT {
     // advance well past unload period.
     ticker.advance(2, TimeUnit.HOURS);
 
-    // force clean-up and cache activity to get async unload to occur.
-    ((ZooPropStore) propStore).cleanUp();
     var tableBPropKey = TablePropKey.of(INSTANCE_ID, tidB);
     propStore.create(tableBPropKey, Map.of());
     Thread.sleep(150);

Reply via email to