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; package com.massivecraft.mcore.mcorecmd;
import java.util.List; import java.util.List;
import java.util.Map.Entry;
import com.massivecraft.mcore.MCorePerm; import com.massivecraft.mcore.MCorePerm;
import com.massivecraft.mcore.cmd.arg.ARColl;
import com.massivecraft.mcore.cmd.req.ReqHasPerm; import com.massivecraft.mcore.cmd.req.ReqHasPerm;
import com.massivecraft.mcore.store.Coll; import com.massivecraft.mcore.store.Coll;
import com.massivecraft.mcore.store.ExamineThread; import com.massivecraft.mcore.store.ExamineThread;
import com.massivecraft.mcore.util.MUtil;
import com.massivecraft.mcore.util.Txt; import com.massivecraft.mcore.util.Txt;
public class CmdMCoreMStoreStats extends MCoreCommand public class CmdMCoreMStoreStats extends MCoreCommand
@ -14,21 +17,70 @@ public class CmdMCoreMStoreStats extends MCoreCommand
{ {
super(aliases); super(aliases);
this.addOptionalArg("coll", Coll.TOTAL);
this.addRequirements(ReqHasPerm.get(MCorePerm.CMD_MCORE_MSTORE_STATS.node)); this.addRequirements(ReqHasPerm.get(MCorePerm.CMD_MCORE_MSTORE_STATS.node));
} }
@Override @Override
public void perform() 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("<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>=="); 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); String name = entry.getKey();
long out = Coll.getSyncCount(name, false); 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); 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.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
@ -30,31 +27,18 @@ public class Coll<E> implements CollInterface<E>
// GLOBAL REGISTRY // GLOBAL REGISTRY
// -------------------------------------------- // // -------------------------------------------- //
public final static String TOTAL = "*total*";
// All instances registered here are considered inited. // All instances registered here are considered inited.
private static List<Coll<?>> instances = new CopyOnWriteArrayList<Coll<?>>(); private static Map<String, Coll<?>> name2instance = new ConcurrentSkipListMap<String, Coll<?>>(NaturalOrderComparator.get());
public static List<Coll<?>> getInstances() { return instances; }
private static TreeSet<String> names = new TreeSet<String>(NaturalOrderComparator.get()); private static Map<String, Coll<?>> umap = Collections.unmodifiableMap(name2instance);
public static TreeSet<String> getNames() { return names; } 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. public static Map<String, Coll<?>> getMap() { return umap; }
private static Map<String, Long> name2out = new TreeMap<String, Long>(String.CASE_INSENSITIVE_ORDER); public static Set<String> getNames() { return unames; }
private static Map<String, Long> name2in = new TreeMap<String, Long>(String.CASE_INSENSITIVE_ORDER); public static Collection<Coll<?>> getInstances() { return uinstances; }
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);
}
// -------------------------------------------- // // -------------------------------------------- //
// WHAT DO WE HANDLE? // WHAT DO WE HANDLE?
@ -364,6 +348,29 @@ public class Coll<E> implements CollInterface<E>
this.lastDefault.remove(id); 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 // SYNC LOWLEVEL IO ACTIONS
// -------------------------------------------- // // -------------------------------------------- //
@ -543,20 +550,36 @@ public class Coll<E> implements CollInterface<E>
case LOCAL_ALTER: case LOCAL_ALTER:
case LOCAL_ATTACH: case LOCAL_ATTACH:
this.saveToRemote(id); this.saveToRemote(id);
if (this.inited()) addSyncCount(this.getName(), false); if (this.inited())
{
this.addSyncCount(TOTAL, false);
this.addSyncCount(id, false);
}
break; break;
case LOCAL_DETACH: case LOCAL_DETACH:
this.removeAtRemote(id); this.removeAtRemote(id);
if (this.inited()) addSyncCount(this.getName(), false); if (this.inited())
{
this.addSyncCount(TOTAL, false);
this.addSyncCount(id, false);
}
break; break;
case REMOTE_ALTER: case REMOTE_ALTER:
case REMOTE_ATTACH: case REMOTE_ATTACH:
this.loadFromRemote(id); this.loadFromRemote(id);
if (this.inited()) addSyncCount(this.getName(), true); if (this.inited())
{
this.addSyncCount(TOTAL, true);
this.addSyncCount(id, true);
}
break; break;
case REMOTE_DETACH: case REMOTE_DETACH:
this.removeAtLocal(id); this.removeAtLocal(id);
if (this.inited()) addSyncCount(this.getName(), true); if (this.inited())
{
this.addSyncCount(TOTAL, true);
this.addSyncCount(id, true);
}
break; break;
default: default:
this.clearIdentifiedChanges(id); this.clearIdentifiedChanges(id);
@ -688,25 +711,27 @@ public class Coll<E> implements CollInterface<E>
public void init() public void init()
{ {
if (this.inited()) return; if (this.inited()) return;
// TODO: Could this be more efficient by considering it's the first sync? // TODO: Could this be more efficient by considering it's the first sync?
this.syncAll(); this.syncAll();
instances.add(this);
names.add(this.getName()); name2instance.put(this.getName(), this);
} }
@Override @Override
public void deinit() public void deinit()
{ {
if (!this.inited()) return; if (!this.inited()) return;
// TODO: Save outwards only? We may want to avoid loads at this stage... // TODO: Save outwards only? We may want to avoid loads at this stage...
this.syncAll(); this.syncAll();
instances.remove(this);
names.remove(this.getName()); name2instance.remove(this.getName());
} }
@Override @Override
public boolean inited() 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 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 // SYNC LOWLEVEL IO ACTIONS
// -------------------------------------------- // // -------------------------------------------- //