Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.earth2me.essentials.utils.VersionUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.Economy;
import com.earth2me.essentials.config.EssentialsConfiguration;
import net.ess3.api.IEssentials;
import net.ess3.api.IItemDb;
import net.ess3.api.IJails;
Expand Down Expand Up @@ -570,6 +571,8 @@ public void onDisable() {
Trade.closeLog();
getUsers().shutdown();

EssentialsConfiguration.shutdownExecutor();

HandlerList.unregisterAll(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,32 @@
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.logging.Level;

public class ConfigurationSaveTask implements Runnable {
private final YamlConfigurationLoader loader;
private final CommentedConfigurationNode node;
private final Supplier<CommentedConfigurationNode> nodeSupplier;
private final AtomicInteger pendingWrites;

public ConfigurationSaveTask(final YamlConfigurationLoader loader, final CommentedConfigurationNode node, final AtomicInteger pendingWrites) {
public ConfigurationSaveTask(final YamlConfigurationLoader loader, final Supplier<CommentedConfigurationNode> nodeSupplier, final AtomicInteger pendingWrites) {
this.loader = loader;
this.node = node;
this.nodeSupplier = nodeSupplier;
this.pendingWrites = pendingWrites;
}

@Override
public void run() {
synchronized (loader) {
// Check if there are more writes in queue.
// If that's the case, we shouldn't bother writing data which is already out-of-date.
if (pendingWrites.get() > 1) {
pendingWrites.decrementAndGet();
}
if (pendingWrites.decrementAndGet() > 0) {
return;
}

synchronized (loader) {
try {
final CommentedConfigurationNode node = nodeSupplier.get();
loader.save(node);
} catch (ConfigurateException e) {
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
} finally {
pendingWrites.decrementAndGet();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;

import static com.earth2me.essentials.I18n.tlLiteral;

public class EssentialsConfiguration {
private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
private static volatile ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
private static final ObjectMapper.Factory MAPPER_FACTORY = ObjectMapper.factoryBuilder()
.addProcessor(DeleteOnEmpty.class, (data, value) -> new DeleteOnEmptyProcessor())
.addProcessor(DeleteIfIncomplete.class, (data, value) -> new DeleteIfIncompleteProcessor())
Expand Down Expand Up @@ -462,21 +462,50 @@ public synchronized void save() {

public synchronized void blockingSave() {
try {
delaySave().get();
delaySave();
getExecutor().submit(() -> {}).get();
} catch (final InterruptedException | ExecutionException e) {
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
}
}

private Future<?> delaySave() {
private void delaySave() {
if (saveHook != null) {
saveHook.run();
}

final CommentedConfigurationNode node = configurationNode.copy();

pendingWrites.incrementAndGet();
try {
getExecutor().submit(new ConfigurationSaveTask(loader, () -> configurationNode.copy(), pendingWrites));
} catch (RejectedExecutionException rex) {
try {
synchronized (loader) {
loader.save(configurationNode.copy());
}
} catch (ConfigurateException e) {
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
} finally {
pendingWrites.decrementAndGet();
}
}
}

return EXECUTOR_SERVICE.submit(new ConfigurationSaveTask(loader, node, pendingWrites));
public static void shutdownExecutor() {
final ExecutorService exec = EXECUTOR_SERVICE;
exec.shutdown();
try {
if (!exec.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS)) {
exec.shutdownNow();
}
} catch (InterruptedException ignored) {
exec.shutdownNow();
}
}

private static synchronized ExecutorService getExecutor() {
if (EXECUTOR_SERVICE == null || EXECUTOR_SERVICE.isShutdown() || EXECUTOR_SERVICE.isTerminated()) {
EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
}
return EXECUTOR_SERVICE;
}
}