Even better statistics.

This commit is contained in:
Olof Larsson 2013-05-27 09:39:53 +02:00
parent 1b7a6c45e6
commit 9d01aa974e
4 changed files with 160 additions and 39 deletions

View File

@ -0,0 +1,40 @@
package com.massivecraft.mcore.cmd.arg;
import java.util.Collection;
import org.bukkit.command.CommandSender;
import com.massivecraft.mcore.store.Coll;
public class ARColl extends ARAbstractSelect<Coll<?>>
{
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
private static ARColl i = new ARColl();
public static ARColl get() { return i; }
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public String typename()
{
return "coll";
}
@Override
public Coll<?> select(String arg, CommandSender sender)
{
return Coll.getMap().get(arg);
}
@Override
public Collection<String> altNames(CommandSender sender)
{
return Coll.getNames();
}
}

View File

@ -1,11 +1,14 @@
package com.massivecraft.mcore.mcorecmd;
import java.util.List;
import java.util.Map.Entry;
import com.massivecraft.mcore.MCorePerm;
import com.massivecraft.mcore.cmd.arg.ARColl;
import com.massivecraft.mcore.cmd.req.ReqHasPerm;
import com.massivecraft.mcore.store.Coll;
import com.massivecraft.mcore.store.ExamineThread;
import com.massivecraft.mcore.util.MUtil;
import com.massivecraft.mcore.util.Txt;
public class CmdMCoreMStoreStats extends MCoreCommand
@ -14,21 +17,70 @@ public class CmdMCoreMStoreStats extends MCoreCommand
{
super(aliases);
this.addOptionalArg("coll", Coll.TOTAL);
this.addRequirements(ReqHasPerm.get(MCorePerm.CMD_MCORE_MSTORE_STATS.node));
}
@Override
public void perform()
{
msg(Txt.titleize("MStore Statistics"));
if (!this.argIsSet(0) || this.arg(0).equalsIgnoreCase(Coll.TOTAL))
{
this.performTotal();
}
else
{
Coll<?> coll = this.arg(0, ARColl.get());
if (coll == null) return;
this.performColl(coll);
}
}
public void performTotal()
{
msg(Txt.titleize("MStore Total Statistics"));
msg("<k>Last Examine Duration: <v>%d<i>ms", ExamineThread.get().getLastDurationMillis());
msg("<a>== <k>Coll <a>| <k>Sync Count In <a>| <k>Sync Count Out <a>==");
for (String name : Coll.getNames())
for (Entry<String, Coll<?>> entry : Coll.getMap().entrySet())
{
long in = Coll.getSyncCount(name, true);
long out = Coll.getSyncCount(name, false);
String name = entry.getKey();
Coll<?> coll = entry.getValue();
long in = coll.getSyncCount(Coll.TOTAL, true);
long out = coll.getSyncCount(Coll.TOTAL, false);
msg("<v>%s <a>| <v>%d <a>| <v>%d", name, in, out);
}
}
public void performColl(Coll<?> coll)
{
msg(Txt.titleize("MStore "+coll.getName()+" Statistics"));
msg("<k>Entity Count: <v>%d", coll.getIds().size());
msg("<k>Basename: <v>%s", coll.getBasename());
msg("<k>Universe: <v>%s", coll.getUniverse());
msg("<k>Entity Class: <v>%s", coll.getEntityClass().getName());
msg("<k>Plugin: <v>%s", coll.getPlugin().getDescription().getFullName());
msg("<k>Database: <v>%s", coll.getDb().getName());
msg("<k>Driver: <v>%s", coll.getDriver().getName());
int limit;
msg("<a>== Sync Count In <a>==");
limit = 30;
for (Entry<String, Long> entry : MUtil.entriesSortedByValues(coll.getSyncMap(true), false))
{
if (limit-- == 0) break;
msg("<k>%s <v>%d", entry.getKey(), entry.getValue());
}
msg("<a>== Sync Count Out <a>==");
limit = 30;
for (Entry<String, Long> entry : MUtil.entriesSortedByValues(coll.getSyncMap(false), false))
{
if (limit-- == 0) break;
msg("<k>%s <v>%d", entry.getKey(), entry.getValue());
}
}
}

View File

@ -4,15 +4,12 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import org.bukkit.plugin.Plugin;
@ -30,31 +27,18 @@ public class Coll<E> implements CollInterface<E>
// GLOBAL REGISTRY
// -------------------------------------------- //
public final static String TOTAL = "*total*";
// All instances registered here are considered inited.
private static List<Coll<?>> instances = new CopyOnWriteArrayList<Coll<?>>();
public static List<Coll<?>> getInstances() { return instances; }
private static Map<String, Coll<?>> name2instance = new ConcurrentSkipListMap<String, Coll<?>>(NaturalOrderComparator.get());
private static TreeSet<String> names = new TreeSet<String>(NaturalOrderComparator.get());
public static TreeSet<String> getNames() { return names; }
private static Map<String, Coll<?>> umap = Collections.unmodifiableMap(name2instance);
private static Set<String> unames = Collections.unmodifiableSet(name2instance.keySet());
private static Collection<Coll<?>> uinstances = Collections.unmodifiableCollection(name2instance.values());
// Log database syncronization for display in the "/mcore mstore stats" command.
private static Map<String, Long> name2out = new TreeMap<String, Long>(String.CASE_INSENSITIVE_ORDER);
private static Map<String, Long> name2in = new TreeMap<String, Long>(String.CASE_INSENSITIVE_ORDER);
public static long getSyncCount(String name, boolean in)
{
Long count = (in ? name2in.get(name) : name2out.get(name));
if (count == null) return 0;
return count;
}
public static void addSyncCount(String name, boolean in)
{
long count = getSyncCount(name, in);
count++;
Map<String, Long> map = (in ? name2in : name2out);
map.put(name, count);
}
public static Map<String, Coll<?>> getMap() { return umap; }
public static Set<String> getNames() { return unames; }
public static Collection<Coll<?>> getInstances() { return uinstances; }
// -------------------------------------------- //
// WHAT DO WE HANDLE?
@ -364,6 +348,29 @@ public class Coll<E> implements CollInterface<E>
this.lastDefault.remove(id);
}
// Log database syncronization for display in the "/mcore mstore stats" command.
private Map<String, Long> id2out = new TreeMap<String, Long>();
private Map<String, Long> id2in = new TreeMap<String, Long>();
public Map<String, Long> getSyncMap(boolean in)
{
return in ? this.id2in : this.id2out;
}
public long getSyncCount(String id, boolean in)
{
Long count = this.getSyncMap(in).get(id);
if (count == null) return 0;
return count;
}
public void addSyncCount(String id, boolean in)
{
long count = this.getSyncCount(id, in);
count++;
this.getSyncMap(in).put(id, count);
}
// -------------------------------------------- //
// SYNC LOWLEVEL IO ACTIONS
// -------------------------------------------- //
@ -542,21 +549,37 @@ public class Coll<E> implements CollInterface<E>
{
case LOCAL_ALTER:
case LOCAL_ATTACH:
this.saveToRemote(id);
if (this.inited()) addSyncCount(this.getName(), false);
this.saveToRemote(id);
if (this.inited())
{
this.addSyncCount(TOTAL, false);
this.addSyncCount(id, false);
}
break;
case LOCAL_DETACH:
this.removeAtRemote(id);
if (this.inited()) addSyncCount(this.getName(), false);
if (this.inited())
{
this.addSyncCount(TOTAL, false);
this.addSyncCount(id, false);
}
break;
case REMOTE_ALTER:
case REMOTE_ATTACH:
this.loadFromRemote(id);
if (this.inited()) addSyncCount(this.getName(), true);
if (this.inited())
{
this.addSyncCount(TOTAL, true);
this.addSyncCount(id, true);
}
break;
case REMOTE_DETACH:
this.removeAtLocal(id);
if (this.inited()) addSyncCount(this.getName(), true);
if (this.inited())
{
this.addSyncCount(TOTAL, true);
this.addSyncCount(id, true);
}
break;
default:
this.clearIdentifiedChanges(id);
@ -688,25 +711,27 @@ public class Coll<E> implements CollInterface<E>
public void init()
{
if (this.inited()) return;
// TODO: Could this be more efficient by considering it's the first sync?
this.syncAll();
instances.add(this);
names.add(this.getName());
name2instance.put(this.getName(), this);
}
@Override
public void deinit()
{
if (!this.inited()) return;
// TODO: Save outwards only? We may want to avoid loads at this stage...
this.syncAll();
instances.remove(this);
names.remove(this.getName());
name2instance.remove(this.getName());
}
@Override
public boolean inited()
{
return instances.contains(this);
return name2instance.containsKey(this.getName());
}
}

View File

@ -107,6 +107,10 @@ public interface CollInterface<E>
public void clearSynclog(Object oid);
*/
public Map<String, Long> getSyncMap(boolean in);
public long getSyncCount(String name, boolean in);
public void addSyncCount(String name, boolean in);
// -------------------------------------------- //
// SYNC LOWLEVEL IO ACTIONS
// -------------------------------------------- //