diff --git a/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/DefaultAutoTuneService.java b/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/DefaultAutoTuneService.java index f47b29ba8..11182ec19 100644 --- a/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/DefaultAutoTuneService.java +++ b/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/DefaultAutoTuneService.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; /** * Implementation of the AutoTuneService which is comprised of profiling and query tuning. @@ -22,6 +23,8 @@ public class DefaultAutoTuneService implements AutoTuneService { private static final Logger logger = LoggerFactory.getLogger(DefaultAutoTuneService.class); + private final ReentrantLock lock = new ReentrantLock(false); + private final SpiEbeanServer server; private final long defaultGarbageCollectionWait; @@ -127,8 +130,8 @@ public class DefaultAutoTuneService implements AutoTuneService { * Collect profiling, check for new/diff to existing tuning and apply changes. */ private void runtimeTuningUpdate() { - - synchronized (this) { + lock.lock(); + try { try { long start = System.currentTimeMillis(); @@ -150,12 +153,14 @@ public class DefaultAutoTuneService implements AutoTuneService { } catch (Throwable e) { logger.error("Error collecting or applying automatic query tuning", e); } + } finally { + lock.unlock(); } } private void saveProfilingOnShutdown(boolean reset) { - - synchronized (this) { + lock.lock(); + try { if (isRuntimeTuningUpdates()) { runtimeTuningUpdate(); outputAllTuning(); @@ -174,6 +179,8 @@ public class DefaultAutoTuneService implements AutoTuneService { logger.info("writing new:{} diff:{} profiling entries for server:{}", event.getNewCount(), event.getDiffCount(), serverName); } } + } finally { + lock.unlock(); } } diff --git a/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileManager.java b/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileManager.java index 1486ecc57..dfbdc5800 100644 --- a/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileManager.java +++ b/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileManager.java @@ -11,12 +11,15 @@ import io.ebeaninternal.server.deploy.BeanDescriptor; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantLock; /** * Manages the collection of object graph usage profiling. */ public class ProfileManager implements ProfilingListener { + private final ReentrantLock lock = new ReentrantLock(false); + private final boolean queryTuningAddVersion; /** @@ -32,8 +35,6 @@ public class ProfileManager implements ProfilingListener { */ private final Map profileMap = new ConcurrentHashMap<>(); - private final Object monitor = new Object(); - private final SpiEbeanServer server; public ProfileManager(AutoTuneConfig config, SpiEbeanServer server) { @@ -101,8 +102,11 @@ public class ProfileManager implements ProfilingListener { } private ProfileOrigin getProfileOrigin(ObjectGraphOrigin originQueryPoint) { - synchronized (monitor) { + lock.lock(); + try { return profileMap.computeIfAbsent(originQueryPoint.getKey(), k -> new ProfileOrigin(originQueryPoint, queryTuningAddVersion, profilingBase, profilingRate)); + } finally { + lock.unlock(); } } diff --git a/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileOrigin.java b/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileOrigin.java index 0ddf120d3..62feec130 100644 --- a/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileOrigin.java +++ b/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileOrigin.java @@ -12,9 +12,12 @@ import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReentrantLock; public class ProfileOrigin { + private final ReentrantLock lock = new ReentrantLock(false); + private static final long RESET_COUNT = -1000000000L; private final ObjectGraphOrigin origin; @@ -29,8 +32,6 @@ public class ProfileOrigin { private final Map nodeUsageMap = new ConcurrentHashMap<>(); - private final Object monitor = new Object(); - private final AtomicLong requestCount = new AtomicLong(); private final AtomicLong profileCount = new AtomicLong(); @@ -74,8 +75,8 @@ public class ProfileOrigin { * Collect profiling information with the option to reset the underlying profiling detail. */ public void profilingCollection(BeanDescriptor rootDesc, AutoTuneCollection req, boolean reset) { - - synchronized (monitor) { + lock.lock(); + try { if (nodeUsageMap.isEmpty()) { return; } @@ -94,6 +95,8 @@ public class ProfileOrigin { profileCount.set(0); } } + } finally { + lock.unlock(); } } @@ -155,8 +158,8 @@ public class ProfileOrigin { } private ProfileOriginNodeUsage getNodeStats(String path) { - - synchronized (monitor) { + lock.lock(); + try { // handle null paths as using ConcurrentHashMap path = (path == null) ? "" : path; ProfileOriginNodeUsage nodeStats = nodeUsageMap.get(path); @@ -165,6 +168,8 @@ public class ProfileOrigin { nodeUsageMap.put(path, nodeStats); } return nodeStats; + } finally { + lock.unlock(); } } diff --git a/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileOriginNodeUsage.java b/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileOriginNodeUsage.java index be6d840b8..dc632e2cd 100644 --- a/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileOriginNodeUsage.java +++ b/ebean-autotune/src/main/java/io/ebeaninternal/server/autotune/service/ProfileOriginNodeUsage.java @@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory; import java.util.LinkedHashSet; import java.util.Set; +import java.util.concurrent.locks.ReentrantLock; /** * Collects usages statistics for a given node in the object graph. @@ -20,7 +21,7 @@ public class ProfileOriginNodeUsage { private static final Logger logger = LoggerFactory.getLogger(ProfileOriginNodeUsage.class); - private final Object monitor = new Object(); + private final ReentrantLock lock = new ReentrantLock(false); private final String path; @@ -38,9 +39,8 @@ public class ProfileOriginNodeUsage { } protected void buildTunedFetch(PathProperties pathProps, BeanDescriptor rootDesc, boolean addVersionProperty) { - - synchronized (monitor) { - + lock.lock(); + try { BeanDescriptor desc = rootDesc; if (path != null) { ElPropertyValue elGetValue = rootDesc.getElGetValue(path); @@ -95,6 +95,8 @@ public class ProfileOriginNodeUsage { ElPropertyValue assocOne = rootDesc.getElGetValue(path); pathProps.addToPath(SplitName.parent(path), assocOne.getName()); } + } finally { + lock.unlock(); } } @@ -102,9 +104,8 @@ public class ProfileOriginNodeUsage { * Collect usage from a node. */ protected void collectUsageInfo(NodeUsageCollector profile) { - - synchronized (monitor) { - + lock.lock(); + try { Set used = profile.getUsed(); profileCount++; @@ -115,6 +116,8 @@ public class ProfileOriginNodeUsage { if (profile.isModified()) { modified = true; } + } finally { + lock.unlock(); } }