mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-23 00:12:29 +00:00
Wait for thread executors to shut down
This commit is contained in:
parent
9dd514a73b
commit
8692405363
@ -1,14 +1,11 @@
|
|||||||
package emu.grasscutter;
|
package emu.grasscutter;
|
||||||
|
|
||||||
import static emu.grasscutter.config.Configuration.SERVER;
|
|
||||||
import static emu.grasscutter.utils.lang.Language.translate;
|
|
||||||
|
|
||||||
import ch.qos.logback.classic.*;
|
import ch.qos.logback.classic.*;
|
||||||
import emu.grasscutter.auth.*;
|
import emu.grasscutter.auth.*;
|
||||||
import emu.grasscutter.command.*;
|
import emu.grasscutter.command.*;
|
||||||
import emu.grasscutter.config.ConfigContainer;
|
import emu.grasscutter.config.ConfigContainer;
|
||||||
import emu.grasscutter.data.ResourceLoader;
|
import emu.grasscutter.data.ResourceLoader;
|
||||||
import emu.grasscutter.database.DatabaseManager;
|
import emu.grasscutter.database.*;
|
||||||
import emu.grasscutter.plugin.PluginManager;
|
import emu.grasscutter.plugin.PluginManager;
|
||||||
import emu.grasscutter.plugin.api.ServerHelper;
|
import emu.grasscutter.plugin.api.ServerHelper;
|
||||||
import emu.grasscutter.server.dispatch.DispatchServer;
|
import emu.grasscutter.server.dispatch.DispatchServer;
|
||||||
@ -21,16 +18,20 @@ import emu.grasscutter.tools.Tools;
|
|||||||
import emu.grasscutter.utils.*;
|
import emu.grasscutter.utils.*;
|
||||||
import emu.grasscutter.utils.lang.Language;
|
import emu.grasscutter.utils.lang.Language;
|
||||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||||
import java.io.*;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.jline.reader.*;
|
import org.jline.reader.*;
|
||||||
import org.jline.terminal.*;
|
import org.jline.terminal.*;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
import static emu.grasscutter.config.Configuration.SERVER;
|
||||||
|
import static emu.grasscutter.utils.lang.Language.translate;
|
||||||
|
|
||||||
public final class Grasscutter {
|
public final class Grasscutter {
|
||||||
public static final File configFile = new File("./config.json");
|
public static final File configFile = new File("./config.json");
|
||||||
public static final Reflections reflector = new Reflections("emu.grasscutter");
|
public static final Reflections reflector = new Reflections("emu.grasscutter");
|
||||||
@ -183,6 +184,22 @@ public final class Grasscutter {
|
|||||||
private static void onShutdown() {
|
private static void onShutdown() {
|
||||||
// Disable all plugins.
|
// Disable all plugins.
|
||||||
if (pluginManager != null) pluginManager.disablePlugins();
|
if (pluginManager != null) pluginManager.disablePlugins();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Wait for Grasscutter's thread pool to finish.
|
||||||
|
var executor = Grasscutter.getThreadPool();
|
||||||
|
executor.shutdown();
|
||||||
|
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||||
|
executor.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for database operations to finish.
|
||||||
|
var dbExecutor = DatabaseHelper.getEventExecutor();
|
||||||
|
dbExecutor.shutdown();
|
||||||
|
if (!dbExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||||
|
dbExecutor.shutdownNow();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ignored) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
package emu.grasscutter.database;
|
package emu.grasscutter.database;
|
||||||
|
|
||||||
import static com.mongodb.client.model.Filters.eq;
|
import dev.morphia.query.*;
|
||||||
|
|
||||||
import dev.morphia.query.FindOptions;
|
|
||||||
import dev.morphia.query.Sort;
|
|
||||||
import dev.morphia.query.experimental.filters.Filters;
|
import dev.morphia.query.experimental.filters.Filters;
|
||||||
import emu.grasscutter.GameConstants;
|
import emu.grasscutter.*;
|
||||||
import emu.grasscutter.Grasscutter;
|
|
||||||
import emu.grasscutter.game.Account;
|
import emu.grasscutter.game.Account;
|
||||||
import emu.grasscutter.game.achievement.Achievements;
|
import emu.grasscutter.game.achievement.Achievements;
|
||||||
import emu.grasscutter.game.activity.PlayerActivityData;
|
import emu.grasscutter.game.activity.PlayerActivityData;
|
||||||
@ -23,12 +19,16 @@ import emu.grasscutter.game.quest.GameMainQuest;
|
|||||||
import emu.grasscutter.game.world.SceneGroupInstance;
|
import emu.grasscutter.game.world.SceneGroupInstance;
|
||||||
import emu.grasscutter.utils.objects.Returnable;
|
import emu.grasscutter.utils.objects.Returnable;
|
||||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static com.mongodb.client.model.Filters.eq;
|
||||||
|
|
||||||
public final class DatabaseHelper {
|
public final class DatabaseHelper {
|
||||||
private static final ExecutorService eventExecutor =
|
@Getter private static final ExecutorService eventExecutor =
|
||||||
new ThreadPoolExecutor(
|
new ThreadPoolExecutor(
|
||||||
6,
|
6,
|
||||||
6,
|
6,
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package emu.grasscutter.server.game;
|
package emu.grasscutter.server.game;
|
||||||
|
|
||||||
import static emu.grasscutter.config.Configuration.*;
|
|
||||||
import static emu.grasscutter.utils.lang.Language.translate;
|
|
||||||
|
|
||||||
import emu.grasscutter.*;
|
import emu.grasscutter.*;
|
||||||
import emu.grasscutter.Grasscutter.ServerRunMode;
|
import emu.grasscutter.Grasscutter.ServerRunMode;
|
||||||
import emu.grasscutter.database.DatabaseHelper;
|
import emu.grasscutter.database.DatabaseHelper;
|
||||||
@ -32,14 +29,19 @@ import emu.grasscutter.server.event.internal.*;
|
|||||||
import emu.grasscutter.server.event.types.ServerEvent;
|
import emu.grasscutter.server.event.types.ServerEvent;
|
||||||
import emu.grasscutter.server.scheduler.ServerTaskScheduler;
|
import emu.grasscutter.server.scheduler.ServerTaskScheduler;
|
||||||
import emu.grasscutter.task.TaskMap;
|
import emu.grasscutter.task.TaskMap;
|
||||||
import java.net.*;
|
import emu.grasscutter.utils.Utils;
|
||||||
import java.time.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import kcp.highway.*;
|
import kcp.highway.*;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
|
import java.time.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
import static emu.grasscutter.config.Configuration.*;
|
||||||
|
import static emu.grasscutter.utils.lang.Language.translate;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public final class GameServer extends KcpServer implements Iterable<Player> {
|
public final class GameServer extends KcpServer implements Iterable<Player> {
|
||||||
// Game server base
|
// Game server base
|
||||||
@ -326,16 +328,27 @@ public final class GameServer extends KcpServer implements Iterable<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onServerShutdown() {
|
public void onServerShutdown() {
|
||||||
ServerStopEvent event = new ServerStopEvent(ServerEvent.Type.GAME, OffsetDateTime.now());
|
var event = new ServerStopEvent(ServerEvent.Type.GAME, OffsetDateTime.now());
|
||||||
event.call();
|
event.call();
|
||||||
|
|
||||||
this.getPlayers()
|
this.getPlayers()
|
||||||
.forEach(
|
.forEach(
|
||||||
(uid, player) -> {
|
(uid, player) -> player.getSession().close());
|
||||||
player.getSession().close();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.getWorlds().forEach(World::save);
|
this.getWorlds().forEach(World::save);
|
||||||
|
|
||||||
|
Utils.sleep(1000L); // Wait 1 second for operations to finish.
|
||||||
|
|
||||||
|
try {
|
||||||
|
var threadPool = GameSessionManager.getLogicThread();
|
||||||
|
|
||||||
|
// Shutdown network thread.
|
||||||
|
threadPool.shutdownGracefully();
|
||||||
|
// Wait for the network thread to finish.
|
||||||
|
if (!threadPool.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||||
|
Grasscutter.getLogger().error("Logic thread did not terminate!");
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ignored) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull @Override
|
@NotNull @Override
|
||||||
|
@ -2,16 +2,16 @@ package emu.grasscutter.server.game;
|
|||||||
|
|
||||||
import emu.grasscutter.Grasscutter;
|
import emu.grasscutter.Grasscutter;
|
||||||
import emu.grasscutter.utils.Utils;
|
import emu.grasscutter.utils.Utils;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.*;
|
||||||
import io.netty.buffer.Unpooled;
|
|
||||||
import io.netty.channel.DefaultEventLoop;
|
import io.netty.channel.DefaultEventLoop;
|
||||||
|
import kcp.highway.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import kcp.highway.KcpListener;
|
|
||||||
import kcp.highway.Ukcp;
|
|
||||||
|
|
||||||
public class GameSessionManager {
|
public class GameSessionManager {
|
||||||
private static final DefaultEventLoop logicThread = new DefaultEventLoop();
|
@Getter private static final DefaultEventLoop logicThread = new DefaultEventLoop();
|
||||||
private static final ConcurrentHashMap<Ukcp, GameSession> sessions = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<Ukcp, GameSession> sessions = new ConcurrentHashMap<>();
|
||||||
private static final KcpListener listener =
|
private static final KcpListener listener =
|
||||||
new KcpListener() {
|
new KcpListener() {
|
||||||
|
@ -504,9 +504,7 @@ public final class Utils {
|
|||||||
* @return A list of all fields in the class.
|
* @return A list of all fields in the class.
|
||||||
*/
|
*/
|
||||||
public static List<Field> getAllFields(Class<?> type) {
|
public static List<Field> getAllFields(Class<?> type) {
|
||||||
var fields = new LinkedList<>(
|
var fields = new LinkedList<>(Arrays.asList(type.getDeclaredFields()));
|
||||||
Arrays.asList(type.getDeclaredFields())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check for superclasses.
|
// Check for superclasses.
|
||||||
if (type.getSuperclass() != null) {
|
if (type.getSuperclass() != null) {
|
||||||
@ -515,4 +513,16 @@ public final class Utils {
|
|||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sleeps the current thread without an exception.
|
||||||
|
*
|
||||||
|
* @param millis The amount of milliseconds to sleep.
|
||||||
|
*/
|
||||||
|
public static void sleep(long millis) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(millis);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user