diff --git a/src/main/java/org/ultramine/server/UMEventHandler.java b/src/main/java/org/ultramine/server/UMEventHandler.java index 6c6fd80..96ee954 100644 --- a/src/main/java/org/ultramine/server/UMEventHandler.java +++ b/src/main/java/org/ultramine/server/UMEventHandler.java @@ -1,6 +1,5 @@ package org.ultramine.server; -import org.ultramine.server.data.player.io.PlayerDataIOExecutor; import org.ultramine.server.util.BasicTypeParser; import org.ultramine.server.util.WarpLocation; @@ -38,7 +37,6 @@ { if(e.phase == TickEvent.Phase.START) { - PlayerDataIOExecutor.tick(); Teleporter.tick(); } } diff --git a/src/main/java/org/ultramine/server/data/ServerDataLoader.java b/src/main/java/org/ultramine/server/data/ServerDataLoader.java index b81ee28..f60ae50 100644 --- a/src/main/java/org/ultramine/server/data/ServerDataLoader.java +++ b/src/main/java/org/ultramine/server/data/ServerDataLoader.java @@ -11,9 +11,10 @@ import org.ultramine.server.data.player.PlayerData; import org.ultramine.server.data.player.PlayerDataExtension; import org.ultramine.server.data.player.PlayerDataExtensionInfo; -import org.ultramine.server.data.player.io.PlayerDataIOExecutor; +import org.ultramine.server.util.TwoStepsExecutor; import org.ultramine.server.util.WarpLocation; +import com.google.common.base.Function; import com.mojang.authlib.GameProfile; import cpw.mods.fml.common.FMLCommonHandler; @@ -30,6 +31,7 @@ public class ServerDataLoader { private static final boolean isClient = FMLCommonHandler.instance().getSide().isClient(); + private final TwoStepsExecutor executor = isClient ? null : new TwoStepsExecutor("PlayerData loader #%d"); private final ServerConfigurationManager mgr; private IDataProvider dataProvider; private final List dataExtinfos = new ArrayList(); @@ -118,6 +120,7 @@ { dataProvider = isClient || !ConfigurationHandler.getServerConfig().settings.inSQLServerStorage.enabled ? new NBTFileDataProvider(mgr) : new JDBCDataProvider(mgr); dataProvider.init(); + if(!isClient) executor.register(); for(PlayerData data : dataProvider.loadAllPlayerData()) { @@ -149,7 +152,7 @@ } } - public void initializeConnectionToPlayer(NetworkManager network, EntityPlayerMP player, NetHandlerPlayServer nethandler) + public void initializeConnectionToPlayer(final NetworkManager network, final EntityPlayerMP player, final NetHandlerPlayServer nethandler) { if(isClient) { @@ -159,7 +162,29 @@ } else { - PlayerDataIOExecutor.requestData(getDataProvider(), network, player, nethandler, this, !playerDataCache.containsKey(player.getGameProfile().getId())); + //PlayerDataIOExecutor.requestData(getDataProvider(), network, player, nethandler, this, !playerDataCache.containsKey(player.getGameProfile().getId())); + final boolean loadData = !playerDataCache.containsKey(player.getGameProfile().getId()); + executor.execute(new Function() + { + @Override + public LoadedDataStruct apply(Void input) //async + { + NBTTagCompound nbt = getDataProvider().loadPlayer(player.getGameProfile()); + PlayerData data = loadData ? getDataProvider().loadPlayerData(player.getGameProfile()) : null; + return new LoadedDataStruct(nbt, data); + } + }, new Function() + { + @Override + public Void apply(LoadedDataStruct data) //sync + { + if(data.getNBT() != null) + player.readFromNBT(data.getNBT()); + playerLoadCallback(network, player, nethandler, data.getNBT(), data.getPlayerData()); + + return null; + } + }); } } @@ -204,4 +229,26 @@ { return dataExtinfos; } + + private class LoadedDataStruct + { + private final NBTTagCompound nbt; + private final PlayerData data; + + public LoadedDataStruct(NBTTagCompound nbt, PlayerData data) + { + this.nbt = nbt; + this.data = data; + } + + public NBTTagCompound getNBT() + { + return nbt; + } + + public PlayerData getPlayerData() + { + return data; + } + } } diff --git a/src/main/java/org/ultramine/server/data/player/io/LoadedDataStruct.java b/src/main/java/org/ultramine/server/data/player/io/LoadedDataStruct.java deleted file mode 100644 index 99db9a8..0000000 --- a/src/main/java/org/ultramine/server/data/player/io/LoadedDataStruct.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.ultramine.server.data.player.io; - -import org.ultramine.server.data.player.PlayerData; - -import net.minecraft.nbt.NBTTagCompound; - -public class LoadedDataStruct -{ - private final NBTTagCompound nbt; - private final PlayerData data; - - public LoadedDataStruct(NBTTagCompound nbt, PlayerData data) - { - this.nbt = nbt; - this.data = data; - } - - public NBTTagCompound getNBT() - { - return nbt; - } - - public PlayerData getPlayerData() - { - return data; - } -} diff --git a/src/main/java/org/ultramine/server/data/player/io/PlayerDataIOExecutor.java b/src/main/java/org/ultramine/server/data/player/io/PlayerDataIOExecutor.java deleted file mode 100644 index 19eb620..0000000 --- a/src/main/java/org/ultramine/server/data/player/io/PlayerDataIOExecutor.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.ultramine.server.data.player.io; - -import org.ultramine.server.data.IDataProvider; -import org.ultramine.server.data.ServerDataLoader; - -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.network.NetHandlerPlayServer; -import net.minecraft.network.NetworkManager; -import net.minecraftforge.common.util.AsynchronousExecutor; - -public class PlayerDataIOExecutor -{ - private static final AsynchronousExecutor instance - = new AsynchronousExecutor(new PlayerDataIOProvider(), 1); - - public static void requestData(IDataProvider provider, NetworkManager network, EntityPlayerMP player, NetHandlerPlayServer nethandler, - ServerDataLoader callback, boolean loadData) - { - instance.add(new QueuedPlayer(provider, network, player, nethandler, loadData), callback); - } - - public static void tick() - { - instance.finishActive(); - } -} diff --git a/src/main/java/org/ultramine/server/data/player/io/PlayerDataIOProvider.java b/src/main/java/org/ultramine/server/data/player/io/PlayerDataIOProvider.java deleted file mode 100644 index 18719b0..0000000 --- a/src/main/java/org/ultramine/server/data/player/io/PlayerDataIOProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.ultramine.server.data.player.io; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.ultramine.server.data.ServerDataLoader; -import org.ultramine.server.data.player.PlayerData; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.common.util.AsynchronousExecutor; - -public class PlayerDataIOProvider implements AsynchronousExecutor.CallBackProvider -{ - private final AtomicInteger threadNumber = new AtomicInteger(1); - - @Override - public Thread newThread(Runnable runnable) - { - Thread thread = new Thread(runnable, "PlayerData I/O Executor Thread-" + threadNumber.getAndIncrement()); - thread.setDaemon(true); - return thread; - } - - @Override - public LoadedDataStruct callStage1(QueuedPlayer param) throws RuntimeException - { - NBTTagCompound nbt = param.getDataProvider().loadPlayer(param.getPlayer().getGameProfile()); - PlayerData data = param.shouldLoadData() ? param.getDataProvider().loadPlayerData(param.getPlayer().getGameProfile()) : null; - - return new LoadedDataStruct(nbt, data); - } - - @Override - public void callStage2(QueuedPlayer param, LoadedDataStruct data) throws RuntimeException - { - if(data.getNBT() != null) - param.getPlayer().readFromNBT(data.getNBT()); - } - - @Override - public void callStage3(QueuedPlayer param, LoadedDataStruct data, ServerDataLoader callback) throws RuntimeException - { - callback.playerLoadCallback(param.getNetwork(), param.getPlayer(), param.getNethandler(), data.getNBT(), data.getPlayerData()); - } -} diff --git a/src/main/java/org/ultramine/server/data/player/io/QueuedPlayer.java b/src/main/java/org/ultramine/server/data/player/io/QueuedPlayer.java deleted file mode 100644 index 940b361..0000000 --- a/src/main/java/org/ultramine/server/data/player/io/QueuedPlayer.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.ultramine.server.data.player.io; - -import org.ultramine.server.data.IDataProvider; - -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.network.NetHandlerPlayServer; -import net.minecraft.network.NetworkManager; - -public class QueuedPlayer -{ - private final IDataProvider provider; - private final NetworkManager network; - private final EntityPlayerMP player; - private final NetHandlerPlayServer nethandler; - private final boolean loadData; - - public QueuedPlayer(IDataProvider provider, NetworkManager network, EntityPlayerMP player, NetHandlerPlayServer nethandler, boolean loadData) - { - this.provider = provider; - this.network = network; - this.player = player; - this.nethandler = nethandler; - this.loadData = loadData; - } - - public IDataProvider getDataProvider() - { - return provider; - } - - public NetworkManager getNetwork() - { - return network; - } - - public EntityPlayerMP getPlayer() - { - return player; - } - - public NetHandlerPlayServer getNethandler() - { - return nethandler; - } - - public boolean shouldLoadData() - { - return loadData; - } -} diff --git a/src/main/java/org/ultramine/server/util/TwoStepsExecutor.java b/src/main/java/org/ultramine/server/util/TwoStepsExecutor.java new file mode 100644 index 0000000..169785e --- /dev/null +++ b/src/main/java/org/ultramine/server/util/TwoStepsExecutor.java @@ -0,0 +1,87 @@ +package org.ultramine.server.util; + +import java.util.Queue; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import com.google.common.base.Function; +import com.google.common.collect.Queues; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; + +public final class TwoStepsExecutor +{ + private final Executor exec; + private final Queue> queue = Queues.newConcurrentLinkedQueue(); + + public TwoStepsExecutor(Executor exec) + { + this.exec = exec; + } + + public TwoStepsExecutor(String threadNameFormat) + { + this(Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(threadNameFormat).setDaemon(true).build())); + } + + public void register() + { + FMLCommonHandler.instance().bus().register(this); + } + + public void execute(final Function async, final Function sync) + { + execute(null, async, sync); + } + + public void execute(final P param, final Function async, final Function sync) + { + exec.execute(new Runnable() + { + @Override + public void run() + { + R ret = async.apply(param); + queue.add(new CallbackDataStruct(sync, ret)); + } + }); + } + + @SubscribeEvent + public void onServerTick(TickEvent.ServerTickEvent e) + { + if(e.phase == TickEvent.Phase.START) + { + while(!queue.isEmpty()) + queue.poll().call(); + } + } + + protected void finalize() + { + try + { + FMLCommonHandler.instance().bus().unregister(this); + } catch(Throwable ignored){} + } + + private static class CallbackDataStruct + { + private Function callback; + private T param; + + public CallbackDataStruct(Function callback, T param) + { + this.callback = callback; + this.param = param; + } + + public void call() + { + callback.apply(param); + } + } +}