summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsnowleo <schneeleo@gmail.com>2011-11-28 18:53:38 +0100
committersnowleo <schneeleo@gmail.com>2011-11-28 18:53:38 +0100
commiteea7785b7f1281b63cefa86363dd4ffbf5d3f54e (patch)
tree7627e00ea017552cffc37034abcaa4ba1c03bd17
parent7268e1965d24b443d3ec4b2eddd6cde1967250e2 (diff)
downloadEssentials-eea7785b7f1281b63cefa86363dd4ffbf5d3f54e.tar
Essentials-eea7785b7f1281b63cefa86363dd4ffbf5d3f54e.tar.gz
Essentials-eea7785b7f1281b63cefa86363dd4ffbf5d3f54e.tar.lz
Essentials-eea7785b7f1281b63cefa86363dd4ffbf5d3f54e.tar.xz
Essentials-eea7785b7f1281b63cefa86363dd4ffbf5d3f54e.zip
Calculation of /balancetop is now async to prevent slowdown of the server
-rw-r--r--Essentials/src/com/earth2me/essentials/UserMap.java20
-rw-r--r--Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java150
2 files changed, 136 insertions, 34 deletions
diff --git a/Essentials/src/com/earth2me/essentials/UserMap.java b/Essentials/src/com/earth2me/essentials/UserMap.java
index 3de18080a..c30d97214 100644
--- a/Essentials/src/com/earth2me/essentials/UserMap.java
+++ b/Essentials/src/com/earth2me/essentials/UserMap.java
@@ -5,12 +5,10 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.ConcurrentHashMultiset;
import java.io.File;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ExecutionException;
-import java.util.logging.Level;
-import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -104,21 +102,9 @@ public class UserMap extends CacheLoader<String, User> implements IConf
users.invalidate(name.toLowerCase(Locale.ENGLISH));
}
- public Set<User> getAllUsers()
+ public Set<String> getAllUniqueUsers()
{
- final Set<User> userSet = new HashSet<User>();
- for (String name : keys)
- {
- try
- {
- userSet.add(users.get(name));
- }
- catch (ExecutionException ex)
- {
- Bukkit.getLogger().log(Level.INFO, "Failed to load user " + name, ex);
- }
- }
- return userSet;
+ return Collections.unmodifiableSet(keys.elementSet());
}
public int getUniqueUsers()
diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java b/Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java
index 838e27628..0a02ee7a7 100644
--- a/Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java
+++ b/Essentials/src/com/earth2me/essentials/commands/Commandbalancetop.java
@@ -1,10 +1,10 @@
package com.earth2me.essentials.commands;
import static com.earth2me.essentials.I18n._;
-import com.earth2me.essentials.User;
import com.earth2me.essentials.Util;
import java.util.*;
import java.util.Map.Entry;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
@@ -15,6 +15,12 @@ public class Commandbalancetop extends EssentialsCommand
{
super("balancetop");
}
+
+ private static final int CACHETIME = 5 * 60 * 1000;
+ public static final int MINUSERS = 50;
+ private static List<String> cache = new ArrayList<String>();
+ private static long cacheage = 0;
+ private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
@Override
protected void run(final Server server, final CommandSender sender, final String commandLabel, final String[] args) throws Exception
@@ -24,7 +30,7 @@ public class Commandbalancetop extends EssentialsCommand
{
try
{
- if (Integer.parseInt(args[0]) < 10)
+ if (Integer.parseInt(args[0]) < 19)
{
max = Integer.parseInt(args[0]);
}
@@ -34,31 +40,141 @@ public class Commandbalancetop extends EssentialsCommand
//catch it because they tried to enter a string not number.
}
}
- final Map<User, Double> balances = new HashMap<User, Double>();
- for (User u : ess.getUserMap().getAllUsers())
+
+ if (lock.readLock().tryLock())
{
- balances.put(u, u.getMoney());
+ try
+ {
+ if (cacheage > System.currentTimeMillis() - CACHETIME)
+ {
+ outputCache(sender, max);
+ return;
+ }
+ if (ess.getUserMap().getUniqueUsers() > MINUSERS)
+ {
+ sender.sendMessage("Calculating results");
+ }
+ }
+ finally
+ {
+ lock.readLock().unlock();
+ }
+ ess.scheduleAsyncDelayedTask(new Viewer(sender, max));
}
-
- final List<Map.Entry<User, Double>> sortedEntries = new ArrayList<Map.Entry<User, Double>>(balances.entrySet());
- Collections.sort(sortedEntries, new Comparator<Map.Entry<User, Double>>()
+ else
{
- @Override
- public int compare(final Entry<User, Double> entry1, final Entry<User, Double> entry2)
+ if (ess.getUserMap().getUniqueUsers() > MINUSERS)
{
- return -entry1.getValue().compareTo(entry2.getValue());
+ sender.sendMessage("Calculating results");
}
- });
- int count = 0;
+ ess.scheduleAsyncDelayedTask(new Viewer(sender, max));
+ }
+
+ }
+
+ private static void outputCache(final CommandSender sender, int max)
+ {
sender.sendMessage(_("balanceTop", max));
- for (Map.Entry<User, Double> entry : sortedEntries)
+ for (String line : cache)
{
- if (count == max)
+ if (max == 0)
{
break;
}
- sender.sendMessage(entry.getKey().getDisplayName() + ", " + Util.formatCurrency(entry.getValue(), ess));
- count++;
+ max--;
+ sender.sendMessage(line);
+ }
+ }
+
+
+ private class Calculator implements Runnable
+ {
+ private final transient Viewer viewer;
+
+ public Calculator(final Viewer viewer)
+ {
+ this.viewer = viewer;
+ }
+
+ @Override
+ public void run()
+ {
+ lock.writeLock().lock();
+ try
+ {
+ if (cacheage < System.currentTimeMillis() - 5 * 60 * 1000)
+ {
+ final Map<String, Double> balances = new HashMap<String, Double>();
+ for (String u : ess.getUserMap().getAllUniqueUsers())
+ {
+ try
+ {
+ balances.put(u, ess.getUserMap().getUser(u).getMoney());
+ }
+ catch (NullPointerException ex)
+ {
+ }
+ }
+
+ final List<Map.Entry<String, Double>> sortedEntries = new ArrayList<Map.Entry<String, Double>>(balances.entrySet());
+ Collections.sort(sortedEntries, new Comparator<Map.Entry<String, Double>>()
+ {
+ @Override
+ public int compare(final Entry<String, Double> entry1, final Entry<String, Double> entry2)
+ {
+ return -entry1.getValue().compareTo(entry2.getValue());
+ }
+ });
+ int count = 0;
+ for (Map.Entry<String, Double> entry : sortedEntries)
+ {
+ if (count == 20)
+ {
+ break;
+ }
+ cache.add(entry.getKey() + ", " + Util.formatCurrency(entry.getValue(), ess));
+ count++;
+ }
+ cacheage = System.currentTimeMillis();
+ }
+ }
+ finally
+ {
+ lock.writeLock().unlock();
+ }
+ ess.scheduleAsyncDelayedTask(viewer);
+ }
+ }
+
+
+ private class Viewer implements Runnable
+ {
+ private final transient CommandSender sender;
+ private final transient int max;
+
+ public Viewer(final CommandSender sender, final int max)
+ {
+ this.sender = sender;
+ this.max = max;
+ }
+
+ @Override
+ public void run()
+ {
+ lock.readLock().lock();
+ try
+ {
+ if (cacheage > System.currentTimeMillis() - 5 * 60 * 1000)
+ {
+ outputCache(sender, max);
+ return;
+ }
+ }
+ finally
+ {
+ lock.readLock().unlock();
+ }
+ ess.scheduleAsyncDelayedTask(new Calculator(new Viewer(sender, max)));
}
}
}