From f8af92eb5b189eab579fdc149de9ef88e3d8969c Mon Sep 17 00:00:00 2001 From: "Kristian S. Stangeland" Date: Tue, 20 Nov 2012 00:26:16 +0100 Subject: [PATCH] Add the error reporter to the background compiler. --- .../comphenix/protocol/ProtocolLibrary.java | 21 ++++--- .../protocol/error/DetailedErrorReporter.java | 2 +- .../reflect/compiler/BackgroundCompiler.java | 56 ++++++++++++++++--- 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLibrary.java b/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLibrary.java index c62ae46b..2e1fe58c 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLibrary.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLibrary.java @@ -90,13 +90,14 @@ public class ProtocolLibrary extends JavaPlugin { logger = getLoggerSafely(); // Add global parameters - DetailedErrorReporter reporter = new DetailedErrorReporter(this); + DetailedErrorReporter detailedReporter = new DetailedErrorReporter(this); updater = new Updater(this, logger, "protocollib", getFile(), "protocol.info"); + reporter = detailedReporter; try { config = new ProtocolConfig(this); } catch (Exception e) { - reporter.reportWarning(this, "Cannot load configuration", e); + detailedReporter.reportWarning(this, "Cannot load configuration", e); // Load it again deleteConfig(); @@ -105,18 +106,18 @@ public class ProtocolLibrary extends JavaPlugin { try { unhookTask = new DelayedSingleTask(this); - protocolManager = new PacketFilterManager(getClassLoader(), getServer(), unhookTask, reporter); - reporter.addGlobalParameter("manager", protocolManager); + protocolManager = new PacketFilterManager(getClassLoader(), getServer(), unhookTask, detailedReporter); + detailedReporter.addGlobalParameter("manager", protocolManager); // Initialize command handlers - commandProtocol = new CommandProtocol(reporter, this, updater, config); - commandPacket = new CommandPacket(reporter, this, logger, protocolManager); + commandProtocol = new CommandProtocol(detailedReporter, this, updater, config); + commandPacket = new CommandPacket(detailedReporter, this, logger, protocolManager); // Send logging information to player listeners too broadcastUsers(PERMISSION_INFO); } catch (Throwable e) { - reporter.reportDetailed(this, "Cannot load ProtocolLib.", e, protocolManager); + detailedReporter.reportDetailed(this, "Cannot load ProtocolLib.", e, protocolManager); disablePlugin(); } } @@ -167,8 +168,12 @@ public class ProtocolLibrary extends JavaPlugin { // Initialize background compiler if (backgroundCompiler == null && config.isBackgroundCompilerEnabled()) { - backgroundCompiler = new BackgroundCompiler(getClassLoader()); + backgroundCompiler = new BackgroundCompiler(getClassLoader(), reporter); BackgroundCompiler.setInstance(backgroundCompiler); + + logger.info("Started structure compiler thread."); + } else { + logger.info("Structure compiler thread has been disabled."); } // Set up command handlers diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/error/DetailedErrorReporter.java b/ProtocolLib/src/main/java/com/comphenix/protocol/error/DetailedErrorReporter.java index 7fd85123..3e9aafa6 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/error/DetailedErrorReporter.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/error/DetailedErrorReporter.java @@ -170,7 +170,7 @@ public class DetailedErrorReporter implements ErrorReporter { if (pluginReference.get() != null) { Plugin plugin = pluginReference.get(); writer.println("Version:"); - writer.println(addPrefix(plugin.toString() + "-" + plugin.getDescription().getVersion(), SECOND_LEVEL_PREFIX)); + writer.println(addPrefix(plugin.toString(), SECOND_LEVEL_PREFIX)); } // Add the server version too diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/BackgroundCompiler.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/BackgroundCompiler.java index 647206a9..6f636c49 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/BackgroundCompiler.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/compiler/BackgroundCompiler.java @@ -22,11 +22,16 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nullable; + +import com.comphenix.protocol.error.ErrorReporter; import com.comphenix.protocol.reflect.StructureModifier; +import com.google.common.util.concurrent.ThreadFactoryBuilder; /** * Compiles structure modifiers on a background thread. @@ -37,6 +42,11 @@ import com.comphenix.protocol.reflect.StructureModifier; */ public class BackgroundCompiler { + /** + * The default format for the name of new worker threads. + */ + public static final String THREAD_FORMAT = "ProtocolLib-StructureCompiler %s"; + // How long to wait for a shutdown public static final int SHUTDOWN_DELAY_MS = 2000; @@ -48,6 +58,7 @@ public class BackgroundCompiler { private boolean shuttingDown; private ExecutorService executor; + private ErrorReporter reporter; /** * Retrieves the current background compiler. @@ -64,27 +75,41 @@ public class BackgroundCompiler { public static void setInstance(BackgroundCompiler backgroundCompiler) { BackgroundCompiler.backgroundCompiler = backgroundCompiler; } - + /** * Initialize a background compiler. + *

+ * Uses the default {@link #THREAD_FORMAT} to name worker threads. * @param loader - class loader from Bukkit. + * @param reporter - current error reporter. */ - public BackgroundCompiler(ClassLoader loader) { - this(loader, Executors.newSingleThreadExecutor()); + public BackgroundCompiler(ClassLoader loader, ErrorReporter reporter) { + ThreadFactory factory = new ThreadFactoryBuilder(). + setDaemon(true). + setNameFormat(THREAD_FORMAT). + build(); + initializeCompiler(loader, reporter, Executors.newSingleThreadExecutor(factory)); } - + /** * Initialize a background compiler utilizing the given thread pool. * @param loader - class loader from Bukkit. + * @param reporter - current error reporter. * @param executor - thread pool we'll use. */ - public BackgroundCompiler(ClassLoader loader, ExecutorService executor) { + public BackgroundCompiler(ClassLoader loader, ErrorReporter reporter, ExecutorService executor) { + initializeCompiler(loader, reporter, executor); + } + + // Avoid "Constructor call must be the first statement". + private void initializeCompiler(ClassLoader loader, @Nullable ErrorReporter reporter, ExecutorService executor) { if (loader == null) throw new IllegalArgumentException("loader cannot be NULL"); if (executor == null) throw new IllegalArgumentException("executor cannot be NULL"); this.compiler = new StructureCompiler(loader); + this.reporter = reporter; this.executor = executor; this.enabled = true; } @@ -129,15 +154,30 @@ public class BackgroundCompiler { executor.submit(new Callable() { @Override public Object call() throws Exception { - StructureModifier modifier = uncompiled; // Do our compilation - modifier = compiler.compile(modifier); - listener.onCompiled(modifier); + try { + modifier = compiler.compile(modifier); + listener.onCompiled(modifier); + + } catch (Throwable e) { + // Disable future compilations! + setEnabled(false); + + // Inform about this error as best as we can + if (reporter != null) { + reporter.reportDetailed(BackgroundCompiler.this, + "Cannot compile structure. Disabing compiler.", e, uncompiled); + } else { + System.err.println("Exception occured in structure compiler: "); + e.printStackTrace(); + } + } // We'll also return the new structure modifier return modifier; + } }); } catch (RejectedExecutionException e) {