Refactor synchronized to ReentrantLock (#2081)

This commit is contained in:
Rob Bygrave authored and GitHub committed 2020-10-16 00:20:42 +13:00
1 parent 0faa6a8efd
commit 14181932ec
30 files changed
+368 -185

No files matched your search

@@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.locks.ReentrantLock;
/**
* Manages the construction of caches.
@@ -26,17 +27,14 @@ class DefaultCacheHolder {
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.ALL");
private final ReentrantLock lock = new ReentrantLock(false);
private final ConcurrentHashMap<String, ServerCache> allCaches = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Set<String>> collectIdCaches = new ConcurrentHashMap<>();
private final ServerCacheFactory cacheFactory;
private final ServerCacheOptions beanDefault;
private final ServerCacheOptions queryDefault;
private final CurrentTenantProvider tenantProvider;
private final QueryCacheEntryValidate queryCacheEntryValidate;
DefaultCacheHolder(CacheManagerOptions builder) {
@@ -87,8 +85,11 @@ class DefaultCacheHolder {
private ServerCache createCache(Class<?> beanType, ServerCacheType type, String key, String shortName) {
ServerCacheOptions options = getCacheOptions(beanType, type);
if (type == ServerCacheType.COLLECTION_IDS) {
synchronized (this) {
lock.lock();
try {
collectIdCaches.computeIfAbsent(beanType.getName(), s -> new ConcurrentSkipListSet<>()).add(key);
} finally {
lock.unlock();
}
}
return cacheFactory.createCache(new ServerCacheConfig(type, key, shortName, options, tenantProvider, queryCacheEntryValidate));
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* Manages the cluster service.
@@ -17,6 +18,8 @@ public class ClusterManager implements ServerLookup {
private static final Logger clusterLogger = LoggerFactory.getLogger("io.ebean.Cluster");
private final ReentrantLock lock = new ReentrantLock(false);
private final ConcurrentHashMap<String, EbeanServer> serverMap = new ConcurrentHashMap<>();
private final Object monitor = new Object();
@@ -51,18 +54,24 @@ public class ClusterManager implements ServerLookup {
}
public void registerServer(EbeanServer server) {
synchronized (monitor) {
lock.lock();
try {
serverMap.put(server.getName(), server);
if (!started) {
startup();
}
} finally {
lock.unlock();
}
}
@Override
public EbeanServer getServer(String name) {
synchronized (monitor) {
lock.lock();
try {
return serverMap.get(name);
} finally {
lock.unlock();
}
}
@@ -26,6 +26,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.ServiceLoader;
import java.util.concurrent.locks.ReentrantLock;
/**
* Default Server side implementation of ServerFactory.
@@ -34,6 +35,7 @@ public class DefaultContainer implements SpiContainer {
private static final Logger logger = LoggerFactory.getLogger("io.ebean.internal.DefaultContainer");
private final ReentrantLock lock = new ReentrantLock(false);
private final ClusterManager clusterManager;
public DefaultContainer(ContainerConfig containerConfig) {
@@ -72,7 +74,8 @@ public class DefaultContainer implements SpiContainer {
*/
@Override
public SpiEbeanServer createServer(DatabaseConfig config) {
synchronized (this) {
lock.lock();
try {
applyConfigServices(config);
setNamingConvention(config);
BootupClasses bootupClasses = getBootupClasses(config);
@@ -114,6 +117,8 @@ public class DefaultContainer implements SpiContainer {
}
DbOffline.reset();
return server;
} finally {
lock.unlock();
}
}
@@ -36,11 +36,13 @@ import io.ebean.Version;
import io.ebean.annotation.Platform;
import io.ebean.annotation.TxIsolation;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanLoader;
import io.ebean.bean.CallOrigin;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.PersistenceContext;
import io.ebean.bean.PersistenceContext.WithOption;
import io.ebean.bean.SingleBeanLoader;
import io.ebean.cache.ServerCacheManager;
import io.ebean.common.CopyOnFirstWriteList;
import io.ebean.config.CurrentTenantProvider;
@@ -142,6 +144,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -157,98 +160,47 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
private static final Logger logger = LoggerFactory.getLogger(DefaultServer.class);
private final ReentrantLock lock = new ReentrantLock(false);
private final DatabaseConfig config;
private final String serverName;
private final DatabasePlatform databasePlatform;
private final TransactionManager transactionManager;
private final QueryPlanManager queryPlanManager;
private final ExtraMetrics extraMetrics;
private final DataTimeZone dataTimeZone;
/**
* Clock to use for WhenModified and WhenCreated.
*/
private final ClockService clockService;
private final CallOriginFactory callStackFactory;
/**
* Handles the save, delete, updateSql CallableSql.
*/
private final Persister persister;
private final OrmQueryEngine queryEngine;
private final RelationalQueryEngine relationalQueryEngine;
private final DtoQueryEngine dtoQueryEngine;
private final ServerCacheManager serverCacheManager;
private final DtoBeanManager dtoBeanManager;
private final BeanDescriptorManager beanDescriptorManager;
private final AutoTuneService autoTuneService;
private final ReadAuditPrepare readAuditPrepare;
private final ReadAuditLogger readAuditLogger;
private final CQueryEngine cqueryEngine;
private final List<Plugin> serverPlugins;
private final SpiDdlGenerator ddlGenerator;
private final ScriptRunner scriptRunner;
private final ExpressionFactory expressionFactory;
private final SpiBackgroundExecutor backgroundExecutor;
private final DefaultBeanLoader beanLoader;
private final EncryptKeyManager encryptKeyManager;
private final SpiJsonContext jsonContext;
private final DocumentStore documentStore;
private final MetaInfoManager metaInfoManager;
private final CurrentTenantProvider currentTenantProvider;
private final SpiLogManager logManager;
/**
* The default PersistenceContextScope used if it is not explicitly set on a query.
*/
private final PersistenceContextScope defaultPersistenceContextScope;
/**
* Flag set when the server has shutdown.
*/
private boolean shutdown;
/**
* The default batch size for lazy loading beans or collections.
*/
private final int lazyLoadBatchSize;
private final int queryBatchSize;
private final boolean updateAllPropertiesInBatch;
private final long slowQueryMicros;
private final SlowQueryListener slowQueryListener;
private final boolean disableL2Cache;
private boolean shutdown;
/**
* Create the DefaultServer.
@@ -452,8 +404,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
public void shutdown() {
synchronized (this) {
lock.lock();
try {
shutdownInternal(true, false);
} finally {
lock.unlock();
}
}
@@ -462,10 +417,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
*/
@Override
public void shutdown(boolean shutdownDataSource, boolean deregisterDriver) {
synchronized (this) {
// Unregister from JVM Shutdown hook
lock.lock();
try {
ShutdownManager.unregisterDatabase(this);
shutdownInternal(shutdownDataSource, deregisterDriver);
} finally {
lock.unlock();
}
}
@@ -575,6 +532,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
beanLoader.loadBean(loadRequest);
}
@Override
public BeanLoader beanLoader() {
return new SingleBeanLoader.Dflt(this);
}
@Override
public void loadBean(EntityBeanIntercept ebi) {
beanLoader.loadBean(ebi);
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.core;
import java.util.HashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* Used to reduce memory consumption of strings used in deployment processing.
@@ -12,6 +13,8 @@ public final class InternString {
private static final HashMap<String, String> map = new HashMap<>();
private static final ReentrantLock lock = new ReentrantLock(false);
/**
* Return the shared instance of this string.
*/
@@ -19,8 +22,8 @@ public final class InternString {
if (s == null) {
return null;
}
//noinspection SynchronizationOnStaticField
synchronized (map) {
lock.lock();
try {
String v = map.get(s);
if (v != null) {
return v;
@@ -28,6 +31,8 @@ public final class InternString {
map.put(s, s);
return s;
}
} finally {
lock.unlock();
}
}
}
@@ -7,6 +7,7 @@ import java.security.SecureRandom;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,6 +45,8 @@ public class UuidV1RndIdGenerator implements PlatformIdGenerator {
private AtomicLong nanoToMilliOffset = new AtomicLong(currentUuidTime());
private final ReentrantLock lock = new ReentrantLock(false);
/**
* Returns the uuid epoch.
@@ -106,7 +109,8 @@ public class UuidV1RndIdGenerator implements PlatformIdGenerator {
logger.info("Clock skew of {} ms detected", delta / -10000);
// The clock was adjusted back about 2 seconds, or we were generating a lot of ids too fast
// if so, we try to set the current as last and also increment the clockSeq.
synchronized (this) {
lock.lock();
try {
if (clockSeq.compareAndSet(seq, seq + 1)) {
timeStamp.set(current);
saveState();
@@ -114,6 +118,8 @@ public class UuidV1RndIdGenerator implements PlatformIdGenerator {
} else {
continue;
}
} finally {
lock.unlock();
}
}
// If current is in the future (most of the cases) try to set it.
@@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* A "CachedThreadPool" based on Daemon threads.
@@ -16,6 +17,8 @@ public final class DaemonExecutorService {
private static final Logger logger = LoggerFactory.getLogger(DaemonExecutorService.class);
private final ReentrantLock lock = new ReentrantLock(false);
private final String namePrefix;
private final int shutdownWaitSeconds;
@@ -49,7 +52,8 @@ public final class DaemonExecutorService {
* </p>
*/
public void shutdown() {
synchronized (this) {
lock.lock();
try {
if (service.isShutdown()) {
logger.debug("DaemonExecutorService[{}] already shut down", namePrefix);
return;
@@ -66,6 +70,8 @@ public final class DaemonExecutorService {
logger.error("Error during shutdown of DaemonThreadPool[" + namePrefix + "]", e);
e.printStackTrace();
}
} finally {
lock.unlock();
}
}
@@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* Daemon based ScheduleThreadPool.
@@ -16,6 +17,8 @@ public final class DaemonScheduleThreadPool extends ScheduledThreadPoolExecutor
private static final Logger logger = LoggerFactory.getLogger(DaemonScheduleThreadPool.class);
private final ReentrantLock lock = new ReentrantLock(false);
private final String namePrefix;
private final int shutdownWaitSeconds;
@@ -38,7 +41,8 @@ public final class DaemonScheduleThreadPool extends ScheduledThreadPoolExecutor
*/
@Override
public void shutdown() {
synchronized (this) {
lock.lock();
try {
if (super.isShutdown()) {
logger.debug("DaemonScheduleThreadPool {} already shut down", namePrefix);
return;
@@ -55,6 +59,8 @@ public final class DaemonScheduleThreadPool extends ScheduledThreadPoolExecutor
logger.error("Error during shutdown of " + namePrefix, e);
e.printStackTrace();
}
} finally {
lock.unlock();
}
}
}
@@ -7,11 +7,15 @@ import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
import java.util.concurrent.locks.ReentrantLock;
/**
* Base class for Bean and BeanCollection loading (lazy loading and query join loading).
*/
abstract class DLoadBaseContext {
protected final ReentrantLock lock = new ReentrantLock(false);
protected final DLoadContext parent;
protected final BeanDescriptor<?> desc;
@@ -17,6 +17,8 @@ import io.ebeaninternal.server.querydefn.OrmQueryProperties;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* ToOne bean load context.
@@ -86,11 +88,11 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
@Override
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, boolean forEach) {
if (!queryFetch) {
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
}
synchronized (this) {
lock.lock();
try {
if (bufferList != null) {
for (LoadBuffer loadBuffer : bufferList) {
if (!loadBuffer.list.isEmpty()) {
@@ -108,6 +110,8 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
}
}
}
} finally {
lock.unlock();
}
}
@@ -116,6 +120,7 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
*/
static class LoadBuffer implements BeanLoader, LoadBeanBuffer {
private final ReentrantLock bufferLock = new ReentrantLock(false);
private final DLoadBeanContext context;
private final int batchSize;
private final List<EntityBeanIntercept> list;
@@ -127,6 +132,12 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
this.list = new ArrayList<>(batchSize);
}
@Override
public Lock lock() {
bufferLock.lock();
return bufferLock;
}
@Override
public int getBatchSize() {
return batchSize;
@@ -182,7 +193,7 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
@Override
public void loadBean(EntityBeanIntercept ebi) {
// A synchronized (this) is effectively held by EntityBeanIntercept.loadBean()
// A lock is effectively held by EntityBeanIntercept.loadBean()
if (context.desc.lazyLoadMany(ebi, context)) {
// lazy load property was a Many
return;
@@ -16,6 +16,7 @@ import io.ebeaninternal.server.querydefn.OrmQueryProperties;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
/**
* ToMany bean load context.
@@ -94,11 +95,11 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
@Override
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, boolean forEach) {
if (!queryFetch) {
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
}
synchronized (this) {
lock.lock();
try {
if (bufferList != null) {
for (LoadBuffer loadBuffer : bufferList) {
if (!loadBuffer.list.isEmpty()) {
@@ -118,6 +119,8 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
this.bufferList = null;
}
}
} finally {
lock.unlock();
}
}
@@ -127,6 +130,7 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
*/
static class LoadBuffer implements BeanCollectionLoader, LoadManyBuffer {
private final ReentrantLock lock = new ReentrantLock(false);
private final PersistenceContext persistenceContext;
private final DLoadManyContext context;
private final int batchSize;
@@ -208,7 +212,8 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
@Override
public void loadMany(BeanCollection<?> bc, boolean onlyIds) {
synchronized (this) {
lock.lock();
try {
boolean useCache = !onlyIds && context.hitCache && context.property.isUseCache();
if (useCache) {
EntityBean ownerBean = bc.getOwnerBean();
@@ -231,6 +236,8 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
LoadManyRequest req = new LoadManyRequest(this, onlyIds, useCache);
context.parent.getEbeanServer().loadMany(req);
} finally {
lock.unlock();
}
}
@@ -39,6 +39,7 @@ import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
/**
* An object that represents a SqlSelect statement.
@@ -58,6 +59,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
private static final CQueryCollectionAddNoop NOOP_ADD = new CQueryCollectionAddNoop();
private final ReentrantLock lock = new ReentrantLock(false);
/**
* The resultSet rows read.
*/
@@ -288,7 +291,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
@Override
public void cancel() {
synchronized (this) {
lock.lock();
try {
this.cancelled = true;
if (pstmt != null) {
try {
@@ -298,6 +302,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
throw new PersistenceException(msg, e);
}
}
} finally {
lock.unlock();
}
}
@@ -326,8 +332,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
}
ResultSet prepareResultSet(boolean forwardOnlyHint) throws SQLException {
synchronized (this) {
lock.lock();
try {
if (cancelled || query.isCancelled()) {
// cancelled before we started
cancelled = true;
@@ -370,6 +376,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
// executeQuery
return pstmt.executeQuery();
} finally {
lock.unlock();
}
}
@@ -524,8 +532,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
}
boolean hasNext() throws SQLException {
synchronized (this) {
lock.lock();
try {
if (noMoreRows || cancelled) {
return false;
}
@@ -534,6 +542,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
}
hasNextCache = readNextBean();
return hasNextCache;
} finally {
lock.unlock();
}
}
@@ -5,10 +5,13 @@ import io.ebeaninternal.api.SpiQueryBindCapture;
import io.ebeaninternal.api.SpiQueryPlan;
import io.ebeaninternal.server.type.bindcapture.BindCapture;
import java.util.concurrent.locks.ReentrantLock;
class CQueryBindCapture implements SpiQueryBindCapture {
private static final double multiplier = 1.3d;
private final ReentrantLock lock = new ReentrantLock(false);
private final CQueryPlanManager manager;
private final SpiQueryPlan queryPlan;
@@ -35,13 +38,16 @@ class CQueryBindCapture implements SpiQueryBindCapture {
@Override
public void setBind(BindCapture bindCapture, long queryTimeMicros, long startNanos) {
synchronized (this) {
lock.lock();
try {
this.thresholdMicros = Math.round(queryTimeMicros * multiplier);
this.captureCount++;
this.bindCapture = bindCapture;
this.queryTimeMicros = queryTimeMicros;
lastBindCapture = System.currentTimeMillis();
manager.notifyBindCapture(this, startNanos);
} finally {
lock.unlock();
}
}
@@ -1,31 +1,29 @@
package io.ebeaninternal.server.query;
import io.ebean.PagedList;
import io.ebeaninternal.api.Monitor;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import javax.persistence.PersistenceException;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReentrantLock;
/**
* PagedList implementation based on limit offset types of queries.
*
* @param <T> the entity bean type
*/
public class LimitOffsetPagedList<T> implements PagedList<T> {
private final transient SpiEbeanServer server;
private final transient ReentrantLock lock = new ReentrantLock(false);
private final SpiQuery<T> query;
private final int firstRow;
private final int maxRows;
private final Monitor monitor = new Monitor();
private int foregroundTotalRowCount = -1;
private Future<Integer> futureRowCount;
@@ -49,21 +47,27 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
@Override
public Future<Integer> getFutureCount() {
synchronized (monitor) {
lock.lock();
try {
if (futureRowCount == null) {
futureRowCount = server.findFutureCount(query, null);
}
return futureRowCount;
} finally {
lock.unlock();
}
}
@Override
public List<T> getList() {
synchronized (monitor) {
lock.lock();
try {
if (list == null) {
list = server.findList(query, null);
}
return list;
} finally {
lock.unlock();
}
}
@@ -77,7 +81,6 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
@Override
public int getTotalPageCount() {
int rowCount = getTotalCount();
if (rowCount == 0) {
return 0;
@@ -88,7 +91,8 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
@Override
public int getTotalCount() {
synchronized (monitor) {
lock.lock();
try {
if (futureRowCount != null) {
try {
// background query already initiated so get it with a wait
@@ -103,6 +107,8 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
// just using foreground thread
foregroundTotalRowCount = server.findCount(query, null);
return foregroundTotalRowCount;
} finally {
lock.unlock();
}
}
@@ -123,11 +129,9 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
@Override
public String getDisplayXtoYofZ(String to, String of) {
int first = firstRow + 1;
int last = firstRow + getList().size();
int total = getTotalCount();
return first + to + last + of + total;
}
@@ -71,6 +71,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -88,6 +89,8 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
private static final FetchConfig FETCH_LAZY = new FetchConfig().lazy();
private final ReentrantLock lock = new ReentrantLock(false);
private final Class<T> beanType;
private final ExpressionFactory expressionFactory;
@@ -1992,8 +1995,11 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
@Override
public void setCancelableQuery(CancelableQuery cancelableQuery) {
synchronized (this) {
lock.lock();
try {
this.cancelableQuery = cancelableQuery;
} finally {
lock.unlock();
}
}
@@ -2026,18 +2032,24 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
@Override
public void cancel() {
synchronized (this) {
lock.lock();
try {
cancelled = true;
if (cancelableQuery != null) {
cancelableQuery.cancel();
}
} finally {
lock.unlock();
}
}
@Override
public boolean isCancelled() {
synchronized (this) {
lock.lock();
try {
return cancelled;
} finally {
lock.unlock();
}
}
@@ -1,12 +1,12 @@
package io.ebeaninternal.server.transaction;
import io.ebean.bean.PersistenceContext;
import io.ebeaninternal.api.Monitor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
/**
* Default implementation of PersistenceContext.
@@ -32,7 +32,7 @@ public final class DefaultPersistenceContext implements PersistenceContext {
*/
private final HashMap<Class<?>, ClassContext> typeCache = new HashMap<>();
private final Monitor monitor = new Monitor();
private final ReentrantLock lock = new ReentrantLock(false);
private int putCount;
@@ -68,7 +68,8 @@ public final class DefaultPersistenceContext implements PersistenceContext {
}
public boolean resetLimit() {
synchronized (monitor) {
lock.lock();
try {
if (putCount < 100) {
return false;
}
@@ -80,6 +81,8 @@ public final class DefaultPersistenceContext implements PersistenceContext {
}
// checking after another 100 puts
return false;
} finally {
lock.unlock();
}
}
@@ -88,17 +91,23 @@ public final class DefaultPersistenceContext implements PersistenceContext {
*/
@Override
public void put(Class<?> rootType, Object id, Object bean) {
synchronized (monitor) {
lock.lock();
try {
putCount++;
getClassContext(rootType).put(id, bean);
} finally {
lock.unlock();
}
}
@Override
public Object putIfAbsent(Class<?> rootType, Object id, Object bean) {
synchronized (monitor) {
lock.lock();
try {
putCount++;
return getClassContext(rootType).putIfAbsent(id, bean);
} finally {
lock.unlock();
}
}
@@ -107,15 +116,21 @@ public final class DefaultPersistenceContext implements PersistenceContext {
*/
@Override
public Object get(Class<?> rootType, Object id) {
synchronized (monitor) {
lock.lock();
try {
return getClassContext(rootType).get(id);
} finally {
lock.unlock();
}
}
@Override
public WithOption getWithOption(Class<?> rootType, Object id) {
synchronized (monitor) {
lock.lock();
try {
return getClassContext(rootType).getWithOption(id);
} finally {
lock.unlock();
}
}
@@ -124,9 +139,12 @@ public final class DefaultPersistenceContext implements PersistenceContext {
*/
@Override
public int size(Class<?> rootType) {
synchronized (monitor) {
lock.lock();
try {
ClassContext classMap = typeCache.get(rootType);
return classMap == null ? 0 : classMap.size();
} finally {
lock.unlock();
}
}
@@ -135,45 +153,60 @@ public final class DefaultPersistenceContext implements PersistenceContext {
*/
@Override
public void clear() {
synchronized (monitor) {
lock.lock();
try {
typeCache.clear();
} finally {
lock.unlock();
}
}
@Override
public void clear(Class<?> rootType) {
synchronized (monitor) {
lock.lock();
try {
ClassContext classMap = typeCache.get(rootType);
if (classMap != null) {
classMap.clear();
}
} finally {
lock.unlock();
}
}
@Override
public void deleted(Class<?> rootType, Object id) {
synchronized (monitor) {
lock.lock();
try {
ClassContext classMap = typeCache.get(rootType);
if (classMap != null && id != null) {
classMap.deleted(id);
}
} finally {
lock.unlock();
}
}
@Override
public void clear(Class<?> rootType, Object id) {
synchronized (monitor) {
lock.lock();
try {
ClassContext classMap = typeCache.get(rootType);
if (classMap != null && id != null) {
classMap.remove(id);
}
} finally {
lock.unlock();
}
}
@Override
public String toString() {
synchronized (monitor) {
lock.lock();
try {
return typeCache.toString();
} finally {
lock.unlock();
}
}
@@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
@@ -65,6 +66,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
private final ExecutorService executor;
private final ReentrantLock lock = new ReentrantLock(false);
private final File dir;
private final long minMicros;
@@ -117,7 +120,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
}
private void flushCurrentFile() {
synchronized (this) {
lock.lock();
try {
if (out != null) {
try {
out.close();
@@ -126,6 +130,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
log.error("Failed to flush and close transaction profiling file ", e);
}
}
} finally {
lock.unlock();
}
}
@@ -133,7 +139,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
* Move to the next file to write to.
*/
private void incrementFile() {
synchronized (this) {
lock.lock();
try {
flushCurrentFile();
try {
String now = DTF.format(LocalDateTime.now());
@@ -142,6 +149,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
} catch (IOException e) {
log.error("Not expected", e);
}
} finally {
lock.unlock();
}
}