diff --git a/.run/CoreMaster.run.xml b/.run/CoreMaster.run.xml new file mode 100644 index 00000000..d9b6b1c4 --- /dev/null +++ b/.run/CoreMaster.run.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/API/src/main/java/net/juligames/core/api/data/HazelDataApi.java b/API/src/main/java/net/juligames/core/api/data/HazelDataApi.java index a75ff20f..130b5d1a 100644 --- a/API/src/main/java/net/juligames/core/api/data/HazelDataApi.java +++ b/API/src/main/java/net/juligames/core/api/data/HazelDataApi.java @@ -1,6 +1,7 @@ package net.juligames.core.api.data; import de.bentzin.tools.Hardcode; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -55,5 +56,12 @@ default Map getMasterInformation() { return getMap("master_information"); } + /** + * This method trys to guess if {@link #getMasterInformation()} will provide a populated map. + * It provides no information about the last update + */ + @ApiStatus.AvailableSince("1.6") + boolean isMasterInformationAvailable(); + } diff --git a/API/src/main/java/net/juligames/core/api/misc/APIUtils.java b/API/src/main/java/net/juligames/core/api/misc/APIUtils.java index 06bcc2ad..7ce385b1 100644 --- a/API/src/main/java/net/juligames/core/api/misc/APIUtils.java +++ b/API/src/main/java/net/juligames/core/api/misc/APIUtils.java @@ -6,11 +6,9 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.function.Function; +import java.util.function.Supplier; import java.util.logging.Logger; import java.util.stream.Stream; @@ -132,6 +130,24 @@ public static boolean executedWithoutExceptionL(@NotNull Runnable runnable) { return list.stream(); } + @ApiStatus.Experimental + public static void executeAndSwallow(ThrowingRunnable throwingRunnable) { + try { + throwingRunnable.run(); + } catch (Exception ignored) { + } + } + + @SafeVarargs + public static Optional executeAndReturnFirstSuccess(Supplier @NotNull ... suppliers) { + for (Supplier supplier : suppliers) { + try { + return Optional.of(supplier.get()); + }catch (Exception ignore) {} + } + return Optional.empty(); + } + /** * Creates a JavaLogger instance from a {@link Logger}. * diff --git a/Core/src/main/java/net/juligames/core/Core.java b/Core/src/main/java/net/juligames/core/Core.java index b3915633..2cf0d0fc 100644 --- a/Core/src/main/java/net/juligames/core/Core.java +++ b/Core/src/main/java/net/juligames/core/Core.java @@ -173,6 +173,7 @@ public void start(String core_name, @NotNull Logger logger, boolean member) { .addMessageListener(coreNotificationApi); + if(getHazelDataApi().isMasterInformationAvailable()) { if (!Boolean.getBoolean("acknowledgeUnsafeMasterCheck")) { coreLogger.info("checking compatibility with master.."); @@ -196,6 +197,7 @@ public void start(String core_name, @NotNull Logger logger, boolean member) { } } } + else logger.debug("master information is not available! If you see this on the Master it is expected behavior"); logger.info("hooking to shutdown..."); getJavaRuntime().addShutdownHook(new Thread(() -> { diff --git a/Core/src/main/java/net/juligames/core/config/CoreConfiguration.java b/Core/src/main/java/net/juligames/core/config/CoreConfiguration.java index 7c3a032c..69f3649b 100644 --- a/Core/src/main/java/net/juligames/core/config/CoreConfiguration.java +++ b/Core/src/main/java/net/juligames/core/config/CoreConfiguration.java @@ -60,7 +60,7 @@ public CoreConfiguration(String name) { for (Map.Entry entry : entries) { if (override) { String old = map.put(entry.getKey().toString(), entry.getValue().toString()); //oh man... oh man - Core.getInstance().getCoreLogger().debug("OVERRIDE: set " + entry.getKey() + "from " + old + " to " + entry.getValue()); + Core.getInstance().getCoreLogger().debug("OVERRIDE: set " + entry.getKey() + " from " + old + " to " + entry.getValue()); } else if (!map.containsKey(entry.getKey().toString())) { String old = map.put(entry.getKey().toString(), entry.getValue().toString()); //oh man... oh man Core.getInstance().getCoreLogger().debug("set " + entry.getKey() + "from " + old + " to " + entry.getValue()); diff --git a/Core/src/main/java/net/juligames/core/data/HazelDataCore.java b/Core/src/main/java/net/juligames/core/data/HazelDataCore.java index 0eadaa92..577a6071 100644 --- a/Core/src/main/java/net/juligames/core/data/HazelDataCore.java +++ b/Core/src/main/java/net/juligames/core/data/HazelDataCore.java @@ -49,6 +49,11 @@ public final class HazelDataCore implements HazelDataApi, NativeHazelDataAPI { return getHazelcastInstance().getList(hazel); } + @Override + public boolean isMasterInformationAvailable() { + return getMasterInformation().containsKey("available"); + } + @Override public @NotNull ITopic getTopic(@NotNull String hazel) { return getHazelcastInstance().getTopic(hazel); diff --git a/Master/src/main/java/net/juligames/core/master/CoreMaster.java b/Master/src/main/java/net/juligames/core/master/CoreMaster.java index 12967be6..cc925fde 100644 --- a/Master/src/main/java/net/juligames/core/master/CoreMaster.java +++ b/Master/src/main/java/net/juligames/core/master/CoreMaster.java @@ -35,23 +35,26 @@ private CoreMaster() { public static void main(String[] args) { + //Setup + MasterLogger.setupJavaLogging(); + logger = new MasterLogger("Master", java.util.logging.Logger.getLogger(Core.getShortRelease())); //entry point for Master masterCommandRunner = new MasterCommandRunner(logger); masterConfigManager = new MasterConfigManager(); - logger.info("welcome to " + Core.getFullCoreName() + " Master by Ture Bentzin "); + logger.info("Welcome to " + Core.getFullCoreName() + " Master by Ture Bentzin "); - logger.info("preparing directory..."); + logger.info("Preparing directory..."); masterConfigManager.createDatabaseConfiguration(); - logger.info("booting hazelcast (MEMBER CORE):"); + logger.info("Booting hazelcast (MEMBER CORE):"); Core core = new Core(); try { core.getHazelcastPostPreparationWorkers().register(hazelcastInstance -> { - logger.info("loading config"); + logger.info("Loading config"); masterConfigManager.load(); }); } catch (Registerator.DuplicateEntryException ignored) { @@ -67,11 +70,11 @@ public static void main(String[] args) { logger.error("FAILED TO SETUP HAZELCAST - Master will probably start anyway but the master should be restarted as soon as possible"); } - logger.info("hazelcast boot was completed - advice: hazelcast could potentially fail to boot for a variety of reasons, so if you should see" + + logger.info("Hazelcast boot was completed - advice: hazelcast could potentially fail to boot for a variety of reasons, so if you should see" + "an error above then you might want to restart the master. In the case that the Clients are put on hold by the core you should also" + "consider restarting."); - logger.debug("sql: start"); + logger.debug("SQL: start"); SQLManager = Core.getInstance().getSQLManager(); SQLManager.createTables(); //MASTER CREATES TABLES (NOT THE CORE!!!) @@ -83,7 +86,7 @@ public static void main(String[] args) { //Data masterHazelInformationProvider = new MasterHazelInformationProvider(hazelcast); - logger.warning("not all code execution on master is stable because the master DOES NOT PROVIDE a fully usable core!!!"); + logger.warning("Not all code execution on master is stable because the master DOES NOT PROVIDE a fully usable core!!!"); try { registerCommands(); } catch (Registerator.DuplicateEntryException e) { @@ -92,15 +95,15 @@ public static void main(String[] args) { } //CommandSystem - logger.info("registering CommandHandler..."); + logger.info("Registering CommandHandler..."); core.getCommandApi().setCommandHandler(new CommandHandler()); - logger.info("master is now ready to receive commands from hazelcast"); + logger.info("Master is now ready to receive commands from hazelcast"); //HOOK Core.getInstance().getJavaRuntime().addShutdownHook(new Thread(() -> { try { - logger.info("master is going down!!"); + logger.info("Master is going down!!"); } catch (Exception ignored) { System.out.println("Seems like everything is cursed right now. Please report this!"); } diff --git a/Master/src/main/java/net/juligames/core/master/cmd/PrintMapCommand.java b/Master/src/main/java/net/juligames/core/master/cmd/PrintMapCommand.java index 56fd2dcd..8a7b7e99 100644 --- a/Master/src/main/java/net/juligames/core/master/cmd/PrintMapCommand.java +++ b/Master/src/main/java/net/juligames/core/master/cmd/PrintMapCommand.java @@ -2,11 +2,18 @@ import com.hazelcast.core.DistributedObject; import com.hazelcast.map.IMap; +import de.bentzin.tools.logging.Logger; import net.juligames.core.Core; import net.juligames.core.api.TODO; +import net.juligames.core.api.misc.APIUtils; import org.jetbrains.annotations.NotNull; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; + +import static net.juligames.core.api.misc.APIUtils.executeAndReturnFirstSuccess; +import static net.juligames.core.api.misc.APIUtils.executeAndSwallow; /** * @author Ture Bentzin @@ -23,27 +30,59 @@ public PrintMapCommand() { public void executeCommand(@NotNull String commandString) { String[] s = commandString.replaceFirst(" ", "").split(" "); String ident = s[0]; - Optional optionalDistributedObject = - Core.getInstance().getOrThrow().getDistributedObjects().stream() - .filter(distributedObject -> distributedObject.getName().equals(ident)) - .findFirst(); - if (optionalDistributedObject.isEmpty()) { - throw new IllegalArgumentException("cant find: " + ident); - } - IMap map = Core.getInstance().getOrThrow().getMap(ident); - Core.getInstance().getCoreLogger().info("printing result of printMap: " + ident); - final boolean[] first = {true}; - Core.getInstance().getCoreLogger().warning("The here referenced classes may be inaccurate"); + final IMap map = findMap(ident); + Logger coreLogger = Core.getInstance().getCoreLogger(); + coreLogger.info("printing result of printMap: " + map.getName()); + + AtomicReference> keyClass = new AtomicReference<>(); + AtomicReference> valueClass = new AtomicReference<>(); map.forEach((o, o2) -> { - if (first[0]) { - first[0] = false; - Core.getInstance().getCoreLogger().info("keyClass: " + o.getClass().getSimpleName()); - Core.getInstance().getCoreLogger().info("valueClass: " + o2.getClass().getSimpleName()); + if (o == null || o2 == null) { + coreLogger.warning("FLAWED: " + o + " :! " + o2); + return; } - Core.getInstance().getCoreLogger().info(o.toString() + " : " + o2.toString()); + if (keyClass.get() != o.getClass() || valueClass.get() != o2.getClass()) { + coreLogger.info(o.getClass().getSimpleName() + " | " + o2.getClass().getSimpleName()); + keyClass.set(o.getClass()); + valueClass.set(o2.getClass()); + } + + coreLogger.info(o + " : " + o2); }); } + + + @SuppressWarnings("unchecked") + protected IMap findMap(String query) { + return (IMap) executeAndReturnFirstSuccess( + //Equal names + () -> findMapHard(query,distributedObject -> distributedObject.getName().equals(query)), + //Semi Equal names + () -> findMapHard(query,distributedObject -> distributedObject.getName().equalsIgnoreCase(query)), + //Starts with + () -> findMapHard(query, distributedObject -> distributedObject.getName().startsWith(query)), + //Starts with (semi) + () -> findMapHard(query, distributedObject -> distributedObject.getName().toLowerCase().startsWith(query.toLowerCase())), + //Contains + () -> findMapHard(query, distributedObject -> distributedObject.getName().contains(query)), + //Contains (semi) + () -> findMapHard(query, distributedObject -> distributedObject.getName().toLowerCase().contains(query.toLowerCase())) + + ).orElseThrow(() -> new IllegalArgumentException("cant find a map for query: \"" + query + "\"")); + } + + @SuppressWarnings("unchecked") + private @NotNull IMap findMapHard(String name, Predicate predicate) { + Optional optionalDistributedObject = + Core.getInstance().getOrThrow().getDistributedObjects().stream() + .filter(predicate) + .findFirst(); + if (optionalDistributedObject.isEmpty()) { + throw new IllegalArgumentException("cant find: " + name); + } + return (IMap)optionalDistributedObject.get(); + } } diff --git a/Master/src/main/java/net/juligames/core/master/data/MasterHazelInformationProvider.java b/Master/src/main/java/net/juligames/core/master/data/MasterHazelInformationProvider.java index c4bcfb89..55a40a50 100644 --- a/Master/src/main/java/net/juligames/core/master/data/MasterHazelInformationProvider.java +++ b/Master/src/main/java/net/juligames/core/master/data/MasterHazelInformationProvider.java @@ -38,15 +38,16 @@ protected void genMap() { public void update() { //Locale DBLocale defaultEnglish = CoreSQLManager.defaultEnglish(); + informationMap().put("available", ""); informationMap().put("default_locale", defaultEnglish.getLocale()); informationMap().put("default_locale_description", defaultEnglish.getDescription()); informationMap().put("master_uuid", hazelcast.getLocalEndpoint().getUuid().toString()); informationMap().put("master_name", hazelcast.getName()); informationMap().put("master_boot", String.valueOf(CoreMaster.getBootMillis().orElseThrow())); informationMap().put("master_version", API.get().getVersion()); - informationMap().put("last_update", System.currentTimeMillis() + ""); + informationMap().put("last_update", String.valueOf(System.currentTimeMillis())); //Experimental - informationMap().put("master_commands", CoreMaster.getMasterCommandRunner().getIndex() + ""); + informationMap().put("master_commands", CoreMaster.getMasterCommandRunner().getIndex().toString()); informationMap().put("hazelcast_version", VersionFinder.getVersion()); informationMap().put("master_os", VersionFinder.OS.name()); informationMap().put("java_version", VersionFinder.JAVA_VERSION); diff --git a/Master/src/main/java/net/juligames/core/master/logging/MasterLogger.java b/Master/src/main/java/net/juligames/core/master/logging/MasterLogger.java index 53ee208f..943c39dc 100644 --- a/Master/src/main/java/net/juligames/core/master/logging/MasterLogger.java +++ b/Master/src/main/java/net/juligames/core/master/logging/MasterLogger.java @@ -2,6 +2,7 @@ import de.bentzin.tools.logging.JavaLogger; import de.bentzin.tools.logging.Logger; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import java.time.LocalDateTime; @@ -13,6 +14,11 @@ */ public final class MasterLogger extends JavaLogger { + @ApiStatus.AvailableSince("1.6") + public static void setupJavaLogging() { + System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT] [%4$-7s] %5$s %n"); + } + public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(" HH:mm:ss"); public MasterLogger(String name, @NotNull Logger parent, java.util.logging.@NotNull Logger logger) {