mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-23 01:27:42 +01:00
UserData is now copied to avoid null pointer exception after some data is removed from cache while analysis is running. Additionally added access and stopAccessing to analysis in case the copy constructor is somehow flawed, to prevent the data from getting cleared while analysis is being run. Also added clear prevention to inspect cache if the data is accessed.
This commit is contained in:
parent
ef57c59d43
commit
236a2bd702
@ -6,9 +6,11 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.api.Gender;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
@ -127,6 +129,43 @@ public class UserData {
|
||||
playerKills = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new UserData object with copied values.
|
||||
* @param data UserData to copy into the new object.
|
||||
*/
|
||||
public UserData(UserData data) {
|
||||
this.accessing = 0;
|
||||
this.uuid = data.getUuid();
|
||||
this.location = data.getLocation();
|
||||
this.locations = new ArrayList<>();
|
||||
locations.addAll(data.getLocations());
|
||||
this.ips = new HashSet<>();
|
||||
ips.addAll(data.getIps());
|
||||
this.nicknames = new HashSet<>();
|
||||
nicknames.addAll(data.getNicknames());
|
||||
this.lastNick = data.getLastNick();
|
||||
this.registered = data.getRegistered();
|
||||
this.lastPlayed = data.getLastPlayed();
|
||||
this.playTime = data.getPlayTime();
|
||||
this.loginTimes = data.getLoginTimes();
|
||||
this.timesKicked = data.getTimesKicked();
|
||||
this.lastGmSwapTime = data.getLastGmSwapTime();
|
||||
this.lastGamemode = data.getLastGamemode();
|
||||
this.gmTimes = new HashMap<>();
|
||||
gmTimes.putAll(data.getGmTimes());
|
||||
this.isOp = data.isOp();
|
||||
this.isBanned = data.isBanned();
|
||||
DemographicsData dem = data.getDemData();
|
||||
this.demData = new DemographicsData(dem.getAge(), dem.getGender(), dem.getGeoLocation());
|
||||
this.mobKills = data.getMobKills();
|
||||
this.playerKills = data.getPlayerKills();
|
||||
this.deaths = data.getDeaths();
|
||||
this.name = data.getName();
|
||||
this.isOnline = data.isOnline();
|
||||
this.sessions = new ArrayList<>();
|
||||
sessions.addAll(data.getSessions());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ip
|
||||
@ -630,4 +669,75 @@ public class UserData {
|
||||
public void setLastNick(String lastNick) {
|
||||
this.lastNick = lastNick;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final UserData other = (UserData) obj;
|
||||
if (this.accessing != other.accessing) {
|
||||
return false;
|
||||
}
|
||||
if (this.registered != other.registered) {
|
||||
return false;
|
||||
}
|
||||
if (this.lastPlayed != other.lastPlayed) {
|
||||
return false;
|
||||
}
|
||||
if (this.playTime != other.playTime) {
|
||||
return false;
|
||||
}
|
||||
if (this.loginTimes != other.loginTimes) {
|
||||
return false;
|
||||
}
|
||||
if (this.timesKicked != other.timesKicked) {
|
||||
return false;
|
||||
}
|
||||
if (this.lastGmSwapTime != other.lastGmSwapTime) {
|
||||
return false;
|
||||
}
|
||||
if (this.mobKills != other.mobKills) {
|
||||
return false;
|
||||
}
|
||||
if (this.deaths != other.deaths) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.lastNick, other.lastNick)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.name, other.name)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.uuid, other.uuid)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.ips, other.ips)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.nicknames, other.nicknames)) {
|
||||
return false;
|
||||
}
|
||||
if (this.lastGamemode != other.lastGamemode) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.gmTimes, other.gmTimes)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.playerKills, other.playerKills)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.sessions, other.sessions)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public class InspectCacheHandler {
|
||||
DBCallableProcessor cacher = new DBCallableProcessor() {
|
||||
@Override
|
||||
public void process(UserData data) {
|
||||
cache.put(uuid, data);
|
||||
cache.put(uuid, new UserData(data));
|
||||
}
|
||||
};
|
||||
handler.getUserDataForProcessing(cacher, uuid, false);
|
||||
@ -69,7 +69,9 @@ public class InspectCacheHandler {
|
||||
@Override
|
||||
public void run() {
|
||||
if (new Date().toInstant().getEpochSecond() - clearTimes.get(uuid) < 30) {
|
||||
clearFomCache(uuid);
|
||||
if (!cache.get(uuid).isAccessed()) {
|
||||
clearFomCache(uuid);
|
||||
}
|
||||
} else {
|
||||
this.cancel();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import main.java.com.djrapitops.plan.Phrase;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.Settings;
|
||||
@ -30,8 +31,6 @@ public class Analysis {
|
||||
|
||||
private final Plan plugin;
|
||||
private final InspectCacheHandler inspectCache;
|
||||
private final List<UserData> rawData;
|
||||
private final List<UUID> added;
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
@ -40,9 +39,7 @@ public class Analysis {
|
||||
*/
|
||||
public Analysis(Plan plugin) {
|
||||
this.plugin = plugin;
|
||||
this.inspectCache = plugin.getInspectCache();
|
||||
rawData = new ArrayList<>();
|
||||
added = new ArrayList<>();
|
||||
this.inspectCache = plugin.getInspectCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -50,13 +47,13 @@ public class Analysis {
|
||||
*
|
||||
* First retrieves all Offlineplayers and checks those that are in the
|
||||
* database. Then Runs a new Analysis Task Asyncronously. Saves AnalysisData
|
||||
* to the provided Cache. Saves all UserData to InspectCache for 8 minutes.
|
||||
* to the provided Cache. Saves all UserData to InspectCache for 15 minutes.
|
||||
*
|
||||
* @param analysisCache Cache that the data is saved to.
|
||||
*/
|
||||
public void analyze(AnalysisCacheHandler analysisCache) {
|
||||
rawData.clear();
|
||||
added.clear();
|
||||
List<UserData> rawData = new ArrayList<>();
|
||||
List<UUID> added = new ArrayList<>();
|
||||
log(Phrase.ANALYSIS_START + "");
|
||||
|
||||
List<UUID> uuids = fetchPlayersInDB();
|
||||
@ -68,7 +65,7 @@ public class Analysis {
|
||||
BukkitTask asyncAnalysisTask = (new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
uuids.stream().filter(uuid -> uuid != null).forEach((uuid) -> {
|
||||
uuids.stream().forEach((uuid) -> {
|
||||
inspectCache.cache(uuid, 15);
|
||||
});
|
||||
log(Phrase.ANALYSIS_FETCH_DATA + "");
|
||||
@ -80,6 +77,7 @@ public class Analysis {
|
||||
UserData userData = inspectCache.getFromCache(uuid);
|
||||
if (userData != null) {
|
||||
rawData.add(userData);
|
||||
userData.access();
|
||||
added.add(uuid);
|
||||
}
|
||||
}
|
||||
@ -135,12 +133,12 @@ public class Analysis {
|
||||
sorted.addTotalDeaths(uData.getDeaths());
|
||||
sorted.getSessiondata().addAll(uData.getSessions());
|
||||
sorted.getRegistered().add(uData.getRegistered());
|
||||
uData.stopAccessing();
|
||||
} catch (NullPointerException e) {
|
||||
plugin.logError(Phrase.DATA_CORRUPTION_WARN.parse(uData.getUuid() + ""));
|
||||
plugin.toLog(this.getClass().getName(), e);
|
||||
}
|
||||
});
|
||||
|
||||
// Analyze & Save RawAnalysisData to AnalysisData
|
||||
createPlayerActivityGraphs(analysisData, sorted.getSessiondata(), sorted.getRegistered());
|
||||
|
||||
@ -166,7 +164,7 @@ public class Analysis {
|
||||
|
||||
analysisData.setRefreshDate(new Date().getTime());
|
||||
analysisCache.cache(analysisData);
|
||||
plugin.log(Phrase.ANALYSIS_COMPLETE + "");
|
||||
plugin.log(Phrase.ANALYSIS_COMPLETE + "");
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@ -240,19 +238,19 @@ public class Analysis {
|
||||
}
|
||||
|
||||
private List<UUID> fetchPlayersInDB() {
|
||||
final List<UUID> uuids = new ArrayList<>();
|
||||
log(Phrase.ANALYSIS_FETCH_PLAYERS + "");
|
||||
try {
|
||||
// final List<UUID> uuids = new ArrayList<>();
|
||||
log(Phrase.ANALYSIS_FETCH_PLAYERS + "");
|
||||
Set<UUID> savedUUIDs = plugin.getDB().getSavedUUIDs();
|
||||
savedUUIDs.parallelStream()
|
||||
List<UUID> uuids = savedUUIDs.parallelStream()
|
||||
.filter(uuid -> uuid != null)
|
||||
.filter((uuid) -> (getOfflinePlayer(uuid).hasPlayedBefore()))
|
||||
.forEach((uuid) -> {
|
||||
uuids.add(uuid);
|
||||
});
|
||||
.collect(Collectors.toList());
|
||||
return uuids;
|
||||
} catch (Exception e) {
|
||||
plugin.toLog(this.getClass().getName(), e);
|
||||
}
|
||||
return uuids;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private void log(String msg) {
|
||||
|
@ -75,6 +75,7 @@ public class AnalysisUtils {
|
||||
int newPlayers = 0;
|
||||
if (!registered.isEmpty()) {
|
||||
newPlayers = registered.stream()
|
||||
.filter((reg) -> (reg != null))
|
||||
.filter((reg) -> (reg > now - scale))
|
||||
.map((_item) -> 1).reduce(newPlayers, Integer::sum);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
name: Plan
|
||||
author: Rsl1122
|
||||
main: main.java.com.djrapitops.plan.Plan
|
||||
version: 2.8.0
|
||||
version: 2.8.1
|
||||
|
||||
softdepend:
|
||||
- OnTime
|
||||
|
Loading…
Reference in New Issue
Block a user