refactor: removed client side threads from a server, improved test log files rotation;

This commit is contained in:
Oleg Agafonov 2023-11-27 18:13:05 +04:00
parent 0470ae9799
commit c5632f6868
6 changed files with 75 additions and 62 deletions

View file

@ -58,7 +58,7 @@ public class MageEditorPane extends JEditorPane {
if (Arrays.stream(getHyperlinkListeners()).findAny().isPresent()) {
throw new IllegalStateException("Wrong code usage: popup links support enabled already");
}
addHyperlinkListener(e -> ThreadUtils.threadPoolPopups.submit(() -> {
addHyperlinkListener(e -> MageUI.threadPoolPopups.submit(() -> {
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_TOOLTIPS_DELAY, 300) == 0) {
// if disabled
return;

View file

@ -1,16 +1,51 @@
package mage.client.components;
import mage.utils.ThreadUtils;
import org.apache.log4j.Logger;
import java.awt.Component;
import java.util.EnumMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.swing.JButton;
public class MageUI {
private static final Logger logger = Logger.getLogger(MageUI.class);
private final Map<MageComponents, Component> ui = new EnumMap<>(MageComponents.class);
private final Map<MageComponents, Object> sync = new EnumMap<>(MageComponents.class);
public static final ThreadPoolExecutor threadPoolPopups;
private static int threadCount;
static {
threadPoolPopups = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
threadCount++;
Thread thread = new Thread(runnable, "POPUP-" + threadCount);
thread.setDaemon(true);
return thread;
}
}) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
// catch errors in popup threads (example: card popup over cards or chat/log messages)
t = ThreadUtils.findRealException(r, t);
if (t != null) {
logger.error("Catch unhandled error in POPUP thread: " + t.getMessage(), t);
}
}
};
threadPoolPopups.prestartAllCoreThreads();
}
public JButton getButton(MageComponents name) throws InterruptedException {
//System.out.println("request for " + name);
Object buttonSync;

View file

@ -10,6 +10,7 @@ import mage.client.SessionHandler;
import mage.client.cards.BigCard;
import mage.client.cards.CardEventProducer;
import mage.client.components.MageComponents;
import mage.client.components.MageUI;
import mage.client.dialog.PreferencesDialog;
import mage.client.game.GamePane;
import mage.client.plugins.impl.Plugins;
@ -187,7 +188,7 @@ public class MageActionCallback implements ActionCallback {
private void showCardHintPopup(final TransferData data, final Component parentComponent, final Point parentPoint) {
MageCard cardPanel = data.getComponent().getTopPanelRef();
ThreadUtils.threadPoolPopups.submit(new Runnable() {
MageUI.threadPoolPopups.submit(new Runnable() {
@Override
public void run() {
ThreadUtils.sleep(tooltipDelay);
@ -647,7 +648,7 @@ public class MageActionCallback implements ActionCallback {
private void displayEnlargedCard(final CardView cardView, final TransferData data) {
MageCard cardPanel = data.getComponent().getTopPanelRef();
ThreadUtils.threadPoolPopups.submit(() -> {
MageUI.threadPoolPopups.submit(() -> {
if (cardView == null) {
return;
}

View file

@ -7,6 +7,10 @@ import java.util.Queue;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
@ -25,6 +29,31 @@ public class LinePool {
private final org.apache.log4j.Logger logger = Logger.getLogger(LinePool.class);
private static final int LINE_CLEANUP_INTERVAL = 30000;
private static final ThreadPoolExecutor threadPoolSounds;
private static int threadCount = 0;
static {
threadPoolSounds = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
threadCount++;
Thread thread = new Thread(runnable, "SOUND-" + threadCount);
thread.setDaemon(true);
return thread;
}
}) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
t = ThreadUtils.findRealException(r, t);
if (t != null) {
// TODO: show sound errors in client logs?
//logger.error("Catch unhandled error in SOUND thread: " + t.getMessage(), t);
}
}
};
threadPoolSounds.prestartAllCoreThreads();
}
private final Queue<SourceDataLine> freeLines = new ArrayDeque<>();
private final Queue<SourceDataLine> activeLines = new ArrayDeque<>();
private final Set<SourceDataLine> busyLines = new HashSet<>();
@ -106,7 +135,7 @@ public class LinePool {
}
logLineStats();
}
ThreadUtils.threadPoolSounds.submit(() -> {
threadPoolSounds.submit(() -> {
synchronized (LinePool.this) {
try {
if (!line.isOpen()) {

View file

@ -1,8 +1,8 @@
package mage.utils;
import org.apache.log4j.Logger;
import java.util.concurrent.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* Util method to work with threads.
@ -11,57 +11,6 @@ import java.util.concurrent.*;
*/
public final class ThreadUtils {
private static final Logger logger = Logger.getLogger(ThreadUtils.class);
public static final ThreadPoolExecutor threadPoolSounds;
public static final ThreadPoolExecutor threadPoolPopups;
private static int threadCount;
static {
threadPoolSounds = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
threadCount++;
Thread thread = new Thread(runnable, "SOUND-" + threadCount);
thread.setDaemon(true);
return thread;
}
}) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
t = findRealException(r, t);
if (t != null) {
// TODO: show sound errors in client logs?
//logger.error("Catch unhandled error in SOUND thread: " + t.getMessage(), t);
}
}
};
threadPoolSounds.prestartAllCoreThreads();
threadPoolPopups = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
threadCount++;
Thread thread = new Thread(runnable, "POPUP-" + threadCount);
thread.setDaemon(true);
return thread;
}
}) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
// catch errors in popup threads (example: card popup over cards or chat/log messages)
t = findRealException(r, t);
if (t != null) {
logger.error("Catch unhandled error in POPUP thread: " + t.getMessage(), t);
}
}
};
threadPoolPopups.prestartAllCoreThreads();
}
public static void sleep(int millis) {
try {
Thread.sleep(millis);
@ -81,9 +30,6 @@ public final class ThreadUtils {
/**
* Find real exception object after thread task completed. Can be used in afterExecute
*
* @param r
* @param t
* @return
*/
public static Throwable findRealException(Runnable r, Throwable t) {
// executer.submit - return exception in result

View file

@ -30,8 +30,10 @@ log4j.appender.logfileByIndex.MaxBackupIndex=3
log4j.appender.logfileByIndex.append=true
#file log - errors only
log4j.appender.watchdog=org.apache.log4j.FileAppender
log4j.appender.watchdog=org.apache.log4j.RollingFileAppender
log4j.appender.watchdog.layout=org.apache.log4j.PatternLayout
log4j.appender.watchdog.layout.ConversionPattern=%-5p [%d{yyyy-MM-dd HH:mm [ss:SSS]}] %C{1}[%t]: %m%n
log4j.appender.watchdog.file=magetestErrors.log
log4j.appender.watchdog.MaxFileSize=10MB
log4j.appender.watchdog.MaxBackupIndex=1
log4j.appender.watchdog.Threshold=error