Even better statistics.
This commit is contained in:
parent
1b7a6c45e6
commit
9d01aa974e
40
src/com/massivecraft/mcore/cmd/arg/ARColl.java
Normal file
40
src/com/massivecraft/mcore/cmd/arg/ARColl.java
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
Loading…
Reference in New Issue
Block a user