mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-11-01 00:10:12 +01:00
Log connection holding call sites in dev-mode
This commit is contained in:
parent
4615c6b6b0
commit
5ddbd52d37
@ -59,7 +59,7 @@ public class SQLiteDB extends SQLDB {
|
||||
* one thread closing the connection while another is executing a statement as
|
||||
* that might lead to a SIGSEGV signal JVM crash.
|
||||
*/
|
||||
private final SemaphoreAccessCounter connectionLock = new SemaphoreAccessCounter();
|
||||
private final SemaphoreAccessCounter connectionLock;
|
||||
|
||||
private Constructor<?> connectionConstructor;
|
||||
|
||||
@ -76,6 +76,7 @@ public class SQLiteDB extends SQLDB {
|
||||
super(() -> serverInfo.get().getServerUUID(), locale, config, files, runnableFactory, logger, errorLogger);
|
||||
dbName = databaseFile.getName();
|
||||
this.databaseFile = databaseFile;
|
||||
connectionLock = new SemaphoreAccessCounter(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,24 +16,65 @@
|
||||
*/
|
||||
package com.djrapitops.plan.utilities;
|
||||
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.PluginSettings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class SemaphoreAccessCounter {
|
||||
|
||||
private final PlanConfig config;
|
||||
|
||||
private final AtomicInteger accessCounter;
|
||||
private final Object lockObject;
|
||||
private final Collection<String> holds = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private AtomicBoolean logHolds = null;
|
||||
|
||||
public SemaphoreAccessCounter() {
|
||||
public SemaphoreAccessCounter(PlanConfig config) {
|
||||
this.config = config;
|
||||
accessCounter = new AtomicInteger(0);
|
||||
lockObject = new Object();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getAccessingThing() {
|
||||
boolean previousWasAccess = false;
|
||||
List<StackTraceElement> accessors = new ArrayList<>();
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (previousWasAccess) {
|
||||
accessors.add(e);
|
||||
previousWasAccess = false;
|
||||
}
|
||||
String call = e.getClassName() + "." + e.getMethodName();
|
||||
if ("com.djrapitops.plan.storage.database.SQLDB.query".equals(call)
|
||||
|| "com.djrapitops.plan.storage.database.SQLDB.executeTransaction".equals(call)) {
|
||||
previousWasAccess = true;
|
||||
}
|
||||
}
|
||||
return accessors.toString();
|
||||
}
|
||||
|
||||
public void enter() {
|
||||
accessCounter.incrementAndGet();
|
||||
|
||||
if (logHolds == null) logHolds = new AtomicBoolean(config.isTrue(PluginSettings.DEV_MODE));
|
||||
if (logHolds.get()) holds.add(getAccessingThing());
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
synchronized (lockObject) {
|
||||
if (logHolds == null) logHolds = new AtomicBoolean(config.isTrue(PluginSettings.DEV_MODE));
|
||||
if (logHolds.get()) holds.remove(getAccessingThing());
|
||||
|
||||
int value = accessCounter.decrementAndGet();
|
||||
if (value == 0) {
|
||||
lockObject.notifyAll();
|
||||
@ -45,6 +86,7 @@ public class SemaphoreAccessCounter {
|
||||
while (accessCounter.get() > 0) {
|
||||
synchronized (lockObject) {
|
||||
try {
|
||||
logAccess();
|
||||
lockObject.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
@ -52,4 +94,18 @@ public class SemaphoreAccessCounter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void logAccess() {
|
||||
if (logHolds != null && logHolds.get()) {
|
||||
Logger logger = Logger.getLogger("Plan");
|
||||
if (logger == null) logger = Logger.getGlobal();
|
||||
|
||||
if (logger.isLoggable(Level.INFO) && !holds.isEmpty()) {
|
||||
logger.log(Level.INFO, "DEBUG - Following call sites are holding connection:");
|
||||
for (String hold : holds) {
|
||||
logger.log(Level.INFO, String.format("DEBUG - %s", hold));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user