Make removal of unused playerdata more predictable and independent of

JOIN/LEAVE events.
This commit is contained in:
Evenprime 2011-10-23 16:05:18 +02:00
parent a6ae2d1e90
commit 15e5367175
6 changed files with 39 additions and 112 deletions

View File

@ -3,7 +3,7 @@ name: NoCheat
author: Evenprime author: Evenprime
main: cc.co.evenprime.bukkit.nocheat.NoCheat main: cc.co.evenprime.bukkit.nocheat.NoCheat
version: 2.13a version: 2.13b
commands: commands:
nocheat: nocheat:

View File

@ -29,7 +29,6 @@ import cc.co.evenprime.bukkit.nocheat.events.BlockBreakEventManager;
import cc.co.evenprime.bukkit.nocheat.events.EntityDamageEventManager; import cc.co.evenprime.bukkit.nocheat.events.EntityDamageEventManager;
import cc.co.evenprime.bukkit.nocheat.events.EventManager; import cc.co.evenprime.bukkit.nocheat.events.EventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerChatEventManager; import cc.co.evenprime.bukkit.nocheat.events.PlayerChatEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerQuitEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerMoveEventManager; import cc.co.evenprime.bukkit.nocheat.events.PlayerMoveEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerTeleportEventManager; import cc.co.evenprime.bukkit.nocheat.events.PlayerTeleportEventManager;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel; import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
@ -101,7 +100,6 @@ public class NoCheat extends JavaPlugin {
eventManagers.add(new PlayerChatEventManager(this)); eventManagers.add(new PlayerChatEventManager(this));
eventManagers.add(new BlockBreakEventManager(this)); eventManagers.add(new BlockBreakEventManager(this));
eventManagers.add(new BlockPlaceEventManager(this)); eventManagers.add(new BlockPlaceEventManager(this));
eventManagers.add(new PlayerQuitEventManager(this));
eventManagers.add(new EntityDamageEventManager(this)); eventManagers.add(new EntityDamageEventManager(this));
// Then set up a task to monitor server lag // Then set up a task to monitor server lag
@ -137,26 +135,14 @@ public class NoCheat extends JavaPlugin {
data.clearCriticalData(playerName); data.clearCriticalData(playerName);
} }
public void playerLeft(String playerName) {
// Get rid of the critical data that's stored for player immediately
clearCriticalData(playerName);
data.queueForRemoval(playerName);
}
public void playerJoined(String playerName) { public void playerJoined(String playerName) {
data.unqueueForRemoval(playerName); clearCriticalData(playerName);
} }
public Performance getPerformance(Type type) { public Performance getPerformance(Type type) {
return performance.get(type); return performance.get(type);
} }
public void cleanDataMap() {
if(data != null)
data.cleanDataMap();
}
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return CommandHandler.handleCommand(this, sender, command, label, args); return CommandHandler.handleCommand(this, sender, command, label, args);
@ -197,6 +183,16 @@ public class NoCheat extends JavaPlugin {
public void reloadConfig() { public void reloadConfig() {
conf.cleanup(); conf.cleanup();
this.conf = new ConfigurationManager(this.getDataFolder().getPath()); this.conf = new ConfigurationManager(this.getDataFolder().getPath());
this.data.clearCriticalData(); data.cleanDataMap();
data.clearCriticalData();
}
/**
* Call this periodically to walk over the stored data map and remove old/unused entries
*
*/
public void cleanDataMap() {
data.cleanDataMap();
} }
} }

View File

@ -9,9 +9,9 @@ public class BaseData extends Data {
public final MovingData moving; public final MovingData moving;
public final FightData fight; public final FightData fight;
private final Data[] data; // for convenience private final Data[] data; // for convenience
private long removalTime; public long lastUsedTime;
public BaseData() { public BaseData() {
this.blockbreak = new BlockBreakData(); this.blockbreak = new BlockBreakData();
@ -21,8 +21,6 @@ public class BaseData extends Data {
this.moving = new MovingData(); this.moving = new MovingData();
this.fight = new FightData(); this.fight = new FightData();
this.removalTime = 0;
data = new Data[] {this.blockbreak, this.blockplace, this.chat, data = new Data[] {this.blockbreak, this.blockplace, this.chat,
this.log, this.moving, this.fight}; this.log, this.moving, this.fight};
} }
@ -32,17 +30,8 @@ public class BaseData extends Data {
d.clearCriticalData(); d.clearCriticalData();
} }
} }
public void markForRemoval(boolean removal) { public boolean shouldBeRemoved(long currentTimeInMilliseconds) {
if(removal) { return lastUsedTime + 60000L < currentTimeInMilliseconds;
// 1 minute in the future
this.removalTime = System.currentTimeMillis() + 60000;
} else {
this.removalTime = 0;
}
}
public boolean shouldBeRemoved() {
return removalTime != 0 && removalTime < System.currentTimeMillis();
} }
} }

View File

@ -40,6 +40,8 @@ public class DataManager {
this.map.put(playerName, data); this.map.put(playerName, data);
} }
data.lastUsedTime = System.currentTimeMillis();
return data; return data;
} }
@ -54,47 +56,28 @@ public class DataManager {
} }
/** /**
* put a players data on the queue for later deletion (unless it comes back * check if some data hasn't been used for a while and remove it
* before)
*
*/
public void queueForRemoval(String playerName) {
BaseData data = this.map.get(playerName);
if(data != null) {
data.markForRemoval(true);
}
}
public void unqueueForRemoval(String playerName) {
BaseData data = this.map.get(playerName);
if(data != null) {
data.markForRemoval(false);
}
}
/**
* check if queued for removal data is ready to get removed
* *
*/ */
public void cleanDataMap() { public void cleanDataMap() {
try { synchronized(removals) {
for(Entry<String, BaseData> p : this.map.entrySet()) { long time = System.currentTimeMillis();
if(p.getValue().shouldBeRemoved()) { try {
removals.add(p.getKey()); for(Entry<String, BaseData> p : this.map.entrySet()) {
if(p.getValue().shouldBeRemoved(time)) {
removals.add(p.getKey());
}
} }
}
for(String p : removals) { for(String p : removals) {
this.map.remove(p); this.map.remove(p);
} }
removals.clear(); removals.clear();
} catch(Exception e) { } catch(Exception e) {
// Ignore problems, as they really don't matter much e.printStackTrace();
}
} }
} }
public void clearCriticalData(String playerName) { public void clearCriticalData(String playerName) {

View File

@ -9,6 +9,7 @@ public class LagMeasureTask implements Runnable {
private long lastIngamesecondDuration = 2000L; private long lastIngamesecondDuration = 2000L;
private boolean skipCheck = true; private boolean skipCheck = true;
private int lagMeasureTaskId = -1; private int lagMeasureTaskId = -1;
private final NoCheat plugin; private final NoCheat plugin;
public LagMeasureTask(NoCheat plugin) { public LagMeasureTask(NoCheat plugin) {
@ -38,7 +39,9 @@ public class LagMeasureTask implements Runnable {
ingameseconds++; ingameseconds++;
// Check if some data is outdated now and let it be removed // Check if some data is outdated now and let it be removed
plugin.cleanDataMap(); if(ingameseconds % 62 == 0) {
plugin.cleanDataMap();
}
} }

View File

@ -1,44 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.events;
import java.util.Collections;
import java.util.List;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
public class PlayerQuitEventManager extends PlayerListener implements EventManager {
private final NoCheat plugin;
public PlayerQuitEventManager(NoCheat plugin) {
this.plugin = plugin;
PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvent(Event.Type.PLAYER_QUIT, this, Priority.Monitor, plugin);
pm.registerEvent(Event.Type.PLAYER_JOIN, this, Priority.Monitor, plugin);
}
@Override
public void onPlayerQuit(PlayerQuitEvent event) {
// But only after a certain time, get rid of the rest of the data
plugin.playerLeft(event.getPlayer().getName());
}
@Override
public void onPlayerJoin(PlayerJoinEvent event) {
// A player came back early, so make sure that his data gets recycled
plugin.playerJoined(event.getPlayer().getName());
}
public List<String> getActiveChecks(ConfigurationCache cc) {
return Collections.emptyList();
}
}