Database improvements
Adding a modification mixin. Merging Entity and EntityMeta Making the use of the Entity class mandatory. And other few tweaks.
This commit is contained in:
parent
b2bc9ed9ab
commit
fdd530998a
@ -99,9 +99,7 @@ public class MassiveCoreMConf extends Entity<MassiveCoreMConf>
|
|||||||
// MSTORE CONFIGURATON
|
// MSTORE CONFIGURATON
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
public volatile long millisBetweenLocalPoll = 1000;
|
public volatile long millisBetweenLocalPoll = 5_000;
|
||||||
public volatile long millisBetweenLocalPollColl = 100;
|
public volatile long millisBetweenRemotePollWithoutPusher = 5_000;
|
||||||
|
public volatile long millisBetweenRemotePollWithPusher = 30_000;
|
||||||
public volatile long millisBetweenRemotePoll = 1000;
|
|
||||||
public volatile long millisBetweenRemotePollColl = 100;
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import com.massivecraft.massivecore.command.requirement.RequirementHasPerm;
|
|||||||
import com.massivecraft.massivecore.command.type.primitive.TypeString;
|
import com.massivecraft.massivecore.command.type.primitive.TypeString;
|
||||||
import com.massivecraft.massivecore.store.Coll;
|
import com.massivecraft.massivecore.store.Coll;
|
||||||
import com.massivecraft.massivecore.store.Db;
|
import com.massivecraft.massivecore.store.Db;
|
||||||
|
import com.massivecraft.massivecore.store.Entity;
|
||||||
import com.massivecraft.massivecore.store.MStore;
|
import com.massivecraft.massivecore.store.MStore;
|
||||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ public class CmdMassiveCoreStoreCopydb extends MassiveCommand
|
|||||||
// OVERRIDE
|
// OVERRIDE
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
@Override
|
@Override
|
||||||
public void perform() throws MassiveException
|
public void perform() throws MassiveException
|
||||||
{
|
{
|
||||||
@ -71,8 +73,8 @@ public class CmdMassiveCoreStoreCopydb extends MassiveCommand
|
|||||||
for (String collname : fromDb.getCollnames())
|
for (String collname : fromDb.getCollnames())
|
||||||
{
|
{
|
||||||
countCollCurrent++;
|
countCollCurrent++;
|
||||||
final Coll<?> fromColl = new Coll<Object>(collname, Object.class, fromDb, MassiveCore.get());
|
final Coll fromColl = new Coll(collname, Entity.class, fromDb, MassiveCore.get());
|
||||||
final Coll<?> toColl = new Coll<Object>(collname, Object.class, toDb, MassiveCore.get());
|
final Coll toColl = new Coll(collname, Entity.class, toDb, MassiveCore.get());
|
||||||
|
|
||||||
Collection<String> ids = fromDb.getIds(fromColl);
|
Collection<String> ids = fromDb.getIds(fromColl);
|
||||||
msg("<i>Now copying collection <h>%d/%d %s <i>with <h>%d <i>documents.", countCollCurrent, countCollTotal, collname, ids.size());
|
msg("<i>Now copying collection <h>%d/%d %s <i>with <h>%d <i>documents.", countCollCurrent, countCollTotal, collname, ids.size());
|
||||||
|
@ -216,7 +216,6 @@ public abstract class TypeAbstractChoice<T> extends TypeAbstract<T> implements A
|
|||||||
// MATCHES
|
// MATCHES
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public List<T> getMatches(Map<String, T> options, String arg, boolean levenshtein)
|
public List<T> getMatches(Map<String, T> options, String arg, boolean levenshtein)
|
||||||
{
|
{
|
||||||
// Create
|
// Create
|
||||||
|
@ -16,6 +16,8 @@ import com.massivecraft.massivecore.Predicate;
|
|||||||
import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave;
|
import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave;
|
||||||
import com.massivecraft.massivecore.mson.Mson;
|
import com.massivecraft.massivecore.mson.Mson;
|
||||||
import com.massivecraft.massivecore.ps.PS;
|
import com.massivecraft.massivecore.ps.PS;
|
||||||
|
import com.massivecraft.massivecore.store.Coll;
|
||||||
|
import com.massivecraft.massivecore.store.Entity;
|
||||||
import com.massivecraft.massivecore.teleport.Destination;
|
import com.massivecraft.massivecore.teleport.Destination;
|
||||||
|
|
||||||
public class Mixin
|
public class Mixin
|
||||||
@ -72,6 +74,10 @@ public class Mixin
|
|||||||
public static CommandMixin getCommandMixin() { return commandMixin; }
|
public static CommandMixin getCommandMixin() { return commandMixin; }
|
||||||
public static void setCommandMixin(CommandMixin val) { commandMixin = val; }
|
public static void setCommandMixin(CommandMixin val) { commandMixin = val; }
|
||||||
|
|
||||||
|
private static ModificationMixin modificationMixin = ModificationMixinDefault.get();
|
||||||
|
public static ModificationMixin getModificationMixin() { return modificationMixin; }
|
||||||
|
public static void setModificationMixin(ModificationMixin val) { modificationMixin = val; }
|
||||||
|
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
// STATIC EXPOSE: WORLD
|
// STATIC EXPOSE: WORLD
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
@ -398,4 +404,18 @@ public class Mixin
|
|||||||
return getCommandMixin().dispatchCommand(presentObject, senderObject, commandLine);
|
return getCommandMixin().dispatchCommand(presentObject, senderObject, commandLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------- //
|
||||||
|
// STATIC EXPOSE: MODIFCATION
|
||||||
|
// -------------------------------------------- //
|
||||||
|
|
||||||
|
public static void syncModification(Entity<?> entity)
|
||||||
|
{
|
||||||
|
getModificationMixin().syncModification(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void syncModification(Coll<?> coll, String id)
|
||||||
|
{
|
||||||
|
getModificationMixin().syncModification(coll, id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.massivecraft.massivecore.mixin;
|
||||||
|
|
||||||
|
import com.massivecraft.massivecore.store.Coll;
|
||||||
|
import com.massivecraft.massivecore.store.Entity;
|
||||||
|
|
||||||
|
public interface ModificationMixin
|
||||||
|
{
|
||||||
|
public void syncModification(Entity<?> entity);
|
||||||
|
public void syncModification(Coll<?> coll, String id);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.massivecraft.massivecore.mixin;
|
||||||
|
|
||||||
|
import com.massivecraft.massivecore.store.Entity;
|
||||||
|
|
||||||
|
public abstract class ModificationMixinAbstract implements ModificationMixin
|
||||||
|
{
|
||||||
|
public void syncModification(Entity<?> entity)
|
||||||
|
{
|
||||||
|
this.syncModification(entity.getColl(), entity.getId());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.massivecraft.massivecore.mixin;
|
||||||
|
|
||||||
|
import com.massivecraft.massivecore.store.Coll;
|
||||||
|
|
||||||
|
public class ModificationMixinDefault extends ModificationMixinAbstract
|
||||||
|
{
|
||||||
|
// -------------------------------------------- //
|
||||||
|
// INSTANCE & CONSTRUCT
|
||||||
|
// -------------------------------------------- //
|
||||||
|
|
||||||
|
private static ModificationMixinDefault i = new ModificationMixinDefault();
|
||||||
|
public static ModificationMixinDefault get() { return i; }
|
||||||
|
|
||||||
|
// -------------------------------------------- //
|
||||||
|
// OVERRIDE
|
||||||
|
// -------------------------------------------- //
|
||||||
|
@Override
|
||||||
|
public void syncModification(Coll<?> coll, String id)
|
||||||
|
{
|
||||||
|
// Nothing to do here
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,13 +17,12 @@ import org.bukkit.plugin.Plugin;
|
|||||||
import com.massivecraft.massivecore.MassiveCore;
|
import com.massivecraft.massivecore.MassiveCore;
|
||||||
import com.massivecraft.massivecore.MassivePlugin;
|
import com.massivecraft.massivecore.MassivePlugin;
|
||||||
import com.massivecraft.massivecore.NaturalOrderComparator;
|
import com.massivecraft.massivecore.NaturalOrderComparator;
|
||||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
import com.massivecraft.massivecore.mixin.Mixin;
|
||||||
import com.massivecraft.massivecore.util.Txt;
|
import com.massivecraft.massivecore.util.Txt;
|
||||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
|
||||||
|
|
||||||
public class Coll<E> extends CollAbstract<E>
|
public class Coll<E extends Entity<E>> extends CollAbstract<E>
|
||||||
{
|
{
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
// GLOBAL REGISTRY
|
// GLOBAL REGISTRY
|
||||||
@ -189,9 +188,9 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
@Override public boolean isLowercasing() { return this.lowercasing; }
|
@Override public boolean isLowercasing() { return this.lowercasing; }
|
||||||
@Override public void setLowercasing(boolean lowercasing) { this.lowercasing = lowercasing; }
|
@Override public void setLowercasing(boolean lowercasing) { this.lowercasing = lowercasing; }
|
||||||
|
|
||||||
protected int localPollFrequency = 5;
|
protected int localPollInfrequency = MStore.DEFAULT_LOCAL_POLL_INFREQUENCY;
|
||||||
@Override public int getLocalPollFrequency() { return this.localPollFrequency; }
|
@Override public int getLocalPollInfrequency() { return this.localPollInfrequency; }
|
||||||
@Override public void setLocalPollFrequency(int frequency) { this.localPollFrequency = frequency; }
|
@Override public void setLocalPollInfrequency(int infrequence) { this.localPollInfrequency = infrequence; }
|
||||||
|
|
||||||
// We often try to call Entity#changed to inform that an entity has been changed locally.
|
// We often try to call Entity#changed to inform that an entity has been changed locally.
|
||||||
// And on some Colls we expect it to always be done.
|
// And on some Colls we expect it to always be done.
|
||||||
@ -205,14 +204,7 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// If it is default it should not be saved.
|
// If it is default it should not be saved.
|
||||||
@Override public boolean isDefault(E entity)
|
@Override public boolean isDefault(E entity)
|
||||||
{
|
{
|
||||||
if (entity instanceof Entity)
|
return entity.isDefault();
|
||||||
{
|
|
||||||
return ((Entity<?>)entity).isDefault();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
@ -220,34 +212,14 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public void copy(Object ofrom, Object oto)
|
public void copy(E ofrom, E oto)
|
||||||
{
|
{
|
||||||
if (ofrom == null) throw new NullPointerException("ofrom");
|
if (ofrom == null) throw new NullPointerException("ofrom");
|
||||||
if (oto == null) throw new NullPointerException("oto");
|
if (oto == null) throw new NullPointerException("oto");
|
||||||
|
|
||||||
if (ofrom instanceof Entity)
|
Entity efrom = (Entity)ofrom;
|
||||||
{
|
Entity eto = (Entity)oto;
|
||||||
Entity efrom = (Entity)ofrom;
|
eto.load(efrom);
|
||||||
Entity eto = (Entity)oto;
|
|
||||||
|
|
||||||
eto.load(efrom);
|
|
||||||
}
|
|
||||||
else if (ofrom instanceof JsonObject)
|
|
||||||
{
|
|
||||||
JsonObject jfrom = (JsonObject)ofrom;
|
|
||||||
JsonObject jto = (JsonObject)oto;
|
|
||||||
// Clear To
|
|
||||||
jto.entrySet().clear();
|
|
||||||
// Copy
|
|
||||||
for (Entry<String, JsonElement> entry : jfrom.entrySet())
|
|
||||||
{
|
|
||||||
jto.add(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Accessor.get(this.getEntityClass()).copy(ofrom, oto);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This simply creates and returns a new instance
|
// This simply creates and returns a new instance
|
||||||
@ -291,7 +263,6 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
return this.attach(entity, oid, true);
|
return this.attach(entity, oid, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
protected synchronized String attach(E entity, Object oid, boolean noteModification)
|
protected synchronized String attach(E entity, Object oid, boolean noteModification)
|
||||||
{
|
{
|
||||||
// Check entity
|
// Check entity
|
||||||
@ -316,26 +287,19 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
this.preAttach(entity, id);
|
this.preAttach(entity, id);
|
||||||
|
|
||||||
// Add entity reference info
|
// Add entity reference info
|
||||||
if (entity instanceof Entity)
|
entity.setColl(this);
|
||||||
{
|
entity.setId(id);
|
||||||
((Entity)entity).setColl(this);
|
|
||||||
((Entity)entity).setId(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach
|
// Attach
|
||||||
this.id2entity.put(id, entity);
|
this.id2entity.put(id, entity);
|
||||||
this.entity2id.put(entity, id);
|
this.entity2id.put(entity, id);
|
||||||
|
|
||||||
EntityMeta meta = new EntityMeta();
|
|
||||||
|
|
||||||
// Identify Modification
|
// Identify Modification
|
||||||
if (noteModification)
|
if (noteModification)
|
||||||
{
|
{
|
||||||
this.identifiedModifications.put(id, Modification.LOCAL_ATTACH);
|
this.identifiedModifications.put(id, Modification.LOCAL_ATTACH);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.metaData.put(id, meta);
|
|
||||||
|
|
||||||
// POST
|
// POST
|
||||||
this.postAttach(entity, id);
|
this.postAttach(entity, id);
|
||||||
|
|
||||||
@ -392,37 +356,25 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
@Override
|
@Override
|
||||||
public void preAttach(E entity, String id)
|
public void preAttach(E entity, String id)
|
||||||
{
|
{
|
||||||
if (entity instanceof Entity)
|
entity.preAttach(id);
|
||||||
{
|
|
||||||
((Entity<?>)entity).preAttach(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postAttach(E entity, String id)
|
public void postAttach(E entity, String id)
|
||||||
{
|
{
|
||||||
if (entity instanceof Entity)
|
entity.postAttach(id);
|
||||||
{
|
|
||||||
((Entity<?>)entity).postAttach(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preDetach(E entity, String id)
|
public void preDetach(E entity, String id)
|
||||||
{
|
{
|
||||||
if (entity instanceof Entity)
|
entity.preDetach(id);
|
||||||
{
|
|
||||||
((Entity<?>)entity).preDetach(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postDetach(E entity, String id)
|
public void postDetach(E entity, String id)
|
||||||
{
|
{
|
||||||
if (entity instanceof Entity)
|
entity.postDetach(id);
|
||||||
{
|
|
||||||
((Entity<?>)entity).postDetach(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
@ -450,28 +402,6 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// SYNCLOG
|
// SYNCLOG
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
// The strings are the ids.
|
|
||||||
protected Map<String, EntityMeta> metaData;
|
|
||||||
|
|
||||||
protected EntityMeta getMetaFixed(String id)
|
|
||||||
{
|
|
||||||
if (id == null) throw new NullPointerException("id");
|
|
||||||
EntityMeta meta = this.metaData.get(id);
|
|
||||||
if (meta == null)
|
|
||||||
{
|
|
||||||
meta = new EntityMeta();
|
|
||||||
this.metaData.put(id, meta);
|
|
||||||
}
|
|
||||||
return meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected EntityMeta setMetaFixed(String id, EntityMeta meta)
|
|
||||||
{
|
|
||||||
if (id == null) throw new NullPointerException("id");
|
|
||||||
if (meta == null) return this.metaData.remove(id);
|
|
||||||
else return this.metaData.put(id, meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log database synchronization for display in the "/massivecore mstore stats" command.
|
// Log database synchronization for display in the "/massivecore mstore stats" command.
|
||||||
private Map<String, Long> id2out = new TreeMap<String, Long>();
|
private Map<String, Long> id2out = new TreeMap<String, Long>();
|
||||||
private Map<String, Long> id2in = new TreeMap<String, Long>();
|
private Map<String, Long> id2in = new TreeMap<String, Long>();
|
||||||
@ -502,26 +432,22 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// SYNC LOWLEVEL IO ACTIONS
|
// SYNC LOWLEVEL IO ACTIONS
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized E removeAtLocalFixed(String id)
|
public synchronized E removeAtLocalFixed(String id)
|
||||||
{
|
{
|
||||||
if (id == null) throw new NullPointerException("id");
|
if (id == null) throw new NullPointerException("id");
|
||||||
|
|
||||||
this.removeIdentifiedModificationFixed(id);
|
this.removeIdentifiedModificationFixed(id);
|
||||||
this.setMetaFixed(id, null);
|
|
||||||
|
|
||||||
E entity = this.id2entity.remove(id);
|
E entity = this.id2entity.remove(id);
|
||||||
if (entity == null) return null;
|
if (entity == null) return null;
|
||||||
|
entity.clearSyncLogFields();
|
||||||
|
|
||||||
this.entity2id.remove(entity);
|
this.entity2id.remove(entity);
|
||||||
|
|
||||||
// Remove entity reference info
|
// Remove entity reference info
|
||||||
if (entity instanceof Entity)
|
entity.setColl(null);
|
||||||
{
|
entity.setId(null);
|
||||||
((Entity)entity).setColl(null);
|
|
||||||
((Entity)entity).setId(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
@ -532,9 +458,9 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
if (id == null) throw new NullPointerException("id");
|
if (id == null) throw new NullPointerException("id");
|
||||||
|
|
||||||
this.removeIdentifiedModificationFixed(id);
|
this.removeIdentifiedModificationFixed(id);
|
||||||
this.setMetaFixed(id, null);
|
|
||||||
|
|
||||||
this.getDb().delete(this, id);
|
this.getDb().delete(this, id);
|
||||||
|
Mixin.syncModification(this, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -543,20 +469,18 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
if (id == null) throw new NullPointerException("id");
|
if (id == null) throw new NullPointerException("id");
|
||||||
|
|
||||||
this.removeIdentifiedModificationFixed(id);
|
this.removeIdentifiedModificationFixed(id);
|
||||||
this.setMetaFixed(id, null);
|
|
||||||
|
|
||||||
E entity = this.id2entity.get(id);
|
E entity = this.id2entity.get(id);
|
||||||
if (entity == null) return;
|
if (entity == null) return;
|
||||||
|
entity.clearSyncLogFields();
|
||||||
EntityMeta meta = this.getMetaFixed(id);
|
|
||||||
|
|
||||||
JsonElement raw = this.getGson().toJsonTree(entity, this.getEntityClass());
|
JsonElement raw = this.getGson().toJsonTree(entity, this.getEntityClass());
|
||||||
meta.setLastRaw(raw);
|
entity.setLastRaw(raw);
|
||||||
|
|
||||||
if (this.isDefault(entity))
|
if (this.isDefault(entity))
|
||||||
{
|
{
|
||||||
this.getDb().delete(this, id);
|
this.getDb().delete(this, id);
|
||||||
meta.setDefault(true);
|
entity.setLastDefault(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -564,8 +488,9 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// TODO: This fail should not happen often. We could handle it better though.
|
// TODO: This fail should not happen often. We could handle it better though.
|
||||||
// Perhaps we should log it, or simply try again.
|
// Perhaps we should log it, or simply try again.
|
||||||
if (mtime == 0) return;
|
if (mtime == 0) return;
|
||||||
meta.setMtime(mtime);
|
entity.setLastMtime(mtime);
|
||||||
}
|
}
|
||||||
|
Mixin.syncModification(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -612,11 +537,9 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
this.attach(entity, id, false);
|
this.attach(entity, id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityMeta meta = this.getMetaFixed(id);
|
entity.setLastRaw(raw);
|
||||||
|
entity.setLastMtime(mtime);
|
||||||
meta.setLastRaw(raw);
|
entity.setLastDefault(false);
|
||||||
meta.setMtime(mtime);
|
|
||||||
meta.setDefault(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remoteEntryIsOk(String id, Entry<JsonElement, Long> remoteEntry)
|
public boolean remoteEntryIsOk(String id, Entry<JsonElement, Long> remoteEntry)
|
||||||
@ -667,7 +590,6 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
if (id == null) throw new NullPointerException("id");
|
if (id == null) throw new NullPointerException("id");
|
||||||
// Meta might be non-existing. But then we create it here.
|
// Meta might be non-existing. But then we create it here.
|
||||||
// If it is examined then it will be attached anyways.
|
// If it is examined then it will be attached anyways.
|
||||||
EntityMeta meta = this.getMetaFixed(id);
|
|
||||||
Modification current = this.identifiedModifications.get(id);
|
Modification current = this.identifiedModifications.get(id);
|
||||||
// DEBUG
|
// DEBUG
|
||||||
// if (Bukkit.isPrimaryThread())
|
// if (Bukkit.isPrimaryThread())
|
||||||
@ -692,7 +614,7 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// If we have it both locally and remotely.
|
// If we have it both locally and remotely.
|
||||||
if (existsLocal && existsRemote)
|
if (existsLocal && existsRemote)
|
||||||
{
|
{
|
||||||
long lastMtime = meta.getMtime();
|
long lastMtime = localEntity.getLastMtime();
|
||||||
|
|
||||||
// If mtime is not equal remote takes priority, and we assume it is altered.
|
// If mtime is not equal remote takes priority, and we assume it is altered.
|
||||||
if ( ! remoteMtime.equals(lastMtime)) return Modification.REMOTE_ALTER;
|
if ( ! remoteMtime.equals(lastMtime)) return Modification.REMOTE_ALTER;
|
||||||
@ -704,7 +626,7 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
else if (existsLocal)
|
else if (existsLocal)
|
||||||
{
|
{
|
||||||
// ...and it was default and thus not saved to the db...
|
// ...and it was default and thus not saved to the db...
|
||||||
if (meta.isDefault())
|
if (localEntity.getLastDefault())
|
||||||
{
|
{
|
||||||
// ...and also actually altered.
|
// ...and also actually altered.
|
||||||
// Then it is a local alter.
|
// Then it is a local alter.
|
||||||
@ -756,7 +678,6 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// Because they are performed by calling a method on this coll.
|
// Because they are performed by calling a method on this coll.
|
||||||
// Meta might be non-existing. But then we create it here.
|
// Meta might be non-existing. But then we create it here.
|
||||||
// If it is examined then it will be attached anyways.
|
// If it is examined then it will be attached anyways.
|
||||||
EntityMeta meta = this.getMetaFixed(id);
|
|
||||||
Modification current = this.identifiedModifications.get(id);
|
Modification current = this.identifiedModifications.get(id);
|
||||||
if (current != null && current.hasTopPriority()) return current;
|
if (current != null && current.hasTopPriority()) return current;
|
||||||
|
|
||||||
@ -773,14 +694,12 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// So we don't have this anywhere?
|
// So we don't have this anywhere?
|
||||||
if ( ! existsLocal && ! existsRemote) return Modification.UNKNOWN;
|
if ( ! existsLocal && ! existsRemote) return Modification.UNKNOWN;
|
||||||
|
|
||||||
Long lastMtime = meta.getMtime();
|
|
||||||
|
|
||||||
// If time is different
|
// If time is different
|
||||||
// then it is remotely altered
|
// then it is remotely altered
|
||||||
if (existsLocal && existsRemote && ! lastMtime.equals(remoteMtime)) return Modification.REMOTE_ALTER;
|
if (existsLocal && existsRemote && ! remoteMtime.equals(localEntity.getLastMtime())) return Modification.REMOTE_ALTER;
|
||||||
|
|
||||||
// If it doesn't exist remotely, and it wasn't because it was default. It was detached remotely.
|
// If it doesn't exist remotely, and it wasn't because it was default. It was detached remotely.
|
||||||
if (!existsRemote && ! meta.isDefault()) return Modification.REMOTE_DETACH;
|
if (!existsRemote && existsLocal && ! localEntity.getLastDefault()) return Modification.REMOTE_DETACH;
|
||||||
|
|
||||||
// If it doesn't exist locally, it was attached remotely.
|
// If it doesn't exist locally, it was attached remotely.
|
||||||
if (!existsLocal) return Modification.REMOTE_ATTACH;
|
if (!existsLocal) return Modification.REMOTE_ATTACH;
|
||||||
@ -792,7 +711,7 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
|
|
||||||
protected boolean examineHasLocalAlterFixed(String id, E entity)
|
protected boolean examineHasLocalAlterFixed(String id, E entity)
|
||||||
{
|
{
|
||||||
JsonElement lastRaw = this.getMetaFixed(id).getLastRaw();
|
JsonElement lastRaw = entity.getLastRaw();
|
||||||
JsonElement currentRaw = null;
|
JsonElement currentRaw = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -1026,7 +945,6 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
// CONSTRUCT
|
// CONSTRUCT
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Coll(String name, Class<E> entityClass, Db db, Plugin plugin, boolean creative, boolean lowercasing, boolean sorted)
|
public Coll(String name, Class<E> entityClass, Db db, Plugin plugin, boolean creative, boolean lowercasing, boolean sorted)
|
||||||
{
|
{
|
||||||
// Setup the name and the parsed parts
|
// Setup the name and the parsed parts
|
||||||
@ -1057,7 +975,6 @@ public class Coll<E> extends CollAbstract<E>
|
|||||||
this.entity2id = (Entity.class.isAssignableFrom(entityClass) && sorted) ? new ConcurrentSkipListMap<E, String>((Comparator<? super E>) ComparatorEntityId.get()) : new ConcurrentHashMap<E, String>();
|
this.entity2id = (Entity.class.isAssignableFrom(entityClass) && sorted) ? new ConcurrentSkipListMap<E, String>((Comparator<? super E>) ComparatorEntityId.get()) : new ConcurrentHashMap<E, String>();
|
||||||
|
|
||||||
// ENTITY DATA
|
// ENTITY DATA
|
||||||
this.metaData = new ConcurrentHashMap<String, EntityMeta>();
|
|
||||||
this.identifiedModifications = new ConcurrentHashMap<String, Modification>();
|
this.identifiedModifications = new ConcurrentHashMap<String, Modification>();
|
||||||
|
|
||||||
this.tickTask = new Runnable()
|
this.tickTask = new Runnable()
|
||||||
|
@ -10,7 +10,7 @@ import com.massivecraft.massivecore.util.MUtil;
|
|||||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||||
|
|
||||||
|
|
||||||
public abstract class CollAbstract<E> implements CollInterface<E>
|
public abstract class CollAbstract<E extends Entity<E>> implements CollInterface<E>
|
||||||
{
|
{
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
// WHAT DO WE HANDLE?
|
// WHAT DO WE HANDLE?
|
||||||
|
@ -12,7 +12,7 @@ import com.massivecraft.massivecore.Named;
|
|||||||
import com.massivecraft.massivecore.Predicate;
|
import com.massivecraft.massivecore.Predicate;
|
||||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||||
|
|
||||||
public interface CollInterface<E> extends Named
|
public interface CollInterface<E extends Entity<E>> extends Named
|
||||||
{
|
{
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
// WHAT DO WE HANDLE?
|
// WHAT DO WE HANDLE?
|
||||||
@ -93,8 +93,8 @@ public interface CollInterface<E> extends Named
|
|||||||
public boolean isLowercasing();
|
public boolean isLowercasing();
|
||||||
public void setLowercasing(boolean lowercasing);
|
public void setLowercasing(boolean lowercasing);
|
||||||
|
|
||||||
public int getLocalPollFrequency();
|
public int getLocalPollInfrequency();
|
||||||
public void setLocalPollFrequency(int frequency);
|
public void setLocalPollInfrequency(int frequency);
|
||||||
|
|
||||||
public boolean isWarningOnLocalAlter();
|
public boolean isWarningOnLocalAlter();
|
||||||
public void setWarnOnLocalAlter(boolean warnOnLocalAlter);
|
public void setWarnOnLocalAlter(boolean warnOnLocalAlter);
|
||||||
@ -107,7 +107,7 @@ public interface CollInterface<E> extends Named
|
|||||||
// COPY AND CREATE
|
// COPY AND CREATE
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
public void copy(Object fromo, Object too);
|
public void copy(E fromo, E too);
|
||||||
|
|
||||||
// This simply creates and returns a new instance
|
// This simply creates and returns a new instance
|
||||||
// It does not detach/attach or anything. Just creates a new instance.
|
// It does not detach/attach or anything. Just creates a new instance.
|
||||||
|
@ -9,7 +9,7 @@ import com.massivecraft.massivecore.Aspect;
|
|||||||
import com.massivecraft.massivecore.Multiverse;
|
import com.massivecraft.massivecore.Multiverse;
|
||||||
import com.massivecraft.massivecore.util.MUtil;
|
import com.massivecraft.massivecore.util.MUtil;
|
||||||
|
|
||||||
public abstract class Colls<C extends Coll<E>, E>
|
public abstract class Colls<C extends Coll<E>, E extends Entity<E>>
|
||||||
{
|
{
|
||||||
protected Map<String, C> name2coll = new HashMap<String, C>();
|
protected Map<String, C> name2coll = new HashMap<String, C>();
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package com.massivecraft.massivecore.store;
|
|||||||
import com.massivecraft.massivecore.MassiveCore;
|
import com.massivecraft.massivecore.MassiveCore;
|
||||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
import com.massivecraft.massivecore.store.accessor.Accessor;
|
||||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||||
|
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usage of this class is highly optional. You may persist anything. If you are
|
* Usage of this class is highly optional. You may persist anything. If you are
|
||||||
@ -12,10 +13,10 @@ import com.massivecraft.massivecore.xlib.gson.Gson;
|
|||||||
|
|
||||||
// Self referencing generic.
|
// Self referencing generic.
|
||||||
// http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206
|
// http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206
|
||||||
public abstract class Entity<E extends Entity<E>>
|
public class Entity<E extends Entity<E>>
|
||||||
{
|
{
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
// COLL & ID
|
// FIELDS
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
protected transient Coll<E> coll;
|
protected transient Coll<E> coll;
|
||||||
@ -34,6 +35,25 @@ public abstract class Entity<E extends Entity<E>>
|
|||||||
return coll.getUniverse();
|
return coll.getUniverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private volatile transient JsonElement lastRaw = null;
|
||||||
|
public JsonElement getLastRaw() { return this.lastRaw; }
|
||||||
|
public void setLastRaw(JsonElement lastRaw) { this.lastRaw = lastRaw; }
|
||||||
|
|
||||||
|
private volatile transient long lastMtime = 0;
|
||||||
|
public long getLastMtime() { return this.lastMtime; }
|
||||||
|
public void setLastMtime(long lastMtime) { this.lastMtime = lastMtime; }
|
||||||
|
|
||||||
|
private volatile transient boolean lastDefault = false;
|
||||||
|
public boolean getLastDefault() { return this.lastDefault; }
|
||||||
|
public void setLastDefault(boolean lastDefault) { this.lastDefault = lastDefault; }
|
||||||
|
|
||||||
|
public void clearSyncLogFields()
|
||||||
|
{
|
||||||
|
this.lastRaw = null;
|
||||||
|
this.lastMtime = 0;
|
||||||
|
this.lastDefault = false;
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
// ATTACH AND DETACH
|
// ATTACH AND DETACH
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
package com.massivecraft.massivecore.store;
|
|
||||||
|
|
||||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
|
||||||
|
|
||||||
//TODO: Merge with entity
|
|
||||||
public class EntityMeta
|
|
||||||
{
|
|
||||||
// -------------------------------------------- //
|
|
||||||
// CONSTANTS
|
|
||||||
// -------------------------------------------- //
|
|
||||||
|
|
||||||
public static final JsonElement DEFAULT_LAST_RAW = null;
|
|
||||||
public static final long DEFAULT_MTIME = 0;
|
|
||||||
public static final boolean DEFAULT_DEFAULT = false;
|
|
||||||
|
|
||||||
// -------------------------------------------- //
|
|
||||||
// FIELDS
|
|
||||||
// -------------------------------------------- //
|
|
||||||
|
|
||||||
private volatile JsonElement lastRaw = DEFAULT_LAST_RAW;
|
|
||||||
public JsonElement getLastRaw() { return this.lastRaw; }
|
|
||||||
public void setLastRaw(JsonElement lastRaw) { this.lastRaw = lastRaw; }
|
|
||||||
|
|
||||||
private volatile long mtime = DEFAULT_MTIME;
|
|
||||||
public long getMtime() { return this.mtime; }
|
|
||||||
public void setMtime(long mtime) { this.mtime = mtime; }
|
|
||||||
|
|
||||||
private volatile boolean isDefault = DEFAULT_DEFAULT;
|
|
||||||
public boolean isDefault() { return this.isDefault; }
|
|
||||||
public void setDefault(boolean isDefault) { this.isDefault = isDefault; }
|
|
||||||
|
|
||||||
}
|
|
@ -9,6 +9,8 @@ import java.util.UUID;
|
|||||||
import com.massivecraft.massivecore.ConfServer;
|
import com.massivecraft.massivecore.ConfServer;
|
||||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||||
|
|
||||||
|
// This class also serves the purpose of containing
|
||||||
|
// database related constants.
|
||||||
public class MStore
|
public class MStore
|
||||||
{
|
{
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
@ -16,6 +18,7 @@ public class MStore
|
|||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
public static boolean DEBUG_ENABLED = false;
|
public static boolean DEBUG_ENABLED = false;
|
||||||
|
public static final int DEFAULT_LOCAL_POLL_INFREQUENCY = 10;
|
||||||
|
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
// DRIVER REGISTRY
|
// DRIVER REGISTRY
|
||||||
|
@ -56,14 +56,9 @@ public abstract class ModificationPollerAbstract extends Thread
|
|||||||
|
|
||||||
public void identify() throws InterruptedException
|
public void identify() throws InterruptedException
|
||||||
{
|
{
|
||||||
final long waitEfterColl = this.getMillisBetweenPollColl();
|
|
||||||
for (Coll<?> coll : Coll.getInstances())
|
for (Coll<?> coll : Coll.getInstances())
|
||||||
{
|
{
|
||||||
if (this.poll(coll, this.iterationCount))
|
this.poll(coll, this.iterationCount);
|
||||||
{
|
|
||||||
Thread.sleep(waitEfterColl);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +67,5 @@ public abstract class ModificationPollerAbstract extends Thread
|
|||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
|
||||||
public abstract long getMillisBetweenPoll();
|
public abstract long getMillisBetweenPoll();
|
||||||
public abstract long getMillisBetweenPollColl();
|
|
||||||
public abstract boolean poll(Coll<?> coll, long iterationCount);
|
public abstract boolean poll(Coll<?> coll, long iterationCount);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@ package com.massivecraft.massivecore.store;
|
|||||||
|
|
||||||
import com.massivecraft.massivecore.MassiveCoreMConf;
|
import com.massivecraft.massivecore.MassiveCoreMConf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class polls for local changes in all colls.
|
||||||
|
*/
|
||||||
public class ModificationPollerLocal extends ModificationPollerAbstract
|
public class ModificationPollerLocal extends ModificationPollerAbstract
|
||||||
{
|
{
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
@ -22,19 +25,15 @@ public class ModificationPollerLocal extends ModificationPollerAbstract
|
|||||||
@Override
|
@Override
|
||||||
public long getMillisBetweenPoll()
|
public long getMillisBetweenPoll()
|
||||||
{
|
{
|
||||||
return MassiveCoreMConf.get().millisBetweenLocalPoll;
|
// The user specifies how often a default coll should be polled.
|
||||||
}
|
// Some colls might be polled more or less frequently.
|
||||||
|
return MassiveCoreMConf.get().millisBetweenLocalPoll / MStore.DEFAULT_LOCAL_POLL_INFREQUENCY;
|
||||||
@Override
|
|
||||||
public long getMillisBetweenPollColl()
|
|
||||||
{
|
|
||||||
return MassiveCoreMConf.get().millisBetweenLocalPollColl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean poll(Coll<?> coll, long iterationCount)
|
public boolean poll(Coll<?> coll, long iterationCount)
|
||||||
{
|
{
|
||||||
if (iterationCount % coll.getLocalPollFrequency() == 0)
|
if (iterationCount % coll.getLocalPollInfrequency() == 0)
|
||||||
{
|
{
|
||||||
coll.identifyLocalModifications(false);
|
coll.identifyLocalModifications(false);
|
||||||
return true;
|
return true;
|
||||||
|
@ -2,6 +2,9 @@ package com.massivecraft.massivecore.store;
|
|||||||
|
|
||||||
import com.massivecraft.massivecore.MassiveCoreMConf;
|
import com.massivecraft.massivecore.MassiveCoreMConf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class polls for remote changes in colls.
|
||||||
|
*/
|
||||||
public class ModificationPollerRemote extends ModificationPollerAbstract
|
public class ModificationPollerRemote extends ModificationPollerAbstract
|
||||||
{
|
{
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
@ -23,13 +26,16 @@ public class ModificationPollerRemote extends ModificationPollerAbstract
|
|||||||
@Override
|
@Override
|
||||||
public long getMillisBetweenPoll()
|
public long getMillisBetweenPoll()
|
||||||
{
|
{
|
||||||
return MassiveCoreMConf.get().millisBetweenRemotePoll;
|
// We will use the default DB for this check
|
||||||
}
|
if (MStore.getDb().supportsPusher())
|
||||||
|
{
|
||||||
|
return MassiveCoreMConf.get().millisBetweenRemotePollWithPusher;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return MassiveCoreMConf.get().millisBetweenRemotePollWithoutPusher;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMillisBetweenPollColl()
|
|
||||||
{
|
|
||||||
return MassiveCoreMConf.get().millisBetweenRemotePollColl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,6 +21,10 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.massivecraft.massivecore.MassiveCore;
|
import com.massivecraft.massivecore.MassiveCore;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This pusher looks for changes in a flatfile database system.
|
||||||
|
* Hopefully it is quicker than the poller.
|
||||||
|
*/
|
||||||
public class PusherCollFlatfile extends Thread implements PusherColl
|
public class PusherCollFlatfile extends Thread implements PusherColl
|
||||||
{
|
{
|
||||||
// -------------------------------------------- //
|
// -------------------------------------------- //
|
||||||
|
Loading…
Reference in New Issue
Block a user