From e16333b8220f71332f99fab8be75d8b9715814de Mon Sep 17 00:00:00 2001 From: Olof Larsson Date: Thu, 5 Mar 2015 16:11:50 +0100 Subject: [PATCH] MassiveStore improvements --- .../massivecore/MassiveCoreEngineMain.java | 114 +++++++- .../CmdMassiveCoreStoreCopydb.java | 12 +- .../CmdMassiveCoreStoreListcolls.java | 4 +- .../massivecore/CmdMassiveCoreStoreStats.java | 4 +- .../massivecraft/massivecore/store/Coll.java | 265 +++++++++--------- .../massivecore/store/CollInterface.java | 20 +- .../massivecraft/massivecore/store/Db.java | 40 ++- .../massivecore/store/DbAbstract.java | 70 ++++- .../massivecore/store/DbFlatfile.java | 33 +-- .../massivecore/store/DbMongo.java | 21 +- .../massivecore/store/Driver.java | 21 +- .../massivecore/store/DriverAbstract.java | 2 +- .../massivecore/store/DriverFlatfile.java | 71 +++-- .../massivecore/store/DriverMongo.java | 55 ++-- .../massivecore/store/Entity.java | 10 +- .../massivecore/store/ExamineThread.java | 2 +- .../massivecore/store/JsonFileFilter.java | 2 +- .../massivecore/store/MStore.java | 4 +- ...dificationState.java => Modification.java} | 4 +- 19 files changed, 483 insertions(+), 271 deletions(-) rename src/com/massivecraft/massivecore/store/{ModificationState.java => Modification.java} (82%) diff --git a/src/com/massivecraft/massivecore/MassiveCoreEngineMain.java b/src/com/massivecraft/massivecore/MassiveCoreEngineMain.java index 93f9eee6..6484c4f9 100644 --- a/src/com/massivecraft/massivecore/MassiveCoreEngineMain.java +++ b/src/com/massivecraft/massivecore/MassiveCoreEngineMain.java @@ -3,8 +3,10 @@ package com.massivecraft.massivecore; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; @@ -14,6 +16,8 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageByBlockEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result; import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerChatTabCompleteEvent; @@ -34,6 +38,7 @@ import com.massivecraft.massivecore.store.Coll; import com.massivecraft.massivecore.store.SenderColl; import com.massivecraft.massivecore.util.IdUtil; import com.massivecraft.massivecore.util.SmokeUtil; +import com.massivecraft.massivecore.xlib.gson.JsonElement; public class MassiveCoreEngineMain extends EngineAbstract { @@ -320,35 +325,114 @@ public class MassiveCoreEngineMain extends EngineAbstract }); } + // -------------------------------------------- // + // MASSIVE STORE: LOGIN SYNC + // -------------------------------------------- // + // This section handles the automatic sync of a players corresponding massive store entries on login. + // If possible the database IO is made during the AsyncPlayerPreLoginEvent to offloat the main server thread. + + protected Map, Entry>> idToRemoteEntries = new ConcurrentHashMap, Entry>>(); + + // Intended to be ran asynchronously. + public void storeRemoteEntries(String playerId) + { + // Create remote entries ... + Map, Entry> remoteEntries = createRemoteEntries(playerId); + + // ... and store them. + this.idToRemoteEntries.put(playerId, remoteEntries); + } + + // Intended to be ran synchronously. + // It will use remoteEntries from AsyncPlayerPreLoginEvent if possible. + // If no such remoteEntries are available it will create them and thus lock the main server thread a bit. + public Map, Entry> getRemoteEntries(String playerId) + { + // If there are stored remote entries we used those ... + Map, Entry> ret = idToRemoteEntries.remove(playerId); + if (ret != null) return ret; + + // ... otherwise we create brand new ones. + return createRemoteEntries(playerId); + } + + // Used by the two methods above. + public Map, Entry> createRemoteEntries(String playerId) + { + // Create Ret + Map, Entry> ret = new HashMap, Entry>(); + + // Fill Ret + for (final SenderColl coll : Coll.getSenderInstances()) + { + Entry remoteEntry = coll.getDb().load(coll, playerId); + ret.put(coll, remoteEntry); + } + + // Return Ret + return ret; + } + + @EventHandler(priority = EventPriority.MONITOR) + public void massiveStoreLoginSync(AsyncPlayerPreLoginEvent event) + { + // DEBUG + // long before = System.nanoTime(); + + // If the login was allowed ... + if (event.getLoginResult() != Result.ALLOWED) return; + + // ... get player id ... + final String playerId = event.getUniqueId().toString(); + + // ... and store the remote entries. + this.storeRemoteEntries(playerId); + + // DEBUG + // long after = System.nanoTime(); + // long duration = after - before; + // double ms = (double)duration / 1000000D; + // String message = Txt.parse("AsyncPlayerPreLoginEvent for %s took %.2f ms.", event.getName(), ms); + // MassiveCore.get().log(message); + // NOTE: I get values between 5 and 20 ms. + } + + // Can not be cancelled. + @EventHandler(priority = EventPriority.LOWEST) + public void massiveStoreLoginSync(PlayerLoginEvent event) + { + // Get player id ... + final String playerId = event.getPlayer().getUniqueId().toString(); + + // ... get remote entries ... + Map, Entry> remoteEntries = getRemoteEntries(playerId); + + // ... and sync each of them. + for (Entry, Entry> entry : remoteEntries.entrySet()) + { + SenderColl coll = entry.getKey(); + Entry remoteEntry = entry.getValue(); + coll.syncId(playerId, null, remoteEntry); + } + } + // -------------------------------------------- // // SYNC PLAYER ON LOGON AND LEAVE // -------------------------------------------- // - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void syncOnPlayerLogin(PlayerLoginEvent event) - { - //MassiveCore.get().log("LOWEST syncOnPlayerLogin", event.getPlayer().getName()); - this.syncAllForPlayer(event.getPlayer()); - } - @EventHandler(priority = EventPriority.MONITOR) public void syncOnPlayerLeave(EventMassiveCorePlayerLeave event) { - //MassiveCore.get().log("MONITOR syncOnPlayerLeave", event.getPlayer().getName()); + // TODO: This is going to take quite a bit of power :( this.syncAllForPlayer(event.getPlayer()); } public void syncAllForPlayer(Player player) { - // TODO: For now we sync them both! - String playerName = player.getName(); String playerId = player.getUniqueId().toString(); - for (Coll coll : Coll.getInstances()) + for (SenderColl coll : Coll.getSenderInstances()) { - if (!(coll instanceof SenderColl)) continue; - SenderColl pcoll = (SenderColl)coll; - pcoll.syncId(playerName); - pcoll.syncId(playerId); + coll.syncId(playerId); } } diff --git a/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreCopydb.java b/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreCopydb.java index 4eee3aba..0b8e1c4b 100644 --- a/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreCopydb.java +++ b/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreCopydb.java @@ -10,7 +10,6 @@ import com.massivecraft.massivecore.cmd.MassiveCommand; import com.massivecraft.massivecore.cmd.req.ReqHasPerm; import com.massivecraft.massivecore.store.Coll; import com.massivecraft.massivecore.store.Db; -import com.massivecraft.massivecore.store.Driver; import com.massivecraft.massivecore.store.MStore; import com.massivecraft.massivecore.xlib.gson.JsonElement; @@ -58,9 +57,6 @@ public class CmdMassiveCoreStoreCopydb extends MassiveCommand } // Prepare - final Driver fromDriver = fromDb.getDriver(); - final Driver toDriver = toDb.getDriver(); - Set collnames = fromDb.getCollnames(); // Statistics @@ -76,11 +72,11 @@ public class CmdMassiveCoreStoreCopydb extends MassiveCommand final Coll fromColl = new Coll(collname, Object.class, fromDb, MassiveCore.get()); final Coll toColl = new Coll(collname, Object.class, toDb, MassiveCore.get()); - Collection ids = fromDriver.getIds(fromColl); + Collection ids = fromDb.getIds(fromColl); msg("Now copying collection %d/%d %s with %d documents.", countCollCurrent, countCollTotal, collname, ids.size()); // Do a load check to verify we have access to this folder. - if (ids.size() > 0 && fromDriver.load(fromColl, ids.iterator().next()) == null) + if (ids.size() > 0 && fromDb.load(fromColl, ids.iterator().next()) == null) { msg("Skipping %s since could not load data.", collname); continue; @@ -88,8 +84,8 @@ public class CmdMassiveCoreStoreCopydb extends MassiveCommand for (String id : ids) { - Entry data = fromDriver.load(fromColl, id); - toDriver.save(toColl, id, data.getKey()); + Entry data = fromDb.load(fromColl, id); + toDb.save(toColl, id, data.getKey()); } } long after = System.currentTimeMillis(); diff --git a/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreListcolls.java b/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreListcolls.java index bfd042a4..458a5b04 100644 --- a/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreListcolls.java +++ b/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreListcolls.java @@ -54,7 +54,7 @@ public class CmdMassiveCoreStoreListcolls extends MassiveCommand collnames.addAll(db.getCollnames()); // Do it! - msg(Txt.titleize("Collections in "+db.getName())); + msg(Txt.titleize("Collections in "+db.getDbName())); for (String collname : collnames) { String message = Txt.parse("") + collname; @@ -63,7 +63,7 @@ public class CmdMassiveCoreStoreListcolls extends MassiveCommand for (Coll collCandidate : Coll.getInstances()) { - if (!collCandidate.getName().equals(collname)) continue; + if ( ! collCandidate.getName().equals(collname)) continue; if (collCandidate.getDb() != db) continue; coll = collCandidate; break; diff --git a/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreStats.java b/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreStats.java index cd9394da..27ed2dde 100644 --- a/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreStats.java +++ b/src/com/massivecraft/massivecore/cmd/massivecore/CmdMassiveCoreStoreStats.java @@ -72,8 +72,8 @@ public class CmdMassiveCoreStoreStats extends MassiveCommand msg("Entity Count: %d", coll.getIds().size()); msg("Entity Class: %s", coll.getEntityClass().getName()); msg("Plugin: %s", coll.getPlugin().getDescription().getFullName()); - msg("Database: %s", coll.getDb().getName()); - msg("Driver: %s", coll.getDriver().getName()); + msg("Database: %s", coll.getDb().getDbName()); + msg("Driver: %s", coll.getDb().getDriverName()); int limit; diff --git a/src/com/massivecraft/massivecore/store/Coll.java b/src/com/massivecraft/massivecore/store/Coll.java index 3836bbb9..94d687d6 100644 --- a/src/com/massivecraft/massivecore/store/Coll.java +++ b/src/com/massivecraft/massivecore/store/Coll.java @@ -1,5 +1,6 @@ package com.massivecraft.massivecore.store; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -44,6 +45,17 @@ public class Coll implements CollInterface public static Map> getMap() { return umap; } public static Set getNames() { return unames; } public static Collection> getInstances() { return uinstances; } + public static Collection> getSenderInstances() + { + List> ret = new ArrayList>(); + for (Coll coll : getInstances()) + { + if ( ! (coll instanceof SenderColl)) continue; + SenderColl senderColl = (SenderColl)coll; + ret.add(senderColl); + } + return ret; + } // -------------------------------------------- // // WHAT DO WE HANDLE? @@ -81,7 +93,6 @@ public class Coll implements CollInterface protected Db db; @Override public Db getDb() { return this.db; } - @Override public Driver getDriver() { return this.db.getDriver(); } protected Object collDriverObject; @Override public Object getCollDriverObject() { return this.collDriverObject; } @@ -94,8 +105,6 @@ public class Coll implements CollInterface protected Map id2entity; protected Map entity2id; - @Override public Collection getIds() { return Collections.unmodifiableCollection(this.id2entity.keySet()); } - @Override public Map getId2entity() { return Collections.unmodifiableMap(this.id2entity); } @Override public E get(Object oid) @@ -107,18 +116,18 @@ public class Coll implements CollInterface { return this.get(oid, creative, true); } - protected E get(Object oid, boolean creative, boolean noteChange) + protected E get(Object oid, boolean creative, boolean noteModification) { String id = this.fixId(oid); if (id == null) return null; E ret = this.id2entity.get(id); if (ret != null) return ret; if ( ! creative) return null; - return this.create(id, noteChange); + return this.create(id, noteModification); } - @Override public Collection getIdsLoaded() { return Collections.unmodifiableCollection(this.id2entity.keySet()); } - @Override public Collection getIdsRemote() { return this.getDb().getDriver().getIds(this); } + @Override public Collection getIds() { return Collections.unmodifiableCollection(this.id2entity.keySet()); } + @Override public Collection getIdsRemote() { return this.getDb().getIds(this); } @Override public boolean containsId(Object oid) { @@ -270,10 +279,10 @@ public class Coll implements CollInterface return this.create(oid, true); } - public synchronized E create(Object oid, boolean noteChange) + public synchronized E create(Object oid, boolean noteModification) { E entity = this.createNewInstance(); - if (this.attach(entity, oid, noteChange) == null) return null; + if (this.attach(entity, oid, noteModification) == null) return null; return entity; } @@ -294,7 +303,7 @@ public class Coll implements CollInterface } @SuppressWarnings({ "unchecked", "rawtypes" }) - protected synchronized String attach(E entity, Object oid, boolean noteChange) + protected synchronized String attach(E entity, Object oid, boolean noteModification) { // Check entity if (entity == null) return null; @@ -327,11 +336,10 @@ public class Coll implements CollInterface this.id2entity.put(id, entity); this.entity2id.put(entity, id); - // Make note of the change - if (noteChange) + // Identify Modification + if (noteModification) { - this.localAttachIds.add(id); - this.changedIds.add(id); + this.identifiedModifications.put(id, Modification.LOCAL_ATTACH); } // POST @@ -383,9 +391,8 @@ public class Coll implements CollInterface // Remove @ local this.removeAtLocal(id); - // Identify the change - this.localDetachIds.add(id); - this.changedIds.add(id); + // Identify Modification + this.identifiedModifications.put(id, Modification.LOCAL_DETACH); // POST this.postDetach(entity, id); @@ -428,21 +435,16 @@ public class Coll implements CollInterface } // -------------------------------------------- // - // IDENTIFIED CHANGES + // IDENTIFIED MODIFICATIONS // -------------------------------------------- // - protected Set localAttachIds; - protected Set localDetachIds; - protected Set changedIds; + protected Map identifiedModifications; - protected synchronized void clearIdentifiedChanges(Object oid) + protected void removeIdentifiedModification(Object oid) { if (oid == null) throw new NullPointerException("oid"); - String id = this.fixId(oid); - this.localAttachIds.remove(id); - this.localDetachIds.remove(id); - this.changedIds.remove(id); + this.identifiedModifications.remove(id); } // -------------------------------------------- // @@ -463,7 +465,7 @@ public class Coll implements CollInterface this.lastDefault.remove(id); } - // Log database syncronization for display in the "/massivecore mstore stats" command. + // Log database synchronization for display in the "/massivecore mstore stats" command. private Map id2out = new TreeMap(); private Map id2in = new TreeMap(); @@ -494,11 +496,11 @@ public class Coll implements CollInterface @Override public synchronized E removeAtLocal(Object oid) { + // Fix Id if (oid == null) throw new NullPointerException("oid"); - String id = this.fixId(oid); - this.clearIdentifiedChanges(id); + this.removeIdentifiedModification(id); this.clearSynclog(id); E entity = this.id2entity.remove(id); @@ -519,24 +521,24 @@ public class Coll implements CollInterface @Override public synchronized void removeAtRemote(Object oid) { + // Fix Id if (oid == null) throw new NullPointerException("oid"); - String id = this.fixId(oid); - this.clearIdentifiedChanges(id); + this.removeIdentifiedModification(id); this.clearSynclog(id); - this.getDb().getDriver().delete(this, id); + this.getDb().delete(this, id); } @Override public synchronized void saveToRemote(Object oid) { + // Fix Id if (oid == null) throw new NullPointerException("oid"); - String id = this.fixId(oid); - this.clearIdentifiedChanges(id); + this.removeIdentifiedModification(id); this.clearSynclog(id); E entity = this.id2entity.get(id); @@ -547,31 +549,32 @@ public class Coll implements CollInterface if (this.isDefault(entity) && isCustomDataDefault(entity)) { - this.db.getDriver().delete(this, id); + this.getDb().delete(this, id); this.lastDefault.add(id); } else { - Long mtime = this.db.getDriver().save(this, id, raw); - if (mtime == null) return; // This fail should not happen often. We could handle it better though. + long mtime = this.getDb().save(this, id, raw); + if (mtime == 0) return; // This fail should not happen often. We could handle it better though. this.lastMtime.put(id, mtime); } } @SuppressWarnings("unchecked") @Override - public synchronized void loadFromRemote(Object oid, Entry entry, boolean entrySupplied) + public synchronized void loadFromRemote(Object oid, Entry remoteEntry) { + // Fix Id if (oid == null) throw new NullPointerException("oid"); String id = this.fixId(oid); - this.clearIdentifiedChanges(id); + this.removeIdentifiedModification(id); - if ( ! entrySupplied) + if (remoteEntry == null) { try { - entry = this.getDriver().load(this, id); + remoteEntry = this.getDb().load(this, id); } catch (Exception e) { @@ -580,13 +583,20 @@ public class Coll implements CollInterface } } - if (entry == null) + Long mtime = remoteEntry.getValue(); + if (mtime == null) { - logLoadError(id, "MStore driver could not load data entry. The file might not be readable or simply not exist."); + logLoadError(id, "Last modification time (mtime) was null. The file might not be readable or simply not exist."); return; } - JsonElement raw = entry.getKey(); + if (mtime == 0) + { + logLoadError(id, "Last modification time (mtime) was 0. The file might not be readable or simply not exist."); + return; + } + + JsonElement raw = remoteEntry.getKey(); if (raw == null) { logLoadError(id, "Raw data was null. Is the file completely empty?"); @@ -598,13 +608,6 @@ public class Coll implements CollInterface return; } - Long mtime = entry.getValue(); - if (mtime == null) - { - logLoadError(id, "Last modification time (mtime) was null."); - return; - } - // Calculate temp but handle raw cases. E temp = null; if (this.getEntityClass().isAssignableFrom(JsonObject.class)) @@ -651,61 +654,63 @@ public class Coll implements CollInterface // -------------------------------------------- // @Override - public ModificationState examineId(Object oid) + public Modification examineId(Object oid) { + // Fix Id + if (oid == null) throw new NullPointerException("oid"); String id = this.fixId(oid); - return this.examineId(id, null, false); + + return this.examineId(id, null); } @Override - public ModificationState examineId(Object oid, Long remoteMtime) - { - String id = this.fixId(oid); - return this.examineId(id, remoteMtime, true); - } - - protected ModificationState examineId(Object oid, Long remoteMtime, boolean remoteMtimeSupplied) + public Modification examineId(Object oid, Long remoteMtime) { + // Fix Id + if (oid == null) throw new NullPointerException("oid"); String id = this.fixId(oid); - if (this.localDetachIds.contains(id)) return ModificationState.LOCAL_DETACH; - if (this.localAttachIds.contains(id)) return ModificationState.LOCAL_ATTACH; + // Local Attach and Detach has the top priority. + // Otherwise newly attached entities would be removed thinking it was a remote detach. + // Otherwise newly detached entities would be loaded thinking it was a remote attach. + Modification ret = this.identifiedModifications.get(id); + if (ret == Modification.LOCAL_ATTACH || ret == Modification.LOCAL_DETACH) return ret; E localEntity = this.id2entity.get(id); - if ( ! remoteMtimeSupplied) + if (remoteMtime == null) { - remoteMtime = this.getDriver().getMtime(this, id); + remoteMtime = this.getDb().getMtime(this, id); } boolean existsLocal = (localEntity != null); - boolean existsRemote = (remoteMtime != null); + boolean existsRemote = (remoteMtime != 0); - if ( ! existsLocal && ! existsRemote) return ModificationState.UNKNOWN; + if ( ! existsLocal && ! existsRemote) return Modification.UNKNOWN; if (existsLocal && existsRemote) { Long lastMtime = this.lastMtime.get(id); - if (remoteMtime.equals(lastMtime) == false) return ModificationState.REMOTE_ALTER; + if (remoteMtime.equals(lastMtime) == false) return Modification.REMOTE_ALTER; - if (this.examineHasLocalAlter(id, localEntity)) return ModificationState.LOCAL_ALTER; + if (this.examineHasLocalAlter(id, localEntity)) return Modification.LOCAL_ALTER; } else if (existsLocal) { if (this.lastDefault.contains(id)) { - if (this.examineHasLocalAlter(id, localEntity)) return ModificationState.LOCAL_ALTER; + if (this.examineHasLocalAlter(id, localEntity)) return Modification.LOCAL_ALTER; } else { - return ModificationState.REMOTE_DETACH; + return Modification.REMOTE_DETACH; } } else if (existsRemote) { - return ModificationState.REMOTE_ATTACH; + return Modification.REMOTE_ATTACH; } - return ModificationState.NONE; + return Modification.NONE; } protected boolean examineHasLocalAlter(String id, E entity) @@ -730,15 +735,36 @@ public class Coll implements CollInterface } @Override - public ModificationState syncId(Object oid) + public Modification syncId(Object oid) { + return this.syncId(oid, null); + } + + @Override + public Modification syncId(Object oid, Modification modification) + { + return this.syncId(oid, modification, null); + } + + @Override + public Modification syncId(Object oid, Modification modification, Entry remoteEntry) + { + // Fix Id + if (oid == null) throw new NullPointerException("oid"); String id = this.fixId(oid); - ModificationState mstate = this.examineId(id); + if (modification == null || modification == Modification.UNKNOWN) + { + Long remoteMtime = null; + if (remoteEntry != null) remoteMtime = remoteEntry.getValue(); + + modification = this.examineId(id, remoteMtime); + } - //mplugin.log("syncId: It seems", id, "has state", mstate); + // DEBUG + // MassiveCore.get().log(Txt.parse("Coll: %s Entity: %s Modification: %s", this.getName(), id, modification)); - switch (mstate) + switch (modification) { case LOCAL_ALTER: case LOCAL_ATTACH: @@ -759,7 +785,7 @@ public class Coll implements CollInterface break; case REMOTE_ALTER: case REMOTE_ATTACH: - this.loadFromRemote(id, null, false); + this.loadFromRemote(id, remoteEntry); if (this.inited()) { this.addSyncCount(TOTAL, true); @@ -775,47 +801,18 @@ public class Coll implements CollInterface } break; default: - this.clearIdentifiedChanges(id); + this.removeIdentifiedModification(id); break; } - return mstate; + return modification; } @Override - public void syncSuspects() + public void identifyModifications() { - /*if (MassiveCore.get().doderp) - { - if (this.changedIds.size() > 0) - { - System.out.println("Coll " + this.getName() + " had suspects " + Txt.implode(this.changedIds, " ")); - } - }*/ - - for (String id : this.changedIds) - { - this.syncId(id); - } - } - - @Override - public void syncAll() - { - // Find all ids - Set allids = new HashSet(this.id2entity.keySet()); - allids.addAll(this.getDriver().getIds(this)); - for (String id : allids) - { - this.syncId(id); - } - } - - @Override - public void findSuspects() - { - // Get remote id and mtime snapshot - Map id2RemoteMtime = this.getDb().getDriver().getId2mtime(this); + // Get remote id2mtime snapshot + Map id2RemoteMtime = this.getDb().getId2mtime(this); // Compile a list of all ids (both remote and local) Set allids = new HashSet(); @@ -826,27 +823,45 @@ public class Coll implements CollInterface for (String id : allids) { Long remoteMtime = id2RemoteMtime.get(id); - ModificationState state = this.examineId(id, remoteMtime); - //mplugin.log("findSuspects: It seems", id, "has state", state); - if (state.isModified()) + if (remoteMtime == null) remoteMtime = 0L; + + Modification modification = this.examineId(id, remoteMtime); + if (modification.isModified()) { - //System.out.println("It seems "+id+" has state "+state); - this.changedIds.add(id); + this.identifiedModifications.put(id, modification); } } } + @Override + public void syncIdentified() + { + for (Entry entry : this.identifiedModifications.entrySet()) + { + String id = entry.getKey(); + Modification modification = entry.getValue(); + this.syncId(id, modification); + } + } + + @Override + public void syncAll() + { + this.identifyModifications(); + this.syncIdentified(); + } + @Override public void initLoadAllFromRemote() { - Map> idToEntryMap = this.getDb().getDriver().loadAll(this); + Map> idToEntryMap = this.getDb().loadAll(this); if (idToEntryMap == null) return; for (Entry> idToEntry : idToEntryMap.entrySet()) { String id = idToEntry.getKey(); - Entry entry = idToEntry.getValue(); - loadFromRemote(id, entry, true); + Entry remoteEntry = idToEntry.getValue(); + loadFromRemote(id, remoteEntry); } } @@ -859,7 +874,7 @@ public class Coll implements CollInterface @Override public void onTick() { - this.syncSuspects(); + this.syncIdentified(); } // -------------------------------------------- // @@ -889,7 +904,7 @@ public class Coll implements CollInterface // SUPPORTING SYSTEM this.plugin = plugin; this.db = db; - this.collDriverObject = db.getCollDriverObject(this); + this.collDriverObject = db.createCollDriverObject(this); // STORAGE if (entityComparator == null && !Comparable.class.isAssignableFrom(entityClass)) @@ -900,10 +915,8 @@ public class Coll implements CollInterface this.id2entity = new ConcurrentSkipListMap(idComparator); this.entity2id = new ConcurrentSkipListMap(entityComparator); - // IDENTIFIED CHANGES - this.localAttachIds = new ConcurrentSkipListSet(idComparator); - this.localDetachIds = new ConcurrentSkipListSet(idComparator); - this.changedIds = new ConcurrentSkipListSet(idComparator); + // IDENTIFIED MODIFICATIONS + this.identifiedModifications = new ConcurrentSkipListMap(idComparator); // SYNCLOG this.lastMtime = new ConcurrentSkipListMap(idComparator); @@ -941,7 +954,7 @@ public class Coll implements CollInterface @Override public void deinit() { - if (!this.inited()) return; + if ( ! this.inited()) return; // TODO: Save outwards only? We may want to avoid loads at this stage... this.syncAll(); diff --git a/src/com/massivecraft/massivecore/store/CollInterface.java b/src/com/massivecraft/massivecore/store/CollInterface.java index 6de606db..87402739 100644 --- a/src/com/massivecraft/massivecore/store/CollInterface.java +++ b/src/com/massivecraft/massivecore/store/CollInterface.java @@ -27,7 +27,6 @@ public interface CollInterface public Plugin getPlugin(); public Db getDb(); - public Driver getDriver(); public Object getCollDriverObject(); // -------------------------------------------- // @@ -36,9 +35,8 @@ public interface CollInterface public Map getId2entity(); public E get(Object oid); public E get(Object oid, boolean creative); - public Collection getIds(); // All ideas we know of whether they are loaded or not - public Collection getIdsRemote(); // All remote ids loaded sync via driver - public Collection getIdsLoaded(); // All locally loaded ids + public Collection getIds(); + public Collection getIdsRemote(); public boolean containsId(Object oid); public Map getEntity2id(); @@ -130,19 +128,21 @@ public interface CollInterface public E removeAtLocal(Object oid); public void removeAtRemote(Object oid); public void saveToRemote(Object oid); - public void loadFromRemote(Object oid, Entry entry, boolean entrySupplied); + public void loadFromRemote(Object oid, Entry remoteEntry); // -------------------------------------------- // // SYNC EXAMINE AND DO // -------------------------------------------- // - public ModificationState examineId(Object oid); - public ModificationState examineId(Object oid, Long remoteMtime); + public Modification examineId(Object oid); + public Modification examineId(Object oid, Long remoteMtime); - public ModificationState syncId(Object oid); - public void syncSuspects(); + public Modification syncId(Object oid); + public Modification syncId(Object oid, Modification modificationState); + public Modification syncId(Object oid, Modification modificationState, Entry remoteEntry); + public void syncIdentified(); public void syncAll(); - public void findSuspects(); + public void identifyModifications(); public void initLoadAllFromRemote(); // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/store/Db.java b/src/com/massivecraft/massivecore/store/Db.java index 0847aa3e..2c23abb2 100644 --- a/src/com/massivecraft/massivecore/store/Db.java +++ b/src/com/massivecraft/massivecore/store/Db.java @@ -1,16 +1,44 @@ package com.massivecraft.massivecore.store; +import java.util.Collection; +import java.util.Map; import java.util.Set; +import java.util.Map.Entry; + +import com.massivecraft.massivecore.xlib.gson.JsonElement; public interface Db -{ - public String getName(); +{ + // -------------------------------------------- // + // FIELDS + // -------------------------------------------- // - public boolean drop(); - - public Set getCollnames(); + // Returns the name of the database. + public String getDbName(); + // Returns the driver running this database. public Driver getDriver(); - public Object getCollDriverObject(Coll coll); + // Creates a new collection driver object. + // This object will be stored inside the Coll. + public Object createCollDriverObject(Coll coll); + + // -------------------------------------------- // + // DRIVER + // -------------------------------------------- // + + public String getDriverName(); + public Db getDb(String uri); + public boolean dropDb(); + public Set getCollnames(); + public boolean renameColl(String from, String to); + public boolean containsId(Coll coll, String id); + public long getMtime(Coll coll, String id); + public Collection getIds(Coll coll); + public Map getId2mtime(Coll coll); + public Entry load(Coll coll, String id); + public Map> loadAll(Coll coll); + public long save(Coll coll, String id, JsonElement data); + public void delete(Coll coll, String id); + } \ No newline at end of file diff --git a/src/com/massivecraft/massivecore/store/DbAbstract.java b/src/com/massivecraft/massivecore/store/DbAbstract.java index e73745df..a51b3d0c 100644 --- a/src/com/massivecraft/massivecore/store/DbAbstract.java +++ b/src/com/massivecraft/massivecore/store/DbAbstract.java @@ -1,12 +1,80 @@ package com.massivecraft.massivecore.store; +import java.util.Collection; +import java.util.Map; import java.util.Set; +import java.util.Map.Entry; + +import com.massivecraft.massivecore.xlib.gson.JsonElement; public abstract class DbAbstract implements Db { - @Override + // -------------------------------------------- // + // DRIVER + // -------------------------------------------- // + + public String getDriverName() + { + return this.getDriver().getDriverName(); + } + + public Db getDb(String uri) + { + return this.getDriver().getDb(uri); + } + + public boolean dropDb() + { + return this.getDriver().dropDb(this); + } + public Set getCollnames() { return this.getDriver().getCollnames(this); } + + public boolean renameColl(String from, String to) + { + return this.getDriver().renameColl(this, from, to); + } + + public boolean containsId(Coll coll, String id) + { + return this.getDriver().containsId(coll, id); + } + + public long getMtime(Coll coll, String id) + { + return this.getDriver().getMtime(coll, id); + } + + public Collection getIds(Coll coll) + { + return this.getDriver().getIds(coll); + } + + public Map getId2mtime(Coll coll) + { + return this.getDriver().getId2mtime(coll); + } + + public Entry load(Coll coll, String id) + { + return this.getDriver().load(coll, id); + } + + public Map> loadAll(Coll coll) + { + return this.getDriver().loadAll(coll); + } + + public long save(Coll coll, String id, JsonElement data) + { + return this.getDriver().save(coll, id, data); + } + + public void delete(Coll coll, String id) + { + this.getDriver().delete(coll, id); + } } diff --git a/src/com/massivecraft/massivecore/store/DbFlatfile.java b/src/com/massivecraft/massivecore/store/DbFlatfile.java index b8230db2..ac227768 100644 --- a/src/com/massivecraft/massivecore/store/DbFlatfile.java +++ b/src/com/massivecraft/massivecore/store/DbFlatfile.java @@ -2,56 +2,41 @@ package com.massivecraft.massivecore.store; import java.io.File; -import com.massivecraft.massivecore.util.DiscUtil; - public class DbFlatfile extends DbAbstract { // -------------------------------------------- // // FIELDS // -------------------------------------------- // - public File dir; + public File directory; protected DriverFlatfile driver; @Override public DriverFlatfile getDriver() { return driver; } // -------------------------------------------- // - // CONSTRUCTORS + // CONSTRUCT // -------------------------------------------- // - public DbFlatfile(DriverFlatfile driver, File folder) + public DbFlatfile(DriverFlatfile driver, File directory) { this.driver = driver; - this.dir = folder; + this.directory = directory; } // -------------------------------------------- // - // IMPLEMENTATION + // OVERRIDE // -------------------------------------------- // @Override - public String getName() + public String getDbName() { - return dir.getAbsolutePath(); + return directory.getAbsolutePath(); } @Override - public boolean drop() + public Object createCollDriverObject(Coll coll) { - try - { - return DiscUtil.deleteRecursive(this.dir); - } - catch (Exception e) - { - return false; - } - } - - @Override - public Object getCollDriverObject(Coll coll) - { - return new File(dir, coll.getName()); + return new File(directory, coll.getName()); } } diff --git a/src/com/massivecraft/massivecore/store/DbMongo.java b/src/com/massivecraft/massivecore/store/DbMongo.java index 55e0e496..03f774af 100644 --- a/src/com/massivecraft/massivecore/store/DbMongo.java +++ b/src/com/massivecraft/massivecore/store/DbMongo.java @@ -24,32 +24,19 @@ public class DbMongo extends DbAbstract } // -------------------------------------------- // - // IMPLEMENTATION + // OVERRIDE // -------------------------------------------- // @Override - public String getName() + public String getDbName() { return db.getName(); } @Override - public boolean drop() - { - try - { - this.db.dropDatabase(); - return true; - } - catch (Exception e) - { - return false; - } - } - - @Override - public Object getCollDriverObject(Coll coll) + public Object createCollDriverObject(Coll coll) { return db.getCollection(coll.getName()); } + } diff --git a/src/com/massivecraft/massivecore/store/Driver.java b/src/com/massivecraft/massivecore/store/Driver.java index 82749ef3..73ef3a08 100644 --- a/src/com/massivecraft/massivecore/store/Driver.java +++ b/src/com/massivecraft/massivecore/store/Driver.java @@ -10,12 +10,15 @@ import com.massivecraft.massivecore.xlib.gson.JsonElement; public interface Driver { // Returns the name of the driver. - public String getName(); + public String getDriverName(); // Get a database instance from the driver public Db getDb(String uri); - // What collections are in the database? + // This will delete the whole database and all collections therein. + public boolean dropDb(Db db); + + // What collections are in the database? public Set getCollnames(Db db); // Rename a collection @@ -25,7 +28,10 @@ public interface Driver public boolean containsId(Coll coll, String id); // When was X last altered? - public Long getMtime(Coll coll, String id); + // return == null will never happen. + // return != 0 means X exists and return is when it last was altered. + // return == 0 means X does not exist in the database. + public long getMtime(Coll coll, String id); // What ids are in the collection? public Collection getIds(Coll coll); @@ -34,15 +40,20 @@ public interface Driver public Map getId2mtime(Coll coll); // Load the raw data for X. The second part of the entry is the remote mtime at the load. + // return == null will never happen. + // return.getKey() == null || return.getValue() == 0 means something failed. public Entry load(Coll coll, String id); // Load all database content at once + // NOTE: This method is assumed to be based on the one above. + // NOTE: Values where JsonElement == null and Long == 0 may occur. public Map> loadAll(Coll coll); // Save raw data as X // Return value is the new mtime (we caused the change). - // If the mtime is null something failed. - public Long save(Coll coll, String id, JsonElement data); + // return == null will never happen. + // return == 0 means something failed. Usually failures are not catched, though. System.currentTimeMillis() is returned most of the time. + public long save(Coll coll, String id, JsonElement data); // Delete X public void delete(Coll coll, String id); diff --git a/src/com/massivecraft/massivecore/store/DriverAbstract.java b/src/com/massivecraft/massivecore/store/DriverAbstract.java index 376e41c3..ba00a786 100644 --- a/src/com/massivecraft/massivecore/store/DriverAbstract.java +++ b/src/com/massivecraft/massivecore/store/DriverAbstract.java @@ -7,7 +7,7 @@ public abstract class DriverAbstract implements Driver // -------------------------------------------- // private final String name; - @Override public String getName() { return this.name; } + @Override public String getDriverName() { return this.name; } // -------------------------------------------- // // CONSTRUCT diff --git a/src/com/massivecraft/massivecore/store/DriverFlatfile.java b/src/com/massivecraft/massivecore/store/DriverFlatfile.java index d55157b5..d0ddf6ef 100644 --- a/src/com/massivecraft/massivecore/store/DriverFlatfile.java +++ b/src/com/massivecraft/massivecore/store/DriverFlatfile.java @@ -41,9 +41,25 @@ public class DriverFlatfile extends DriverAbstract public Db getDb(String uri) { // "flatfile://" is 8+3=11 chars - File folder = new File(uri.substring(NAME.length() + 3)); - folder.mkdirs(); - return new DbFlatfile(this, folder); + File directory = new File(uri.substring(NAME.length() + 3)); + directory.mkdirs(); + return new DbFlatfile(this, directory); + } + + @Override + public boolean dropDb(Db db) + { + if ( ! (db instanceof DbFlatfile)) throw new IllegalArgumentException("db"); + DbFlatfile dbFlatfile = (DbFlatfile)db; + + try + { + return DiscUtil.deleteRecursive(dbFlatfile.directory); + } + catch (Exception e) + { + return false; + } } @Override @@ -51,10 +67,10 @@ public class DriverFlatfile extends DriverAbstract { Set ret = new LinkedHashSet(); - for (File f : ((DbFlatfile)db).dir.listFiles()) + for (File file : ((DbFlatfile)db).directory.listFiles()) { - if ( ! f.isDirectory()) continue; - ret.add(f.getName()); + if ( ! file.isDirectory()) continue; + ret.add(file.getName()); } return ret; @@ -63,7 +79,7 @@ public class DriverFlatfile extends DriverAbstract @Override public boolean renameColl(Db db, String from, String to) { - File dir = ((DbFlatfile)db).dir; + File dir = ((DbFlatfile)db).directory; File fileFrom = new File(dir, from); File fileTo = new File(dir, to); return fileFrom.renameTo(fileTo); @@ -76,10 +92,10 @@ public class DriverFlatfile extends DriverAbstract } @Override - public Long getMtime(Coll coll, String id) + public long getMtime(Coll coll, String id) { File file = fileFromId(coll, id); - if ( ! file.isFile()) return null; + if ( ! file.isFile()) return 0; return file.lastModified(); } @@ -89,7 +105,7 @@ public class DriverFlatfile extends DriverAbstract List ret = new ArrayList(); // Scan the collection folder for .json files - File collDir = getCollDir(coll); + File collDir = getDirectory(coll); if ( ! collDir.isDirectory()) return ret; for (File file : collDir.listFiles(JsonFileFilter.get())) { @@ -105,15 +121,16 @@ public class DriverFlatfile extends DriverAbstract // Create Ret Map ret = new HashMap(); - // Get collection directory - File collDir = getCollDir(coll); - if (!collDir.isDirectory()) return ret; + // Get Directory + File directory = getDirectory(coll); + if ( ! directory.isDirectory()) return ret; // For each .json file - for (File file : collDir.listFiles(JsonFileFilter.get())) + for (File file : directory.listFiles(JsonFileFilter.get())) { String id = idFromFile(file); long mtime = file.lastModified(); + // TODO: Check is 0 here? ret.put(id, mtime); } @@ -130,11 +147,8 @@ public class DriverFlatfile extends DriverAbstract public Entry loadFile(File file) { - Long mtime = file.lastModified(); - if (mtime == 0) return null; - + long mtime = file.lastModified(); JsonElement raw = loadFileJson(file); - if (raw == null) return null; return new SimpleEntry(raw, mtime); } @@ -153,15 +167,15 @@ public class DriverFlatfile extends DriverAbstract @Override public Map> loadAll(Coll coll) { - // Declare Ret + // Create Ret Map> ret = null; - // Get collection directory - File collDir = getCollDir(coll); - if ( ! collDir.isDirectory()) return ret; + // Get Directory + File directory = getDirectory(coll); + if ( ! directory.isDirectory()) return ret; // Find All - File[] files = collDir.listFiles(JsonFileFilter.get()); + File[] files = directory.listFiles(JsonFileFilter.get()); // Create Ret ret = new LinkedHashMap>(files.length); @@ -174,6 +188,9 @@ public class DriverFlatfile extends DriverAbstract // Get Entry Entry entry = loadFile(file); + // NOTE: The entry can be a failed one with null and 0. + // NOTE: We add it anyways since it's an informative failure. + // NOTE: This is supported by our defined specification. // Add ret.put(id, entry); @@ -184,11 +201,11 @@ public class DriverFlatfile extends DriverAbstract } @Override - public Long save(Coll coll, String id, JsonElement data) + public long save(Coll coll, String id, JsonElement data) { File file = fileFromId(coll, id); String content = coll.getGson().toJson(data); - if (DiscUtil.writeCatch(file, content) == false) return null; + if (DiscUtil.writeCatch(file, content) == false) return 0; return file.lastModified(); } @@ -203,7 +220,7 @@ public class DriverFlatfile extends DriverAbstract // UTIL // -------------------------------------------- // - public static File getCollDir(Coll coll) + public static File getDirectory(Coll coll) { return (File) coll.getCollDriverObject(); } @@ -217,7 +234,7 @@ public class DriverFlatfile extends DriverAbstract public static File fileFromId(Coll coll, String id) { - File collDir = getCollDir(coll); + File collDir = getDirectory(coll); File idFile = new File(collDir, id + DOTJSON); return idFile; } diff --git a/src/com/massivecraft/massivecore/store/DriverMongo.java b/src/com/massivecraft/massivecore/store/DriverMongo.java index a06a7547..4b097881 100644 --- a/src/com/massivecraft/massivecore/store/DriverMongo.java +++ b/src/com/massivecraft/massivecore/store/DriverMongo.java @@ -51,6 +51,23 @@ public class DriverMongo extends DriverAbstract DB db = this.getDbInner(uri); return new DbMongo(this, db); } + + @Override + public boolean dropDb(Db db) + { + if ( ! (db instanceof DbMongo)) throw new IllegalArgumentException("db"); + DbMongo dbMongo = (DbMongo)db; + + try + { + dbMongo.db.dropDatabase(); + return true; + } + catch (Exception e) + { + return false; + } + } @Override public Set getCollnames(Db db) @@ -81,15 +98,17 @@ public class DriverMongo extends DriverAbstract } @Override - public Long getMtime(Coll coll, String id) + public long getMtime(Coll coll, String id) { DBCollection dbcoll = fixColl(coll); BasicDBObject found = (BasicDBObject)dbcoll.findOne(new BasicDBObject(ID_FIELD, id), dboKeysMtime); - if (found == null) return null; + if (found == null) return 0; - // In case there is no _mtime set we assume 0. Probably a manual database addition by the server owner. - long mtime = found.getLong(MTIME_FIELD, 0); + // In case there is no _mtime set we assume 1337. + // NOTE: We can not use 0 since that one is reserved for errors. + // Probably a manual database addition by the server owner. + long mtime = found.getLong(MTIME_FIELD, 1337L); return mtime; } @@ -105,7 +124,7 @@ public class DriverMongo extends DriverAbstract try { ret = new ArrayList(cursor.count()); - while(cursor.hasNext()) + while (cursor.hasNext()) { Object remoteId = cursor.next().get(ID_FIELD); ret.add(remoteId.toString()); @@ -130,13 +149,15 @@ public class DriverMongo extends DriverAbstract try { ret = new HashMap(cursor.count()); - while(cursor.hasNext()) + while (cursor.hasNext()) { BasicDBObject raw = (BasicDBObject)cursor.next(); Object remoteId = raw.get(ID_FIELD); - // In case there is no _mtime set we assume 0. Probably a manual database addition by the server owner. - long mtime = raw.getLong(MTIME_FIELD, 0); + // In case there is no _mtime set we assume 1337. + // NOTE: We can not use 0 since that one is reserved for errors. + // Probably a manual database addition by the server owner. + long mtime = raw.getLong(MTIME_FIELD, 1337L); ret.put(remoteId.toString(), mtime); } @@ -159,13 +180,15 @@ public class DriverMongo extends DriverAbstract public Entry loadRaw(BasicDBObject raw) { - if (raw == null) return null; + if (raw == null) return new SimpleEntry(null, 0L); // Throw away the id field raw.removeField(ID_FIELD); - // In case there is no _mtime set we assume 0. Probably a manual database addition by the server owner. - Long mtime = 0L; + // In case there is no _mtime set we assume 1337. + // NOTE: We can not use 0 since that one is reserved for errors. + // Probably a manual database addition by the server owner. + long mtime = 1337L; Object mtimeObject = raw.removeField(MTIME_FIELD); if (mtimeObject != null) { @@ -207,9 +230,9 @@ public class DriverMongo extends DriverAbstract // Get Entry Entry entry = loadRaw(raw); - //if (entry == null) continue; - // Actually allow adding null entries! - // they are informative failures! + // NOTE: The entry can be a failed one with null and 0. + // NOTE: We add it anyways since it's an informative failure. + // NOTE: This is supported by our defined specification. // Add ret.put(id, entry); @@ -226,13 +249,13 @@ public class DriverMongo extends DriverAbstract } @Override - public Long save(Coll coll, String id, JsonElement data) + public long save(Coll coll, String id, JsonElement data) { DBCollection dbcoll = fixColl(coll); BasicDBObject dbo = new BasicDBObject(); - Long mtime = System.currentTimeMillis(); + long mtime = System.currentTimeMillis(); dbo.put(ID_FIELD, id); dbo.put(MTIME_FIELD, mtime); diff --git a/src/com/massivecraft/massivecore/store/Entity.java b/src/com/massivecraft/massivecore/store/Entity.java index d52b085c..ad094f3d 100644 --- a/src/com/massivecraft/massivecore/store/Entity.java +++ b/src/com/massivecraft/massivecore/store/Entity.java @@ -109,15 +109,15 @@ public abstract class Entity> implements Comparable Coll coll = this.getColl(); if (coll == null) return; - if (!coll.inited()) return; + if ( ! coll.inited()) return; - coll.changedIds.add(id); + coll.identifiedModifications.put(id, Modification.UNKNOWN); } - public ModificationState sync() + public Modification sync() { String id = this.getId(); - if (id == null) return ModificationState.UNKNOWN; + if (id == null) return Modification.UNKNOWN; return this.getColl().syncId(id); } @@ -134,7 +134,7 @@ public abstract class Entity> implements Comparable String id = this.getId(); if (id == null) return; - this.getColl().loadFromRemote(id, null, false); + this.getColl().loadFromRemote(id, null); } // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/store/ExamineThread.java b/src/com/massivecraft/massivecore/store/ExamineThread.java index fbe95c64..828721b4 100644 --- a/src/com/massivecraft/massivecore/store/ExamineThread.java +++ b/src/com/massivecraft/massivecore/store/ExamineThread.java @@ -43,7 +43,7 @@ public class ExamineThread extends Thread long before = System.currentTimeMillis(); for (Coll coll : Coll.getInstances()) { - coll.findSuspects(); + coll.identifyModifications(); } long after = System.currentTimeMillis(); long duration = after-before; diff --git a/src/com/massivecraft/massivecore/store/JsonFileFilter.java b/src/com/massivecraft/massivecore/store/JsonFileFilter.java index 996f27c3..6554cd41 100644 --- a/src/com/massivecraft/massivecore/store/JsonFileFilter.java +++ b/src/com/massivecraft/massivecore/store/JsonFileFilter.java @@ -15,7 +15,7 @@ public class JsonFileFilter implements FileFilter // INSTANCE & CONSTRUCT // -------------------------------------------- // - private static JsonFileFilter i = new JsonFileFilter(); + private static final JsonFileFilter i = new JsonFileFilter(); public static JsonFileFilter get() { return i; } // -------------------------------------------- // diff --git a/src/com/massivecraft/massivecore/store/MStore.java b/src/com/massivecraft/massivecore/store/MStore.java index 77088bf3..01b4cfd5 100644 --- a/src/com/massivecraft/massivecore/store/MStore.java +++ b/src/com/massivecraft/massivecore/store/MStore.java @@ -18,8 +18,8 @@ public class MStore private static Map drivers = new HashMap(); public static boolean registerDriver(Driver driver) { - if (drivers.containsKey(driver.getName())) return false; - drivers.put(driver.getName(), driver); + if (drivers.containsKey(driver.getDriverName())) return false; + drivers.put(driver.getDriverName(), driver); return true; } diff --git a/src/com/massivecraft/massivecore/store/ModificationState.java b/src/com/massivecraft/massivecore/store/Modification.java similarity index 82% rename from src/com/massivecraft/massivecore/store/ModificationState.java rename to src/com/massivecraft/massivecore/store/Modification.java index 593a6ecd..812d4422 100644 --- a/src/com/massivecraft/massivecore/store/ModificationState.java +++ b/src/com/massivecraft/massivecore/store/Modification.java @@ -1,6 +1,6 @@ package com.massivecraft.massivecore.store; -public enum ModificationState +public enum Modification { LOCAL_ALTER (true, true), LOCAL_ATTACH (true, true), @@ -19,7 +19,7 @@ public enum ModificationState public boolean isLocal() { return this.local; } public boolean isRemote() { return this.local == false; } - private ModificationState(boolean modified, boolean local) + private Modification(boolean modified, boolean local) { this.modified = modified; this.local = local;