Io write Update
Removed usage of busy loop in handling sent packets.
This commit is contained in:
@@ -61,7 +61,6 @@ import net.server.world.World;
|
|||||||
|
|
||||||
import org.apache.mina.core.session.IoSession;
|
import org.apache.mina.core.session.IoSession;
|
||||||
|
|
||||||
import net.server.world.announcer.MapleAnnouncerCoordinator;
|
|
||||||
import client.inventory.MapleInventoryType;
|
import client.inventory.MapleInventoryType;
|
||||||
import constants.GameConstants;
|
import constants.GameConstants;
|
||||||
import constants.ServerConstants;
|
import constants.ServerConstants;
|
||||||
@@ -95,7 +94,6 @@ public class MapleClient {
|
|||||||
private MapleAESOFB receive;
|
private MapleAESOFB receive;
|
||||||
private final IoSession session;
|
private final IoSession session;
|
||||||
private MapleCharacter player;
|
private MapleCharacter player;
|
||||||
private MapleAnnouncerCoordinator announcer = MapleAnnouncerCoordinator.getInstance();
|
|
||||||
private int channel = 1;
|
private int channel = 1;
|
||||||
private int accId = -4;
|
private int accId = -4;
|
||||||
private boolean loggedIn = false;
|
private boolean loggedIn = false;
|
||||||
@@ -120,6 +118,7 @@ public class MapleClient {
|
|||||||
private final Semaphore actionsSemaphore = new Semaphore(7);
|
private final Semaphore actionsSemaphore = new Semaphore(7);
|
||||||
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT, true);
|
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT, true);
|
||||||
private final Lock encoderLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ENCODER, true);
|
private final Lock encoderLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ENCODER, true);
|
||||||
|
private final Lock announcerLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ANNOUNCER, true);
|
||||||
private static final Lock loginLocks[] = new Lock[200]; // thanks Masterrulax & try2hack for pointing out a bottleneck issue here
|
private static final Lock loginLocks[] = new Lock[200]; // thanks Masterrulax & try2hack for pointing out a bottleneck issue here
|
||||||
private Calendar tempBanCalendar;
|
private Calendar tempBanCalendar;
|
||||||
private int votePoints;
|
private int votePoints;
|
||||||
@@ -1143,13 +1142,6 @@ public class MapleClient {
|
|||||||
|
|
||||||
public void setWorld(int world) {
|
public void setWorld(int world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
|
|
||||||
World wserv = Server.getInstance().getWorld(world);
|
|
||||||
if (wserv != null) {
|
|
||||||
this.announcer = wserv.getAnnouncerCoordinator();
|
|
||||||
} else {
|
|
||||||
this.announcer = MapleAnnouncerCoordinator.getInstance();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pongReceived() {
|
public void pongReceived() {
|
||||||
@@ -1475,7 +1467,12 @@ public class MapleClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void announce(final byte[] packet) { // thanks GitGud for noticing an opportunity for improvement by overcoming "synchronized announce"
|
public void announce(final byte[] packet) { // thanks GitGud for noticing an opportunity for improvement by overcoming "synchronized announce"
|
||||||
announcer.append(session, packet);
|
announcerLock.lock();
|
||||||
|
try {
|
||||||
|
session.write(packet);
|
||||||
|
} finally {
|
||||||
|
announcerLock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void announceHint(String msg, int length) {
|
public void announceHint(String msg, int length) {
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ import net.server.worker.RankingLoginWorker;
|
|||||||
import net.server.worker.ReleaseLockWorker;
|
import net.server.worker.ReleaseLockWorker;
|
||||||
import net.server.worker.RespawnWorker;
|
import net.server.worker.RespawnWorker;
|
||||||
import net.server.world.World;
|
import net.server.world.World;
|
||||||
import net.server.world.announcer.MapleAnnouncerCoordinator;
|
|
||||||
|
|
||||||
import org.apache.mina.core.buffer.IoBuffer;
|
import org.apache.mina.core.buffer.IoBuffer;
|
||||||
import org.apache.mina.core.buffer.SimpleBufferAllocator;
|
import org.apache.mina.core.buffer.SimpleBufferAllocator;
|
||||||
@@ -950,7 +949,6 @@ public class Server {
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MapleAnnouncerCoordinator.getInstance().init();
|
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
if(ServerConstants.USE_FAMILY_SYSTEM) {
|
if(ServerConstants.USE_FAMILY_SYSTEM) {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public enum MonitoredLockType {
|
|||||||
CHARACTER_EVT,
|
CHARACTER_EVT,
|
||||||
CHARACTER_STA,
|
CHARACTER_STA,
|
||||||
CLIENT,
|
CLIENT,
|
||||||
|
CLIENT_ANNOUNCER,
|
||||||
CLIENT_ENCODER,
|
CLIENT_ENCODER,
|
||||||
CLIENT_SESSION,
|
CLIENT_SESSION,
|
||||||
CLIENT_LOGIN,
|
CLIENT_LOGIN,
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ import net.server.worker.ServerMessageWorker;
|
|||||||
import net.server.worker.TimedMapObjectWorker;
|
import net.server.worker.TimedMapObjectWorker;
|
||||||
import net.server.worker.TimeoutWorker;
|
import net.server.worker.TimeoutWorker;
|
||||||
import net.server.worker.WeddingReservationWorker;
|
import net.server.worker.WeddingReservationWorker;
|
||||||
import net.server.world.announcer.MapleAnnouncerCoordinator;
|
|
||||||
import tools.DatabaseConnection;
|
import tools.DatabaseConnection;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
@@ -125,7 +124,6 @@ public class World {
|
|||||||
private PlayerStorage players = new PlayerStorage();
|
private PlayerStorage players = new PlayerStorage();
|
||||||
private MapleMatchCheckerCoordinator matchChecker = new MapleMatchCheckerCoordinator();
|
private MapleMatchCheckerCoordinator matchChecker = new MapleMatchCheckerCoordinator();
|
||||||
private MaplePartySearchCoordinator partySearch = new MaplePartySearchCoordinator();
|
private MaplePartySearchCoordinator partySearch = new MaplePartySearchCoordinator();
|
||||||
private MapleAnnouncerCoordinator announcer = new MapleAnnouncerCoordinator();
|
|
||||||
|
|
||||||
private final ReentrantReadWriteLock chnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_CHANNELS, true);
|
private final ReentrantReadWriteLock chnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_CHANNELS, true);
|
||||||
private ReadLock chnRLock = chnLock.readLock();
|
private ReadLock chnRLock = chnLock.readLock();
|
||||||
@@ -224,8 +222,6 @@ public class World {
|
|||||||
FamilyDailyResetWorker.resetEntitlementUsage(this);
|
FamilyDailyResetWorker.resetEntitlementUsage(this);
|
||||||
tman.register(new FamilyDailyResetWorker(this), 24 * 60 * 60 * 1000, timeLeft);
|
tman.register(new FamilyDailyResetWorker(this), 24 * 60 * 60 * 1000, timeLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
announcer.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getChannelsSize() {
|
public int getChannelsSize() {
|
||||||
@@ -557,10 +553,6 @@ public class World {
|
|||||||
return partySearch;
|
return partySearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapleAnnouncerCoordinator getAnnouncerCoordinator() {
|
|
||||||
return announcer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addPlayer(MapleCharacter chr) {
|
public void addPlayer(MapleCharacter chr) {
|
||||||
players.addPlayer(chr);
|
players.addPlayer(chr);
|
||||||
}
|
}
|
||||||
@@ -2170,7 +2162,6 @@ public class World {
|
|||||||
players.disconnectAll();
|
players.disconnectAll();
|
||||||
players = null;
|
players = null;
|
||||||
|
|
||||||
announcer.shutdown();
|
|
||||||
clearWorldData();
|
clearWorldData();
|
||||||
System.out.println("Finished shutting down world " + id + "\r\n");
|
System.out.println("Finished shutting down world " + id + "\r\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,83 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package net.server.world.announcer;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import org.apache.mina.core.session.IoSession;
|
|
||||||
import net.server.world.announcer.MapleAnnouncerEntryPool.SessionPacket;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Ronan
|
|
||||||
*/
|
|
||||||
public class MapleAnnouncerCoordinator {
|
|
||||||
|
|
||||||
private static final MapleAnnouncerCoordinator instance = new MapleAnnouncerCoordinator();
|
|
||||||
|
|
||||||
public static MapleAnnouncerCoordinator getInstance() { // world-agnostic Announcer coordinator
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MapleAnnouncerEntryPool pool = new MapleAnnouncerEntryPool();
|
|
||||||
private ConcurrentLinkedQueue<SessionPacket> queue = new ConcurrentLinkedQueue<>();
|
|
||||||
private Thread t;
|
|
||||||
|
|
||||||
public void append(IoSession io, byte[] packet) {
|
|
||||||
queue.offer(pool.getSessionPacket(io, packet));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() {
|
|
||||||
final Runnable r = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
while (!Thread.interrupted()) {
|
|
||||||
try {
|
|
||||||
SessionPacket p = queue.poll();
|
|
||||||
if (p != null) {
|
|
||||||
IoSession session = p.getSession();
|
|
||||||
byte[] packet = p.getPacket();
|
|
||||||
|
|
||||||
session.write(packet);
|
|
||||||
pool.returnSessionPacket(p);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
t = new Thread(r);
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutdown() {
|
|
||||||
t.interrupt();
|
|
||||||
try {
|
|
||||||
t.join();
|
|
||||||
} catch (InterruptedException ie) {
|
|
||||||
ie.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
queue.clear();
|
|
||||||
pool.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package net.server.world.announcer;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import org.apache.mina.core.session.IoSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Ronan
|
|
||||||
*/
|
|
||||||
public class MapleAnnouncerEntryPool {
|
|
||||||
|
|
||||||
private ConcurrentLinkedQueue<SessionPacket> instancedPairs = new ConcurrentLinkedQueue<>();
|
|
||||||
private final static int initialCount = 20000; // initial length of the instanced pool
|
|
||||||
|
|
||||||
public MapleAnnouncerEntryPool() {
|
|
||||||
for (int i = 0; i < initialCount; i++) {
|
|
||||||
instancedPairs.offer(new SessionPacket());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SessionPacket {
|
|
||||||
|
|
||||||
private IoSession session;
|
|
||||||
private byte[] packet;
|
|
||||||
|
|
||||||
public IoSession getSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getPacket() {
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionPacket getSessionPacket(IoSession session, byte[] packet) {
|
|
||||||
SessionPacket sp = instancedPairs.poll();
|
|
||||||
if (sp == null) {
|
|
||||||
sp = new SessionPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
sp.session = session;
|
|
||||||
sp.packet = packet;
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void returnSessionPacket(SessionPacket sp) {
|
|
||||||
instancedPairs.offer(sp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutdown() {
|
|
||||||
instancedPairs.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user