Make lastRaw storage optional

This commit is contained in:
Magnus Ulf Jørgensen 2018-02-18 18:06:53 +01:00
parent c9236895a4
commit 17526c3f5f
12 changed files with 171 additions and 51 deletions

View File

@ -19,6 +19,8 @@ public class ConfServer extends SimpleConfig
// FIELDS // FIELDS
// -------------------------------------------- // // -------------------------------------------- //
public static boolean localPollingEnabled = true;
public static String serverid = UUID.randomUUID().toString(); public static String serverid = UUID.randomUUID().toString();
public static String dburi = "default"; public static String dburi = "default";

View File

@ -253,7 +253,7 @@ public class MassiveCore extends MassivePlugin
// Start the examine threads // Start the examine threads
// Start AFTER initializing the MConf, because they rely on the MConf. // Start AFTER initializing the MConf, because they rely on the MConf.
ModificationPollerLocal.get().start(); if (ConfServer.localPollingEnabled) ModificationPollerLocal.get().start();
ModificationPollerRemote.get().start(); ModificationPollerRemote.get().start();
// Delete Files (at once and additionally after all plugins loaded) // Delete Files (at once and additionally after all plugins loaded)

View File

@ -1,5 +1,6 @@
package com.massivecraft.massivecore.store; package com.massivecraft.massivecore.store;
import com.massivecraft.massivecore.ConfServer;
import com.massivecraft.massivecore.MassiveCore; import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.MassiveCoreMConf; import com.massivecraft.massivecore.MassiveCoreMConf;
import com.massivecraft.massivecore.MassivePlugin; import com.massivecraft.massivecore.MassivePlugin;
@ -7,6 +8,7 @@ import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.comparator.ComparatorNaturalOrder; import com.massivecraft.massivecore.comparator.ComparatorNaturalOrder;
import com.massivecraft.massivecore.mixin.MixinModification; import com.massivecraft.massivecore.mixin.MixinModification;
import com.massivecraft.massivecore.store.migrator.MigratorUtil; import com.massivecraft.massivecore.store.migrator.MigratorUtil;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.util.ReflectionUtil; import com.massivecraft.massivecore.util.ReflectionUtil;
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;
@ -156,6 +158,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
{ {
if (id == null) throw new NullPointerException("id"); if (id == null) throw new NullPointerException("id");
if (modification == null) throw new NullPointerException("modification"); if (modification == null) throw new NullPointerException("modification");
Modification old = this.identifiedModifications.get(id); Modification old = this.identifiedModifications.get(id);
if (old != null && modification.getPriority() <= old.getPriority()) return; if (old != null && modification.getPriority() <= old.getPriority()) return;
this.identifiedModifications.put(id, modification); this.identifiedModifications.put(id, modification);
@ -168,6 +171,13 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
this.identifiedModifications.remove(id); this.identifiedModifications.remove(id);
} }
@Override
public Modification getIdentifiedModificationFixed(String id)
{
if (id == null) throw new NullPointerException("id");
return this.identifiedModifications.get(id);
}
// -------------------------------------------- // // -------------------------------------------- //
// SYNCLOG // SYNCLOG
// -------------------------------------------- // // -------------------------------------------- //
@ -243,7 +253,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
entity.clearSyncLogFields(); entity.clearSyncLogFields();
JsonObject raw = this.getGson().toJsonTree(entity, this.getEntityClass()).getAsJsonObject(); JsonObject raw = this.getGson().toJsonTree(entity, this.getEntityClass()).getAsJsonObject();
entity.setLastRaw(raw); if (ConfServer.localPollingEnabled) entity.setLastRaw(raw);
if (this.isDefault(entity)) if (this.isDefault(entity))
{ {
@ -341,7 +351,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
// this.putIdentifiedModificationFixed(id, Modification.UNKNOWN); // this.putIdentifiedModificationFixed(id, Modification.UNKNOWN);
} }
entity.setLastRaw(raw); if (ConfServer.localPollingEnabled) entity.setLastRaw(raw);
entity.setLastMtime(mtime); entity.setLastMtime(mtime);
entity.setLastDefault(false); entity.setLastDefault(false);
@ -429,11 +439,11 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
// ...and it was modified remotely. // ...and it was modified remotely.
if ( ! remoteMtime.equals(lastMtime)) return Modification.REMOTE_ALTER; if ( ! remoteMtime.equals(lastMtime)) return Modification.REMOTE_ALTER;
} }
// ...and we are looking for local changes // ...and we are looking for local changes ...
if (local) if (local)
{ {
// ...and it was modified locally. // ... and it was modified locally.
if (this.examineHasLocalAlterFixed(id, localEntity)) return Modification.LOCAL_ALTER; if (this.examineHasLocalAlterFixed(id, localEntity)) return Modification.LOCAL_ALTER;
} }
} }
// Otherwise, if we only have it locally... // Otherwise, if we only have it locally...
@ -464,6 +474,16 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
protected boolean examineHasLocalAlterFixed(String id, E entity) protected boolean examineHasLocalAlterFixed(String id, E entity)
{ {
if (!ConfServer.localPollingEnabled)
{
if (MStore.DEBUG_ENABLED)
{
this.getPlugin().log("Attempted examineHasLocalAlterFixed in " + this.getDebugName() + " for " + id);
MUtil.stackTraceDebug("examineHasLocalAlterFixed");
}
return false;
}
JsonObject lastRaw = entity.getLastRaw(); JsonObject lastRaw = entity.getLastRaw();
JsonObject currentRaw = null; JsonObject currentRaw = null;
@ -479,32 +499,18 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
MassiveCore.get().log(Txt.parse("<k>Collection: <v>%s", this.getName())); MassiveCore.get().log(Txt.parse("<k>Collection: <v>%s", this.getName()));
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return !MStore.equal(lastRaw, currentRaw); return !MStore.equal(lastRaw, currentRaw);
} }
@Override @Override
public Modification syncIdFixed(String id, Modification modification, Entry<JsonObject, Long> remoteEntry) public Modification syncIdFixed(String id, final Modification suppliedModification, Entry<JsonObject, Long> remoteEntry)
{ {
if (id == null) throw new NullPointerException("id"); if (id == null) throw new NullPointerException("id");
if (modification == null || modification.isUnknown())
{
Long remoteMtime = null;
if (remoteEntry != null) remoteMtime = remoteEntry.getValue();
Modification actualModification = this.examineIdFixed(id, remoteMtime, true, true);
if (MassiveCoreMConf.get().warnOnLocalAlter && modification == Modification.UNKNOWN_LOG && actualModification.isModified())
{
E entity = this.idToEntity.get(id);
if (entity != null)
{
this.logModification(entity, actualModification);
}
}
modification = actualModification;
}
if (MStore.DEBUG_ENABLED) System.out.println(this.getDebugName() + " syncronising " + modification + " on " + id);
Modification modification = getActualModification(id, suppliedModification, remoteEntry);
if (MStore.DEBUG_ENABLED) this.getPlugin().log((this.getDebugName() + " syncronising " + modification + " (" + suppliedModification + ") on " + id));
// DEBUG // DEBUG
// MassiveCore.get().log(Txt.parse("<a>syncId <k>Coll: <v>%s <k>Entity: <v>%s <k>Modification: <v>%s", this.getName(), id, modification)); // MassiveCore.get().log(Txt.parse("<a>syncId <k>Coll: <v>%s <k>Entity: <v>%s <k>Modification: <v>%s", this.getName(), id, modification));
@ -553,10 +559,66 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
return modification; return modification;
} }
private Modification getActualModification(String id, Modification modification, Entry<JsonObject, Long> remoteEntry)
{
if (id == null) throw new NullPointerException("id");
if (modification != null && !modification.isUnknown())
{
return modification;
}
Long remoteMtime = null;
if (remoteEntry != null) remoteMtime = remoteEntry.getValue();
// We look only remotely for changes, because local ones should be caught by .changed()
// or by the poller. This way we are certain, that all local changes where .changed() is not called
// they are found by the poller and then reported appropriately.
Modification actualModification = this.examineIdFixed(id, remoteMtime, false, true);
if (actualModification == Modification.NONE && (modification == Modification.UNKNOWN_CHANGED || modification == Modification.UNKNOWN_LOG))
{
actualModification = Modification.LOCAL_ALTER;
checkActuallyModifiedFixed(id);
}
if (MassiveCoreMConf.get().warnOnLocalAlter && modification == Modification.UNKNOWN_LOG && actualModification.isModified())
{
E entity = this.idToEntity.get(id);
if (entity != null)
{
this.logModification(entity, actualModification);
}
}
return actualModification;
}
private void checkActuallyModifiedFixed(String id)
{
if (!ConfServer.localPollingEnabled || !MassiveCoreMConf.get().warnOnLocalAlter) return;
E entity = this.getFixed(id);
boolean modified = this.examineHasLocalAlterFixed(id, entity);
if (modified) return;
List<String> messages = new MassiveList<>();
messages.add(Txt.parse("<pink>%s", this.getDebugName()));
messages.add(Txt.parse("<aqua>%s", entity.getId()));
String change = Txt.implode(messages, Txt.parse("<silver> | "));
String message = Txt.parse("<b>[No Modification] %s", change);
this.getPlugin().log(message);
}
protected void logModification(E entity, Modification modification) protected void logModification(E entity, Modification modification)
{ {
JsonObject lastRaw = entity.getLastRaw(); JsonObject lastRaw = entity.getLastRaw();
if (!ConfServer.localPollingEnabled)
{
if (MStore.DEBUG_ENABLED) this.getPlugin().log("Attempted logModification in " + this.getDebugName() + " for " + entity.getId());
return;
}
if (lastRaw == null) if (lastRaw == null)
{ {
List<String> messages = new MassiveList<>(); List<String> messages = new MassiveList<>();
@ -603,7 +665,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
String change = Txt.implode(changes, Txt.parse("<silver> | ")); String change = Txt.implode(changes, Txt.parse("<silver> | "));
String message = Txt.parse("<b>[Unreported Modification] %s", change); String message = Txt.parse("<b>[Unreported Modification] %s", change);
MassiveCore.get().log(message); this.getPlugin().log(message);
} }
@Override @Override
@ -694,7 +756,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
{ {
if (modification.isModified()) if (modification.isModified())
{ {
if (MStore.DEBUG_ENABLED) System.out.println(this.getDebugName() + " identified " + modification + " on " + id); if (MStore.DEBUG_ENABLED) this.getPlugin().log(this.getDebugName() + " identified " + modification + " on " + id);
if (veto != null && ! modification.isSafe()) modification = veto; if (veto != null && ! modification.isSafe()) modification = veto;
this.putIdentifiedModificationFixed(id, modification); this.putIdentifiedModificationFixed(id, modification);
} }
@ -714,7 +776,7 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
@Override @Override
public void syncAll() public void syncAll()
{ {
this.identifyModifications(null); this.identifyRemoteModifications(null);
this.syncIdentified(); this.syncIdentified();
} }
@ -891,8 +953,10 @@ public class Coll<E extends Entity<E>> extends CollAbstract<E>
this.getPusher().deinit(); this.getPusher().deinit();
} }
// TODO: Save outwards only? We may want to avoid loads at this stage... // syncIdentified is probably good enough. We need not load, and when
this.syncAll(); // lastRaw is not present we can't identify local modifications anyway.
//this.syncAll();
this.syncIdentified();
name2instance.remove(this.getName()); name2instance.remove(this.getName());
} }

View File

@ -99,7 +99,7 @@ public abstract class CollAbstract<E extends Entity<E>> extends EntityContainerA
public Modification syncIdFixed(String id) public Modification syncIdFixed(String id)
{ {
if (id == null) throw new NullPointerException("id"); if (id == null) throw new NullPointerException("id");
return this.syncIdFixed(id, null); return this.syncIdFixed(id, this.getIdentifiedModificationFixed(id));
} }
@Override @Override
@ -109,4 +109,11 @@ public abstract class CollAbstract<E extends Entity<E>> extends EntityContainerA
return this.syncIdFixed(id, modification, null); return this.syncIdFixed(id, modification, null);
} }
@Override
public Modification getIdentifiedModification(Object oid)
{
if (oid == null) throw new NullPointerException("oid");
return this.getIdentifiedModificationFixed(this.fixIdOrThrow(oid));
}
} }

View File

@ -98,6 +98,9 @@ public interface CollInterface<E extends Entity<E>> extends Named, Active, Ident
void identifyRemoteModifications(Modification veto); void identifyRemoteModifications(Modification veto);
void identifyRemoteModificationFixed(String id, Long remoteMtime, Modification veto); void identifyRemoteModificationFixed(String id, Long remoteMtime, Modification veto);
Modification getIdentifiedModification(Object oid);
Modification getIdentifiedModificationFixed(String id);
// Init // Init
void initLoadAllFromRemote(); void initLoadAllFromRemote();

View File

@ -3,6 +3,7 @@ package com.massivecraft.massivecore.store;
import com.massivecraft.massivecore.Identified; import com.massivecraft.massivecore.Identified;
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.util.MUtil;
import com.massivecraft.massivecore.xlib.gson.Gson; import com.massivecraft.massivecore.xlib.gson.Gson;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@ -96,7 +97,7 @@ public class EntityInternal<E extends EntityInternal<E>> implements Identified
//System.out.println(this.getColl().getName() + ": " +this.getId() + " was modified locally"); //System.out.println(this.getColl().getName() + ": " +this.getId() + " was modified locally");
this.getContainer().putIdentifiedModificationFixed(this.getId(), Modification.UNKNOWN); this.getContainer().putIdentifiedModificationFixed(this.getId(), Modification.UNKNOWN_CHANGED);
} }
// -------------------------------------------- // // -------------------------------------------- //
@ -132,6 +133,19 @@ public class EntityInternal<E extends EntityInternal<E>> implements Identified
return Objects.equals(value, standard) ? null : value; return Objects.equals(value, standard) ? null : value;
} }
public <T> T convertSet(T value, T current, T standard)
{
current = this.convertGet(current, standard);
this.changed(value, current);
return Objects.equals(value, standard) ? null : value;
}
public void changed(Object o1, Object o2)
{
if (MUtil.equalsishObject(o1, o2)) return;
changed();
}
// BOOLEAN // BOOLEAN
public boolean convertGet(Boolean value) public boolean convertGet(Boolean value)
{ {

View File

@ -1,5 +1,6 @@
package com.massivecraft.massivecore.store; package com.massivecraft.massivecore.store;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.xlib.gson.JsonArray; import com.massivecraft.massivecore.xlib.gson.JsonArray;
import com.massivecraft.massivecore.xlib.gson.JsonElement; import com.massivecraft.massivecore.xlib.gson.JsonElement;
import com.massivecraft.massivecore.xlib.gson.JsonNull; import com.massivecraft.massivecore.xlib.gson.JsonNull;
@ -139,7 +140,7 @@ public class GsonEqualsChecker
if (floating) if (floating)
{ {
// Our epsilon is pretty big in order to see float and double as the same. // Our epsilon is pretty big in order to see float and double as the same.
return Math.abs(oneNumber.doubleValue() - twoNumber.doubleValue()) < 0.0001D; return MUtil.equalsishNumber(oneNumber, twoNumber);
} }
else else
{ {

View File

@ -7,22 +7,26 @@ public enum Modification
// ENUM // ENUM
// -------------------------------------------- // // -------------------------------------------- //
LOCAL_ALTER (true, 4), LOCAL_ALTER (true, 40),
LOCAL_ATTACH (true, 8), LOCAL_ATTACH (true, 80),
LOCAL_DETACH (true, 9), LOCAL_DETACH (true, 90),
REMOTE_ALTER (true, 5), REMOTE_ALTER (true, 50),
REMOTE_ATTACH (true, 6), REMOTE_ATTACH (true, 60),
REMOTE_DETACH (true, 7), REMOTE_DETACH (true, 70),
NONE (false, 1), NONE (false, 10),
UNKNOWN (false, 3), UNKNOWN (false, 30),
UNKNOWN_LOG(false, 2), UNKNOWN_LOG(false, 20),
UNKNOWN_CHANGED(false, 35),
; ;
// -------------------------------------------- // // -------------------------------------------- //
// CONSTANTS // CONSTANTS
// -------------------------------------------- // // -------------------------------------------- //
public static final int TOP_PRIORITY = 7; // The modifications take priority over all others.
// It is local attach and local detach, because otherwise
// the system would think it was a remote attach or remote detach.
public static final int TOP_PRIORITY = 80;
// -------------------------------------------- // // -------------------------------------------- //
// FIELDS // FIELDS
@ -83,6 +87,6 @@ public enum Modification
public boolean isUnknown() public boolean isUnknown()
{ {
return this == Modification.UNKNOWN || this == Modification.UNKNOWN_LOG; return this == Modification.UNKNOWN || this == Modification.UNKNOWN_LOG || this == Modification.UNKNOWN_CHANGED;
} }
} }

View File

@ -1,5 +1,7 @@
package com.massivecraft.massivecore.store; package com.massivecraft.massivecore.store;
import com.massivecraft.massivecore.ConfServer;
public abstract class ModificationPollerAbstract extends Thread public abstract class ModificationPollerAbstract extends Thread
{ {
// -------------------------------------------- // // -------------------------------------------- //
@ -54,7 +56,7 @@ public abstract class ModificationPollerAbstract extends Thread
this.poll(coll); this.poll(coll);
} }
} }
// -------------------------------------------- // // -------------------------------------------- //
// ABSTRACT // ABSTRACT
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -1,5 +1,6 @@
package com.massivecraft.massivecore.store; package com.massivecraft.massivecore.store;
import com.massivecraft.massivecore.ConfServer;
import com.massivecraft.massivecore.MassiveCoreMConf; import com.massivecraft.massivecore.MassiveCoreMConf;
/* /*
@ -32,6 +33,6 @@ public class ModificationPollerLocal extends ModificationPollerAbstract
public void poll(Coll<?> coll) public void poll(Coll<?> coll)
{ {
coll.identifyLocalModifications(Modification.UNKNOWN_LOG); coll.identifyLocalModifications(Modification.UNKNOWN_LOG);
}
}
} }

View File

@ -126,6 +126,7 @@ public class PusherCollFlatfile extends Thread implements PusherColl
case NONE: case NONE:
case UNKNOWN: case UNKNOWN:
case UNKNOWN_LOG: case UNKNOWN_LOG:
case UNKNOWN_CHANGED:
return; return;
// It was modified remotely. // It was modified remotely.

View File

@ -931,7 +931,7 @@ public class MUtil
if ( ! isFinite(factor)) throw new IllegalStateException("not finite factor: " + factor); if ( ! isFinite(factor)) throw new IllegalStateException("not finite factor: " + factor);
// No Change? // No Change?
if (equalsish(factor, 1)) return; if (equalsishNumber(factor, 1)) return;
for (DamageModifier modifier : DamageModifier.values()) for (DamageModifier modifier : DamageModifier.values())
{ {
@ -1766,6 +1766,8 @@ public class MUtil
return object1.equals(object2); return object1.equals(object2);
} }
public static boolean equals(Object... objects) public static boolean equals(Object... objects)
{ {
@ -1791,14 +1793,33 @@ public class MUtil
// -------------------------------------------- // // -------------------------------------------- //
public static final double EQUALSISH_EPSILON = 0.0001; public static final double EQUALSISH_EPSILON = 0.0001;
public static boolean equalsish(Number number1, Number number2) public static boolean equalsishObject(Object o1, Object o2)
{
if (o1 instanceof Number && o2 instanceof Number)
{
return equalsishNumber((Number) o1, (Number) o2);
}
return equals(o1, o2);
}
public static boolean equalsishNumber(Number number1, Number number2)
{ {
if (number1 == null) return number2 == null; if (number1 == null) return number2 == null;
if (number2 == null) return false; if (number2 == null) return false;
return Math.abs(number1.doubleValue() - number2.doubleValue()) < EQUALSISH_EPSILON; return Math.abs(number1.doubleValue() - number2.doubleValue()) < EQUALSISH_EPSILON;
} }
/**
* @deprecated use equalsishNumber
*/
@Deprecated
public static boolean equalsish(Number number1, Number number2)
{
return equalsishNumber(number1, number2);
}
// -------------------------------------------- // // -------------------------------------------- //
// SORTING // SORTING