From c7af125afc7a4440bc5a7a7bcb253f7da4367b3f Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 11:32:15 +0200 Subject: [PATCH 01/11] Remove FaceExpressionService Face expressions are automatically defaulted back after 5 seconds by the client, anyway --- src/main/java/client/Character.java | 9 +- src/main/java/net/server/channel/Channel.java | 7 - .../task/channel/FaceExpressionService.java | 122 ------------------ .../server/services/type/ChannelServices.java | 1 - src/main/java/server/maps/MapleMap.java | 4 - 5 files changed, 3 insertions(+), 140 deletions(-) delete mode 100644 src/main/java/net/server/services/task/channel/FaceExpressionService.java diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java index ec324f9927..6b72085e54 100644 --- a/src/main/java/client/Character.java +++ b/src/main/java/client/Character.java @@ -52,9 +52,7 @@ import net.server.guild.Alliance; import net.server.guild.Guild; import net.server.guild.GuildCharacter; import net.server.guild.GuildPackets; -import net.server.services.task.channel.FaceExpressionService; import net.server.services.task.world.CharacterSaveService; -import net.server.services.type.ChannelServices; import net.server.services.type.WorldServices; import net.server.world.*; import org.slf4j.Logger; @@ -2754,11 +2752,10 @@ public class Character extends AbstractCharacterObject { public void changeFaceExpression(int emote) { long timeNow = Server.getInstance().getCurrentTime(); - if (timeNow - lastExpression > 2000) { + // Client allows changing every 2 seconds. Give it a little bit of overhead for packet delays. + if (timeNow - lastExpression > 1500) { lastExpression = timeNow; - - FaceExpressionService service = (FaceExpressionService) client.getChannelServer().getServiceAccess(ChannelServices.FACE_EXPRESSION); - service.registerFaceExpression(map, this, emote); + getMap().broadcastMessage(this, PacketCreator.facialExpression(this, emote), false); } } diff --git a/src/main/java/net/server/channel/Channel.java b/src/main/java/net/server/channel/Channel.java index feb22becb8..e1c4daf9aa 100644 --- a/src/main/java/net/server/channel/Channel.java +++ b/src/main/java/net/server/channel/Channel.java @@ -109,9 +109,6 @@ public final class Channel { private final MonitoredReentrantReadWriteLock merchantLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MERCHANT, true); private final MonitoredReadLock merchRlock = MonitoredReadLockFactory.createLock(merchantLock); private final MonitoredWriteLock merchWlock = MonitoredWriteLockFactory.createLock(merchantLock); - - private final MonitoredReentrantLock[] faceLock = new MonitoredReentrantLock[YamlConfig.config.server.CHANNEL_LOCKS]; - private MonitoredReentrantLock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHANNEL, true); public Channel(final int world, final int channel, long startTime) { @@ -224,10 +221,6 @@ public final class Channel { } private void emptyLocks() { - for (int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) { - faceLock[i] = faceLock[i].dispose(); - } - lock = lock.dispose(); } diff --git a/src/main/java/net/server/services/task/channel/FaceExpressionService.java b/src/main/java/net/server/services/task/channel/FaceExpressionService.java deleted file mode 100644 index 98ea9c8261..0000000000 --- a/src/main/java/net/server/services/task/channel/FaceExpressionService.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.services.task.channel; - -import client.Character; -import config.YamlConfig; -import net.server.audit.LockCollector; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; -import net.server.services.BaseScheduler; -import net.server.services.BaseService; -import server.maps.MapleMap; -import tools.PacketCreator; - -import java.util.Collections; - -/** - * @author Ronan - */ -public class FaceExpressionService extends BaseService { - - private final FaceExpressionScheduler[] faceExpressionSchedulers = new FaceExpressionScheduler[YamlConfig.config.server.CHANNEL_LOCKS]; - private final MonitoredReentrantLock[] faceLock = new MonitoredReentrantLock[YamlConfig.config.server.CHANNEL_LOCKS]; - - public FaceExpressionService() { - for (int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) { - faceLock[i] = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHANNEL_FACEEXPRS, true); - faceExpressionSchedulers[i] = new FaceExpressionScheduler(faceLock[i]); - } - } - - private void emptyLocks() { - for (int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) { - faceLock[i] = faceLock[i].dispose(); - } - } - - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - @Override - public void dispose() { - for (int i = 0; i < YamlConfig.config.server.CHANNEL_LOCKS; i++) { - if (faceExpressionSchedulers[i] != null) { - faceExpressionSchedulers[i].dispose(); - faceExpressionSchedulers[i] = null; - } - } - - disposeLocks(); - } - - public void registerFaceExpression(final MapleMap map, final Character chr, int emote) { - int lockid = getChannelSchedulerIndex(map.getId()); - - Runnable cancelAction = () -> { - if (chr.isLoggedinWorld()) { - map.broadcastMessage(chr, PacketCreator.facialExpression(chr, 0), false); - } - }; - - faceLock[lockid].lock(); - try { - if (!chr.isLoggedinWorld()) { - return; - } - - faceExpressionSchedulers[lockid].registerFaceExpression(chr.getId(), cancelAction); - } finally { - faceLock[lockid].unlock(); - } - - map.broadcastMessage(chr, PacketCreator.facialExpression(chr, emote), false); - } - - public void unregisterFaceExpression(int mapid, Character chr) { - int lockid = getChannelSchedulerIndex(mapid); - - faceLock[lockid].lock(); - try { - faceExpressionSchedulers[lockid].unregisterFaceExpression(chr.getId()); - } finally { - faceLock[lockid].unlock(); - } - } - - private class FaceExpressionScheduler extends BaseScheduler { - - public FaceExpressionScheduler(final MonitoredReentrantLock channelFaceLock) { - super(MonitoredLockType.CHANNEL_FACESCHDL, Collections.singletonList(channelFaceLock)); - } - - public void registerFaceExpression(Integer characterId, Runnable runAction) { - registerEntry(characterId, runAction, 5000); - } - - public void unregisterFaceExpression(Integer characterId) { - interruptEntry(characterId); - } - - } - -} diff --git a/src/main/java/net/server/services/type/ChannelServices.java b/src/main/java/net/server/services/type/ChannelServices.java index aedebeb1ce..bd3cadf9b2 100644 --- a/src/main/java/net/server/services/type/ChannelServices.java +++ b/src/main/java/net/server/services/type/ChannelServices.java @@ -33,7 +33,6 @@ public enum ChannelServices implements ServiceType { MOB_ANIMATION(MobAnimationService.class), MOB_CLEAR_SKILL(MobClearSkillService.class), MOB_MIST(MobMistService.class), - FACE_EXPRESSION(FaceExpressionService.class), EVENT(EventService.class), OVERALL(OverallService.class); diff --git a/src/main/java/server/maps/MapleMap.java b/src/main/java/server/maps/MapleMap.java index 0b7064fd47..d0db25fd6b 100644 --- a/src/main/java/server/maps/MapleMap.java +++ b/src/main/java/server/maps/MapleMap.java @@ -47,7 +47,6 @@ import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.audit.locks.factory.MonitoredWriteLockFactory; import net.server.channel.Channel; import net.server.coordinator.world.MonsterAggroCoordinator; -import net.server.services.task.channel.FaceExpressionService; import net.server.services.task.channel.MobMistService; import net.server.services.task.channel.OverallService; import net.server.services.type.ChannelServices; @@ -2677,9 +2676,6 @@ public class MapleMap { public void removePlayer(Character chr) { Channel cserv = chr.getClient().getChannelServer(); - - FaceExpressionService service = (FaceExpressionService) this.getChannelServer().getServiceAccess(ChannelServices.FACE_EXPRESSION); - service.unregisterFaceExpression(mapid, chr); chr.unregisterChairBuff(); Party party = chr.getParty(); From b6c17e944af736284004be03b9ec92afa4f73055 Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 11:55:56 +0200 Subject: [PATCH 02/11] Stop using monitored locks in Channel --- src/main/java/net/server/channel/Channel.java | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/main/java/net/server/channel/Channel.java b/src/main/java/net/server/channel/Channel.java index e1c4daf9aa..9a508a8e9d 100644 --- a/src/main/java/net/server/channel/Channel.java +++ b/src/main/java/net/server/channel/Channel.java @@ -28,11 +28,6 @@ import net.netty.ChannelServer; import net.packet.Packet; import net.server.PlayerStorage; import net.server.Server; -import net.server.audit.LockCollector; -import net.server.audit.locks.*; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import net.server.services.BaseService; import net.server.services.ServicesManager; import net.server.services.type.ChannelServices; @@ -58,6 +53,9 @@ import java.nio.file.Paths; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import static java.util.concurrent.TimeUnit.*; @@ -106,10 +104,9 @@ public final class Channel { private Set ongoingCathedralGuests = null; private long ongoingStartTime; - private final MonitoredReentrantReadWriteLock merchantLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MERCHANT, true); - private final MonitoredReadLock merchRlock = MonitoredReadLockFactory.createLock(merchantLock); - private final MonitoredWriteLock merchWlock = MonitoredWriteLockFactory.createLock(merchantLock); - private MonitoredReentrantLock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHANNEL, true); + private final Lock lock = new ReentrantLock(true);; + private final Lock merchRlock; + private final Lock merchWlock; public Channel(final int world, final int channel, long startTime) { this.world = world; @@ -120,6 +117,10 @@ public final class Channel { this.port = BASE_PORT + (this.channel - 1) + (world * 100); this.ip = YamlConfig.config.server.HOST + ":" + port; + ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true); + this.merchRlock = rwLock.readLock(); + this.merchWlock = rwLock.writeLock(); + try { this.channelServer = initServer(port, world, channel); expedType.addAll(Arrays.asList(ExpeditionType.values())); @@ -213,15 +214,6 @@ public final class Channel { } closeChannelServices(); - disposeLocks(); - } - - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - lock = lock.dispose(); } private void closeAllMerchants() { From 7e848618e82c48f55e128252350a6bf36644ba85 Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 12:07:38 +0200 Subject: [PATCH 03/11] Stop using monitored locks in Server --- src/main/java/net/server/Server.java | 34 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java index 59f310f6b1..bf5df0cc53 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -38,13 +38,6 @@ import constants.net.ServerConstants; import net.netty.LoginServer; import net.packet.Packet; import net.server.audit.ThreadTracker; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import net.server.channel.Channel; import net.server.coordinator.session.IpAddresses; import net.server.coordinator.session.SessionCoordinator; @@ -79,6 +72,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import static java.util.concurrent.TimeUnit.*; @@ -117,16 +113,14 @@ public class Server { private final List>> playerRanking = new LinkedList<>(); - private final Lock srvLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER); - private final Lock disLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER_DISEASES); + private final Lock srvLock = new ReentrantLock(); + private final Lock disLock = new ReentrantLock(); - private final MonitoredReentrantReadWriteLock wldLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.SERVER_WORLDS, true); - private final MonitoredReadLock wldRLock = MonitoredReadLockFactory.createLock(wldLock); - private final MonitoredWriteLock wldWLock = MonitoredWriteLockFactory.createLock(wldLock); + private final Lock wldRLock; + private final Lock wldWLock; - private final MonitoredReentrantReadWriteLock lgnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.SERVER_LOGIN, true); - private final MonitoredReadLock lgnRLock = MonitoredReadLockFactory.createLock(lgnLock); - private final MonitoredWriteLock lgnWLock = MonitoredWriteLockFactory.createLock(lgnLock); + private final Lock lgnRLock; + private final Lock lgnWLock; private final AtomicLong currentTime = new AtomicLong(0); private long serverCurrentTime = 0; @@ -135,6 +129,16 @@ public class Server { private boolean online = false; public static long uptime = System.currentTimeMillis(); + private Server() { + ReadWriteLock worldLock = new ReentrantReadWriteLock(true); + this.wldRLock = worldLock.readLock(); + this.wldWLock = worldLock.writeLock(); + + ReadWriteLock loginLock = new ReentrantReadWriteLock(true); + this.lgnRLock = loginLock.readLock(); + this.lgnWLock = loginLock.writeLock(); + } + public int getCurrentTimestamp() { return (int) (Server.getInstance().getCurrentTime() - Server.uptime); } From 28e8862254abe625af63feefa39e82290f1125cd Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 13:31:55 +0200 Subject: [PATCH 04/11] Stop using monitored locks in World --- src/main/java/net/server/world/World.java | 60 ++++++++++------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/src/main/java/net/server/world/World.java b/src/main/java/net/server/world/World.java index f41775ee6b..c473aba652 100644 --- a/src/main/java/net/server/world/World.java +++ b/src/main/java/net/server/world/World.java @@ -32,11 +32,6 @@ import constants.game.GameConstants; import net.packet.Packet; import net.server.PlayerStorage; import net.server.Server; -import net.server.audit.LockCollector; -import net.server.audit.locks.*; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import net.server.channel.Channel; import net.server.channel.CharacterIdChannelPair; import net.server.coordinator.matchchecker.MatchCheckerCoordinator; @@ -69,6 +64,10 @@ import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import static java.util.concurrent.TimeUnit.*; @@ -103,13 +102,12 @@ public class World { private final MatchCheckerCoordinator matchChecker = new MatchCheckerCoordinator(); private final PartySearchCoordinator partySearch = new PartySearchCoordinator(); - private final MonitoredReentrantReadWriteLock chnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_CHANNELS, true); - private final MonitoredReadLock chnRLock = MonitoredReadLockFactory.createLock(chnLock); - private final MonitoredWriteLock chnWLock = MonitoredWriteLockFactory.createLock(chnLock); + private final Lock chnRLock; + private final Lock chnWLock; private final Map> accountChars = new HashMap<>(); private final Map accountStorages = new HashMap<>(); - private MonitoredReentrantLock accountCharsLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_CHARS, true); + private final Lock accountCharsLock = new ReentrantLock(true); private final Set queuedGuilds = new HashSet<>(); private final Map, Pair>> queuedMarriages = new HashMap<>(); @@ -118,39 +116,39 @@ public class World { private final Map partyChars = new HashMap<>(); private final Map parties = new HashMap<>(); private final AtomicInteger runningPartyId = new AtomicInteger(); - private MonitoredReentrantLock partyLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_PARTY, true); + private final Lock partyLock = new ReentrantLock(true); private final Map owlSearched = new LinkedHashMap<>(); private final List> cashItemBought = new ArrayList<>(9); - private final MonitoredReentrantReadWriteLock suggestLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_SUGGEST, true); - private final MonitoredReadLock suggestRLock = MonitoredReadLockFactory.createLock(suggestLock); - private final MonitoredWriteLock suggestWLock = MonitoredWriteLockFactory.createLock(suggestLock); + + private final Lock suggestRLock; + private final Lock suggestWLock; private final Map disabledServerMessages = new HashMap<>(); // reuse owl lock - private MonitoredReentrantLock srvMessagesLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_SRVMESSAGES); + private final Lock srvMessagesLock = new ReentrantLock(); private ScheduledFuture srvMessagesSchedule; - private MonitoredReentrantLock activePetsLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_PETS, true); + private Lock activePetsLock = new ReentrantLock(true); private final Map activePets = new LinkedHashMap<>(); private ScheduledFuture petsSchedule; private long petUpdate; - private MonitoredReentrantLock activeMountsLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_MOUNTS, true); + private Lock activeMountsLock = new ReentrantLock(true); private final Map activeMounts = new LinkedHashMap<>(); private ScheduledFuture mountsSchedule; private long mountUpdate; - private MonitoredReentrantLock activePlayerShopsLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_PSHOPS, true); + private Lock activePlayerShopsLock = new ReentrantLock(true); private final Map activePlayerShops = new LinkedHashMap<>(); - private MonitoredReentrantLock activeMerchantsLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_MERCHS, true); + private Lock activeMerchantsLock = new ReentrantLock(true); private final Map> activeMerchants = new LinkedHashMap<>(); private ScheduledFuture merchantSchedule; private long merchantUpdate; private final Map registeredTimedMapObjects = new LinkedHashMap<>(); private ScheduledFuture timedMapObjectsSchedule; - private MonitoredReentrantLock timedMapObjectLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_MAPOBJS, true); + private Lock timedMapObjectLock = new ReentrantLock(true); private final Map fishingAttempters = Collections.synchronizedMap(new WeakHashMap<>()); private Map playerHpDec = Collections.synchronizedMap(new WeakHashMap<>()); @@ -177,6 +175,14 @@ public class World { runningPartyId.set(1000000001); // partyid must not clash with charid to solve update item looting issues, found thanks to Vcoc runningMessengerId.set(1); + ReadWriteLock channelLock = new ReentrantReadWriteLock(true); + this.chnRLock = channelLock.readLock(); + this.chnWLock = channelLock.writeLock(); + + ReadWriteLock suggestLock = new ReentrantReadWriteLock(true); + this.suggestRLock = suggestLock.readLock(); + this.suggestWLock = suggestLock.writeLock(); + petUpdate = Server.getInstance().getCurrentTime(); mountUpdate = petUpdate; @@ -2102,22 +2108,6 @@ public class World { } closeWorldServices(); - disposeLocks(); - } - - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - accountCharsLock = accountCharsLock.dispose(); - partyLock = partyLock.dispose(); - srvMessagesLock = srvMessagesLock.dispose(); - activePetsLock = activePetsLock.dispose(); - activeMountsLock = activeMountsLock.dispose(); - activePlayerShopsLock = activePlayerShopsLock.dispose(); - activeMerchantsLock = activeMerchantsLock.dispose(); - timedMapObjectLock = timedMapObjectLock.dispose(); } public final void shutdown() { From 42043c3d6ca01677069ae4070041c9ef10f4c7e9 Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 13:38:16 +0200 Subject: [PATCH 05/11] Stop using monitored locks in MapleMap --- src/main/java/server/maps/MapleMap.java | 35 +++++++++++-------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/main/java/server/maps/MapleMap.java b/src/main/java/server/maps/MapleMap.java index d0db25fd6b..bf44ba733f 100644 --- a/src/main/java/server/maps/MapleMap.java +++ b/src/main/java/server/maps/MapleMap.java @@ -38,13 +38,6 @@ import constants.id.MobId; import constants.inventory.ItemConstants; import net.packet.Packet; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import net.server.channel.Channel; import net.server.coordinator.world.MonsterAggroCoordinator; import net.server.services.task.channel.MobMistService; @@ -77,6 +70,9 @@ import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Predicate; import static java.util.concurrent.TimeUnit.MINUTES; @@ -162,15 +158,15 @@ public class MapleMap { private int timeExpand; //locks - private final MonitoredReadLock chrRLock; - private final MonitoredWriteLock chrWLock; - private final MonitoredReadLock objectRLock; - private final MonitoredWriteLock objectWLock; + private final Lock chrRLock; + private final Lock chrWLock; + private final Lock objectRLock; + private final Lock objectWLock; - private final Lock lootLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_LOOT, true); + private final Lock lootLock = new ReentrantLock(true); // due to the nature of loadMapFromWz (synchronized), sole function that calls 'generateMapDropRangeCache', this lock remains optional. - private static final Lock bndLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_BOUNDS, true); + private static final Lock bndLock = new ReentrantLock(true); public MapleMap(int mapid, int world, int channel, int returnMapId, float monsterRate) { this.mapid = mapid; @@ -181,13 +177,14 @@ public class MapleMap { if (this.monsterRate == 0) { this.monsterRate = 1; } - final MonitoredReentrantReadWriteLock chrLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_CHRS, true); - chrRLock = MonitoredReadLockFactory.createLock(chrLock); - chrWLock = MonitoredWriteLockFactory.createLock(chrLock); - final MonitoredReentrantReadWriteLock objectLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_OBJS, true); - objectRLock = MonitoredReadLockFactory.createLock(objectLock); - objectWLock = MonitoredWriteLockFactory.createLock(objectLock); + final ReadWriteLock chrLock = new ReentrantReadWriteLock(true); + chrRLock = chrLock.readLock(); + chrWLock = chrLock.writeLock(); + + final ReadWriteLock objectLock = new ReentrantReadWriteLock(true); + objectRLock = objectLock.readLock(); + objectWLock = objectLock.writeLock(); aggroMonitor = new MonsterAggroCoordinator(); } From 8ab2058ecc8002717456a2918d25539ce750bb1d Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 13:56:12 +0200 Subject: [PATCH 06/11] Stop using monitored locks in EventInstanceManager --- .../scripting/event/EventInstanceManager.java | 177 +++++++++--------- 1 file changed, 84 insertions(+), 93 deletions(-) diff --git a/src/main/java/scripting/event/EventInstanceManager.java b/src/main/java/scripting/event/EventInstanceManager.java index 6b8c90f539..9ee193cf7a 100644 --- a/src/main/java/scripting/event/EventInstanceManager.java +++ b/src/main/java/scripting/event/EventInstanceManager.java @@ -26,11 +26,6 @@ import client.Skill; import client.SkillFactory; import config.YamlConfig; import constants.inventory.ItemConstants; -import net.server.audit.LockCollector; -import net.server.audit.locks.*; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import net.server.coordinator.world.EventRecallCoordinator; import net.server.world.Party; import net.server.world.PartyCharacter; @@ -58,6 +53,10 @@ import java.awt.*; import java.util.List; import java.util.*; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import static java.util.concurrent.TimeUnit.MINUTES; @@ -82,12 +81,11 @@ public class EventInstanceManager { private Expedition expedition = null; private final List mapIds = new LinkedList<>(); - private final MonitoredReentrantReadWriteLock lock = new MonitoredReentrantReadWriteLock(MonitoredLockType.EIM, true); - private final MonitoredReadLock rL = MonitoredReadLockFactory.createLock(lock); - private final MonitoredWriteLock wL = MonitoredWriteLockFactory.createLock(lock); + private final Lock readLock; + private final Lock writeLock; - private MonitoredReentrantLock pL = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EIM_PARTY, true); - private MonitoredReentrantLock sL = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EIM_SCRIPT, true); + private final Lock propertyLock = new ReentrantLock(true); + private final Lock scriptLock = new ReentrantLock(true); private ScheduledFuture event_schedule = null; private boolean disposed = false; @@ -117,6 +115,10 @@ public class EventInstanceManager { this.name = name; this.ess = new EventScriptScheduler(); this.mapManager = new MapManager(this, em.getWorldServer().getId(), em.getChannelServer().getId()); + + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); + this.readLock = readWriteLock.readLock(); + this.writeLock = readWriteLock.writeLock(); } public void setName(String name) { @@ -124,11 +126,11 @@ public class EventInstanceManager { } public EventManager getEm() { - sL.lock(); + scriptLock.lock(); try { return em; } finally { - sL.unlock(); + scriptLock.unlock(); } } @@ -239,7 +241,7 @@ public class EventInstanceManager { return; } - wL.lock(); + writeLock.lock(); try { if (chars.containsKey(chr.getId())) { return; @@ -248,7 +250,7 @@ public class EventInstanceManager { chars.put(chr.getId(), chr); chr.setEventInstance(this); } finally { - wL.unlock(); + writeLock.unlock(); } if (runEntryScript) { @@ -391,12 +393,12 @@ public class EventInstanceManager { log.error("Event script {} does not implement the playerUnregistered function", em.getName(), ex); } - wL.lock(); + writeLock.lock(); try { chars.remove(chr.getId()); chr.setEventInstance(null); } finally { - wL.unlock(); + writeLock.unlock(); } gridRemove(chr); @@ -404,38 +406,38 @@ public class EventInstanceManager { } public int getPlayerCount() { - rL.lock(); + readLock.lock(); try { return chars.size(); } finally { - rL.unlock(); + readLock.unlock(); } } public Character getPlayerById(int id) { - rL.lock(); + readLock.lock(); try { return chars.get(id); } finally { - rL.unlock(); + readLock.unlock(); } } public List getPlayers() { - rL.lock(); + readLock.lock(); try { return new ArrayList<>(chars.values()); } finally { - rL.unlock(); + readLock.unlock(); } } private List getPlayerList() { - rL.lock(); + readLock.lock(); try { return new LinkedList<>(chars.values()); } finally { - rL.unlock(); + readLock.unlock(); } } @@ -480,7 +482,7 @@ public class EventInstanceManager { public void monsterKilled(final Monster mob, final boolean hasKiller) { int scriptResult = 0; - sL.lock(); + scriptLock.lock(); try { mobs.remove(mob); @@ -492,7 +494,7 @@ public class EventInstanceManager { } } } finally { - sL.unlock(); + scriptLock.unlock(); } if (scriptResult > 0) { @@ -598,13 +600,13 @@ public class EventInstanceManager { } public void dispose() { - rL.lock(); + readLock.lock(); try { for (Character chr : chars.values()) { chr.setEventInstance(null); } } finally { - rL.unlock(); + readLock.unlock(); } dispose(false); @@ -624,7 +626,7 @@ public class EventInstanceManager { ess.dispose(); - wL.lock(); + writeLock.lock(); try { for (Character chr : chars.values()) { chr.setEventInstance(null); @@ -633,7 +635,7 @@ public class EventInstanceManager { mobs.clear(); ess = null; } finally { - wL.unlock(); + writeLock.unlock(); } if (event_schedule != null) { @@ -648,44 +650,33 @@ public class EventInstanceManager { disposeExpedition(); - sL.lock(); + scriptLock.lock(); try { if (!eventCleared) { em.disposeInstance(name); } } finally { - sL.unlock(); + scriptLock.unlock(); } TimerManager.getInstance().schedule(() -> { mapManager.dispose(); // issues from instantly disposing some event objects found thanks to MedicOP - wL.lock(); + writeLock.lock(); try { mapManager = null; em = null; } finally { - wL.unlock(); + writeLock.unlock(); } - - disposeLocks(); }, MINUTES.toMillis(1)); } - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - pL = pL.dispose(); - sL = sL.dispose(); - } - public MapManager getMapFactory() { return mapManager; } public void schedule(final String methodName, long delay) { - rL.lock(); + readLock.lock(); try { if (ess != null) { Runnable r = () -> { @@ -699,7 +690,7 @@ public class EventInstanceManager { ess.registerEntry(r, delay); } } finally { - rL.unlock(); + readLock.unlock(); } } @@ -712,13 +703,13 @@ public class EventInstanceManager { map.setEventInstance(this); if (!mapManager.isMapLoaded(mapId)) { - sL.lock(); + scriptLock.lock(); try { if (em.getProperty("shuffleReactors") != null && em.getProperty("shuffleReactors").equals("true")) { map.shuffleReactors(); } } finally { - sL.unlock(); + scriptLock.unlock(); } } return map; @@ -733,56 +724,56 @@ public class EventInstanceManager { } public void setProperty(String key, String value) { - pL.lock(); + propertyLock.lock(); try { props.setProperty(key, value); } finally { - pL.unlock(); + propertyLock.unlock(); } } public Object setProperty(String key, String value, boolean prev) { - pL.lock(); + propertyLock.lock(); try { return props.setProperty(key, value); } finally { - pL.unlock(); + propertyLock.unlock(); } } public void setObjectProperty(String key, Object obj) { - pL.lock(); + propertyLock.lock(); try { objectProps.put(key, obj); } finally { - pL.unlock(); + propertyLock.unlock(); } } public String getProperty(String key) { - pL.lock(); + propertyLock.lock(); try { return props.getProperty(key); } finally { - pL.unlock(); + propertyLock.unlock(); } } public int getIntProperty(String key) { - pL.lock(); + propertyLock.lock(); try { return Integer.parseInt(props.getProperty(key)); } finally { - pL.unlock(); + propertyLock.unlock(); } } public Object getObjectProperty(String key) { - pL.lock(); + propertyLock.lock(); try { return objectProps.get(key); } finally { - pL.unlock(); + propertyLock.unlock(); } } @@ -957,11 +948,11 @@ public class EventInstanceManager { public final void setExclusiveItems(List items) { List exclusive = convertToIntegerList(items); - wL.lock(); + writeLock.lock(); try { exclusiveItems.addAll(exclusive); } finally { - wL.unlock(); + writeLock.unlock(); } } @@ -989,13 +980,13 @@ public class EventInstanceManager { List rewardQtys = convertToIntegerList(qtys); //rewardsSet and rewardsQty hold temporary values - wL.lock(); + writeLock.lock(); try { collectionSet.put(eventLevel, rewardIds); collectionQty.put(eventLevel, rewardQtys); collectionExp.put(eventLevel, expGiven); } finally { - wL.unlock(); + writeLock.unlock(); } } @@ -1036,7 +1027,7 @@ public class EventInstanceManager { List rewardsSet, rewardsQty; Integer rewardExp; - rL.lock(); + readLock.lock(); try { eventLevel--; //event level starts counting from 1 if (eventLevel >= collectionSet.size()) { @@ -1048,7 +1039,7 @@ public class EventInstanceManager { rewardExp = collectionExp.get(eventLevel); } finally { - rL.unlock(); + readLock.unlock(); } if (rewardExp == null) { @@ -1080,11 +1071,11 @@ public class EventInstanceManager { if (expedition != null) { expedition.dispose(eventCleared); - sL.lock(); + scriptLock.lock(); try { expedition.removeChannelExpedition(em.getChannelServer()); } finally { - sL.unlock(); + scriptLock.unlock(); } expedition = null; @@ -1108,11 +1099,11 @@ public class EventInstanceManager { chr.awardQuestPoint(YamlConfig.config.server.QUEST_POINT_PER_EVENT_CLEAR); } - sL.lock(); + scriptLock.lock(); try { em.disposeInstance(name); } finally { - sL.unlock(); + scriptLock.unlock(); } disposeExpedition(); @@ -1168,7 +1159,7 @@ public class EventInstanceManager { } public final boolean isEventTeamTogether() { - rL.lock(); + readLock.lock(); try { if (chars.size() <= 1) { return true; @@ -1187,7 +1178,7 @@ public class EventInstanceManager { return true; } finally { - rL.unlock(); + readLock.unlock(); } } @@ -1228,29 +1219,29 @@ public class EventInstanceManager { } public final int getLeaderId() { - rL.lock(); + readLock.lock(); try { return leaderId; } finally { - rL.unlock(); + readLock.unlock(); } } public Character getLeader() { - rL.lock(); + readLock.lock(); try { return chars.get(leaderId); } finally { - rL.unlock(); + readLock.unlock(); } } public final void setLeader(Character chr) { - wL.lock(); + writeLock.lock(); try { leaderId = chr.getId(); } finally { - wL.unlock(); + writeLock.unlock(); } } @@ -1293,11 +1284,11 @@ public class EventInstanceManager { map.broadcastMessage(PacketCreator.playSound("Party1/Clear")); if (hasGate) { map.broadcastMessage(PacketCreator.environmentChange(mapObj, newState)); - wL.lock(); + writeLock.lock(); try { openedGates.put(map.getId(), new Pair<>(mapObj, newState)); } finally { - wL.unlock(); + writeLock.unlock(); } } } @@ -1305,13 +1296,13 @@ public class EventInstanceManager { public final void recoverOpenedGate(Character chr, int thisMapId) { Pair gateData = null; - rL.lock(); + readLock.lock(); try { if (openedGates.containsKey(thisMapId)) { gateData = openedGates.get(thisMapId); } } finally { - rL.unlock(); + readLock.unlock(); } if (gateData != null) { @@ -1349,50 +1340,50 @@ public class EventInstanceManager { // registers a player status in an event public final void gridInsert(Character chr, int newStatus) { - wL.lock(); + writeLock.lock(); try { playerGrid.put(chr.getId(), newStatus); } finally { - wL.unlock(); + writeLock.unlock(); } } // unregisters a player status in an event public final void gridRemove(Character chr) { - wL.lock(); + writeLock.lock(); try { playerGrid.remove(chr.getId()); } finally { - wL.unlock(); + writeLock.unlock(); } } // checks a player status public final int gridCheck(Character chr) { - rL.lock(); + readLock.lock(); try { Integer i = playerGrid.get(chr.getId()); return (i != null) ? i : -1; } finally { - rL.unlock(); + readLock.unlock(); } } public final int gridSize() { - rL.lock(); + readLock.lock(); try { return playerGrid.size(); } finally { - rL.unlock(); + readLock.unlock(); } } public final void gridClear() { - wL.lock(); + writeLock.lock(); try { playerGrid.clear(); } finally { - wL.unlock(); + writeLock.unlock(); } } From 8657b765b17b505edc6304739de335fb9292e77e Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 14:16:06 +0200 Subject: [PATCH 07/11] Remove monitored read/write locks, use basic version --- .../java/client/AbstractCharacterObject.java | 22 ++++++------- src/main/java/net/server/PlayerStorage.java | 20 ++++++------ .../factory/MonitoredReadLockFactory.java | 32 ------------------- .../factory/MonitoredWriteLockFactory.java | 32 ------------------- .../partysearch/PartySearchCoordinator.java | 32 +++++++++---------- .../partysearch/PartySearchEchelon.java | 21 ++++++------ .../partysearch/PartySearchStorage.java | 20 ++++++------ .../java/server/life/MobSkillFactory.java | 23 ++++++------- src/main/java/server/maps/DoorObject.java | 18 +++++------ src/main/java/server/maps/MapManager.java | 19 +++++------ src/main/java/tools/IntervalBuilder.java | 22 +++++-------- 11 files changed, 93 insertions(+), 168 deletions(-) delete mode 100644 src/main/java/net/server/audit/locks/factory/MonitoredReadLockFactory.java delete mode 100644 src/main/java/net/server/audit/locks/factory/MonitoredWriteLockFactory.java diff --git a/src/main/java/client/AbstractCharacterObject.java b/src/main/java/client/AbstractCharacterObject.java index d7dc91400d..e178ac1f43 100644 --- a/src/main/java/client/AbstractCharacterObject.java +++ b/src/main/java/client/AbstractCharacterObject.java @@ -21,13 +21,6 @@ package client; import config.YamlConfig; import constants.game.GameConstants; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import server.maps.AbstractAnimatedMapObject; import server.maps.MapleMap; @@ -35,6 +28,9 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author RonanLana @@ -50,14 +46,14 @@ public abstract class AbstractCharacterObject extends AbstractAnimatedMapObject private AbstractCharacterListener listener = null; protected Map statUpdates = new HashMap<>(); - protected Lock effLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_EFF, true); - protected MonitoredReadLock statRlock; - protected MonitoredWriteLock statWlock; + protected final Lock effLock = new ReentrantLock(true); + protected final Lock statRlock; + protected final Lock statWlock; protected AbstractCharacterObject() { - MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.CHARACTER_STA, true); - statRlock = MonitoredReadLockFactory.createLock(locks); - statWlock = MonitoredWriteLockFactory.createLock(locks); + ReadWriteLock statLock = new ReentrantReadWriteLock(true); + this.statRlock = statLock.readLock(); + this.statWlock = statLock.writeLock(); for (int i = 0; i < remainingSp.length; i++) { remainingSp[i] = 0; diff --git a/src/main/java/net/server/PlayerStorage.java b/src/main/java/net/server/PlayerStorage.java index 8fa6b4e472..fd406cadbb 100644 --- a/src/main/java/net/server/PlayerStorage.java +++ b/src/main/java/net/server/PlayerStorage.java @@ -23,21 +23,23 @@ package net.server; import client.Character; import client.Client; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class PlayerStorage { - private final MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_STORAGE, true); private final Map storage = new LinkedHashMap<>(); private final Map nameStorage = new LinkedHashMap<>(); - private final MonitoredReadLock rlock = MonitoredReadLockFactory.createLock(locks); - private final MonitoredWriteLock wlock = MonitoredWriteLockFactory.createLock(locks); + private final Lock rlock; + private final Lock wlock; + + public PlayerStorage() { + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); + this.rlock = readWriteLock.readLock(); + this.wlock = readWriteLock.writeLock(); + } public void addPlayer(Character chr) { wlock.lock(); diff --git a/src/main/java/net/server/audit/locks/factory/MonitoredReadLockFactory.java b/src/main/java/net/server/audit/locks/factory/MonitoredReadLockFactory.java deleted file mode 100644 index ae50172c62..0000000000 --- a/src/main/java/net/server/audit/locks/factory/MonitoredReadLockFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.factory; - -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.active.TrackerReadLock; - -/** - * @author RonanLana - */ -public class MonitoredReadLockFactory { - public static TrackerReadLock createLock(MonitoredReentrantReadWriteLock lock) { - return new TrackerReadLock(lock); - } -} diff --git a/src/main/java/net/server/audit/locks/factory/MonitoredWriteLockFactory.java b/src/main/java/net/server/audit/locks/factory/MonitoredWriteLockFactory.java deleted file mode 100644 index 2445d0bfe2..0000000000 --- a/src/main/java/net/server/audit/locks/factory/MonitoredWriteLockFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.factory; - -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.active.TrackerWriteLock; - -/** - * @author RonanLana - */ -public class MonitoredWriteLockFactory { - public static TrackerWriteLock createLock(MonitoredReentrantReadWriteLock lock) { - return new TrackerWriteLock(lock); - } -} diff --git a/src/main/java/net/server/coordinator/partysearch/PartySearchCoordinator.java b/src/main/java/net/server/coordinator/partysearch/PartySearchCoordinator.java index e93e99fd93..fbaba5e7e9 100644 --- a/src/main/java/net/server/coordinator/partysearch/PartySearchCoordinator.java +++ b/src/main/java/net/server/coordinator/partysearch/PartySearchCoordinator.java @@ -23,12 +23,6 @@ import client.Character; import client.Job; import config.YamlConfig; import constants.id.MapId; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import net.server.coordinator.world.InviteCoordinator; import net.server.coordinator.world.InviteCoordinator.InviteType; import net.server.world.Party; @@ -41,6 +35,9 @@ import tools.Pair; import java.util.*; import java.util.Map.Entry; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author Ronan @@ -51,9 +48,8 @@ public class PartySearchCoordinator { private final Map upcomers = new HashMap<>(); private final List leaderQueue = new LinkedList<>(); - private final MonitoredReentrantReadWriteLock leaderQueueLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_QUEUE, true); - private final MonitoredReadLock leaderQueueRLock = MonitoredReadLockFactory.createLock(leaderQueueLock); - private final MonitoredWriteLock leaderQueueWLock = MonitoredWriteLockFactory.createLock(leaderQueueLock); + private final Lock leaderQueueRLock; + private final Lock leaderQueueWLock; private final Map searchLeaders = new HashMap<>(); private final Map searchSettings = new HashMap<>(); @@ -65,6 +61,17 @@ public class PartySearchCoordinator { private static final Map> mapNeighbors = fetchNeighbouringMaps(); private static final Map jobTable = instantiateJobTable(); + public PartySearchCoordinator() { + for (Job job : jobTable.values()) { + storage.put(job, new PartySearchStorage()); + upcomers.put(job, new PartySearchEchelon()); + } + + ReadWriteLock leaderQueueLock = new ReentrantReadWriteLock(true); + this.leaderQueueRLock = leaderQueueLock.readLock(); + this.leaderQueueWLock = leaderQueueLock.writeLock(); + } + private static Map> fetchNeighbouringMaps() { Map> mapLinks = new HashMap<>(); @@ -176,13 +183,6 @@ public class PartySearchCoordinator { } - public PartySearchCoordinator() { - for (Job job : jobTable.values()) { - storage.put(job, new PartySearchStorage()); - upcomers.put(job, new PartySearchEchelon()); - } - } - public void attachPlayer(Character chr) { upcomers.get(getPartySearchJob(chr.getJob())).attachPlayer(chr); } diff --git a/src/main/java/net/server/coordinator/partysearch/PartySearchEchelon.java b/src/main/java/net/server/coordinator/partysearch/PartySearchEchelon.java index 661f0069e5..60056e8879 100644 --- a/src/main/java/net/server/coordinator/partysearch/PartySearchEchelon.java +++ b/src/main/java/net/server/coordinator/partysearch/PartySearchEchelon.java @@ -20,30 +20,31 @@ package net.server.coordinator.partysearch; import client.Character; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author Ronan */ public class PartySearchEchelon { - - private final MonitoredReentrantReadWriteLock psLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_ECHELON, true); - private final MonitoredReadLock psRLock = MonitoredReadLockFactory.createLock(psLock); - private final MonitoredWriteLock psWLock = MonitoredWriteLockFactory.createLock(psLock); + private final Lock psRLock; + private final Lock psWLock; private final Map> echelon = new HashMap<>(20); + public PartySearchEchelon() { + ReadWriteLock partySearchLock = new ReentrantReadWriteLock(true); + this.psRLock = partySearchLock.readLock(); + this.psWLock = partySearchLock.writeLock(); + } + public List exportEchelon() { psWLock.lock(); // reversing read/write actually could provide a lax yet sure performance/precision trade-off here try { diff --git a/src/main/java/net/server/coordinator/partysearch/PartySearchStorage.java b/src/main/java/net/server/coordinator/partysearch/PartySearchStorage.java index 66aa36f5ca..27a8407e69 100644 --- a/src/main/java/net/server/coordinator/partysearch/PartySearchStorage.java +++ b/src/main/java/net/server/coordinator/partysearch/PartySearchStorage.java @@ -20,15 +20,12 @@ package net.server.coordinator.partysearch; import client.Character; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import tools.IntervalBuilder; import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author Ronan @@ -38,9 +35,14 @@ public class PartySearchStorage { private final List storage = new ArrayList<>(20); private final IntervalBuilder emptyIntervals = new IntervalBuilder(); - private final MonitoredReentrantReadWriteLock psLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_STORAGE, true); - private final MonitoredReadLock psRLock = MonitoredReadLockFactory.createLock(psLock); - private final MonitoredWriteLock psWLock = MonitoredWriteLockFactory.createLock(psLock); + private final Lock psRLock; + private final Lock psWLock; + + public PartySearchStorage() { + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); + this.psRLock = readWriteLock.readLock(); + this.psWLock = readWriteLock.writeLock(); + } public List getStorageList() { psRLock.lock(); diff --git a/src/main/java/server/life/MobSkillFactory.java b/src/main/java/server/life/MobSkillFactory.java index 23463bb962..055cbbc695 100644 --- a/src/main/java/server/life/MobSkillFactory.java +++ b/src/main/java/server/life/MobSkillFactory.java @@ -21,12 +21,6 @@ along with this program. If not, see . */ package server.life; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import provider.Data; import provider.DataProvider; import provider.DataProviderFactory; @@ -38,6 +32,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import static java.util.concurrent.TimeUnit.SECONDS; @@ -49,22 +46,22 @@ public class MobSkillFactory { private static final Map mobSkills = new HashMap<>(); private final static DataProvider dataSource = DataProviderFactory.getDataProvider(WZFiles.SKILL); private static final Data skillRoot = dataSource.getData("MobSkill.img"); - private final static MonitoredReentrantReadWriteLock dataLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MOBSKILL_FACTORY); - private final static MonitoredReadLock rL = MonitoredReadLockFactory.createLock(dataLock); - private final static MonitoredWriteLock wL = MonitoredWriteLockFactory.createLock(dataLock); + private final static ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + private final static Lock readLock = readWriteLock.readLock(); + private final static Lock writeLock = readWriteLock.writeLock(); public static MobSkill getMobSkill(final int skillId, final int level) { final String key = skillId + "" + level; - rL.lock(); + readLock.lock(); try { MobSkill ret = mobSkills.get(key); if (ret != null) { return ret; } } finally { - rL.unlock(); + readLock.unlock(); } - wL.lock(); + writeLock.lock(); try { MobSkill ret; ret = mobSkills.get(key); @@ -114,7 +111,7 @@ public class MobSkillFactory { } return ret; } finally { - wL.unlock(); + writeLock.unlock(); } } } diff --git a/src/main/java/server/maps/DoorObject.java b/src/main/java/server/maps/DoorObject.java index 2af6da1821..12f3ac4ab0 100644 --- a/src/main/java/server/maps/DoorObject.java +++ b/src/main/java/server/maps/DoorObject.java @@ -22,16 +22,13 @@ package server.maps; import client.Character; import client.Client; import constants.id.MapId; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import net.server.world.Party; import tools.PacketCreator; import java.awt.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author Ronan @@ -45,9 +42,8 @@ public class DoorObject extends AbstractMapObject { private int linkedPortalId; private Point linkedPos; - private final MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_DOOR, true); - private final MonitoredReadLock rlock = MonitoredReadLockFactory.createLock(locks); - private final MonitoredWriteLock wlock = MonitoredWriteLockFactory.createLock(locks); + private final Lock rlock; + private final Lock wlock; public DoorObject(int owner, MapleMap destination, MapleMap origin, int townPortalId, Point targetPosition, Point toPosition) { super(); @@ -58,6 +54,10 @@ public class DoorObject extends AbstractMapObject { from = origin; to = destination; linkedPos = toPosition; + + ReadWriteLock lock = new ReentrantReadWriteLock(true); + this.rlock = lock.readLock(); + this.wlock = lock.writeLock(); } public void update(int townPortalId, Point toPosition) { diff --git a/src/main/java/server/maps/MapManager.java b/src/main/java/server/maps/MapManager.java index 547339a4e5..4b79038abf 100644 --- a/src/main/java/server/maps/MapManager.java +++ b/src/main/java/server/maps/MapManager.java @@ -19,16 +19,13 @@ */ package server.maps; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; import scripting.event.EventInstanceManager; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class MapManager { private final int channel; @@ -37,17 +34,17 @@ public class MapManager { private final Map maps = new HashMap<>(); - private final MonitoredReadLock mapsRLock; - private final MonitoredWriteLock mapsWLock; + private final Lock mapsRLock; + private final Lock mapsWLock; public MapManager(EventInstanceManager eim, int world, int channel) { this.world = world; this.channel = channel; this.event = eim; - MonitoredReentrantReadWriteLock rrwl = new MonitoredReentrantReadWriteLock(MonitoredLockType.MAP_MANAGER); - this.mapsRLock = MonitoredReadLockFactory.createLock(rrwl); - this.mapsWLock = MonitoredWriteLockFactory.createLock(rrwl); + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + this.mapsRLock = readWriteLock.readLock(); + this.mapsWLock = readWriteLock.writeLock(); } public MapleMap resetMap(int mapid) { diff --git a/src/main/java/tools/IntervalBuilder.java b/src/main/java/tools/IntervalBuilder.java index e02e9ae657..77a1c3cf78 100644 --- a/src/main/java/tools/IntervalBuilder.java +++ b/src/main/java/tools/IntervalBuilder.java @@ -19,31 +19,25 @@ */ package tools; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.factory.MonitoredReadLockFactory; -import net.server.audit.locks.factory.MonitoredWriteLockFactory; - import java.awt.geom.Line2D; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author Ronan */ public class IntervalBuilder { - private final List intervalLimits = new ArrayList<>(); - - protected MonitoredReadLock intervalRlock; - protected MonitoredWriteLock intervalWlock; + private final Lock intervalRlock; + private final Lock intervalWlock; public IntervalBuilder() { - MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.INTERVAL, true); - intervalRlock = MonitoredReadLockFactory.createLock(locks); - intervalWlock = MonitoredWriteLockFactory.createLock(locks); + ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); + this.intervalRlock = readWriteLock.readLock(); + this.intervalWlock = readWriteLock.writeLock(); } private void refitOverlappedIntervals(int st, int en, int newFrom, int newTo) { From 54878ebe8c454b649bca5c04d37214ddc0ff1222 Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 14:26:23 +0200 Subject: [PATCH 08/11] Remove monitored locks with default fairness, use basic version --- src/main/java/client/Character.java | 5 ++-- src/main/java/client/MonsterBook.java | 5 ++-- .../MonitoredReentrantLockFactory.java | 4 ---- .../session/SessionInitialization.java | 5 ++-- .../world/MonsterAggroCoordinator.java | 16 +++---------- .../java/scripting/event/EventManager.java | 24 ++++--------------- src/main/java/server/CashShop.java | 5 ++-- src/main/java/server/life/Monster.java | 13 +++++----- src/main/java/server/maps/MapItem.java | 5 ++-- 9 files changed, 25 insertions(+), 57 deletions(-) diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java index 6b72085e54..ae10d3f1ee 100644 --- a/src/main/java/client/Character.java +++ b/src/main/java/client/Character.java @@ -94,6 +94,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -219,8 +220,8 @@ public class Character extends AbstractCharacterObject { private final Lock chrLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_CHR, true); private final Lock evtLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_EVT, true); private final Lock petLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_PET, true); - private final Lock prtLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_PRT); - private final Lock cpnLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_CPN); + private final Lock prtLock = new ReentrantLock(); + private final Lock cpnLock = new ReentrantLock(); private final Map> excluded = new LinkedHashMap<>(); private final Set excludedItems = new LinkedHashSet<>(); private final Set disabledPartySearchInvites = new LinkedHashSet<>(); diff --git a/src/main/java/client/MonsterBook.java b/src/main/java/client/MonsterBook.java index d354ab84e7..cb3e882e76 100644 --- a/src/main/java/client/MonsterBook.java +++ b/src/main/java/client/MonsterBook.java @@ -21,8 +21,6 @@ */ package client; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import tools.DatabaseConnection; import tools.PacketCreator; @@ -33,13 +31,14 @@ import java.sql.SQLException; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; public final class MonsterBook { private int specialCard = 0; private int normalCard = 0; private int bookLevel = 1; private final Map cards = new LinkedHashMap<>(); - private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.BOOK); + private final Lock lock = new ReentrantLock(); public Set> getCardSet() { lock.lock(); diff --git a/src/main/java/net/server/audit/locks/factory/MonitoredReentrantLockFactory.java b/src/main/java/net/server/audit/locks/factory/MonitoredReentrantLockFactory.java index b127c0d5c8..94f552da12 100644 --- a/src/main/java/net/server/audit/locks/factory/MonitoredReentrantLockFactory.java +++ b/src/main/java/net/server/audit/locks/factory/MonitoredReentrantLockFactory.java @@ -26,10 +26,6 @@ import net.server.audit.locks.active.TrackerReentrantLock; * @author RonanLana */ public class MonitoredReentrantLockFactory { - public static TrackerReentrantLock createLock(MonitoredLockType id) { - return new TrackerReentrantLock(id); - } - public static TrackerReentrantLock createLock(MonitoredLockType id, boolean fair) { return new TrackerReentrantLock(id, fair); } diff --git a/src/main/java/net/server/coordinator/session/SessionInitialization.java b/src/main/java/net/server/coordinator/session/SessionInitialization.java index 6e160099de..627175d117 100644 --- a/src/main/java/net/server/coordinator/session/SessionInitialization.java +++ b/src/main/java/net/server/coordinator/session/SessionInitialization.java @@ -1,7 +1,5 @@ package net.server.coordinator.session; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,6 +8,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * Manages session initialization using remote host (ip address). @@ -24,7 +23,7 @@ public class SessionInitialization { SessionInitialization() { for (int i = 0; i < 100; i++) { - locks.add(MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER_LOGIN_COORD)); + locks.add(new ReentrantLock()); } } diff --git a/src/main/java/net/server/coordinator/world/MonsterAggroCoordinator.java b/src/main/java/net/server/coordinator/world/MonsterAggroCoordinator.java index f80a181722..a722e20841 100644 --- a/src/main/java/net/server/coordinator/world/MonsterAggroCoordinator.java +++ b/src/main/java/net/server/coordinator/world/MonsterAggroCoordinator.java @@ -22,7 +22,6 @@ package net.server.coordinator.world; import client.Character; import config.YamlConfig; import net.server.Server; -import net.server.audit.LockCollector; import net.server.audit.locks.MonitoredLockType; import net.server.audit.locks.MonitoredReentrantLock; import net.server.audit.locks.factory.MonitoredReentrantLockFactory; @@ -34,13 +33,14 @@ import tools.Pair; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Ronan */ public class MonsterAggroCoordinator { - - private MonitoredReentrantLock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_AGGRO); + private final Lock lock = new ReentrantLock(); private final MonitoredReentrantLock idleLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_AGGRO_IDLE, true); private long lastStopTime = Server.getInstance().getCurrentTime(); @@ -375,15 +375,5 @@ public class MonsterAggroCoordinator { } finally { lock.unlock(); } - - disposeLocks(); - } - - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - lock = lock.dispose(); } } diff --git a/src/main/java/scripting/event/EventManager.java b/src/main/java/scripting/event/EventManager.java index 34ce725f5e..8567b93330 100644 --- a/src/main/java/scripting/event/EventManager.java +++ b/src/main/java/scripting/event/EventManager.java @@ -25,10 +25,6 @@ import client.Character; import config.YamlConfig; import constants.game.GameConstants; import net.server.Server; -import net.server.audit.LockCollector; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.channel.Channel; import net.server.guild.Guild; import net.server.world.Party; @@ -50,6 +46,8 @@ import javax.script.Invocable; import javax.script.ScriptException; import java.util.*; import java.util.concurrent.Semaphore; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; @@ -75,9 +73,9 @@ public class EventManager { private Integer readyId = 0, onLoadInstances = 0; private final Properties props = new Properties(); private final String name; - private MonitoredReentrantLock lobbyLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_LOBBY); - private MonitoredReentrantLock queueLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_QUEUE); - private MonitoredReentrantLock startLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_START); + private final Lock lobbyLock = new ReentrantLock(); + private final Lock queueLock = new ReentrantLock(); + private final Lock startLock = new ReentrantLock(); private final Set playerPermit = new HashSet<>(); private final Semaphore startSemaphore = new Semaphore(7); @@ -139,18 +137,6 @@ public class EventManager { wserv = null; server = null; iv = null; - - disposeLocks(); - } - - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - lobbyLock = lobbyLock.dispose(); - queueLock = queueLock.dispose(); - startLock = startLock.dispose(); } private List convertToIntegerList(List objects) { diff --git a/src/main/java/server/CashShop.java b/src/main/java/server/CashShop.java index aa7a76fc3e..cb5e4f9db8 100644 --- a/src/main/java/server/CashShop.java +++ b/src/main/java/server/CashShop.java @@ -26,8 +26,6 @@ import config.YamlConfig; import constants.id.ItemId; import constants.inventory.ItemConstants; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import provider.Data; import provider.DataProvider; import provider.DataProviderFactory; @@ -42,6 +40,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; @@ -261,7 +260,7 @@ public class CashShop { private final List inventory = new ArrayList<>(); private final List wishList = new ArrayList<>(); private int notes = 0; - private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CASHSHOP); + private final Lock lock = new ReentrantLock(); public CashShop(int accountId, int characterId, int jobType) throws SQLException { this.accountId = accountId; diff --git a/src/main/java/server/life/Monster.java b/src/main/java/server/life/Monster.java index 14c061b941..a11ad18ebe 100644 --- a/src/main/java/server/life/Monster.java +++ b/src/main/java/server/life/Monster.java @@ -66,6 +66,8 @@ import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; public class Monster extends AbstractLoadedLife { private static final Logger log = LoggerFactory.getLogger(Monster.class); @@ -98,11 +100,11 @@ public class Monster extends AbstractLoadedLife { private Runnable removeAfterAction = null; private boolean availablePuppetUpdate = true; - private MonitoredReentrantLock externalLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MOB_EXT); + private final Lock externalLock = new ReentrantLock(); private MonitoredReentrantLock monsterLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MOB, true); - private MonitoredReentrantLock statiLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MOB_STATI); - private MonitoredReentrantLock animationLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MOB_ANI); - private final MonitoredReentrantLock aggroUpdateLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MOB_AGGRO); + private final Lock statiLock = new ReentrantLock(); + private final Lock animationLock = new ReentrantLock(); + private final Lock aggroUpdateLock = new ReentrantLock(); public Monster(int id, MonsterStats stats) { super(id); @@ -2203,9 +2205,6 @@ public class Monster extends AbstractLoadedLife { } private void emptyLocks() { - externalLock = externalLock.dispose(); monsterLock = monsterLock.dispose(); - statiLock = statiLock.dispose(); - animationLock = animationLock.dispose(); } } \ No newline at end of file diff --git a/src/main/java/server/maps/MapItem.java b/src/main/java/server/maps/MapItem.java index cd0384cc4b..9f1086d842 100644 --- a/src/main/java/server/maps/MapItem.java +++ b/src/main/java/server/maps/MapItem.java @@ -23,12 +23,11 @@ package server.maps; import client.Character; import client.Client; import client.inventory.Item; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import tools.PacketCreator; import java.awt.*; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import static java.util.concurrent.TimeUnit.SECONDS; @@ -40,7 +39,7 @@ public class MapItem extends AbstractMapObject { protected byte type; protected boolean pickedUp = false, playerDrop, partyDrop; protected long dropTime; - private final Lock itemLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_ITEM); + private final Lock itemLock = new ReentrantLock(); public MapItem(Item item, Point position, MapObject dropper, Character owner, Client ownerClient, byte type, boolean playerDrop) { setPosition(position); From 4fb632ecdbc4c938e21723d0911b6ff6ad3fe7a4 Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 14:45:48 +0200 Subject: [PATCH 09/11] Remove monitored locks (fair), use basic version --- src/main/java/client/Character.java | 8 ++--- src/main/java/client/Client.java | 9 +++--- src/main/java/client/inventory/Inventory.java | 5 ++- .../java/client/inventory/ItemFactory.java | 5 ++- .../java/net/server/PlayerBuffStorage.java | 5 ++- .../MonitoredReentrantLockFactory.java | 32 ------------------- .../world/MonsterAggroCoordinator.java | 5 +-- src/main/java/net/server/guild/Guild.java | 5 ++- .../net/server/services/BaseScheduler.java | 19 ++--------- .../task/channel/MobAnimationService.java | 16 ++-------- .../task/channel/MobStatusService.java | 16 ++-------- src/main/java/net/server/world/Party.java | 16 ++-------- src/main/java/net/server/world/World.java | 4 --- .../event/scheduler/EventScriptScheduler.java | 22 ++----------- src/main/java/server/Storage.java | 5 ++- .../java/server/expeditions/Expedition.java | 7 ++-- src/main/java/server/life/Monster.java | 15 +-------- src/main/java/server/maps/GenericPortal.java | 9 +++--- src/main/java/server/maps/HiredMerchant.java | 5 ++- src/main/java/server/maps/MiniDungeon.java | 5 ++- src/main/java/server/maps/PlayerShop.java | 5 ++- src/main/java/server/maps/Reactor.java | 7 ++-- 22 files changed, 50 insertions(+), 175 deletions(-) delete mode 100644 src/main/java/net/server/audit/locks/factory/MonitoredReentrantLockFactory.java diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java index ae10d3f1ee..9ca8e421af 100644 --- a/src/main/java/client/Character.java +++ b/src/main/java/client/Character.java @@ -45,8 +45,6 @@ import net.packet.Packet; import net.server.PlayerBuffValueHolder; import net.server.PlayerCoolDownValueHolder; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.coordinator.world.InviteCoordinator; import net.server.guild.Alliance; import net.server.guild.Guild; @@ -217,9 +215,9 @@ public class Character extends AbstractCharacterObject { private ScheduledFuture chairRecoveryTask = null; private ScheduledFuture pendantOfSpirit = null; //1122017 private ScheduledFuture cpqSchedule = null; - private final Lock chrLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_CHR, true); - private final Lock evtLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_EVT, true); - private final Lock petLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_PET, true); + private final Lock chrLock = new ReentrantLock(true); + private final Lock evtLock = new ReentrantLock(true); + private final Lock petLock = new ReentrantLock(true); private final Lock prtLock = new ReentrantLock(); private final Lock cpnLock = new ReentrantLock(); private final Map> excluded = new LinkedHashMap<>(); diff --git a/src/main/java/client/Client.java b/src/main/java/client/Client.java index 46224343f7..b929ff035a 100644 --- a/src/main/java/client/Client.java +++ b/src/main/java/client/Client.java @@ -36,8 +36,6 @@ import net.packet.Packet; import net.packet.logging.LoggingUtil; import net.packet.logging.MonitoredChrLogger; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.channel.Channel; import net.server.coordinator.login.LoginBypassCoordinator; import net.server.coordinator.session.Hwid; @@ -81,6 +79,7 @@ import java.util.Date; import java.util.*; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import static java.util.concurrent.TimeUnit.SECONDS; @@ -122,9 +121,9 @@ public class Client extends ChannelInboundHandlerAdapter { private byte gender = -1; private boolean disconnecting = false; private final Semaphore actionsSemaphore = new Semaphore(7); - private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT, true); - private final Lock encoderLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ENCODER, true); - private final Lock announcerLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ANNOUNCER, true); + private final Lock lock = new ReentrantLock(true); + private final Lock encoderLock = new ReentrantLock(true); + private final Lock announcerLock = new ReentrantLock(true); // thanks Masterrulax & try2hack for pointing out a bottleneck issue with shared locks, shavit for noticing an opportunity for improvement private Calendar tempBanCalendar; private int votePoints; diff --git a/src/main/java/client/inventory/Inventory.java b/src/main/java/client/inventory/Inventory.java index c7cebaf0ce..6e1c9e433c 100644 --- a/src/main/java/client/inventory/Inventory.java +++ b/src/main/java/client/inventory/Inventory.java @@ -25,8 +25,6 @@ import client.Character; import client.Client; import client.inventory.manipulator.InventoryManipulator; import constants.inventory.ItemConstants; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import server.ItemInformationProvider; @@ -36,6 +34,7 @@ import tools.Pair; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Matze, Ronan @@ -44,7 +43,7 @@ public class Inventory implements Iterable { private static final Logger log = LoggerFactory.getLogger(Inventory.class); protected final Map inventory; protected final InventoryType type; - protected final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.INVENTORY, true); + protected final Lock lock = new ReentrantLock(true); protected Character owner; protected byte slotLimit; diff --git a/src/main/java/client/inventory/ItemFactory.java b/src/main/java/client/inventory/ItemFactory.java index 3124c62687..1c24f0108a 100644 --- a/src/main/java/client/inventory/ItemFactory.java +++ b/src/main/java/client/inventory/ItemFactory.java @@ -20,8 +20,6 @@ */ package client.inventory; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import tools.DatabaseConnection; import tools.Pair; @@ -29,6 +27,7 @@ import java.sql.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Flav @@ -52,7 +51,7 @@ public enum ItemFactory { static { for (int i = 0; i < lockCount; i++) { - locks[i] = MonitoredReentrantLockFactory.createLock(MonitoredLockType.ITEM, true); + locks[i] = new ReentrantLock(true); } } diff --git a/src/main/java/net/server/PlayerBuffStorage.java b/src/main/java/net/server/PlayerBuffStorage.java index fb4a4b873e..65874296fd 100644 --- a/src/main/java/net/server/PlayerBuffStorage.java +++ b/src/main/java/net/server/PlayerBuffStorage.java @@ -22,8 +22,6 @@ package net.server; import client.Disease; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import server.life.MobSkill; import tools.Pair; @@ -31,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Danny//changed to map :3 @@ -38,7 +37,7 @@ import java.util.concurrent.locks.Lock; */ public class PlayerBuffStorage { private final int id = (int) (Math.random() * 100); - private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.BUFF_STORAGE, true); + private final Lock lock = new ReentrantLock(true); private final Map> buffs = new HashMap<>(); private final Map>> diseases = new HashMap<>(); diff --git a/src/main/java/net/server/audit/locks/factory/MonitoredReentrantLockFactory.java b/src/main/java/net/server/audit/locks/factory/MonitoredReentrantLockFactory.java deleted file mode 100644 index 94f552da12..0000000000 --- a/src/main/java/net/server/audit/locks/factory/MonitoredReentrantLockFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.factory; - -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.active.TrackerReentrantLock; - -/** - * @author RonanLana - */ -public class MonitoredReentrantLockFactory { - public static TrackerReentrantLock createLock(MonitoredLockType id, boolean fair) { - return new TrackerReentrantLock(id, fair); - } -} diff --git a/src/main/java/net/server/coordinator/world/MonsterAggroCoordinator.java b/src/main/java/net/server/coordinator/world/MonsterAggroCoordinator.java index a722e20841..b5e8bf4113 100644 --- a/src/main/java/net/server/coordinator/world/MonsterAggroCoordinator.java +++ b/src/main/java/net/server/coordinator/world/MonsterAggroCoordinator.java @@ -22,9 +22,6 @@ package net.server.coordinator.world; import client.Character; import config.YamlConfig; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import server.TimerManager; import server.life.Monster; import server.maps.MapleMap; @@ -41,7 +38,7 @@ import java.util.concurrent.locks.ReentrantLock; */ public class MonsterAggroCoordinator { private final Lock lock = new ReentrantLock(); - private final MonitoredReentrantLock idleLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_AGGRO_IDLE, true); + private final Lock idleLock = new ReentrantLock(true); private long lastStopTime = Server.getInstance().getCurrentTime(); private ScheduledFuture aggroMonitor = null; diff --git a/src/main/java/net/server/guild/Guild.java b/src/main/java/net/server/guild/Guild.java index ac86a95c73..2f8ed78034 100644 --- a/src/main/java/net/server/guild/Guild.java +++ b/src/main/java/net/server/guild/Guild.java @@ -27,8 +27,6 @@ import config.YamlConfig; import net.packet.Packet; import net.server.PlayerStorage; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.channel.Channel; import net.server.coordinator.matchchecker.MatchCheckerCoordinator; import net.server.coordinator.world.InviteCoordinator; @@ -45,6 +43,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; public class Guild { private static final Logger log = LoggerFactory.getLogger(Guild.class); @@ -54,7 +53,7 @@ public class Guild { } private final List members; - private final Lock membersLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.GUILD, true); + private final Lock membersLock = new ReentrantLock(true); private final String[] rankTitles = new String[5]; // 1 = master, 2 = jr, 5 = lowest member private String name, notice; diff --git a/src/main/java/net/server/services/BaseScheduler.java b/src/main/java/net/server/services/BaseScheduler.java index 6d15e0fb16..0b764cf06a 100644 --- a/src/main/java/net/server/services/BaseScheduler.java +++ b/src/main/java/net/server/services/BaseScheduler.java @@ -21,16 +21,16 @@ package net.server.services; import config.YamlConfig; import net.server.Server; -import net.server.audit.LockCollector; import net.server.audit.locks.MonitoredLockType; import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import server.TimerManager; import tools.Pair; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Ronan @@ -42,17 +42,14 @@ public abstract class BaseScheduler { private final Map> registeredEntries = new HashMap<>(); private ScheduledFuture schedulerTask = null; - private MonitoredReentrantLock schedulerLock; + private final Lock schedulerLock = new ReentrantLock(true); private final Runnable monitorTask = () -> runBaseSchedule(); protected BaseScheduler(MonitoredLockType lockType) { - schedulerLock = MonitoredReentrantLockFactory.createLock(lockType, true); } // NOTE: practice EXTREME caution when adding external locks to the scheduler system, if you don't know what you're doing DON'T USE THIS. protected BaseScheduler(MonitoredLockType lockType, List extLocks) { - schedulerLock = MonitoredReentrantLockFactory.createLock(lockType, true); - externalLocks.addAll(extLocks); } @@ -184,15 +181,5 @@ public abstract class BaseScheduler { unlockScheduler(); externalLocks.clear(); } - - disposeLocks(); - } - - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - schedulerLock = schedulerLock.dispose(); } } diff --git a/src/main/java/net/server/services/task/channel/MobAnimationService.java b/src/main/java/net/server/services/task/channel/MobAnimationService.java index 1eff4728c1..5e545dbc25 100644 --- a/src/main/java/net/server/services/task/channel/MobAnimationService.java +++ b/src/main/java/net/server/services/task/channel/MobAnimationService.java @@ -20,15 +20,14 @@ package net.server.services.task.channel; import config.YamlConfig; -import net.server.audit.LockCollector; import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.services.BaseScheduler; import net.server.services.BaseService; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Ronan @@ -63,7 +62,7 @@ public class MobAnimationService extends BaseService { private class MobAnimationScheduler extends BaseScheduler { Set onAnimationMobs = new HashSet<>(1000); - private MonitoredReentrantLock animationLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHANNEL_MOBANIMAT, true); + private final Lock animationLock = new ReentrantLock(true); public MobAnimationScheduler() { super(MonitoredLockType.CHANNEL_MOBACTION); @@ -98,18 +97,9 @@ public class MobAnimationService extends BaseService { @Override public void dispose() { - disposeLocks(); super.dispose(); } - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - animationLock = animationLock.dispose(); - } - } } diff --git a/src/main/java/net/server/services/task/channel/MobStatusService.java b/src/main/java/net/server/services/task/channel/MobStatusService.java index bdf9547901..026e557f55 100644 --- a/src/main/java/net/server/services/task/channel/MobStatusService.java +++ b/src/main/java/net/server/services/task/channel/MobStatusService.java @@ -21,10 +21,7 @@ package net.server.services.task.channel; import client.status.MonsterStatusEffect; import config.YamlConfig; -import net.server.audit.LockCollector; import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.services.BaseScheduler; import net.server.services.BaseService; @@ -32,6 +29,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Ronan @@ -71,7 +70,7 @@ public class MobStatusService extends BaseService { private class MobStatusScheduler extends BaseScheduler { private final Map registeredMobStatusOvertime = new HashMap<>(); - private MonitoredReentrantLock overtimeStatusLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHANNEL_OVTSTATUS, true); + private final Lock overtimeStatusLock = new ReentrantLock(true); private class MobStatusOvertimeEntry { private int procCount; @@ -144,18 +143,9 @@ public class MobStatusService extends BaseService { @Override public void dispose() { - disposeLocks(); super.dispose(); } - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - overtimeStatusLock = overtimeStatusLock.dispose(); - } - } } diff --git a/src/main/java/net/server/world/Party.java b/src/main/java/net/server/world/Party.java index 90d33468eb..c466418fdf 100644 --- a/src/main/java/net/server/world/Party.java +++ b/src/main/java/net/server/world/Party.java @@ -24,10 +24,6 @@ package net.server.world; import client.Character; import client.Client; import config.YamlConfig; -import net.server.audit.LockCollector; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.coordinator.matchchecker.MatchCheckerCoordinator; import net.server.coordinator.matchchecker.MatchCheckerListenerFactory.MatchCheckerType; import scripting.event.EventInstanceManager; @@ -38,6 +34,8 @@ import tools.PacketCreator; import java.util.*; import java.util.Map.Entry; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; public class Party { @@ -52,7 +50,7 @@ public class Party { private final Map doors = new HashMap<>(); - private MonitoredReentrantLock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.PARTY, true); + private final Lock lock = new ReentrantLock(true); public Party(int id, PartyCharacter chrfor) { this.leaderId = chrfor.getId(); @@ -281,14 +279,6 @@ public class Party { } } - public void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - lock = lock.dispose(); - } - @Override public int hashCode() { final int prime = 31; diff --git a/src/main/java/net/server/world/World.java b/src/main/java/net/server/world/World.java index c473aba652..2bdf1b3ada 100644 --- a/src/main/java/net/server/world/World.java +++ b/src/main/java/net/server/world/World.java @@ -2103,10 +2103,6 @@ public class World { partyLock.unlock(); } - for (Party p : pList) { - p.disposeLocks(); - } - closeWorldServices(); } diff --git a/src/main/java/scripting/event/scheduler/EventScriptScheduler.java b/src/main/java/scripting/event/scheduler/EventScriptScheduler.java index f0d1e85bc3..ad3c0bbccf 100644 --- a/src/main/java/scripting/event/scheduler/EventScriptScheduler.java +++ b/src/main/java/scripting/event/scheduler/EventScriptScheduler.java @@ -21,10 +21,6 @@ package scripting.event.scheduler; import config.YamlConfig; import net.server.Server; -import net.server.audit.LockCollector; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import server.ThreadManager; import server.TimerManager; @@ -34,6 +30,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Ronan @@ -45,13 +43,9 @@ public class EventScriptScheduler { private final Map registeredEntries = new HashMap<>(); private ScheduledFuture schedulerTask = null; - private MonitoredReentrantLock schedulerLock; + private final Lock schedulerLock = new ReentrantLock(true); private final Runnable monitorTask = () -> runBaseSchedule(); - public EventScriptScheduler() { - schedulerLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EM_SCHDL, true); - } - private void runBaseSchedule() { List toRemove; Map registeredEntriesCopy; @@ -148,16 +142,6 @@ public class EventScriptScheduler { } finally { schedulerLock.unlock(); } - - disposeLocks(); }); } - - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - schedulerLock = schedulerLock.dispose(); - } } diff --git a/src/main/java/server/Storage.java b/src/main/java/server/Storage.java index 2e06ffe144..67e64e75b9 100644 --- a/src/main/java/server/Storage.java +++ b/src/main/java/server/Storage.java @@ -23,8 +23,6 @@ import client.inventory.InventoryType; import client.inventory.Item; import client.inventory.ItemFactory; import constants.game.GameConstants; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import provider.Data; @@ -42,6 +40,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Matze @@ -57,7 +56,7 @@ public class Storage { private byte slots; private final Map> typeItems = new HashMap<>(); private List items = new LinkedList<>(); - private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.STORAGE, true); + private final Lock lock = new ReentrantLock(true); private Storage(int id, byte slots, int meso) { this.id = id; diff --git a/src/main/java/server/expeditions/Expedition.java b/src/main/java/server/expeditions/Expedition.java index 9a7a43b141..2becc69565 100644 --- a/src/main/java/server/expeditions/Expedition.java +++ b/src/main/java/server/expeditions/Expedition.java @@ -28,9 +28,6 @@ import constants.id.MobId; import net.packet.Packet; import net.server.PlayerStorage; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.channel.Channel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,6 +42,8 @@ import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; @@ -100,7 +99,7 @@ public class Expedition { private final boolean silent; private final int minSize; private final int maxSize; - private final MonitoredReentrantLock pL = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EIM_PARTY, true); + private final Lock pL = new ReentrantLock(true); public Expedition(Character player, ExpeditionType met, boolean sil, int minPlayers, int maxPlayers) { leader = player; diff --git a/src/main/java/server/life/Monster.java b/src/main/java/server/life/Monster.java index a11ad18ebe..25de54c4be 100644 --- a/src/main/java/server/life/Monster.java +++ b/src/main/java/server/life/Monster.java @@ -29,10 +29,6 @@ import config.YamlConfig; import constants.id.MobId; import constants.skills.*; import net.packet.Packet; -import net.server.audit.LockCollector; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.channel.Channel; import net.server.coordinator.world.MonsterAggroCoordinator; import net.server.services.task.channel.MobAnimationService; @@ -101,7 +97,7 @@ public class Monster extends AbstractLoadedLife { private boolean availablePuppetUpdate = true; private final Lock externalLock = new ReentrantLock(); - private MonitoredReentrantLock monsterLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MOB, true); + private final Lock monsterLock = new ReentrantLock(true); private final Lock statiLock = new ReentrantLock(); private final Lock animationLock = new ReentrantLock(); private final Lock aggroUpdateLock = new ReentrantLock(); @@ -2197,14 +2193,5 @@ public class Monster extends AbstractLoadedLife { } this.getMap().dismissRemoveAfter(this); - disposeLocks(); - } - - private void disposeLocks() { - LockCollector.getInstance().registerDisposeAction(() -> emptyLocks()); - } - - private void emptyLocks() { - monsterLock = monsterLock.dispose(); } } \ No newline at end of file diff --git a/src/main/java/server/maps/GenericPortal.java b/src/main/java/server/maps/GenericPortal.java index 8ba35f21a3..02d9af95b5 100644 --- a/src/main/java/server/maps/GenericPortal.java +++ b/src/main/java/server/maps/GenericPortal.java @@ -25,13 +25,12 @@ import client.Character; import client.Client; import constants.game.GameConstants; import constants.id.MapId; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import scripting.portal.PortalScriptManager; import tools.PacketCreator; import java.awt.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; public class GenericPortal implements Portal { private String name; @@ -43,7 +42,7 @@ public class GenericPortal implements Portal { private int id; private String scriptName; private boolean portalState; - private MonitoredReentrantLock scriptLock = null; + private Lock scriptLock = null; public GenericPortal(int type) { this.type = type; @@ -120,7 +119,7 @@ public class GenericPortal implements Portal { if (scriptName != null) { if (scriptLock == null) { - scriptLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.PORTAL, true); + scriptLock = new ReentrantLock(true); } } else { scriptLock = null; diff --git a/src/main/java/server/maps/HiredMerchant.java b/src/main/java/server/maps/HiredMerchant.java index dfd9bc9668..c668e2cd24 100644 --- a/src/main/java/server/maps/HiredMerchant.java +++ b/src/main/java/server/maps/HiredMerchant.java @@ -33,8 +33,6 @@ import client.processor.npc.FredrickProcessor; import config.YamlConfig; import net.packet.Packet; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import server.ItemInformationProvider; import server.Trade; import tools.DatabaseConnection; @@ -50,6 +48,7 @@ import java.time.Instant; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author XoticStory @@ -76,7 +75,7 @@ public class HiredMerchant extends AbstractMapObject { private final Visitor[] visitors = new Visitor[3]; private final LinkedList visitorHistory = new LinkedList<>(); private final LinkedHashSet blacklist = new LinkedHashSet<>(); // case-sensitive character names - private final Lock visitorLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.VISITOR_MERCH, true); + private final Lock visitorLock = new ReentrantLock(true); private record Visitor(Character chr, Instant enteredAt) {} diff --git a/src/main/java/server/maps/MiniDungeon.java b/src/main/java/server/maps/MiniDungeon.java index 73e6030829..f69cdb6d43 100644 --- a/src/main/java/server/maps/MiniDungeon.java +++ b/src/main/java/server/maps/MiniDungeon.java @@ -20,8 +20,6 @@ package server.maps; import client.Character; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import server.TimerManager; import tools.PacketCreator; @@ -29,6 +27,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import static java.util.concurrent.TimeUnit.SECONDS; @@ -38,7 +37,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; public class MiniDungeon { List players = new ArrayList<>(); ScheduledFuture timeoutTask = null; - Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MINIDUNGEON, true); + private final Lock lock = new ReentrantLock(true); int baseMap; long expireTime; diff --git a/src/main/java/server/maps/PlayerShop.java b/src/main/java/server/maps/PlayerShop.java index dad0751db7..ab110cc008 100644 --- a/src/main/java/server/maps/PlayerShop.java +++ b/src/main/java/server/maps/PlayerShop.java @@ -29,8 +29,6 @@ import client.inventory.Item; import client.inventory.manipulator.InventoryManipulator; import client.inventory.manipulator.KarmaManipulator; import net.packet.Packet; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import server.Trade; import tools.PacketCreator; import tools.Pair; @@ -38,6 +36,7 @@ import tools.Pair; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Matze @@ -56,7 +55,7 @@ public class PlayerShop extends AbstractMapObject { private final List bannedList = new ArrayList<>(); private final List> chatLog = new LinkedList<>(); private final Map chatSlot = new LinkedHashMap<>(); - private final Lock visitorLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.VISITOR_PSHOP, true); + private final Lock visitorLock = new ReentrantLock(true); public PlayerShop(Character owner, String description, int itemid) { this.setPosition(owner.getPosition()); diff --git a/src/main/java/server/maps/Reactor.java b/src/main/java/server/maps/Reactor.java index 444d853c04..d3c73dbc53 100644 --- a/src/main/java/server/maps/Reactor.java +++ b/src/main/java/server/maps/Reactor.java @@ -24,8 +24,6 @@ package server.maps; import client.Client; import config.YamlConfig; import net.packet.Packet; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.services.task.channel.OverallService; import net.server.services.type.ChannelServices; import scripting.reactor.ReactorScriptManager; @@ -38,6 +36,7 @@ import java.awt.*; import java.util.List; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * @author Lerk @@ -58,8 +57,8 @@ public class Reactor extends AbstractMapObject { private Runnable delayedRespawnRun = null; private GuardianSpawnPoint guardian = null; private byte facingDirection = 0; - private final Lock reactorLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.REACTOR, true); - private final Lock hitLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.REACTOR_HIT, true); + private final Lock reactorLock = new ReentrantLock(true); + private final Lock hitLock = new ReentrantLock(true); public Reactor(ReactorStats stats, int rid) { this.evstate = (byte) 0; From 618f312b84dd0dd8cfe8f438e7a8993035573549 Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 14:57:26 +0200 Subject: [PATCH 10/11] Remove thread tracker system --- config.yaml | 3 - src/main/java/config/ServerConfig.java | 2 - src/main/java/net/server/Server.java | 10 - .../java/net/server/audit/LockCollector.java | 74 ----- .../java/net/server/audit/ThreadTracker.java | 279 ------------------ .../server/audit/locks/MonitoredLockType.java | 111 ------- .../server/audit/locks/MonitoredReadLock.java | 35 --- .../audit/locks/MonitoredReentrantLock.java | 35 --- .../MonitoredReentrantReadWriteLock.java | 49 --- .../audit/locks/MonitoredWriteLock.java | 35 --- .../audit/locks/active/TrackerReadLock.java | 162 ---------- .../locks/active/TrackerReentrantLock.java | 166 ----------- .../audit/locks/active/TrackerWriteLock.java | 162 ---------- .../audit/locks/empty/AbstractEmptyLock.java | 24 -- .../audit/locks/empty/EmptyReadLock.java | 56 ---- .../audit/locks/empty/EmptyReentrantLock.java | 56 ---- .../audit/locks/empty/EmptyWriteLock.java | 56 ---- .../net/server/services/BaseScheduler.java | 22 +- .../services/task/channel/EventService.java | 5 - .../task/channel/MobAnimationService.java | 3 - .../task/channel/MobClearSkillService.java | 5 - .../services/task/channel/MobMistService.java | 5 - .../task/channel/MobStatusService.java | 3 - .../services/task/channel/OverallService.java | 5 - .../task/world/CharacterSaveService.java | 5 - .../java/net/server/task/ReleaseLockTask.java | 33 --- 26 files changed, 5 insertions(+), 1396 deletions(-) delete mode 100644 src/main/java/net/server/audit/LockCollector.java delete mode 100644 src/main/java/net/server/audit/ThreadTracker.java delete mode 100644 src/main/java/net/server/audit/locks/MonitoredLockType.java delete mode 100644 src/main/java/net/server/audit/locks/MonitoredReadLock.java delete mode 100644 src/main/java/net/server/audit/locks/MonitoredReentrantLock.java delete mode 100644 src/main/java/net/server/audit/locks/MonitoredReentrantReadWriteLock.java delete mode 100644 src/main/java/net/server/audit/locks/MonitoredWriteLock.java delete mode 100644 src/main/java/net/server/audit/locks/active/TrackerReadLock.java delete mode 100644 src/main/java/net/server/audit/locks/active/TrackerReentrantLock.java delete mode 100644 src/main/java/net/server/audit/locks/active/TrackerWriteLock.java delete mode 100644 src/main/java/net/server/audit/locks/empty/AbstractEmptyLock.java delete mode 100644 src/main/java/net/server/audit/locks/empty/EmptyReadLock.java delete mode 100644 src/main/java/net/server/audit/locks/empty/EmptyReentrantLock.java delete mode 100644 src/main/java/net/server/audit/locks/empty/EmptyWriteLock.java delete mode 100644 src/main/java/net/server/task/ReleaseLockTask.java diff --git a/config.yaml b/config.yaml index 4d7ec5d6d5..2fb2609786 100644 --- a/config.yaml +++ b/config.yaml @@ -158,9 +158,6 @@ worlds: server: - #Thread Tracker Configuration - USE_THREAD_TRACKER: false #[SEVERE] This deadlock auditing thing will bloat the memory as fast as the time frame one takes to lose track of a raindrop on a tempesting day. Only for debugging purposes. - #Database Configuration DB_URL_FORMAT: "jdbc:mysql://%s:3306/cosmic" DB_HOST: "localhost" diff --git a/src/main/java/config/ServerConfig.java b/src/main/java/config/ServerConfig.java index cbd771246a..f8f7a69585 100644 --- a/src/main/java/config/ServerConfig.java +++ b/src/main/java/config/ServerConfig.java @@ -4,8 +4,6 @@ import java.util.HashMap; import java.util.Map; public class ServerConfig { - //Thread Tracker Configuration - public boolean USE_THREAD_TRACKER; //Database Configuration public String DB_URL_FORMAT; diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java index bf5df0cc53..f47f4770af 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -37,7 +37,6 @@ import constants.net.OpcodeConstants; import constants.net.ServerConstants; import net.netty.LoginServer; import net.packet.Packet; -import net.server.audit.ThreadTracker; import net.server.channel.Channel; import net.server.coordinator.session.IpAddresses; import net.server.coordinator.session.SessionCoordinator; @@ -869,10 +868,6 @@ public class Server { ThreadManager.getInstance().start(); initializeTimelyTasks(); // aggregated method for timely tasks thanks to lxconan - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - ThreadTracker.getInstance().registerThreadTrackerTask(); - } - try { int worldCount = Math.min(GameConstants.WORLD_NAMES.length, YamlConfig.config.server.WORLDS); @@ -945,7 +940,6 @@ public class Server { long timeLeft = getTimeLeftForNextHour(); tMan.register(new CharacterDiseaseTask(), YamlConfig.config.server.UPDATE_INTERVAL, YamlConfig.config.server.UPDATE_INTERVAL); - tMan.register(new ReleaseLockTask(), MINUTES.toMillis(2), MINUTES.toMillis(2)); tMan.register(new CouponTask(), YamlConfig.config.server.COUPON_INTERVAL, timeLeft); tMan.register(new RankingCommandTask(), MINUTES.toMillis(5), MINUTES.toMillis(5)); tMan.register(new RankingLoginTask(), YamlConfig.config.server.RANKING_INTERVAL, timeLeft); @@ -1908,10 +1902,6 @@ public class Server { List allChannels = getAllChannels(); - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - ThreadTracker.getInstance().cancelThreadTrackerTask(); - } - for (Channel ch : allChannels) { while (!ch.finishedShutdown()) { try { diff --git a/src/main/java/net/server/audit/LockCollector.java b/src/main/java/net/server/audit/LockCollector.java deleted file mode 100644 index ba276286f5..0000000000 --- a/src/main/java/net/server/audit/LockCollector.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * @author Ronan - */ -public class LockCollector { - - private static final LockCollector instance = new LockCollector(); - - public static LockCollector getInstance() { - return instance; - } - - private final Map disposableLocks = new HashMap<>(200); - private final Lock lock = new ReentrantLock(true); - - public void registerDisposeAction(Runnable r) { - lock.lock(); - try { - disposableLocks.put(r, 0); - } finally { - lock.unlock(); - } - } - - public void runLockCollector() { - List toDispose = new ArrayList<>(); - - lock.lock(); - try { - for (Entry e : disposableLocks.entrySet()) { - Integer eVal = e.getValue(); - if (eVal > 5) { // updates each 2min - toDispose.add(e.getKey()); - } else { - disposableLocks.put(e.getKey(), ++eVal); - } - } - } finally { - lock.unlock(); - } - - for (Runnable r : toDispose) { - r.run(); - } - } -} diff --git a/src/main/java/net/server/audit/ThreadTracker.java b/src/main/java/net/server/audit/ThreadTracker.java deleted file mode 100644 index 350008727d..0000000000 --- a/src/main/java/net/server/audit/ThreadTracker.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit; - -import net.server.audit.locks.MonitoredLockType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import server.TimerManager; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * @author RonanLana - *

- * This tool has the main purpose of auditing deadlocks throughout the server and must be used only for debugging. The flag is USE_THREAD_TRACKER. - */ -public class ThreadTracker { - private static final Logger log = LoggerFactory.getLogger(ThreadTracker.class); - private static ThreadTracker instance = null; - - public static ThreadTracker getInstance() { - if (instance == null) { - instance = new ThreadTracker(); - } - return instance; - } - - private final Lock ttLock = new ReentrantLock(true); - - private final Map> threadTracker = new HashMap<>(); - private final Map threadUpdate = new HashMap<>(); - private final Map threads = new HashMap<>(); - - private final Map lockCount = new HashMap<>(); - private final Map lockIds = new HashMap<>(); - private final Map lockThreads = new HashMap<>(); - private final Map lockUpdate = new HashMap<>(); - - private final Map> locks = new HashMap<>(); - ScheduledFuture threadTrackerSchedule; - - private String printThreadTrackerState(String dateFormat) { - - Map> lockValues = new HashMap<>(); - Set executingThreads = new HashSet<>(); - - for (Map.Entry lc : lockCount.entrySet()) { - if (lc.getValue().get() != 0) { - executingThreads.add(lockThreads.get(lc.getKey())); - - MonitoredLockType lockId = lockIds.get(lc.getKey()); - List list = lockValues.get(lockId); - - if (list == null) { - list = new ArrayList<>(); - lockValues.put(lockId, list); - } - - list.add(lc.getValue().get()); - } - } - - - String s = "----------------------------\r\n" + dateFormat + "\r\n "; - s += "Lock-thread usage count:"; - for (Map.Entry> lock : lockValues.entrySet()) { - s += ("\r\n " + lock.getKey().name() + ": "); - - for (Integer i : lock.getValue()) { - s += (i + " "); - } - } - s += "\r\n\r\nThread opened lock path:"; - - for (Long tid : executingThreads) { - s += "\r\n"; - for (MonitoredLockType lockid : threadTracker.get(tid)) { - s += (lockid.name() + " "); - } - s += "|"; - } - - s += "\r\n\r\n"; - - return s; - } - - private static String printThreadLog(List stillLockedPath, String dateFormat) { - String s = "----------------------------\r\n" + dateFormat + "\r\n "; - for (MonitoredLockType lock : stillLockedPath) { - s += (lock.name() + " "); - } - s += "\r\n\r\n"; - - return s; - } - - private static String printThreadStack(StackTraceElement[] list, String dateFormat) { - String s = "----------------------------\r\n" + dateFormat + "\r\n"; - for (StackTraceElement stackTraceElement : list) { - s += (" " + stackTraceElement.toString() + "\r\n"); - } - - return s; - } - - public void accessThreadTracker(boolean update, boolean lock, MonitoredLockType lockId, long lockOid) { - ttLock.lock(); - try { - if (update) { - if (!lock) { // update tracker - List toRemove = new ArrayList<>(); - - for (Long l : threadUpdate.keySet()) { - int next = threadUpdate.get(l) + 1; - if (next == 4) { - List tt = threadTracker.get(l); - - if (tt.isEmpty()) { - toRemove.add(l); - } else { - StackTraceElement[] ste = threads.get(l).getStackTrace(); - if (ste.length > 0) { - DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getDefault()); - String df = dateFormat.format(new Date()); - - log.debug("Thread log - {}", printThreadLog(tt, df)); - log.debug("thread stack - {}", printThreadStack(ste, df)); - } - } - } - - threadUpdate.put(l, next); - } - - for (Long l : toRemove) { - threadTracker.remove(l); - threadUpdate.remove(l); - threads.remove(l); - - for (Map threadLock : locks.values()) { - threadLock.remove(l); - } - } - - toRemove.clear(); - - for (Entry it : lockUpdate.entrySet()) { - int val = it.getValue() + 1; - - if (val < 60) { - lockUpdate.put(it.getKey(), val); - } else { - toRemove.add(it.getKey()); // free the structure after 60 silent updates - } - } - - for (Long l : toRemove) { - lockCount.remove(l); - lockIds.remove(l); - lockThreads.remove(l); - lockUpdate.remove(l); - } - } else { // print status - DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getDefault()); - - log.error("Deadlock state: {}", printThreadTrackerState(dateFormat.format(new Date()))); - //FilePrinter.printError(FilePrinter.DEADLOCK_STATE, "[" + dateFormat.format(new Date()) + "] Presenting current lock path for lockid " + lockId.name() + ".\r\n" + printLockStatus(lockId) + "\r\n-------------------------------"); - } - } else { - long tid = Thread.currentThread().getId(); - - if (lock) { - AtomicInteger c = lockCount.get(lockOid); - if (c == null) { - c = new AtomicInteger(0); - lockCount.put(lockOid, c); - lockIds.put(lockOid, lockId); - lockThreads.put(lockOid, tid); - lockUpdate.put(lockOid, 0); - } - c.incrementAndGet(); - - List list = threadTracker.get(tid); - if (list == null) { - list = new ArrayList<>(5); - threadTracker.put(tid, list); - threadUpdate.put(tid, 0); - threads.put(tid, Thread.currentThread()); - } else if (list.isEmpty()) { - threadUpdate.put(tid, 0); - } - list.add(lockId); - - Map threadLock = locks.get(lockId); - if (threadLock == null) { - threadLock = new HashMap<>(5); - locks.put(lockId, threadLock); - } - - Integer lc = threadLock.get(tid); - if (lc != null) { - threadLock.put(tid, lc + 1); - } else { - threadLock.put(tid, 1); - } - } else { - AtomicInteger c = lockCount.get(lockOid); - if (c != null) { // thanks BHB for detecting an NPE here - c.decrementAndGet(); - } - - lockUpdate.put(lockOid, 0); - - List list = threadTracker.get(tid); - for (int i = list.size() - 1; i >= 0; i--) { - if (lockId.equals(list.get(i))) { - list.remove(i); - break; - } - } - - Map threadLock = locks.get(lockId); - threadLock.put(tid, threadLock.get(tid) - 1); - } - } - } finally { - ttLock.unlock(); - } - } - - private String printLockStatus(MonitoredLockType lockId) { - String s = ""; - - for (Long threadid : locks.get(lockId).keySet()) { - for (MonitoredLockType lockid : threadTracker.get(threadid)) { - s += (" " + lockid.name()); - } - - s += " |\r\n"; - } - - return s; - } - - public void registerThreadTrackerTask() { - threadTrackerSchedule = TimerManager.getInstance().register(() -> accessThreadTracker(true, false, MonitoredLockType.UNDEFINED, -1), 10000, 10000); - } - - public void cancelThreadTrackerTask() { - threadTrackerSchedule.cancel(false); - } -} diff --git a/src/main/java/net/server/audit/locks/MonitoredLockType.java b/src/main/java/net/server/audit/locks/MonitoredLockType.java deleted file mode 100644 index 05002d7eb9..0000000000 --- a/src/main/java/net/server/audit/locks/MonitoredLockType.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks; - -/** - * @author RonanLana - */ - -public enum MonitoredLockType { - UNDEFINED, - INTERVAL, - CHARACTER_CHR, - CHARACTER_CPN, - CHARACTER_EFF, - CHARACTER_PET, - CHARACTER_PRT, - CHARACTER_EVT, - CHARACTER_STA, - CLIENT, - CLIENT_ANNOUNCER, - CLIENT_ENCODER, - CLIENT_SESSION, - CLIENT_LOGIN, - BOOK, - ITEM, - INVENTORY, - SRVHANDLER_IDLE, - SRVHANDLER_TEMP, - BUFF_STORAGE, - PLAYER_STORAGE, - PLAYER_DOOR, - SERVER, - SERVER_DISEASES, - SERVER_LOGIN, - SERVER_LOGIN_COORD, - SERVER_WORLDS, - MERCHANT, - CHANNEL, - CHANNEL_EVENTS, - CHANNEL_FACEEXPRS, - CHANNEL_FACESCHDL, - CHANNEL_MOBACTION, - CHANNEL_MOBANIMAT, - CHANNEL_MOBMIST, - CHANNEL_MOBSKILL, - CHANNEL_MOBSTATUS, - CHANNEL_OVTSTATUS, - CHANNEL_OVERALL, - GUILD, - PARTY, - WORLD_PARTY, - WORLD_PARTY_SEARCH_ECHELON, - WORLD_PARTY_SEARCH_QUEUE, - WORLD_PARTY_SEARCH_STORAGE, - WORLD_SRVMESSAGES, - WORLD_PETS, - WORLD_CHARS, - WORLD_CHANNELS, - WORLD_MOUNTS, - WORLD_PSHOPS, - WORLD_MERCHS, - WORLD_MAPOBJS, - WORLD_SAVECHARS, - WORLD_SUGGEST, - EIM, - EIM_PARTY, - EIM_SCRIPT, - EM_LOBBY, - EM_QUEUE, - EM_SCHDL, - EM_START, - CASHSHOP, - VISITOR_PSHOP, - STORAGE, - MOB, - MOB_AGGRO, - MOB_ANI, - MOB_EXT, - MOB_STATI, - MOBSKILL_FACTORY, - PORTAL, - VISITOR_MERCH, - MAP_CHRS, - MAP_OBJS, - MAP_MANAGER, - MAP_ITEM, - MAP_LOOT, - MAP_BOUNDS, - MAP_AGGRO, - MAP_AGGRO_IDLE, - MINIDUNGEON, - REACTOR, - REACTOR_HIT -} diff --git a/src/main/java/net/server/audit/locks/MonitoredReadLock.java b/src/main/java/net/server/audit/locks/MonitoredReadLock.java deleted file mode 100644 index 2e36cecfd0..0000000000 --- a/src/main/java/net/server/audit/locks/MonitoredReadLock.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks; - -/** - * @author RonanLana - */ -public interface MonitoredReadLock { - - void lock(); - - void unlock(); - - boolean tryLock(); - - MonitoredReadLock dispose(); - -} diff --git a/src/main/java/net/server/audit/locks/MonitoredReentrantLock.java b/src/main/java/net/server/audit/locks/MonitoredReentrantLock.java deleted file mode 100644 index 006e3cf06f..0000000000 --- a/src/main/java/net/server/audit/locks/MonitoredReentrantLock.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks; - -/** - * @author RonanLana - */ -public interface MonitoredReentrantLock { - - void lock(); - - void unlock(); - - boolean tryLock(); - - MonitoredReentrantLock dispose(); - -} diff --git a/src/main/java/net/server/audit/locks/MonitoredReentrantReadWriteLock.java b/src/main/java/net/server/audit/locks/MonitoredReentrantReadWriteLock.java deleted file mode 100644 index aa1f7bbcee..0000000000 --- a/src/main/java/net/server/audit/locks/MonitoredReentrantReadWriteLock.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks; - -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * @author RonanLana - */ -public class MonitoredReentrantReadWriteLock extends ReentrantReadWriteLock { - public final MonitoredLockType id; - - public MonitoredReentrantReadWriteLock(MonitoredLockType id) { - super(); - this.id = id; - } - - public MonitoredReentrantReadWriteLock(MonitoredLockType id, boolean fair) { - super(fair); - this.id = id; - } - - @Override - public ReadLock readLock() { - return super.readLock(); - } - - @Override - public WriteLock writeLock() { - return super.writeLock(); - } -} diff --git a/src/main/java/net/server/audit/locks/MonitoredWriteLock.java b/src/main/java/net/server/audit/locks/MonitoredWriteLock.java deleted file mode 100644 index c4a3326157..0000000000 --- a/src/main/java/net/server/audit/locks/MonitoredWriteLock.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks; - -/** - * @author RonanLana - */ -public interface MonitoredWriteLock { - - void lock(); - - void unlock(); - - boolean tryLock(); - - MonitoredWriteLock dispose(); - -} diff --git a/src/main/java/net/server/audit/locks/active/TrackerReadLock.java b/src/main/java/net/server/audit/locks/active/TrackerReadLock.java deleted file mode 100644 index 8e50de8a55..0000000000 --- a/src/main/java/net/server/audit/locks/active/TrackerReadLock.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.active; - -import config.YamlConfig; -import net.server.audit.ThreadTracker; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.empty.EmptyReadLock; -import server.TimerManager; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.TimeZone; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * @author RonanLana - */ -public class TrackerReadLock extends ReentrantReadWriteLock.ReadLock implements MonitoredReadLock { - private ScheduledFuture timeoutSchedule = null; - private StackTraceElement[] deadlockedState = null; - private final MonitoredLockType id; - private final int hashcode; - private final Lock state = new ReentrantLock(true); - private final AtomicInteger reentrantCount = new AtomicInteger(0); - - public TrackerReadLock(MonitoredReentrantReadWriteLock lock) { - super(lock); - this.id = lock.id; - hashcode = this.hashCode(); - } - - @Override - public void lock() { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - if (deadlockedState != null) { - DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getDefault()); - - //FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "[CRITICAL] " + dateFormat.format(new Date()) + " Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState)); - ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode); - deadlockedState = null; - } - - registerLocking(); - } - - super.lock(); - } - - @Override - public void unlock() { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - unregisterLocking(); - } - - super.unlock(); - } - - @Override - public boolean tryLock() { - if (super.tryLock()) { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - if (deadlockedState != null) { - //FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState)); - ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode); - deadlockedState = null; - } - - registerLocking(); - } - return true; - } else { - return false; - } - } - - private void registerLocking() { - state.lock(); - try { - ThreadTracker.getInstance().accessThreadTracker(false, true, id, hashcode); - - if (reentrantCount.incrementAndGet() == 1) { - final Thread t = Thread.currentThread(); - timeoutSchedule = TimerManager.getInstance().schedule(() -> issueDeadlock(t), YamlConfig.config.server.LOCK_MONITOR_TIME); - } - } finally { - state.unlock(); - } - } - - private void unregisterLocking() { - state.lock(); - try { - if (reentrantCount.decrementAndGet() == 0) { - if (timeoutSchedule != null) { - timeoutSchedule.cancel(false); - timeoutSchedule = null; - } - } - - ThreadTracker.getInstance().accessThreadTracker(false, false, id, hashcode); - } finally { - state.unlock(); - } - } - - private void issueDeadlock(Thread t) { - deadlockedState = t.getStackTrace(); - //super.unlock(); - } - - private static String printStackTrace(StackTraceElement[] list) { - String s = ""; - for (StackTraceElement stackTraceElement : list) { - s += (" " + stackTraceElement.toString() + "\r\n"); - } - - return s; - } - - @Override - public MonitoredReadLock dispose() { - state.lock(); - try { - if (timeoutSchedule != null) { - timeoutSchedule.cancel(false); - timeoutSchedule = null; - } - - reentrantCount.set(Integer.MAX_VALUE); - } finally { - state.unlock(); - } - - //unlock(); - return new EmptyReadLock(id); - } -} diff --git a/src/main/java/net/server/audit/locks/active/TrackerReentrantLock.java b/src/main/java/net/server/audit/locks/active/TrackerReentrantLock.java deleted file mode 100644 index b36a00835b..0000000000 --- a/src/main/java/net/server/audit/locks/active/TrackerReentrantLock.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.active; - -import config.YamlConfig; -import net.server.audit.ThreadTracker; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import net.server.audit.locks.empty.EmptyReentrantLock; -import server.TimerManager; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.TimeZone; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * @author RonanLana - */ -public class TrackerReentrantLock extends ReentrantLock implements MonitoredReentrantLock { - private ScheduledFuture timeoutSchedule = null; - private StackTraceElement[] deadlockedState = null; - private final MonitoredLockType id; - private final int hashcode; - private final Lock state = new ReentrantLock(true); - private final AtomicInteger reentrantCount = new AtomicInteger(0); - - public TrackerReentrantLock(MonitoredLockType id) { - super(); - this.id = id; - hashcode = this.hashCode(); - } - - public TrackerReentrantLock(MonitoredLockType id, boolean fair) { - super(fair); - this.id = id; - hashcode = this.hashCode(); - } - - @Override - public void lock() { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - if (deadlockedState != null) { - DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getDefault()); - - //FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "[CRITICAL] " + dateFormat.format(new Date()) + " Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState)); - ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode); - deadlockedState = null; - } - - registerLocking(); - } - - super.lock(); - } - - @Override - public void unlock() { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - unregisterLocking(); - } - - super.unlock(); - } - - @Override - public boolean tryLock() { - if (super.tryLock()) { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - if (deadlockedState != null) { - //FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState)); - ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode); - deadlockedState = null; - } - - registerLocking(); - } - return true; - } else { - return false; - } - } - - private void registerLocking() { - state.lock(); - try { - ThreadTracker.getInstance().accessThreadTracker(false, true, id, hashcode); - - if (reentrantCount.incrementAndGet() == 1) { - final Thread t = Thread.currentThread(); - timeoutSchedule = TimerManager.getInstance().schedule(() -> issueDeadlock(t), YamlConfig.config.server.LOCK_MONITOR_TIME); - } - } finally { - state.unlock(); - } - } - - private void unregisterLocking() { - state.lock(); - try { - if (reentrantCount.decrementAndGet() == 0) { - if (timeoutSchedule != null) { - timeoutSchedule.cancel(false); - timeoutSchedule = null; - } - } - - ThreadTracker.getInstance().accessThreadTracker(false, false, id, hashcode); - } finally { - state.unlock(); - } - } - - private void issueDeadlock(Thread t) { - deadlockedState = t.getStackTrace(); - //super.unlock(); - } - - private static String printStackTrace(StackTraceElement[] list) { - String s = ""; - for (StackTraceElement stackTraceElement : list) { - s += (" " + stackTraceElement.toString() + "\r\n"); - } - - return s; - } - - @Override - public MonitoredReentrantLock dispose() { - state.lock(); - try { - if (timeoutSchedule != null) { - timeoutSchedule.cancel(false); - timeoutSchedule = null; - } - - reentrantCount.set(Integer.MAX_VALUE); - } finally { - state.unlock(); - } - - //unlock(); - return new EmptyReentrantLock(id); - } -} diff --git a/src/main/java/net/server/audit/locks/active/TrackerWriteLock.java b/src/main/java/net/server/audit/locks/active/TrackerWriteLock.java deleted file mode 100644 index 9bbe526b43..0000000000 --- a/src/main/java/net/server/audit/locks/active/TrackerWriteLock.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.active; - -import config.YamlConfig; -import net.server.audit.ThreadTracker; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantReadWriteLock; -import net.server.audit.locks.MonitoredWriteLock; -import net.server.audit.locks.empty.EmptyWriteLock; -import server.TimerManager; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.TimeZone; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * @author RonanLana - */ -public class TrackerWriteLock extends ReentrantReadWriteLock.WriteLock implements MonitoredWriteLock { - private ScheduledFuture timeoutSchedule = null; - private StackTraceElement[] deadlockedState = null; - private final MonitoredLockType id; - private final int hashcode; - private final Lock state = new ReentrantLock(true); - private final AtomicInteger reentrantCount = new AtomicInteger(0); - - public TrackerWriteLock(MonitoredReentrantReadWriteLock lock) { - super(lock); - this.id = lock.id; - hashcode = this.hashCode(); - } - - @Override - public void lock() { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - if (deadlockedState != null) { - DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getDefault()); - - //FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "[CRITICAL] " + dateFormat.format(new Date()) + " Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState)); - ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode); - deadlockedState = null; - } - - registerLocking(); - } - - super.lock(); - } - - @Override - public void unlock() { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - unregisterLocking(); - } - - super.unlock(); - } - - @Override - public boolean tryLock() { - if (super.tryLock()) { - if (YamlConfig.config.server.USE_THREAD_TRACKER) { - if (deadlockedState != null) { - //FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState)); - ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode); - deadlockedState = null; - } - - registerLocking(); - } - return true; - } else { - return false; - } - } - - private void registerLocking() { - state.lock(); - try { - ThreadTracker.getInstance().accessThreadTracker(false, true, id, hashcode); - - if (reentrantCount.incrementAndGet() == 1) { - final Thread t = Thread.currentThread(); - timeoutSchedule = TimerManager.getInstance().schedule(() -> issueDeadlock(t), YamlConfig.config.server.LOCK_MONITOR_TIME); - } - } finally { - state.unlock(); - } - } - - private void unregisterLocking() { - state.lock(); - try { - if (reentrantCount.decrementAndGet() == 0) { - if (timeoutSchedule != null) { - timeoutSchedule.cancel(false); - timeoutSchedule = null; - } - } - - ThreadTracker.getInstance().accessThreadTracker(false, false, id, hashcode); - } finally { - state.unlock(); - } - } - - private void issueDeadlock(Thread t) { - deadlockedState = t.getStackTrace(); - //super.unlock(); - } - - private static String printStackTrace(StackTraceElement[] list) { - String s = ""; - for (StackTraceElement stackTraceElement : list) { - s += (" " + stackTraceElement.toString() + "\r\n"); - } - - return s; - } - - @Override - public MonitoredWriteLock dispose() { - state.lock(); - try { - if (timeoutSchedule != null) { - timeoutSchedule.cancel(false); - timeoutSchedule = null; - } - - reentrantCount.set(Integer.MAX_VALUE); - } finally { - state.unlock(); - } - - //unlock(); - return new EmptyWriteLock(id); - } -} diff --git a/src/main/java/net/server/audit/locks/empty/AbstractEmptyLock.java b/src/main/java/net/server/audit/locks/empty/AbstractEmptyLock.java deleted file mode 100644 index f89e8e01f6..0000000000 --- a/src/main/java/net/server/audit/locks/empty/AbstractEmptyLock.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.server.audit.locks.empty; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; - -public abstract class AbstractEmptyLock { - - protected static String printThreadStack(StackTraceElement[] list) { - DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); // DRY-code opportunity performed by jtumidanski - dateFormat.setTimeZone(TimeZone.getDefault()); - String df = dateFormat.format(new Date()); - - String s = "\r\n" + df + "\r\n"; - for (StackTraceElement stackTraceElement : list) { - s += (" " + stackTraceElement.toString() + "\r\n"); - } - s += "----------------------------\r\n\r\n"; - - return s; - } - -} diff --git a/src/main/java/net/server/audit/locks/empty/EmptyReadLock.java b/src/main/java/net/server/audit/locks/empty/EmptyReadLock.java deleted file mode 100644 index b703a0a87b..0000000000 --- a/src/main/java/net/server/audit/locks/empty/EmptyReadLock.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.empty; - -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReadLock; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author RonanLana - */ -public class EmptyReadLock extends AbstractEmptyLock implements MonitoredReadLock { - private static final Logger log = LoggerFactory.getLogger(EmptyReadLock.class); - private final MonitoredLockType id; - - public EmptyReadLock(MonitoredLockType type) { - this.id = type; - } - - @Override - public void lock() { - log.warn("Captured locking tentative on disposed lock {}: {}", id, printThreadStack(Thread.currentThread().getStackTrace())); - } - - @Override - public void unlock() {} - - @Override - public boolean tryLock() { - log.warn("Captured try-locking tentative on disposed lock {}: {}", id, printThreadStack(Thread.currentThread().getStackTrace())); - return false; - } - - @Override - public MonitoredReadLock dispose() { - return this; - } -} diff --git a/src/main/java/net/server/audit/locks/empty/EmptyReentrantLock.java b/src/main/java/net/server/audit/locks/empty/EmptyReentrantLock.java deleted file mode 100644 index cd4e699b5b..0000000000 --- a/src/main/java/net/server/audit/locks/empty/EmptyReentrantLock.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.empty; - -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author RonanLana - */ -public class EmptyReentrantLock extends AbstractEmptyLock implements MonitoredReentrantLock { - private static final Logger log = LoggerFactory.getLogger(EmptyReentrantLock.class); - private final MonitoredLockType id; - - public EmptyReentrantLock(MonitoredLockType type) { - this.id = type; - } - - @Override - public void lock() { - log.warn("Captured locking tentative on disposed lock {}: {}", id, printThreadStack(Thread.currentThread().getStackTrace())); - } - - @Override - public void unlock() {} - - @Override - public boolean tryLock() { - log.warn("Captured try-locking tentative on disposed lock {}: {}", id, printThreadStack(Thread.currentThread().getStackTrace())); - return false; - } - - @Override - public MonitoredReentrantLock dispose() { - return this; - } -} diff --git a/src/main/java/net/server/audit/locks/empty/EmptyWriteLock.java b/src/main/java/net/server/audit/locks/empty/EmptyWriteLock.java deleted file mode 100644 index 8d3a55e82d..0000000000 --- a/src/main/java/net/server/audit/locks/empty/EmptyWriteLock.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.audit.locks.empty; - -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredWriteLock; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author RonanLana - */ -public class EmptyWriteLock extends AbstractEmptyLock implements MonitoredWriteLock { - private static final Logger log = LoggerFactory.getLogger(EmptyWriteLock.class); - private final MonitoredLockType id; - - public EmptyWriteLock(MonitoredLockType type) { - this.id = type; - } - - @Override - public void lock() { - log.warn("Captured locking tentative on disposed lock {}: {}", id, printThreadStack(Thread.currentThread().getStackTrace())); - } - - @Override - public void unlock() {} - - @Override - public boolean tryLock() { - log.warn("Captured try-locking tentative on dispsoed lock {}: {}", id, printThreadStack(Thread.currentThread().getStackTrace())); - return false; - } - - @Override - public MonitoredWriteLock dispose() { - return this; - } -} diff --git a/src/main/java/net/server/services/BaseScheduler.java b/src/main/java/net/server/services/BaseScheduler.java index 0b764cf06a..5314813f8e 100644 --- a/src/main/java/net/server/services/BaseScheduler.java +++ b/src/main/java/net/server/services/BaseScheduler.java @@ -21,8 +21,6 @@ package net.server.services; import config.YamlConfig; import net.server.Server; -import net.server.audit.locks.MonitoredLockType; -import net.server.audit.locks.MonitoredReentrantLock; import server.TimerManager; import tools.Pair; @@ -38,18 +36,18 @@ import java.util.concurrent.locks.ReentrantLock; public abstract class BaseScheduler { private int idleProcs = 0; private final List listeners = new LinkedList<>(); - private final List externalLocks = new LinkedList<>(); + private final List externalLocks = new LinkedList<>(); private final Map> registeredEntries = new HashMap<>(); private ScheduledFuture schedulerTask = null; private final Lock schedulerLock = new ReentrantLock(true); private final Runnable monitorTask = () -> runBaseSchedule(); - protected BaseScheduler(MonitoredLockType lockType) { + protected BaseScheduler() { } // NOTE: practice EXTREME caution when adding external locks to the scheduler system, if you don't know what you're doing DON'T USE THIS. - protected BaseScheduler(MonitoredLockType lockType, List extLocks) { + protected BaseScheduler(List extLocks) { externalLocks.addAll(extLocks); } @@ -58,22 +56,12 @@ public abstract class BaseScheduler { } private void lockScheduler() { - if (!externalLocks.isEmpty()) { - for (MonitoredReentrantLock l : externalLocks) { - l.lock(); - } - } - + externalLocks.forEach(Lock::lock); schedulerLock.lock(); } private void unlockScheduler() { - if (!externalLocks.isEmpty()) { - for (MonitoredReentrantLock l : externalLocks) { - l.unlock(); - } - } - + externalLocks.forEach(Lock::unlock); schedulerLock.unlock(); } diff --git a/src/main/java/net/server/services/task/channel/EventService.java b/src/main/java/net/server/services/task/channel/EventService.java index 5104486f0d..2fe64fe49e 100644 --- a/src/main/java/net/server/services/task/channel/EventService.java +++ b/src/main/java/net/server/services/task/channel/EventService.java @@ -20,7 +20,6 @@ package net.server.services.task.channel; import config.YamlConfig; -import net.server.audit.locks.MonitoredLockType; import net.server.services.BaseScheduler; import net.server.services.BaseService; @@ -53,10 +52,6 @@ public class EventService extends BaseService { private class EventScheduler extends BaseScheduler { - public EventScheduler() { - super(MonitoredLockType.CHANNEL_EVENTS); - } - public void registerDelayedAction(Runnable runAction, long delay) { registerEntry(runAction, runAction, delay); } diff --git a/src/main/java/net/server/services/task/channel/MobAnimationService.java b/src/main/java/net/server/services/task/channel/MobAnimationService.java index 5e545dbc25..860d2693a1 100644 --- a/src/main/java/net/server/services/task/channel/MobAnimationService.java +++ b/src/main/java/net/server/services/task/channel/MobAnimationService.java @@ -20,7 +20,6 @@ package net.server.services.task.channel; import config.YamlConfig; -import net.server.audit.locks.MonitoredLockType; import net.server.services.BaseScheduler; import net.server.services.BaseService; @@ -65,8 +64,6 @@ public class MobAnimationService extends BaseService { private final Lock animationLock = new ReentrantLock(true); public MobAnimationScheduler() { - super(MonitoredLockType.CHANNEL_MOBACTION); - super.addListener((toRemove, update) -> { animationLock.lock(); try { diff --git a/src/main/java/net/server/services/task/channel/MobClearSkillService.java b/src/main/java/net/server/services/task/channel/MobClearSkillService.java index c06f1e447b..973f948108 100644 --- a/src/main/java/net/server/services/task/channel/MobClearSkillService.java +++ b/src/main/java/net/server/services/task/channel/MobClearSkillService.java @@ -20,7 +20,6 @@ package net.server.services.task.channel; import config.YamlConfig; -import net.server.audit.locks.MonitoredLockType; import net.server.services.BaseScheduler; import net.server.services.BaseService; @@ -53,10 +52,6 @@ public class MobClearSkillService extends BaseService { private class MobClearSkillScheduler extends BaseScheduler { - public MobClearSkillScheduler() { - super(MonitoredLockType.CHANNEL_MOBSKILL); - } - public void registerClearSkillAction(Runnable runAction, long delay) { registerEntry(runAction, runAction, delay); } diff --git a/src/main/java/net/server/services/task/channel/MobMistService.java b/src/main/java/net/server/services/task/channel/MobMistService.java index f3de67899c..5c32d31b81 100644 --- a/src/main/java/net/server/services/task/channel/MobMistService.java +++ b/src/main/java/net/server/services/task/channel/MobMistService.java @@ -20,7 +20,6 @@ package net.server.services.task.channel; import config.YamlConfig; -import net.server.audit.locks.MonitoredLockType; import net.server.services.BaseScheduler; import net.server.services.BaseService; @@ -53,10 +52,6 @@ public class MobMistService extends BaseService { private class MobMistScheduler extends BaseScheduler { - public MobMistScheduler() { - super(MonitoredLockType.CHANNEL_MOBMIST); - } - public void registerMistCancelAction(Runnable runAction, long delay) { registerEntry(runAction, runAction, delay); } diff --git a/src/main/java/net/server/services/task/channel/MobStatusService.java b/src/main/java/net/server/services/task/channel/MobStatusService.java index 026e557f55..25836bef15 100644 --- a/src/main/java/net/server/services/task/channel/MobStatusService.java +++ b/src/main/java/net/server/services/task/channel/MobStatusService.java @@ -21,7 +21,6 @@ package net.server.services.task.channel; import client.status.MonsterStatusEffect; import config.YamlConfig; -import net.server.audit.locks.MonitoredLockType; import net.server.services.BaseScheduler; import net.server.services.BaseService; @@ -93,8 +92,6 @@ public class MobStatusService extends BaseService { } public MobStatusScheduler() { - super(MonitoredLockType.CHANNEL_MOBSTATUS); - super.addListener((toRemove, update) -> { List toRun = new ArrayList<>(); diff --git a/src/main/java/net/server/services/task/channel/OverallService.java b/src/main/java/net/server/services/task/channel/OverallService.java index 7f2ca75978..c8d843b421 100644 --- a/src/main/java/net/server/services/task/channel/OverallService.java +++ b/src/main/java/net/server/services/task/channel/OverallService.java @@ -20,7 +20,6 @@ package net.server.services.task.channel; import config.YamlConfig; -import net.server.audit.locks.MonitoredLockType; import net.server.services.BaseScheduler; import net.server.services.BaseService; @@ -58,10 +57,6 @@ public class OverallService extends BaseService { // thanks Alex for suggestin public class OverallScheduler extends BaseScheduler { - public OverallScheduler() { - super(MonitoredLockType.CHANNEL_OVERALL); - } - public void registerDelayedAction(Runnable runAction, long delay) { registerEntry(runAction, runAction, delay); } diff --git a/src/main/java/net/server/services/task/world/CharacterSaveService.java b/src/main/java/net/server/services/task/world/CharacterSaveService.java index fc2b699e9f..8944a9f2d3 100644 --- a/src/main/java/net/server/services/task/world/CharacterSaveService.java +++ b/src/main/java/net/server/services/task/world/CharacterSaveService.java @@ -19,7 +19,6 @@ */ package net.server.services.task.world; -import net.server.audit.locks.MonitoredLockType; import net.server.services.BaseScheduler; import net.server.services.BaseService; @@ -44,10 +43,6 @@ public class CharacterSaveService extends BaseService { private class CharacterSaveScheduler extends BaseScheduler { - public CharacterSaveScheduler() { - super(MonitoredLockType.WORLD_SAVECHARS); - } - public void registerSaveCharacter(Integer characterId, Runnable runAction) { registerEntry(characterId, runAction, 0); } diff --git a/src/main/java/net/server/task/ReleaseLockTask.java b/src/main/java/net/server/task/ReleaseLockTask.java deleted file mode 100644 index af9d075d4b..0000000000 --- a/src/main/java/net/server/task/ReleaseLockTask.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of the HeavenMS MapleStory Server - Copyleft (L) 2016 - 2019 RonanLana - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation version 3 as published by - the Free Software Foundation. You may not use, modify or distribute - this program under any other version of the GNU Affero General Public - License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -package net.server.task; - -import net.server.audit.LockCollector; - -/** - * @author Ronan - * @info Thread responsible for expiring locks signalized for dispose. - */ -public class ReleaseLockTask implements Runnable { - @Override - public void run() { - LockCollector.getInstance().runLockCollector(); - } -} From 229252cd63ec9750d287f96ce394260c511f6fc5 Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 11 Aug 2022 15:18:09 +0200 Subject: [PATCH 11/11] Fix deprecations --- src/main/java/client/command/CommandsExecutor.java | 10 ++++------ .../net/server/channel/handlers/ReportHandler.java | 7 ++----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/main/java/client/command/CommandsExecutor.java b/src/main/java/client/command/CommandsExecutor.java index 9287dbfbeb..6127052f90 100644 --- a/src/main/java/client/command/CommandsExecutor.java +++ b/src/main/java/client/command/CommandsExecutor.java @@ -126,7 +126,7 @@ public class CommandsExecutor { private void addCommandInfo(String name, Class commandClass) { try { - levelCommandsCursor.getRight().add(commandClass.newInstance().getDescription()); + levelCommandsCursor.getRight().add(commandClass.getDeclaredConstructor().newInstance().getDescription()); levelCommandsCursor.getLeft().add(name); } catch (Exception e) { e.printStackTrace(); @@ -161,14 +161,12 @@ public class CommandsExecutor { addCommandInfo(commandName, commandClass); try { - Command commandInstance = commandClass.newInstance(); // thanks Halcyon for noticing commands getting reinstanced every call + Command commandInstance = commandClass.getDeclaredConstructor().newInstance(); // thanks Halcyon for noticing commands getting reinstanced every call commandInstance.setRank(rank); registeredCommands.put(commandName, commandInstance); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); + } catch (Exception e) { + log.warn("Failed to create command instance", e); } } diff --git a/src/main/java/net/server/channel/handlers/ReportHandler.java b/src/main/java/net/server/channel/handlers/ReportHandler.java index 23c4176243..feb34d1849 100644 --- a/src/main/java/net/server/channel/handlers/ReportHandler.java +++ b/src/main/java/net/server/channel/handlers/ReportHandler.java @@ -32,8 +32,7 @@ import tools.PacketCreator; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.Calendar; +import java.time.OffsetDateTime; /* * @@ -82,11 +81,9 @@ public final class ReportHandler extends AbstractPacketHandler { } public void addReport(int reporterid, int victimid, int reason, String description, String chatlog) { - Calendar calendar = Calendar.getInstance(); - Timestamp currentTimestamp = new java.sql.Timestamp(calendar.getTime().getTime()); try (Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("INSERT INTO reports (`reporttime`, `reporterid`, `victimid`, `reason`, `chatlog`, `description`) VALUES (?, ?, ?, ?, ?, ?)")) { - ps.setString(1, currentTimestamp.toGMTString()); + ps.setString(1, OffsetDateTime.now().toString()); ps.setInt(2, reporterid); ps.setInt(3, victimid); ps.setInt(4, reason);