This is an automated email from the ASF dual-hosted git repository. mmuzaf pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new 0591cb337b8 IGNITE-16732 Add configurable ignite log and metrics messages (#9918) 0591cb337b8 is described below commit 0591cb337b834431862a340f220962cb9863a7c0 Author: Maxim Muzafarov <maxmu...@gmail.com> AuthorDate: Sun Apr 10 22:49:14 2022 +0300 IGNITE-16732 Add configurable ignite log and metrics messages (#9918) --- assembly/dependencies-apache-ignite-lgpl.xml | 1 + assembly/dependencies-apache-ignite-slim.xml | 1 + assembly/dependencies-apache-ignite.xml | 1 + .../org/apache/ignite/internal/IgniteKernal.java | 1024 +------------------- .../org/apache/ignite/internal/IgnitionEx.java | 3 +- .../internal/plugin/IgniteLogInfoProvider.java | 66 ++ .../internal/plugin/IgniteLogInfoProviderImpl.java | 1018 +++++++++++++++++++ .../IgniteCacheDatabaseSharedManager.java | 11 +- .../apache/ignite/internal/util/IgniteUtils.java | 110 ++- .../ignite/thread/IgniteThreadPoolSizeTest.java | 4 +- modules/extdata/logo/licenses/apache-2.0.txt | 202 ++++ modules/extdata/logo/pom.xml | 111 +++ .../ignite/internal/IgniteExtendedLogoTest.java | 42 + .../plugin/IgniteExtLogInfoProviderImpl.java | 47 + .../testsuites/IgniteLogoExtensionTestSuite.java | 32 + ...he.ignite.internal.plugin.IgniteLogInfoProvider | 1 + pom.xml | 1 + 17 files changed, 1671 insertions(+), 1004 deletions(-) diff --git a/assembly/dependencies-apache-ignite-lgpl.xml b/assembly/dependencies-apache-ignite-lgpl.xml index 68ae4d3e010..44cd9ad26dd 100644 --- a/assembly/dependencies-apache-ignite-lgpl.xml +++ b/assembly/dependencies-apache-ignite-lgpl.xml @@ -120,6 +120,7 @@ <exclude>${project.groupId}:ignite-extdata-p2p</exclude> <exclude>${project.groupId}:ignite-extdata-uri</exclude> <exclude>${project.groupId}:ignite-extdata-uri-dep</exclude> + <exclude>${project.groupId}:ignite-extdata-logo</exclude> <exclude>${project.groupId}:ignite-examples</exclude> <exclude>${project.groupId}:ignite-indexing</exclude> <exclude>${project.groupId}:ignite-visor-console</exclude> diff --git a/assembly/dependencies-apache-ignite-slim.xml b/assembly/dependencies-apache-ignite-slim.xml index 08c33072cfc..c5795e8fc0b 100644 --- a/assembly/dependencies-apache-ignite-slim.xml +++ b/assembly/dependencies-apache-ignite-slim.xml @@ -120,6 +120,7 @@ <exclude>${project.groupId}:ignite-extdata-p2p</exclude> <exclude>${project.groupId}:ignite-extdata-uri</exclude> <exclude>${project.groupId}:ignite-extdata-uri-dep</exclude> + <exclude>${project.groupId}:ignite-extdata-logo</exclude> <exclude>${project.groupId}:ignite-examples</exclude> <exclude>${project.groupId}:ignite-indexing</exclude> <exclude>${project.groupId}:ignite-visor-console</exclude> diff --git a/assembly/dependencies-apache-ignite.xml b/assembly/dependencies-apache-ignite.xml index 28fa77cd4df..31ae5068727 100644 --- a/assembly/dependencies-apache-ignite.xml +++ b/assembly/dependencies-apache-ignite.xml @@ -121,6 +121,7 @@ <exclude>${project.groupId}:ignite-extdata-p2p</exclude> <exclude>${project.groupId}:ignite-extdata-uri</exclude> <exclude>${project.groupId}:ignite-extdata-uri-dep</exclude> + <exclude>${project.groupId}:ignite-extdata-logo</exclude> <exclude>${project.groupId}:ignite-examples</exclude> <exclude>${project.groupId}:ignite-indexing</exclude> <exclude>${project.groupId}:ignite-visor-console</exclude> diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java index 2e7c101b2f6..c5537db95cf 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java @@ -18,37 +18,25 @@ package org.apache.ignite.internal; import java.io.Externalizable; -import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.io.InvalidObjectException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; import java.io.Serializable; -import java.io.UncheckedIOException; import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; import java.lang.reflect.Constructor; import java.nio.charset.Charset; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Locale; import java.util.Map; -import java.util.Properties; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; @@ -91,7 +79,6 @@ import org.apache.ignite.PersistenceMetrics; import org.apache.ignite.cache.affinity.Affinity; import org.apache.ignite.cluster.BaselineNode; import org.apache.ignite.cluster.ClusterGroup; -import org.apache.ignite.cluster.ClusterMetrics; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.cluster.ClusterState; import org.apache.ignite.compute.ComputeJob; @@ -99,8 +86,6 @@ import org.apache.ignite.configuration.AtomicConfiguration; import org.apache.ignite.configuration.BinaryConfiguration; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.CollectionConfiguration; -import org.apache.ignite.configuration.DataRegionConfiguration; -import org.apache.ignite.configuration.DataStorageConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.configuration.MemoryConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; @@ -128,6 +113,8 @@ import org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager; import org.apache.ignite.internal.managers.systemview.GridSystemViewManager; import org.apache.ignite.internal.managers.tracing.GridTracingManager; import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller; +import org.apache.ignite.internal.plugin.IgniteLogInfoProvider; +import org.apache.ignite.internal.plugin.IgniteLogInfoProviderImpl; import org.apache.ignite.internal.processors.GridProcessor; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.affinity.GridAffinityProcessor; @@ -141,8 +128,6 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheProxy; import org.apache.ignite.internal.processors.cache.IgniteInternalCache; import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl; import org.apache.ignite.internal.processors.cache.mvcc.MvccProcessorImpl; -import org.apache.ignite.internal.processors.cache.persistence.DataRegion; -import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager; import org.apache.ignite.internal.processors.cache.persistence.filename.PdsConsistentIdProcessor; import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor; import org.apache.ignite.internal.processors.closure.GridClosureProcessor; @@ -173,7 +158,6 @@ import org.apache.ignite.internal.processors.platform.plugin.PlatformPluginProce import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor; import org.apache.ignite.internal.processors.pool.PoolProcessor; import org.apache.ignite.internal.processors.port.GridPortProcessor; -import org.apache.ignite.internal.processors.port.GridPortRecord; import org.apache.ignite.internal.processors.query.GridQueryProcessor; import org.apache.ignite.internal.processors.resource.GridResourceProcessor; import org.apache.ignite.internal.processors.resource.GridSpringResourceContext; @@ -226,23 +210,18 @@ import org.apache.ignite.plugin.PluginNotFoundException; import org.apache.ignite.plugin.PluginProvider; import org.apache.ignite.spi.IgniteSpi; import org.apache.ignite.spi.IgniteSpiVersionCheckException; -import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; import org.apache.ignite.spi.discovery.isolated.IsolatedDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode; import org.apache.ignite.spi.tracing.TracingConfigurationManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static java.util.Optional.ofNullable; import static org.apache.ignite.IgniteSystemProperties.IGNITE_BINARY_MARSHALLER_USE_STRING_SERIALIZATION_VER_2; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_CONFIG_URL; import static org.apache.ignite.IgniteSystemProperties.IGNITE_DAEMON; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_ASCII; import static org.apache.ignite.IgniteSystemProperties.IGNITE_OPTIMIZED_MARSHALLER_USE_DEFAULT_SUID; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_REST_START_ON_CLIENT; import static org.apache.ignite.IgniteSystemProperties.IGNITE_SKIP_CONFIGURATION_CONSISTENCY_CHECK; import static org.apache.ignite.IgniteSystemProperties.IGNITE_STARVATION_CHECK_INTERVAL; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_SUCCESS_FILE; import static org.apache.ignite.IgniteSystemProperties.getBoolean; import static org.apache.ignite.internal.GridKernalState.DISCONNECTED; import static org.apache.ignite.internal.GridKernalState.STARTED; @@ -288,13 +267,10 @@ import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_SHUTDOWN_POLI import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_SPI_CLASS; import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_TX_CONFIG; import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_USER_NAME; -import static org.apache.ignite.internal.IgniteVersionUtils.ACK_VER_STR; import static org.apache.ignite.internal.IgniteVersionUtils.BUILD_TSTAMP_STR; import static org.apache.ignite.internal.IgniteVersionUtils.COPYRIGHT; -import static org.apache.ignite.internal.IgniteVersionUtils.REV_HASH_STR; import static org.apache.ignite.internal.IgniteVersionUtils.VER; import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR; -import static org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager.INTERNAL_DATA_REGION_NAMES; import static org.apache.ignite.lifecycle.LifecycleEventType.AFTER_NODE_START; import static org.apache.ignite.lifecycle.LifecycleEventType.BEFORE_NODE_START; import static org.apache.ignite.mxbean.IgniteMXBean.ACTIVE_DESC; @@ -379,9 +355,6 @@ public class IgniteKernal implements IgniteEx, Externalizable { /** System line separator. */ public static final String NL = U.nl(); - /** System megabyte. */ - private static final int MEGABYTE = 1024 * 1024; - /** * Default interval of checking thread pool state for the starvation. Will be used only if the * {@link IgniteSystemProperties#IGNITE_STARVATION_CHECK_INTERVAL} system property is not set. @@ -407,6 +380,9 @@ public class IgniteKernal implements IgniteEx, Externalizable { /** @see IgniteSystemProperties#IGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP */ public static final boolean DFLT_LOG_CLASSPATH_CONTENT_ON_STARTUP = true; + /** Ignite node information provider. */ + private final IgniteLogInfoProvider info = loadInfoProvider(); + /** Currently used instance of JVM pause detector thread. See {@link LongJVMPauseDetector} for details. */ private LongJVMPauseDetector longJVMPauseDetector; @@ -591,7 +567,7 @@ public class IgniteKernal implements IgniteEx, Externalizable { } /** @return String representation of the uptime. */ - String upTimeFormatted() { + public String upTimeFormatted() { return X.timeSpan2DHMSM(upTime()); } @@ -858,100 +834,6 @@ public class IgniteKernal implements IgniteEx, Externalizable { } } - /** - * @param clsPathEntry Classpath string to process. - * @param clsPathContent StringBuilder to attach path to. - */ - private void ackClassPathEntry(String clsPathEntry, SB clsPathContent) { - File clsPathElementFile = new File(clsPathEntry); - - if (clsPathElementFile.isDirectory()) - clsPathContent.a(clsPathEntry).a(";"); - else { - String extension = clsPathEntry.length() >= 4 - ? clsPathEntry.substring(clsPathEntry.length() - 4).toLowerCase() - : null; - - if (".jar".equals(extension) || ".zip".equals(extension)) - clsPathContent.a(clsPathEntry).a(";"); - } - } - - /** - * @param clsPathEntry Classpath string to process. - * @param clsPathContent StringBuilder to attach path to. - */ - private void ackClassPathWildCard(String clsPathEntry, SB clsPathContent) { - final int lastSeparatorIdx = clsPathEntry.lastIndexOf(File.separator); - - final int asteriskIdx = clsPathEntry.indexOf('*'); - - //just to log possibly incorrent entries to err - if (asteriskIdx >= 0 && asteriskIdx < lastSeparatorIdx) - throw new RuntimeException("Could not parse classpath entry"); - - final int fileMaskFirstIdx = lastSeparatorIdx + 1; - - final String fileMask = - (fileMaskFirstIdx >= clsPathEntry.length()) ? "*.jar" : clsPathEntry.substring(fileMaskFirstIdx); - - Path path = Paths.get(lastSeparatorIdx > 0 ? clsPathEntry.substring(0, lastSeparatorIdx) : ".") - .toAbsolutePath() - .normalize(); - - if (lastSeparatorIdx == 0) - path = path.getRoot(); - - try { - DirectoryStream<Path> files = - Files.newDirectoryStream(path, fileMask); - - for (Path f : files) { - String s = f.toString(); - - if (s.toLowerCase().endsWith(".jar")) - clsPathContent.a(f.toString()).a(";"); - } - } - catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - /** - * Prints the list of {@code *.jar} and {@code *.class} files containing in the classpath. - */ - private void ackClassPathContent() { - assert log != null; - - boolean enabled = IgniteSystemProperties.getBoolean(IGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP, - DFLT_LOG_CLASSPATH_CONTENT_ON_STARTUP); - - if (enabled) { - String clsPath = System.getProperty("java.class.path", "."); - - String[] clsPathElements = clsPath.split(File.pathSeparator); - - U.log(log, "Classpath value: " + clsPath); - - SB clsPathContent = new SB("List of files containing in classpath: "); - - for (String clsPathEntry : clsPathElements) { - try { - if (clsPathEntry.contains("*")) - ackClassPathWildCard(clsPathEntry, clsPathContent); - else - ackClassPathEntry(clsPathEntry, clsPathContent); - } - catch (Exception e) { - U.warn(log, String.format("Could not log class path entry '%s': %s", clsPathEntry, e.getMessage())); - } - } - - U.log(log, clsPathContent.toString()); - } - } - /** * @param cfg Ignite configuration to use. * @param errHnd Error handler to use for notification about startup problems. @@ -965,8 +847,7 @@ public class IgniteKernal implements IgniteEx, Externalizable { WorkersRegistry workerRegistry, Thread.UncaughtExceptionHandler hnd, TimeBag startTimer - ) - throws IgniteCheckedException { + ) throws IgniteCheckedException { gw.compareAndSet(null, new GridKernalGatewayImpl(cfg.getIgniteInstanceName())); GridKernalGateway gw = this.gw.get(); @@ -1018,32 +899,7 @@ public class IgniteKernal implements IgniteEx, Externalizable { longJVMPauseDetector.start(); - RuntimeMXBean rtBean = ManagementFactory.getRuntimeMXBean(); - - // Ack various information. - ackAsciiLogo(); - ackConfigUrl(); - ackConfiguration(cfg); - ackDaemon(); - ackOsInfo(); - ackLanguageRuntime(); - ackRemoteManagement(); - ackLogger(); - ackVmArguments(rtBean); - ackClassPaths(rtBean); - ackSystemProperties(); - ackEnvironmentVariables(); - ackMemoryConfiguration(); - ackCacheConfiguration(); - ackP2pConfiguration(); - ackRebalanceConfiguration(); - ackIPv4StackFlagIsSet(); - ackWaitForBackupsOnShutdownPropertyIsUsed(); - - // Ack 3-rd party licenses location. - if (log.isInfoEnabled() && cfg.getIgniteHome() != null) - log.info("3-rd party licenses can be found at: " + cfg.getIgniteHome() + File.separatorChar + "libs" + - File.separatorChar + "licenses"); + info.ackKernalInited(log, cfg); // Check that user attributes are not conflicting // with internally reserved names. @@ -1052,12 +908,6 @@ public class IgniteKernal implements IgniteEx, Externalizable { throw new IgniteCheckedException("User attribute has illegal name: '" + name + "'. Note that all names " + "starting with '" + ATTR_PREFIX + "' are reserved for internal use."); - // Ack local node user attributes. - logNodeUserAttributes(); - - // Ack configuration. - ackSpis(); - List<PluginProvider> plugins = cfg.getPluginProviders() != null && cfg.getPluginProviders().length > 0 ? Arrays.asList(cfg.getPluginProviders()) : U.allPluginProviders(); @@ -1156,8 +1006,6 @@ public class IgniteKernal implements IgniteEx, Externalizable { startManager(new GridCollisionManager(ctx)); startManager(new GridIndexingManager(ctx)); - ackSecurity(); - // Assign discovery manager to context before other processors start so they // are able to register custom event listener. GridDiscoveryManager discoMgr = new GridDiscoveryManager(ctx); @@ -1494,34 +1342,23 @@ public class IgniteKernal implements IgniteEx, Externalizable { }, interval, interval); } + Ignite g = this; long metricsLogFreq = cfg.getMetricsLogFrequency(); if (metricsLogFreq > 0) { - metricsLogTask = ctx.timeout().schedule(new Runnable() { - private final DecimalFormat dblFmt = doubleFormat(); - - @Override public void run() { - ackNodeMetrics( - dblFmt, - ctx.pools().getExecutorService(), - ctx.pools().getSystemExecutorService(), - ctx.pools().getStripedExecutorService(), - ctx.pools().customExecutors() - ); + metricsLogTask = ctx.timeout().schedule(() -> { + try { + info.ackNodeBasicMetrics(log, g); + info.ackNodeDataStorageMetrics(log, g); + info.ackNodeMemoryStatisticsMetrics(log, g); + } + catch (IgniteClientDisconnectedException ignore) { + // No-op. } }, metricsLogFreq, metricsLogFreq); } - ctx.performance().add("Disable assertions (remove '-ea' from JVM options)", !U.assertionsEnabled()); - - ctx.performance().logSuggestions(log, igniteInstanceName); - - U.quietAndInfo(log, "To start Console Management & Monitoring run ignitevisorcmd.{sh|bat}"); - - if (!IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_QUIET, true)) - ackClassPathContent(); - - ackStart(rtBean); + info.ackKernalStarted(log, this); if (!isDaemon()) ctx.discovery().ackTopology(ctx.discovery().localJoin().joinTopologyVersion().topologyVersion(), @@ -1530,11 +1367,6 @@ public class IgniteKernal implements IgniteEx, Externalizable { startTimer.finishGlobalStage("Await exchange"); } - /** */ - private static DecimalFormat doubleFormat() { - return new DecimalFormat("#.##", DecimalFormatSymbols.getInstance(Locale.US)); - } - /** * @return Ignite security processor. See {@link IgniteSecurity} for details. */ @@ -1801,7 +1633,7 @@ public class IgniteKernal implements IgniteEx, Externalizable { add(ATTR_SHUTDOWN_POLICY, cfg.getShutdownPolicy().index()); add(ATTR_DEPLOYMENT_MODE, cfg.getDeploymentMode()); - add(ATTR_LANG_RUNTIME, getLanguage()); + add(ATTR_LANG_RUNTIME, U.language(U.resolveClassLoader(cfg))); add(ATTR_JVM_PID, U.jvmPid()); @@ -1956,510 +1788,9 @@ public class IgniteKernal implements IgniteEx, Externalizable { } } - /** - * @param helper Helper to attach to kernal context. - */ - private void addHelper(Object helper) { - ctx.addHelper(helper); - } - - /** - * Gets "on" or "off" string for given boolean value. - * - * @param b Boolean value to convert. - * @return Result string. - */ - private String onOff(boolean b) { - return b ? "on" : "off"; - } - - /** - * @return {@code true} if the REST processor is enabled, {@code false} the otherwise. - */ - private boolean isRestEnabled() { - assert cfg != null; - - return cfg.getConnectorConfiguration() != null && - // By default rest processor doesn't start on client nodes. - (!isClientNode() || (isClientNode() && IgniteSystemProperties.getBoolean(IGNITE_REST_START_ON_CLIENT))); - } - - /** - * @return {@code True} if node client or daemon otherwise {@code false}. - */ - private boolean isClientNode() { - return cfg.isClientMode() || cfg.isDaemon(); - } - - /** - * Acks remote management. - */ - private void ackRemoteManagement() { - assert log != null; - - if (!log.isInfoEnabled()) - return; - - SB sb = new SB(); - - sb.a("Remote Management ["); - - boolean on = isJmxRemoteEnabled(); - - sb.a("restart: ").a(onOff(isRestartEnabled())).a(", "); - sb.a("REST: ").a(onOff(isRestEnabled())).a(", "); - sb.a("JMX ("); - sb.a("remote: ").a(onOff(on)); - - if (on) { - sb.a(", "); - - sb.a("port: ").a(System.getProperty("com.sun.management.jmxremote.port", "<n/a>")).a(", "); - sb.a("auth: ").a(onOff(Boolean.getBoolean("com.sun.management.jmxremote.authenticate"))).a(", "); - - // By default SSL is enabled, that's why additional check for null is needed. - // See http://docs.oracle.com/javase/6/docs/technotes/guides/management/agent.html - sb.a("ssl: ").a(onOff(Boolean.getBoolean("com.sun.management.jmxremote.ssl") || - System.getProperty("com.sun.management.jmxremote.ssl") == null)); - } - - sb.a(")"); - - sb.a(']'); - - log.info(sb.toString()); - } - - /** - * Acks configuration URL. - */ - private void ackConfigUrl() { - assert log != null; - - if (log.isInfoEnabled()) - log.info("Config URL: " + System.getProperty(IGNITE_CONFIG_URL, "n/a")); - } - - /** - * @param cfg Ignite configuration to ack. - */ - private void ackConfiguration(IgniteConfiguration cfg) { - assert log != null; - - if (log.isInfoEnabled()) - log.info(cfg.toString()); - } - - /** - * Acks Logger configuration. - */ - private void ackLogger() { - assert log != null; - - if (log.isInfoEnabled()) - log.info("Logger: " + log.getLoggerInfo()); - } - - /** - * Acks ASCII-logo. Thanks to http://patorjk.com/software/taag - */ - private void ackAsciiLogo() { - assert log != null; - - if (System.getProperty(IGNITE_NO_ASCII) == null) { - String ver = "ver. " + ACK_VER_STR; - - // Big thanks to: http://patorjk.com/software/taag - // Font name "Small Slant" - if (log.isInfoEnabled()) { - log.info(NL + NL + - ">>> __________ ________________ " + NL + - ">>> / _/ ___/ |/ / _/_ __/ __/ " + NL + - ">>> _/ // (7 7 // / / / / _/ " + NL + - ">>> /___/\\___/_/|_/___/ /_/ /___/ " + NL + - ">>> " + NL + - ">>> " + ver + NL + - ">>> " + COPYRIGHT + NL + - ">>> " + NL + - ">>> Ignite documentation: " + "http://" + SITE + NL - ); - } - - if (log.isQuiet()) { - U.quiet(false, - " __________ ________________ ", - " / _/ ___/ |/ / _/_ __/ __/ ", - " _/ // (7 7 // / / / / _/ ", - "/___/\\___/_/|_/___/ /_/ /___/ ", - "", - ver, - COPYRIGHT, - "", - "Ignite documentation: " + "http://" + SITE, - "", - "Quiet mode."); - - String fileName = log.fileName(); - - if (fileName != null) - U.quiet(false, " ^-- Logging to file '" + fileName + '\''); - - U.quiet(false, " ^-- Logging by '" + log.getLoggerInfo() + '\''); - - U.quiet(false, - " ^-- To see **FULL** console log here add -DIGNITE_QUIET=false or \"-v\" to ignite.{sh|bat}", - ""); - } - } - } - - /** - * Prints start info. - * - * @param rtBean Java runtime bean. - */ - private void ackStart(RuntimeMXBean rtBean) { - ClusterNode locNode = localNode(); - - if (log.isQuiet()) { - U.quiet(false, ""); - - U.quiet(false, "Ignite node started OK (id=" + U.id8(locNode.id()) + - (F.isEmpty(igniteInstanceName) ? "" : ", instance name=" + igniteInstanceName) + ')'); - } - - if (log.isInfoEnabled()) { - String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR; - - String dash = U.dash(ack.length()); - - SB sb = new SB(); - - for (GridPortRecord rec : ctx.ports().records()) - sb.a(rec.protocol()).a(":").a(rec.port()).a(" "); - - String str = - NL + NL + - ">>> " + dash + NL + - ">>> " + ack + NL + - ">>> " + dash + NL + - ">>> OS name: " + U.osString() + NL + - ">>> CPU(s): " + locNode.metrics().getTotalCpus() + NL + - ">>> Heap: " + U.heapSize(locNode, 2) + "GB" + NL + - ">>> VM name: " + rtBean.getName() + NL + - (igniteInstanceName == null ? "" : ">>> Ignite instance name: " + igniteInstanceName + NL) + - ">>> Local node [" + - "ID=" + locNode.id().toString().toUpperCase() + - ", order=" + locNode.order() + ", clientMode=" + ctx.clientNode() + - "]" + NL + - ">>> Local node addresses: " + U.addressesAsString(locNode) + NL + - ">>> Local ports: " + sb + NL; - - log.info(str); - } - - if (ctx.state().clusterState().state() == ClusterState.INACTIVE) { - U.quietAndInfo(log, ">>> Ignite cluster is in INACTIVE state (limited functionality available). " + - "Use control.(sh|bat) script or IgniteCluster.state(ClusterState.ACTIVE) to change the state."); - } - } - - /** - * Logs out OS information. - */ - private void ackOsInfo() { - assert log != null; - - if (log.isQuiet()) - U.quiet(false, "OS: " + U.osString()); - - if (log.isInfoEnabled()) { - log.info("OS: " + U.osString()); - log.info("OS user: " + System.getProperty("user.name")); - - int jvmPid = U.jvmPid(); - - log.info("PID: " + (jvmPid == -1 ? "N/A" : jvmPid)); - } - } - - /** - * Logs out language runtime. - */ - private void ackLanguageRuntime() { - assert log != null; - - if (log.isQuiet()) - U.quiet(false, "VM information: " + U.jdkString()); - - if (log.isInfoEnabled()) { - log.info("Language runtime: " + getLanguage()); - log.info("VM information: " + U.jdkString()); - log.info("VM total memory: " + U.heapSize(2) + "GB"); - } - } - - /** - * Logs out node metrics. - * - * @param dblFmt Decimal format. - * @param execSvc Executor service. - * @param sysExecSvc System executor service. - * @param customExecSvcs Custom named executors. - */ - private void ackNodeMetrics(DecimalFormat dblFmt, - ExecutorService execSvc, - ExecutorService sysExecSvc, - ExecutorService stripedExecSvc, - Map<String, ? extends ExecutorService> customExecSvcs - ) { - if (!log.isInfoEnabled()) - return; - - try { - ClusterMetrics m = cluster().localNode().metrics(); - - int localCpus = m.getTotalCpus(); - double cpuLoadPct = m.getCurrentCpuLoad() * 100; - double avgCpuLoadPct = m.getAverageCpuLoad() * 100; - double gcPct = m.getCurrentGcCpuLoad() * 100; - - // Heap params. - long heapUsed = m.getHeapMemoryUsed(); - long heapMax = m.getHeapMemoryMaximum(); - - long heapUsedInMBytes = heapUsed / MEGABYTE; - long heapCommInMBytes = m.getHeapMemoryCommitted() / MEGABYTE; - - double freeHeapPct = heapMax > 0 ? ((double)((heapMax - heapUsed) * 100)) / heapMax : -1; - - int hosts = 0; - int servers = 0; - int clients = 0; - int cpus = 0; - - try { - ClusterMetrics metrics = cluster().metrics(); - - Collection<ClusterNode> nodes0 = cluster().nodes(); - - hosts = U.neighborhood(nodes0).size(); - servers = cluster().forServers().nodes().size(); - clients = cluster().forClients().nodes().size(); - cpus = metrics.getTotalCpus(); - } - catch (IgniteException ignore) { - // No-op. - } - - String dataStorageInfo = dataStorageReport(ctx.cache().context().database(), dblFmt, true); - - String id = U.id8(localNode().id()); - - AffinityTopologyVersion topVer = ctx.discovery().topologyVersionEx(); - - ClusterNode locNode = ctx.discovery().localNode(); - - String networkDetails = ""; - - if (!F.isEmpty(cfg.getLocalHost())) - networkDetails += ", localHost=" + cfg.getLocalHost(); - - if (locNode instanceof TcpDiscoveryNode) - networkDetails += ", discoPort=" + ((TcpDiscoveryNode)locNode).discoveryPort(); - - if (cfg.getCommunicationSpi() instanceof TcpCommunicationSpi) - networkDetails += ", commPort=" + ((TcpCommunicationSpi)cfg.getCommunicationSpi()).boundPort(); - - SB msg = new SB(); - - msg.nl() - .a("Metrics for local node (to disable set 'metricsLogFrequency' to 0)").nl() - .a(" ^-- Node [id=").a(id).a(name() != null ? ", name=" + name() : "").a(", uptime=") - .a(upTimeFormatted()).a("]").nl() - .a(" ^-- Cluster [hosts=").a(hosts).a(", CPUs=").a(cpus).a(", servers=").a(servers) - .a(", clients=").a(clients).a(", topVer=").a(topVer.topologyVersion()) - .a(", minorTopVer=").a(topVer.minorTopologyVersion()).a("]").nl() - .a(" ^-- Network [addrs=").a(locNode.addresses()).a(networkDetails).a("]").nl() - .a(" ^-- CPU [CPUs=").a(localCpus).a(", curLoad=").a(dblFmt.format(cpuLoadPct)) - .a("%, avgLoad=").a(dblFmt.format(avgCpuLoadPct)).a("%, GC=").a(dblFmt.format(gcPct)).a("%]").nl() - .a(" ^-- Heap [used=").a(dblFmt.format(heapUsedInMBytes)) - .a("MB, free=").a(dblFmt.format(freeHeapPct)) - .a("%, comm=").a(dblFmt.format(heapCommInMBytes)).a("MB]").nl() - .a(dataStorageInfo) - .a(" ^-- Outbound messages queue [size=").a(m.getOutboundMessagesQueueSize()).a("]").nl() - .a(" ^-- ").a(createExecutorDescription("Public thread pool", execSvc)).nl() - .a(" ^-- ").a(createExecutorDescription("System thread pool", sysExecSvc)).nl() - .a(" ^-- ").a(createExecutorDescription("Striped thread pool", stripedExecSvc)); - - if (customExecSvcs != null) { - for (Map.Entry<String, ? extends ExecutorService> entry : customExecSvcs.entrySet()) - msg.nl().a(" ^-- ").a(createExecutorDescription(entry.getKey(), entry.getValue())); - } - - log.info(msg.toString()); - - ctx.cache().context().database().dumpStatistics(log); - } - catch (IgniteClientDisconnectedException ignore) { - // No-op. - } - } - /** */ - public static String dataStorageReport(IgniteCacheDatabaseSharedManager db, boolean includeMemoryStatistics) { - return dataStorageReport(db, doubleFormat(), includeMemoryStatistics); - } - - /** */ - private static String dataStorageReport(IgniteCacheDatabaseSharedManager db, DecimalFormat dblFmt, - boolean includeMemoryStatistics) { - // Off-heap params. - Collection<DataRegion> regions = db.dataRegions(); - - SB dataRegionsInfo = new SB(); - - long loadedPages = 0; - long offHeapUsedSummary = 0; - long offHeapMaxSummary = 0; - long offHeapCommSummary = 0; - long pdsUsedSummary = 0; - - boolean persistenceEnabled = false; - - if (!F.isEmpty(regions)) { - for (DataRegion region : regions) { - DataRegionConfiguration regCfg = region.config(); - - long pagesCnt = region.pageMemory().loadedPages(); - - long offHeapUsed = region.pageMemory().systemPageSize() * pagesCnt; - long offHeapInit = regCfg.getInitialSize(); - long offHeapMax = regCfg.getMaxSize(); - long offHeapComm = region.metrics().getOffHeapSize(); - - long offHeapUsedInMBytes = offHeapUsed / MEGABYTE; - long offHeapMaxInMBytes = offHeapMax / MEGABYTE; - long offHeapCommInMBytes = offHeapComm / MEGABYTE; - long offHeapInitInMBytes = offHeapInit / MEGABYTE; - - double freeOffHeapPct = offHeapMax > 0 ? - ((double)((offHeapMax - offHeapUsed) * 100)) / offHeapMax : -1; - - offHeapUsedSummary += offHeapUsed; - offHeapMaxSummary += offHeapMax; - offHeapCommSummary += offHeapComm; - loadedPages += pagesCnt; - - String type = "user"; - - try { - if (region == db.dataRegion(null)) - type = "default"; - else if (INTERNAL_DATA_REGION_NAMES.contains(regCfg.getName())) - type = "internal"; - } - catch (IgniteCheckedException ice) { - // Should never happen - ice.printStackTrace(); - } - - dataRegionsInfo.a(" ^-- ") - .a(regCfg.getName()).a(" region [type=").a(type) - .a(", persistence=").a(regCfg.isPersistenceEnabled()) - .a(", lazyAlloc=").a(regCfg.isLazyMemoryAllocation()).a(',').nl() - .a(" ... ") - .a("initCfg=").a(dblFmt.format(offHeapInitInMBytes)) - .a("MB, maxCfg=").a(dblFmt.format(offHeapMaxInMBytes)) - .a("MB, usedRam=").a(dblFmt.format(offHeapUsedInMBytes)) - .a("MB, freeRam=").a(dblFmt.format(freeOffHeapPct)) - .a("%, allocRam=").a(dblFmt.format(offHeapCommInMBytes)).a("MB"); - - if (regCfg.isPersistenceEnabled()) { - long pdsUsed = region.metrics().getTotalAllocatedSize(); - long pdsUsedInMBytes = pdsUsed / MEGABYTE; - - pdsUsedSummary += pdsUsed; - - dataRegionsInfo.a(", allocTotal=").a(dblFmt.format(pdsUsedInMBytes)).a("MB"); - - persistenceEnabled = true; - } - - dataRegionsInfo.a(']').nl(); - } - } - - SB info = new SB(); - - if (includeMemoryStatistics) { - long offHeapUsedInMBytes = offHeapUsedSummary / MEGABYTE; - long offHeapCommInMBytes = offHeapCommSummary / MEGABYTE; - - double freeOffHeapPct = offHeapMaxSummary > 0 ? - ((double)((offHeapMaxSummary - offHeapUsedSummary) * 100)) / offHeapMaxSummary : -1; - - info.a(" ^-- Off-heap memory [used=").a(dblFmt.format(offHeapUsedInMBytes)) - .a("MB, free=").a(dblFmt.format(freeOffHeapPct)) - .a("%, allocated=").a(dblFmt.format(offHeapCommInMBytes)).a("MB]").nl() - .a(" ^-- Page memory [pages=").a(loadedPages).a("]").nl(); - } - - info.a(dataRegionsInfo); - - if (persistenceEnabled) { - long pdsUsedMBytes = pdsUsedSummary / MEGABYTE; - - info.a(" ^-- Ignite persistence [used=").a(dblFmt.format(pdsUsedMBytes)).a("MB]").nl(); - } - - return info.toString(); - } - - /** - * @return Language runtime. - */ - private String getLanguage() { - boolean scala = false; - boolean groovy = false; - boolean clojure = false; - - for (StackTraceElement elem : Thread.currentThread().getStackTrace()) { - String s = elem.getClassName().toLowerCase(); - - if (s.contains("scala")) { - scala = true; - - break; - } - else if (s.contains("groovy")) { - groovy = true; - - break; - } - else if (s.contains("clojure")) { - clojure = true; - - break; - } - } - - if (scala) { - try (InputStream in = getClass().getResourceAsStream("/library.properties")) { - Properties props = new Properties(); - - if (in != null) - props.load(in); - - return "Scala ver. " + props.getProperty("version.number", "<unknown>"); - } - catch (Exception ignore) { - return "Scala ver. <unknown>"; - } - } - - // How to get Groovy and Clojure version at runtime?!? - return groovy ? "Groovy" : clojure ? "Clojure" : U.jdkName() + " ver. " + U.jdkVersion(); + public void dataStorageReport() { + info.ackNodeDataStorageMetrics(log, this); } /** @@ -2630,52 +1961,7 @@ public class IgniteKernal implements IgniteEx, Externalizable { gw.writeUnlock(); } - // Ack stop. - if (log.isQuiet()) { - String nodeName = igniteInstanceName == null ? "" : "name=" + igniteInstanceName + ", "; - - if (!errOnStop) - U.quiet(false, "Ignite node stopped OK [" + nodeName + "uptime=" + - X.timeSpan2DHMSM(U.currentTimeMillis() - startTime) + ']'); - else - U.quiet(true, "Ignite node stopped wih ERRORS [" + nodeName + "uptime=" + - X.timeSpan2DHMSM(U.currentTimeMillis() - startTime) + ']'); - } - - if (log.isInfoEnabled()) - if (!errOnStop) { - String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR + - " stopped OK"; - - String dash = U.dash(ack.length()); - - log.info(NL + NL + - ">>> " + dash + NL + - ">>> " + ack + NL + - ">>> " + dash + NL + - (igniteInstanceName == null ? "" : ">>> Ignite instance name: " + igniteInstanceName + NL) + - ">>> Grid uptime: " + X.timeSpan2DHMSM(U.currentTimeMillis() - startTime) + - NL + - NL); - } - else { - String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR + - " stopped with ERRORS"; - - String dash = U.dash(ack.length()); - - log.info(NL + NL + - ">>> " + ack + NL + - ">>> " + dash + NL + - (igniteInstanceName == null ? "" : ">>> Ignite instance name: " + igniteInstanceName + NL) + - ">>> Grid uptime: " + X.timeSpan2DHMSM(U.currentTimeMillis() - startTime) + - NL + - ">>> See log above for detailed error message." + NL + - ">>> Note that some errors during stop can prevent grid from" + NL + - ">>> maintaining correct topology since this node may have" + NL + - ">>> not exited grid properly." + NL + - NL); - } + info.ackKernalStopped(log, this, errOnStop); try { U.onGridStop(); @@ -2721,49 +2007,6 @@ public class IgniteKernal implements IgniteEx, Externalizable { return ctx; } - /** - * Prints all system properties in debug mode. - */ - private void ackSystemProperties() { - assert log != null; - - if (log.isDebugEnabled() && S.includeSensitive()) - for (Map.Entry<Object, Object> entry : IgniteSystemProperties.snapshot().entrySet()) - log.debug("System property [" + entry.getKey() + '=' + entry.getValue() + ']'); - } - - /** - * Prints all user attributes in info mode. - */ - private void logNodeUserAttributes() { - assert log != null; - - if (log.isInfoEnabled()) - for (Map.Entry<?, ?> attr : cfg.getUserAttributes().entrySet()) - log.info("Local node user attribute [" + attr.getKey() + '=' + attr.getValue() + ']'); - } - - /** - * Prints all environment variables in debug mode. - */ - private void ackEnvironmentVariables() { - assert log != null; - - if (log.isDebugEnabled()) - for (Map.Entry<?, ?> envVar : System.getenv().entrySet()) - log.debug("Environment variable [" + envVar.getKey() + '=' + envVar.getValue() + ']'); - } - - /** - * Acks daemon mode status. - */ - private void ackDaemon() { - assert log != null; - - if (log.isInfoEnabled()) - log.info("Daemon mode: " + (isDaemon() ? "on" : "off")); - } - /** * @return {@code True} is this node is daemon. */ @@ -2780,7 +2023,7 @@ public class IgniteKernal implements IgniteEx, Externalizable { * @return {@code True} if remote JMX management is enabled - {@code false} otherwise. */ @Override public boolean isJmxRemoteEnabled() { - return System.getProperty("com.sun.management.jmxremote") != null; + return U.isJmxRemoteEnabled(); } /** @@ -2792,210 +2035,7 @@ public class IgniteKernal implements IgniteEx, Externalizable { * @see Ignition#restart(boolean) */ @Override public boolean isRestartEnabled() { - return System.getProperty(IGNITE_SUCCESS_FILE) != null; - } - - /** - * Prints all configuration properties in info mode and SPIs in debug mode. - */ - private void ackSpis() { - assert log != null; - - if (log.isDebugEnabled()) { - log.debug("+-------------+"); - log.debug("START SPI LIST:"); - log.debug("+-------------+"); - log.debug("Grid checkpoint SPI : " + Arrays.toString(cfg.getCheckpointSpi())); - log.debug("Grid collision SPI : " + cfg.getCollisionSpi()); - log.debug("Grid communication SPI : " + cfg.getCommunicationSpi()); - log.debug("Grid deployment SPI : " + cfg.getDeploymentSpi()); - log.debug("Grid discovery SPI : " + cfg.getDiscoverySpi()); - log.debug("Grid event storage SPI : " + cfg.getEventStorageSpi()); - log.debug("Grid failover SPI : " + Arrays.toString(cfg.getFailoverSpi())); - log.debug("Grid load balancing SPI : " + Arrays.toString(cfg.getLoadBalancingSpi())); - } - } - - /** - * Acknowledge that the rebalance configuration properties are setted correctly. - * - * @throws IgniteCheckedException If rebalance configuration validation fail. - */ - private void ackRebalanceConfiguration() throws IgniteCheckedException { - if (cfg.isClientMode()) { - if (cfg.getRebalanceThreadPoolSize() != IgniteConfiguration.DFLT_REBALANCE_THREAD_POOL_SIZE) - U.warn(log, "Setting the rebalance pool size has no effect on the client mode"); - } - else { - if (cfg.getRebalanceThreadPoolSize() < 1) - throw new IgniteCheckedException("Rebalance thread pool size minimal allowed value is 1. " + - "Change IgniteConfiguration.rebalanceThreadPoolSize property before next start."); - - if (cfg.getRebalanceBatchesPrefetchCount() < 1) - throw new IgniteCheckedException("Rebalance batches prefetch count minimal allowed value is 1. " + - "Change IgniteConfiguration.rebalanceBatchesPrefetchCount property before next start."); - - if (cfg.getRebalanceBatchSize() <= 0) - throw new IgniteCheckedException("Rebalance batch size must be greater than zero. " + - "Change IgniteConfiguration.rebalanceBatchSize property before next start."); - - if (cfg.getRebalanceThrottle() < 0) - throw new IgniteCheckedException("Rebalance throttle can't have negative value. " + - "Change IgniteConfiguration.rebalanceThrottle property before next start."); - - if (cfg.getRebalanceTimeout() < 0) - throw new IgniteCheckedException("Rebalance message timeout can't have negative value. " + - "Change IgniteConfiguration.rebalanceTimeout property before next start."); - - for (CacheConfiguration ccfg : cfg.getCacheConfiguration()) { - if (ccfg.getRebalanceBatchesPrefetchCount() < 1) - throw new IgniteCheckedException("Rebalance batches prefetch count minimal allowed value is 1. " + - "Change CacheConfiguration.rebalanceBatchesPrefetchCount property before next start. " + - "[cache=" + ccfg.getName() + "]"); - } - } - } - - /** - * Acknowledge the Ignite configuration related to the data storage. - */ - private void ackMemoryConfiguration() { - DataStorageConfiguration memCfg = cfg.getDataStorageConfiguration(); - - if (memCfg == null) - return; - - U.log(log, "System cache's DataRegion size is configured to " + - (memCfg.getSystemDataRegionConfiguration().getInitialSize() / (1024 * 1024)) + " MB. " + - "Use DataStorageConfiguration.systemRegionInitialSize property to change the setting."); - } - - /** - * Acknowledge all caches configurations presented in the IgniteConfiguration. - */ - private void ackCacheConfiguration() { - CacheConfiguration[] cacheCfgs = cfg.getCacheConfiguration(); - - if (cacheCfgs == null || cacheCfgs.length == 0) - U.warn(log, "Cache is not configured - in-memory data grid is off."); - else { - SB sb = new SB(); - - HashMap<String, ArrayList<String>> memPlcNamesMapping = new HashMap<>(); - - for (CacheConfiguration c : cacheCfgs) { - String cacheName = U.maskName(c.getName()); - - String memPlcName = c.getDataRegionName(); - - if (CU.isSystemCache(cacheName)) - memPlcName = "sysMemPlc"; - else if (memPlcName == null && cfg.getDataStorageConfiguration() != null) - memPlcName = cfg.getDataStorageConfiguration().getDefaultDataRegionConfiguration().getName(); - - if (!memPlcNamesMapping.containsKey(memPlcName)) - memPlcNamesMapping.put(memPlcName, new ArrayList<String>()); - - ArrayList<String> cacheNames = memPlcNamesMapping.get(memPlcName); - - cacheNames.add(cacheName); - } - - for (Map.Entry<String, ArrayList<String>> e : memPlcNamesMapping.entrySet()) { - sb.a("in '").a(e.getKey()).a("' dataRegion: ["); - - for (String s : e.getValue()) - sb.a("'").a(s).a("', "); - - sb.d(sb.length() - 2, sb.length()).a("], "); - } - - U.log(log, "Configured caches [" + sb.d(sb.length() - 2, sb.length()).toString() + ']'); - } - } - - /** - * Acknowledge configuration related to the peer class loading. - */ - private void ackP2pConfiguration() { - assert cfg != null; - - if (cfg.isPeerClassLoadingEnabled()) - U.warn( - log, - "Peer class loading is enabled (disable it in production for performance and " + - "deployment consistency reasons)"); - } - - /** - * Prints security status. - */ - private void ackSecurity() { - assert log != null; - - U.quietAndInfo(log, "Security status [authentication=" + onOff(ctx.security().enabled()) - + ", sandbox=" + onOff(ctx.security().sandbox().enabled()) - + ", tls/ssl=" + onOff(ctx.config().getSslContextFactory() != null) + ']'); - } - - /** - * Prints out VM arguments and IGNITE_HOME in info mode. - * - * @param rtBean Java runtime bean. - */ - private void ackVmArguments(RuntimeMXBean rtBean) { - assert log != null; - - // Ack IGNITE_HOME and VM arguments. - if (log.isInfoEnabled() && S.includeSensitive()) { - log.info("IGNITE_HOME=" + cfg.getIgniteHome()); - log.info("VM arguments: " + rtBean.getInputArguments()); - } - } - - /** - * Prints out class paths in debug mode. - * - * @param rtBean Java runtime bean. - */ - private void ackClassPaths(RuntimeMXBean rtBean) { - assert log != null; - - // Ack all class paths. - if (log.isDebugEnabled()) { - try { - log.debug("Boot class path: " + rtBean.getBootClassPath()); - log.debug("Class path: " + rtBean.getClassPath()); - log.debug("Library path: " + rtBean.getLibraryPath()); - } - catch (Exception ignore) { - // No-op: ignore for Java 9+ and non-standard JVMs. - } - } - } - - /** - * Prints warning if 'java.net.preferIPv4Stack=true' is not set. - */ - private void ackIPv4StackFlagIsSet() { - boolean preferIPv4 = Boolean.valueOf(System.getProperty("java.net.preferIPv4Stack")); - - if (!preferIPv4) { - assert log != null; - - U.quietAndWarn(log, "Please set system property '-Djava.net.preferIPv4Stack=true' " + - "to avoid possible problems in mixed environments."); - } - } - - /** - * Prints warning if IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN is used. - */ - private void ackWaitForBackupsOnShutdownPropertyIsUsed() { - if (IgniteSystemProperties.getString(IgniteSystemProperties.IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN) != null) { - log.warning("IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN system property is deprecated and will be removed " + - "in a future version. Use ShutdownPolicy instead."); - } + return U.isRestartEnabled(); } /** @@ -4330,6 +3370,20 @@ public class IgniteKernal implements IgniteEx, Externalizable { } } + /** + * @return Loaded info provider. + */ + private static IgniteLogInfoProvider loadInfoProvider() { + try { + return ofNullable(F.first(U.loadService(IgniteLogInfoProvider.class))).orElse(new IgniteLogInfoProviderImpl()); + } + catch (Throwable t) { + U.error(null, t.getMessage()); + } + + return new IgniteLogInfoProviderImpl(); + } + /** * @param cls Component interface. * @return Name of component implementation class for open source edition. diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java index 1c263a4ee57..20ad0f234bb 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java @@ -141,7 +141,6 @@ import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOCAL_HOST; import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_SHUTDOWN_HOOK; import static org.apache.ignite.IgniteSystemProperties.IGNITE_OVERRIDE_CONSISTENT_ID; import static org.apache.ignite.IgniteSystemProperties.IGNITE_RESTART_CODE; -import static org.apache.ignite.IgniteSystemProperties.IGNITE_SUCCESS_FILE; import static org.apache.ignite.IgniteSystemProperties.IGNITE_SYSTEM_WORKER_BLOCKED_TIMEOUT; import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL; import static org.apache.ignite.cache.CacheMode.PARTITIONED; @@ -475,7 +474,7 @@ public class IgnitionEx { * @see Ignition#RESTART_EXIT_CODE */ public static void restart(boolean cancel) { - String file = System.getProperty(IGNITE_SUCCESS_FILE); + String file = U.IGNITE_SUCCESS_FILE_PROPERTY; if (file == null) U.warn(null, "Cannot restart node when restart not enabled."); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/plugin/IgniteLogInfoProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/plugin/IgniteLogInfoProvider.java new file mode 100644 index 00000000000..6d74eaad08e --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/plugin/IgniteLogInfoProvider.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.plugin; + +import java.util.ServiceLoader; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteLogger; +import org.apache.ignite.configuration.IgniteConfiguration; + +/** + * Pluggable Ignite component that is responsible for printing custom information during the Ignite lifecycle start phase. + * The Ignite info is loaded using JDK {@link ServiceLoader}. + */ +public interface IgniteLogInfoProvider { + /** + * @param log Ignite logger. + * @param cfg Ignite configuration. + */ + public void ackKernalInited(IgniteLogger log, IgniteConfiguration cfg); + + /** + * @param log Ignite logger. + * @param ignite Ignite instance. + */ + public void ackKernalStarted(IgniteLogger log, Ignite ignite); + + /** + * @param log Ignite logger. + * @param ignite Ignite instance. + * @param err {@code True} if error occurred during the Ignite instance stop process. + */ + public void ackKernalStopped(IgniteLogger log, Ignite ignite, boolean err); + + /** + * @param log Ignite logger. + * @param ignite Ignite instance. + */ + public void ackNodeBasicMetrics(IgniteLogger log, Ignite ignite); + + /** + * @param log Ignite logger. + * @param ignite Ignite instance. + */ + public void ackNodeDataStorageMetrics(IgniteLogger log, Ignite ignite); + + /** + * @param log Ignite logger. + * @param ignite Ignite instance. + */ + public void ackNodeMemoryStatisticsMetrics(IgniteLogger log, Ignite ignite); +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/plugin/IgniteLogInfoProviderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/plugin/IgniteLogInfoProviderImpl.java new file mode 100644 index 00000000000..27fed709e3b --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/plugin/IgniteLogInfoProviderImpl.java @@ -0,0 +1,1018 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.plugin; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; +import org.apache.ignite.IgniteLogger; +import org.apache.ignite.IgniteSystemProperties; +import org.apache.ignite.cluster.ClusterMetrics; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.cluster.ClusterState; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.DataRegionConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.GridLoggerProxy; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.IgniteKernal; +import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; +import org.apache.ignite.internal.processors.cache.persistence.DataRegion; +import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager; +import org.apache.ignite.internal.processors.port.GridPortRecord; +import org.apache.ignite.internal.util.StripedExecutor; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.CU; +import org.apache.ignite.internal.util.typedef.internal.S; +import org.apache.ignite.internal.util.typedef.internal.SB; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi; +import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode; + +import static org.apache.ignite.IgniteSystemProperties.IGNITE_CONFIG_URL; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_DAEMON; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_ASCII; +import static org.apache.ignite.internal.IgniteKernal.DFLT_LOG_CLASSPATH_CONTENT_ON_STARTUP; +import static org.apache.ignite.internal.IgniteKernal.NL; +import static org.apache.ignite.internal.IgniteKernal.SITE; +import static org.apache.ignite.internal.IgniteVersionUtils.ACK_VER_STR; +import static org.apache.ignite.internal.IgniteVersionUtils.BUILD_TSTAMP_STR; +import static org.apache.ignite.internal.IgniteVersionUtils.COPYRIGHT; +import static org.apache.ignite.internal.IgniteVersionUtils.REV_HASH_STR; +import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR; +import static org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager.INTERNAL_DATA_REGION_NAMES; +import static org.apache.ignite.internal.util.IgniteUtils.MB; + +/** + * Default implementation of Ignite information. + */ +public class IgniteLogInfoProviderImpl implements IgniteLogInfoProvider { + /** Format of output metrics. */ + private final DecimalFormat decimalFormat = new DecimalFormat("#.##", DecimalFormatSymbols.getInstance(Locale.US)); + + /** {@inheritDoc} */ + @Override public void ackKernalInited(IgniteLogger log, IgniteConfiguration cfg) { + assert log != null; + + RuntimeMXBean rtBean = ManagementFactory.getRuntimeMXBean(); + + ackAsciiLogo(log, cfg, rtBean); + ackConfigUrl(log); + ackConfiguration(log, cfg); + ackDaemon(log, cfg); + ackOsInfo(log); + ackLanguageRuntime(log, cfg); + ackRemoteManagement(log, cfg); + ackLogger(log); + ackVmArguments(log, cfg, rtBean); + ackClassPaths(log, rtBean); + ackSystemProperties(log); + ackEnvironmentVariables(log); + ackMemoryConfiguration(log, cfg); + ackCacheConfiguration(log, cfg); + + if (cfg.isPeerClassLoadingEnabled()) + ackP2pConfiguration(log); + + ackRebalanceConfiguration(log, cfg); + ackIPv4StackFlagIsSet(log); + ackWaitForBackupsOnShutdownPropertyIsUsed(log); + ack3rdPartyLicenses(log, cfg); + logNodeUserAttributes(log, cfg); + ackSpis(log, cfg); + } + + /** {@inheritDoc} */ + @Override public void ackNodeBasicMetrics(IgniteLogger log, Ignite ignite) { + ackNodeBasicMetrics(log, (IgniteEx)ignite, decimalFormat); + } + + /** {@inheritDoc} */ + @Override public void ackNodeDataStorageMetrics(IgniteLogger log, Ignite ignite) { + GridKernalContext ctx = ((IgniteEx)ignite).context(); + + dataStorageReport(log, ctx.cache().context().database(), decimalFormat); + } + + /** {@inheritDoc} */ + @Override public void ackNodeMemoryStatisticsMetrics(IgniteLogger log, Ignite ignite) { + GridKernalContext ctx = ((IgniteEx)ignite).context(); + + memoryStatisticsReport(log, ctx.cache().context().database(), decimalFormat); + } + + /** {@inheritDoc} */ + @Override public void ackKernalStarted(IgniteLogger log, Ignite ignite) { + IgniteEx igEx = (IgniteEx)ignite; + + ackSecurity(log, ignite); + ackPerformanceSuggestions(log, igEx); + ackVisorConsole(log); + ackClassPathContent(log); + ackNodeInfo(log, igEx); + } + + /** {@inheritDoc} */ + @Override public void ackKernalStopped(IgniteLogger log, Ignite ignite, boolean err) { + ackNodeStopped(log, (IgniteEx)ignite, err); + } + + /** + * Acks ASCII-logo. Thanks to http://patorjk.com/software/taag + */ + void ackAsciiLogo(IgniteLogger log, IgniteConfiguration cfg, RuntimeMXBean rtBean) { + if (System.getProperty(IGNITE_NO_ASCII) != null) + return; + + String ver = "ver. " + ACK_VER_STR; + + // Big thanks to: http://patorjk.com/software/taag + // Font name "Small Slant" + if (log.isInfoEnabled()) { + log.info(NL + NL + + ">>> __________ ________________ " + NL + + ">>> / _/ ___/ |/ / _/_ __/ __/ " + NL + + ">>> _/ // (7 7 // / / / / _/ " + NL + + ">>> /___/\\___/_/|_/___/ /_/ /___/ " + NL + + ">>> " + NL + + ">>> " + ver + NL + + ">>> " + COPYRIGHT + NL + + ">>> " + NL + + ">>> Ignite documentation: " + "https://" + SITE + NL + ); + } + + if (log.isQuiet()) { + U.quiet(false, + " __________ ________________ ", + " / _/ ___/ |/ / _/_ __/ __/ ", + " _/ // (7 7 // / / / / _/ ", + "/___/\\___/_/|_/___/ /_/ /x___/ ", + "", + ver, + COPYRIGHT, + "", + "Ignite documentation: " + "https://" + SITE, + "", + "Quiet mode."); + + String fileName = log.fileName(); + + if (fileName != null) + U.quiet(false, " ^-- Logging to file '" + fileName + '\''); + + U.quiet(false, " ^-- Logging by '" + ((GridLoggerProxy)log).getLoggerInfo() + '\''); + + U.quiet(false, + " ^-- To see **FULL** console log here add -DIGNITE_QUIET=false or \"-v\" to ignite.{sh|bat}", + ""); + } + } + + /** + * Acks configuration URL. + */ + void ackConfigUrl(IgniteLogger log) { + if (log.isInfoEnabled()) + log.info("Config URL: " + System.getProperty(IGNITE_CONFIG_URL, "n/a")); + } + + /** + * @param cfg Ignite configuration to ack. + */ + void ackConfiguration(IgniteLogger log, IgniteConfiguration cfg) { + if (log.isInfoEnabled()) + log.info(cfg.toString()); + } + + /** + * Acks daemon mode status. + */ + void ackDaemon(IgniteLogger log, IgniteConfiguration cfg) { + if (log.isInfoEnabled()) + log.info("Daemon mode: " + onOff(cfg.isDaemon() || IgniteSystemProperties.getBoolean(IGNITE_DAEMON))); + } + + /** + * Logs out OS information. + */ + void ackOsInfo(IgniteLogger log) { + if (log.isQuiet()) + U.quiet(false, "OS: " + U.osString()); + + if (log.isInfoEnabled()) { + log.info("OS: " + U.osString()); + log.info("OS user: " + System.getProperty("user.name")); + + int jvmPid = U.jvmPid(); + + log.info("PID: " + (jvmPid == -1 ? "N/A" : jvmPid)); + } + } + + /** + * Logs out language runtime. + */ + void ackLanguageRuntime(IgniteLogger log, IgniteConfiguration cfg) { + if (log.isQuiet()) + U.quiet(false, "VM information: " + U.jdkString()); + + if (log.isInfoEnabled()) { + log.info("Language runtime: " + U.language(U.resolveClassLoader(cfg))); + log.info("VM information: " + U.jdkString()); + log.info("VM total memory: " + U.heapSize(2) + "GB"); + } + } + + /** + * Acks remote management. + */ + void ackRemoteManagement(IgniteLogger log, IgniteConfiguration cfg) { + if (!log.isInfoEnabled()) + return; + + SB sb = new SB(); + + sb.a("Remote Management ["); + + boolean on = U.isJmxRemoteEnabled(); + + sb.a("restart: ").a(onOff(U.isRestartEnabled())).a(", "); + sb.a("REST: ").a(onOff(U.isRestEnabled(cfg))).a(", "); + sb.a("JMX ("); + sb.a("remote: ").a(onOff(on)); + + if (on) { + sb.a(", "); + + sb.a("port: ").a(System.getProperty("com.sun.management.jmxremote.port", "<n/a>")).a(", "); + sb.a("auth: ").a(onOff(Boolean.getBoolean("com.sun.management.jmxremote.authenticate"))).a(", "); + + // By default, SSL is enabled, that's why additional check for null is needed. + // See http://docs.oracle.com/javase/6/docs/technotes/guides/management/agent.html + sb.a("ssl: ").a(onOff(Boolean.getBoolean("com.sun.management.jmxremote.ssl") || + System.getProperty("com.sun.management.jmxremote.ssl") == null)); + } + + sb.a(")"); + + sb.a(']'); + + log.info(sb.toString()); + } + + /** + * Acks Logger configuration. + */ + void ackLogger(IgniteLogger log) { + if (log.isInfoEnabled()) + log.info("Logger: " + ((GridLoggerProxy)log).getLoggerInfo()); + } + + /** + * Prints out VM arguments and IGNITE_HOME in info mode. + * + * @param rtBean Java runtime bean. + */ + void ackVmArguments(IgniteLogger log, IgniteConfiguration cfg, RuntimeMXBean rtBean) { + // Ack IGNITE_HOME and VM arguments. + if (log.isInfoEnabled() && S.includeSensitive()) { + log.info("IGNITE_HOME=" + cfg.getIgniteHome()); + log.info("VM arguments: " + rtBean.getInputArguments()); + } + } + + /** + * Prints out class paths in debug mode. + * + * @param rtBean Java runtime bean. + */ + void ackClassPaths(IgniteLogger log, RuntimeMXBean rtBean) { + // Ack all class paths. + if (log.isDebugEnabled()) { + try { + log.debug("Boot class path: " + rtBean.getBootClassPath()); + log.debug("Class path: " + rtBean.getClassPath()); + log.debug("Library path: " + rtBean.getLibraryPath()); + } + catch (Exception ignore) { + // No-op: ignore for Java 9+ and non-standard JVMs. + } + } + } + + /** + * Prints all system properties in debug mode. + */ + void ackSystemProperties(IgniteLogger log) { + if (log.isDebugEnabled() && S.includeSensitive()) + for (Map.Entry<Object, Object> entry : IgniteSystemProperties.snapshot().entrySet()) + log.debug("System property [" + entry.getKey() + '=' + entry.getValue() + ']'); + } + + /** + * Prints all environment variables in debug mode. + */ + void ackEnvironmentVariables(IgniteLogger log) { + if (log.isDebugEnabled()) + for (Map.Entry<?, ?> envVar : System.getenv().entrySet()) + log.debug("Environment variable [" + envVar.getKey() + '=' + envVar.getValue() + ']'); + } + + /** + * Acknowledge the Ignite configuration related to the data storage. + */ + void ackMemoryConfiguration(IgniteLogger log, IgniteConfiguration cfg) { + DataStorageConfiguration memCfg = cfg.getDataStorageConfiguration(); + + if (memCfg == null) + return; + + U.log(log, "System cache's DataRegion size is configured to " + + (memCfg.getSystemDataRegionConfiguration().getInitialSize() / (1024 * 1024)) + " MB. " + + "Use DataStorageConfiguration.systemRegionInitialSize property to change the setting."); + } + + /** + * Acknowledge all caches configurations presented in the IgniteConfiguration. + */ + void ackCacheConfiguration(IgniteLogger log, IgniteConfiguration cfg) { + CacheConfiguration[] cacheCfgs = cfg.getCacheConfiguration(); + + if (cacheCfgs == null || cacheCfgs.length == 0) + U.warn(log, "Cache is not configured - in-memory data grid is off."); + else { + SB sb = new SB(); + + HashMap<String, ArrayList<String>> memPlcNamesMapping = new HashMap<>(); + + for (CacheConfiguration c : cacheCfgs) { + String cacheName = U.maskName(c.getName()); + + String memPlcName = c.getDataRegionName(); + + if (CU.isSystemCache(cacheName)) + memPlcName = "sysMemPlc"; + else if (memPlcName == null && cfg.getDataStorageConfiguration() != null) + memPlcName = cfg.getDataStorageConfiguration().getDefaultDataRegionConfiguration().getName(); + + if (!memPlcNamesMapping.containsKey(memPlcName)) + memPlcNamesMapping.put(memPlcName, new ArrayList<String>()); + + ArrayList<String> cacheNames = memPlcNamesMapping.get(memPlcName); + + cacheNames.add(cacheName); + } + + for (Map.Entry<String, ArrayList<String>> e : memPlcNamesMapping.entrySet()) { + sb.a("in '").a(e.getKey()).a("' dataRegion: ["); + + for (String s : e.getValue()) + sb.a("'").a(s).a("', "); + + sb.d(sb.length() - 2, sb.length()).a("], "); + } + + U.log(log, "Configured caches [" + sb.d(sb.length() - 2, sb.length()).toString() + ']'); + } + } + + /** + * Acknowledge configuration related to the peer class loading. + */ + void ackP2pConfiguration(IgniteLogger log) { + U.warn(log, + "Peer class loading is enabled (disable it in production for performance and " + + "deployment consistency reasons)"); + } + + /** + * Acknowledge that the rebalance configuration properties are setted correctly. + */ + void ackRebalanceConfiguration(IgniteLogger log, IgniteConfiguration cfg) { + if (cfg.isClientMode()) { + if (cfg.getRebalanceThreadPoolSize() != IgniteConfiguration.DFLT_REBALANCE_THREAD_POOL_SIZE) + U.warn(log, "Setting the rebalance pool size has no effect on the client mode"); + } + else { + if (cfg.getRebalanceThreadPoolSize() < 1) + throw new IgniteException("Rebalance thread pool size minimal allowed value is 1. " + + "Change IgniteConfiguration.rebalanceThreadPoolSize property before next start."); + + if (cfg.getRebalanceBatchesPrefetchCount() < 1) + throw new IgniteException("Rebalance batches prefetch count minimal allowed value is 1. " + + "Change IgniteConfiguration.rebalanceBatchesPrefetchCount property before next start."); + + if (cfg.getRebalanceBatchSize() <= 0) + throw new IgniteException("Rebalance batch size must be greater than zero. " + + "Change IgniteConfiguration.rebalanceBatchSize property before next start."); + + if (cfg.getRebalanceThrottle() < 0) + throw new IgniteException("Rebalance throttle can't have negative value. " + + "Change IgniteConfiguration.rebalanceThrottle property before next start."); + + if (cfg.getRebalanceTimeout() < 0) + throw new IgniteException("Rebalance message timeout can't have negative value. " + + "Change IgniteConfiguration.rebalanceTimeout property before next start."); + + for (CacheConfiguration ccfg : cfg.getCacheConfiguration()) { + if (ccfg.getRebalanceBatchesPrefetchCount() < 1) + throw new IgniteException("Rebalance batches prefetch count minimal allowed value is 1. " + + "Change CacheConfiguration.rebalanceBatchesPrefetchCount property before next start. " + + "[cache=" + ccfg.getName() + "]"); + } + } + } + + /** + * Prints warning if 'java.net.preferIPv4Stack=true' is not set. + */ + void ackIPv4StackFlagIsSet(IgniteLogger log) { + boolean preferIPv4 = Boolean.parseBoolean(System.getProperty("java.net.preferIPv4Stack")); + + if (!preferIPv4) { + U.quietAndWarn(log, "Please set system property '-Djava.net.preferIPv4Stack=true' " + + "to avoid possible problems in mixed environments."); + } + } + + /** + * Prints warning if IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN is used. + */ + void ackWaitForBackupsOnShutdownPropertyIsUsed(IgniteLogger log) { + if (IgniteSystemProperties.getString(IgniteSystemProperties.IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN) == null) + return; + + log.warning("IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN system property is deprecated and will be removed " + + "in a future version. Use ShutdownPolicy instead."); + } + + /** + * Print 3-rd party licenses location. + */ + void ack3rdPartyLicenses(IgniteLogger log, IgniteConfiguration cfg) { + // Ack 3-rd party licenses location. + if (log.isInfoEnabled() && cfg.getIgniteHome() != null) + log.info("3-rd party licenses can be found at: " + cfg.getIgniteHome() + File.separatorChar + "libs" + + File.separatorChar + "licenses"); + } + + /** + * Prints all user attributes in info mode. + */ + void logNodeUserAttributes(IgniteLogger log, IgniteConfiguration cfg) { + if (log.isInfoEnabled()) + for (Map.Entry<?, ?> attr : cfg.getUserAttributes().entrySet()) + log.info("Local node user attribute [" + attr.getKey() + '=' + attr.getValue() + ']'); + } + + /** + * Prints all configuration properties in info mode and SPIs in debug mode. + */ + void ackSpis(IgniteLogger log, IgniteConfiguration cfg) { + if (log.isDebugEnabled()) { + log.debug("+-------------+"); + log.debug("START SPI LIST:"); + log.debug("+-------------+"); + log.debug("Grid checkpoint SPI : " + Arrays.toString(cfg.getCheckpointSpi())); + log.debug("Grid collision SPI : " + cfg.getCollisionSpi()); + log.debug("Grid communication SPI : " + cfg.getCommunicationSpi()); + log.debug("Grid deployment SPI : " + cfg.getDeploymentSpi()); + log.debug("Grid discovery SPI : " + cfg.getDiscoverySpi()); + log.debug("Grid event storage SPI : " + cfg.getEventStorageSpi()); + log.debug("Grid failover SPI : " + Arrays.toString(cfg.getFailoverSpi())); + log.debug("Grid load balancing SPI : " + Arrays.toString(cfg.getLoadBalancingSpi())); + log.debug("Grid Metrics Exporter SPI : " + Arrays.toString(cfg.getMetricExporterSpi())); + } + } + + /** + * Print performance suggestions. + */ + void ackPerformanceSuggestions(IgniteLogger log, IgniteEx ignite) { + GridKernalContext ctx = ignite.context(); + + ctx.performance().add("Disable assertions (remove '-ea' from JVM options)", !U.assertionsEnabled()); + ctx.performance().logSuggestions(log, ignite.name()); + } + + /** + * Print info about visor commandline console. + */ + void ackVisorConsole(IgniteLogger log) { + U.quietAndInfo(log, "To start Console Management & Monitoring run ignitevisorcmd.{sh|bat}"); + } + + /** + * Prints the list of {@code *.jar} and {@code *.class} files containing in the classpath. + */ + void ackClassPathContent(IgniteLogger log) { + if (IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_QUIET, true)) + return; + + boolean enabled = IgniteSystemProperties.getBoolean(IGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP, + DFLT_LOG_CLASSPATH_CONTENT_ON_STARTUP); + + if (enabled) { + String clsPath = System.getProperty("java.class.path", "."); + + String[] clsPathElements = clsPath.split(File.pathSeparator); + + U.log(log, "Classpath value: " + clsPath); + + SB clsPathContent = new SB("List of files containing in classpath: "); + + for (String clsPathEntry : clsPathElements) { + try { + if (clsPathEntry.contains("*")) + ackClassPathWildCard(clsPathEntry, clsPathContent); + else + ackClassPathEntry(clsPathEntry, clsPathContent); + } + catch (Exception e) { + U.warn(log, String.format("Could not log class path entry '%s': %s", clsPathEntry, e.getMessage())); + } + } + + U.log(log, clsPathContent.toString()); + } + } + + /** + * @param clsPathEntry Classpath string to process. + * @param clsPathContent StringBuilder to attach path to. + */ + void ackClassPathWildCard(String clsPathEntry, SB clsPathContent) { + final int lastSeparatorIdx = clsPathEntry.lastIndexOf(File.separator); + + final int asteriskIdx = clsPathEntry.indexOf('*'); + + // Just to log possibly incorrect entries to err. + if (asteriskIdx >= 0 && asteriskIdx < lastSeparatorIdx) + throw new RuntimeException("Could not parse classpath entry"); + + final int fileMaskFirstIdx = lastSeparatorIdx + 1; + + final String fileMask = + (fileMaskFirstIdx >= clsPathEntry.length()) ? "*.jar" : clsPathEntry.substring(fileMaskFirstIdx); + + Path path = Paths.get(lastSeparatorIdx > 0 ? clsPathEntry.substring(0, lastSeparatorIdx) : ".") + .toAbsolutePath() + .normalize(); + + if (lastSeparatorIdx == 0) + path = path.getRoot(); + + try { + DirectoryStream<Path> files = + Files.newDirectoryStream(path, fileMask); + + for (Path f : files) { + String s = f.toString(); + + if (s.toLowerCase().endsWith(".jar")) + clsPathContent.a(f.toString()).a(";"); + } + } + catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * @param clsPathEntry Classpath string to process. + * @param clsPathContent StringBuilder to attach path to. + */ + void ackClassPathEntry(String clsPathEntry, SB clsPathContent) { + File clsPathElementFile = new File(clsPathEntry); + + if (clsPathElementFile.isDirectory()) + clsPathContent.a(clsPathEntry).a(";"); + else { + String extension = clsPathEntry.length() >= 4 + ? clsPathEntry.substring(clsPathEntry.length() - 4).toLowerCase() + : null; + + if (".jar".equals(extension) || ".zip".equals(extension)) + clsPathContent.a(clsPathEntry).a(";"); + } + } + + /** + * Print local node information after kernal startup. + */ + void ackNodeInfo(IgniteLogger log, IgniteEx ignite) { + ClusterNode locNode = ignite.localNode(); + GridKernalContext ctx = ignite.context(); + + if (log.isQuiet()) { + U.quiet(false, ""); + + U.quiet(false, "Ignite node started OK (id=" + U.id8(locNode.id()) + + (F.isEmpty(ignite.name()) ? "" : ", instance name=" + ignite.name()) + ')'); + } + + if (log.isInfoEnabled()) { + String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR; + + String dash = U.dash(ack.length()); + + SB sb = new SB(); + + for (GridPortRecord rec : ctx.ports().records()) + sb.a(rec.protocol()).a(":").a(rec.port()).a(" "); + + String str = + NL + NL + + ">>> " + dash + NL + + ">>> " + ack + NL + + ">>> " + dash + NL + + ">>> OS name: " + U.osString() + NL + + ">>> CPU(s): " + locNode.metrics().getTotalCpus() + NL + + ">>> Heap: " + U.heapSize(locNode, 2) + "GB" + NL + + ">>> VM name: " + ((IgniteKernal)ignite).vmName() + NL + + (ignite.name() == null ? "" : ">>> Ignite instance name: " + ignite.name() + NL) + + ">>> Local node [" + + "ID=" + locNode.id().toString().toUpperCase() + + ", order=" + locNode.order() + ", clientMode=" + ctx.clientNode() + + "]" + NL + + ">>> Local node addresses: " + U.addressesAsString(locNode) + NL + + ">>> Local ports: " + sb + NL + + ">>> " + dash + NL; + + log.info(str); + } + + if (ctx.state().clusterState().state() == ClusterState.INACTIVE) { + U.quietAndInfo(log, ">>> Ignite cluster is in INACTIVE state (limited functionality available). " + + "Use control.(sh|bat) script or IgniteCluster.state(ClusterState.ACTIVE) to change the state."); + } + } + + /** + * Logs out node metrics. + */ + void ackNodeBasicMetrics(IgniteLogger log, IgniteEx ignite, DecimalFormat dblFmt) { + if (!log.isInfoEnabled()) + return; + + GridKernalContext ctx = ignite.context(); + IgniteConfiguration cfg = ignite.configuration(); + + ExecutorService execSvc = ctx.pools().getExecutorService(); + ExecutorService sysExecSvc = ctx.pools().getSystemExecutorService(); + ExecutorService stripedExecSvc = ctx.pools().getStripedExecutorService(); + Map<String, ? extends ExecutorService> customExecSvcs = ctx.pools().customExecutors(); + + ClusterMetrics m = ignite.cluster().localNode().metrics(); + + int localCpus = m.getTotalCpus(); + double cpuLoadPct = m.getCurrentCpuLoad() * 100; + double avgCpuLoadPct = m.getAverageCpuLoad() * 100; + double gcPct = m.getCurrentGcCpuLoad() * 100; + + // Heap params. + long heapUsed = m.getHeapMemoryUsed(); + long heapMax = m.getHeapMemoryMaximum(); + + long heapUsedInMBytes = heapUsed / MB; + long heapCommInMBytes = m.getHeapMemoryCommitted() / MB; + + double freeHeapPct = heapMax > 0 ? ((double)((heapMax - heapUsed) * 100)) / heapMax : -1; + + int hosts = 0; + int servers = 0; + int clients = 0; + int cpus = 0; + + try { + ClusterMetrics metrics = ignite.cluster().metrics(); + + Collection<ClusterNode> nodes0 = ignite.cluster().nodes(); + + hosts = U.neighborhood(nodes0).size(); + servers = ignite.cluster().forServers().nodes().size(); + clients = ignite.cluster().forClients().nodes().size(); + cpus = metrics.getTotalCpus(); + } + catch (IgniteException ignore) { + // No-op. + } + + String id = U.id8(ignite.localNode().id()); + + AffinityTopologyVersion topVer = ctx.discovery().topologyVersionEx(); + + ClusterNode locNode = ctx.discovery().localNode(); + + String networkDetails = ""; + + if (!F.isEmpty(cfg.getLocalHost())) + networkDetails += ", localHost=" + cfg.getLocalHost(); + + if (locNode instanceof TcpDiscoveryNode) + networkDetails += ", discoPort=" + ((TcpDiscoveryNode)locNode).discoveryPort(); + + if (cfg.getCommunicationSpi() instanceof TcpCommunicationSpi) + networkDetails += ", commPort=" + ((TcpCommunicationSpi)cfg.getCommunicationSpi()).boundPort(); + + SB msg = new SB(); + + msg.nl() + .a("Metrics for local node (to disable set 'metricsLogFrequency' to 0)").nl() + .a(" ^-- Node [id=").a(id).a(ignite.name() != null ? ", name=" + ignite.name() : "").a(", uptime=") + .a(((IgniteKernal)ignite).upTimeFormatted()).a("]").nl() + .a(" ^-- Cluster [hosts=").a(hosts).a(", CPUs=").a(cpus).a(", servers=").a(servers) + .a(", clients=").a(clients).a(", topVer=").a(topVer.topologyVersion()) + .a(", minorTopVer=").a(topVer.minorTopologyVersion()).a("]").nl() + .a(" ^-- Network [addrs=").a(locNode.addresses()).a(networkDetails).a("]").nl() + .a(" ^-- CPU [CPUs=").a(localCpus).a(", curLoad=").a(dblFmt.format(cpuLoadPct)) + .a("%, avgLoad=").a(dblFmt.format(avgCpuLoadPct)).a("%, GC=").a(dblFmt.format(gcPct)).a("%]").nl() + .a(" ^-- Heap [used=").a(dblFmt.format(heapUsedInMBytes)) + .a("MB, free=").a(dblFmt.format(freeHeapPct)) + .a("%, comm=").a(dblFmt.format(heapCommInMBytes)).a("MB]").nl() + .a(" ^-- Outbound messages queue [size=").a(m.getOutboundMessagesQueueSize()).a("]").nl() + .a(" ^-- ").a(createExecutorDescription("Public thread pool", execSvc)).nl() + .a(" ^-- ").a(createExecutorDescription("System thread pool", sysExecSvc)).nl() + .a(" ^-- ").a(createExecutorDescription("Striped thread pool", stripedExecSvc)); + + if (customExecSvcs != null) { + for (Map.Entry<String, ? extends ExecutorService> entry : customExecSvcs.entrySet()) + msg.nl().a(" ^-- ").a(createExecutorDescription(entry.getKey(), entry.getValue())); + } + + log.info(msg.toString()); + + ctx.cache().context().database().dumpStatistics(log); + } + + /** + * Create description of an executor service for logging. + * + * @param execSvcName Name of the service. + * @param execSvc Service to create a description for. + */ + String createExecutorDescription(String execSvcName, ExecutorService execSvc) { + int poolSize = 0; + int poolActiveThreads = 0; + int poolQSize = 0; + + if (execSvc instanceof ThreadPoolExecutor) { + ThreadPoolExecutor exec = (ThreadPoolExecutor)execSvc; + + poolSize = exec.getPoolSize(); + poolActiveThreads = Math.min(poolSize, exec.getActiveCount()); + poolQSize = exec.getQueue().size(); + } + else if (execSvc instanceof StripedExecutor) { + StripedExecutor exec = (StripedExecutor)execSvc; + + poolSize = exec.stripesCount(); + poolActiveThreads = exec.activeStripesCount(); + poolQSize = exec.queueSize(); + } + + int poolIdleThreads = poolSize - poolActiveThreads; + + return execSvcName + " [active=" + poolActiveThreads + ", idle=" + poolIdleThreads + ", qSize=" + poolQSize + "]"; + } + + /** + * Print data storage statistics. + */ + void dataStorageReport(IgniteLogger log, IgniteCacheDatabaseSharedManager db, DecimalFormat dblFmt) { + if (F.isEmpty(db.dataRegions())) + return; + + SB dataRegionsInfo = new SB(); + dataRegionsInfo.nl(); + + for (DataRegion region : db.dataRegions()) { + DataRegionConfiguration regCfg = region.config(); + + long pagesCnt = region.pageMemory().loadedPages(); + + long offHeapUsed = region.pageMemory().systemPageSize() * pagesCnt; + long offHeapInit = regCfg.getInitialSize(); + long offHeapMax = regCfg.getMaxSize(); + long offHeapComm = region.metrics().getOffHeapSize(); + + long offHeapUsedInMBytes = offHeapUsed / MB; + long offHeapMaxInMBytes = offHeapMax / MB; + long offHeapCommInMBytes = offHeapComm / MB; + long offHeapInitInMBytes = offHeapInit / MB; + + double freeOffHeapPct = offHeapMax > 0 ? + ((double)((offHeapMax - offHeapUsed) * 100)) / offHeapMax : -1; + + String type = "user"; + + try { + if (region == db.dataRegion(null)) + type = "default"; + else if (INTERNAL_DATA_REGION_NAMES.contains(regCfg.getName())) + type = "internal"; + } + catch (IgniteCheckedException ice) { + // Should never happen + ice.printStackTrace(); + } + + dataRegionsInfo.a(" ^-- ") + .a(regCfg.getName()).a(" region [type=").a(type) + .a(", persistence=").a(regCfg.isPersistenceEnabled()) + .a(", lazyAlloc=").a(regCfg.isLazyMemoryAllocation()).a(',').nl() + .a(" ... ") + .a("initCfg=").a(dblFmt.format(offHeapInitInMBytes)) + .a("MB, maxCfg=").a(dblFmt.format(offHeapMaxInMBytes)) + .a("MB, usedRam=").a(dblFmt.format(offHeapUsedInMBytes)) + .a("MB, freeRam=").a(dblFmt.format(freeOffHeapPct)) + .a("%, allocRam=").a(dblFmt.format(offHeapCommInMBytes)).a("MB"); + + if (regCfg.isPersistenceEnabled()) { + dataRegionsInfo.a(", allocTotal=") + .a(dblFmt.format(region.metrics().getTotalAllocatedSize() / MB)).a("MB"); + } + + dataRegionsInfo.a(']').nl(); + } + + if (log.isQuiet()) + U.quietMultipleLines(false, dataRegionsInfo.toString()); + else if (log.isInfoEnabled()) + log.info(dataRegionsInfo.toString()); + } + + /** + * @param log Ignite Logger. + * @param db Database Shared Manager. + * @param dblFmt Double format. + */ + void memoryStatisticsReport(IgniteLogger log, IgniteCacheDatabaseSharedManager db, DecimalFormat dblFmt) { + if (F.isEmpty(db.dataRegions())) + return; + + SB sb = new SB(); + sb.nl(); + + long loadedPages = 0; + long offHeapUsedSummary = 0; + long offHeapMaxSummary = 0; + long offHeapCommSummary = 0; + long pdsUsedSummary = 0; + boolean persistenceEnabled = false; + + for (DataRegion region : db.dataRegions()) { + DataRegionConfiguration regCfg = region.config(); + + long pagesCnt = region.pageMemory().loadedPages(); + + long offHeapUsed = region.pageMemory().systemPageSize() * pagesCnt; + long offHeapMax = regCfg.getMaxSize(); + long offHeapComm = region.metrics().getOffHeapSize(); + + offHeapUsedSummary += offHeapUsed; + offHeapMaxSummary += offHeapMax; + offHeapCommSummary += offHeapComm; + loadedPages += pagesCnt; + + if (regCfg.isPersistenceEnabled()) { + pdsUsedSummary += region.metrics().getTotalAllocatedSize(); + + persistenceEnabled = true; + } + } + + double freeOffHeapPct = offHeapMaxSummary > 0 ? + ((double)((offHeapMaxSummary - offHeapUsedSummary) * 100)) / offHeapMaxSummary : -1; + + sb.nl() + .a("Data storage metrics for local node (to disable set 'metricsLogFrequency' to 0)").nl() + .a(" ^-- Off-heap memory [used=").a(dblFmt.format(offHeapUsedSummary / MB)) + .a("MB, free=").a(dblFmt.format(freeOffHeapPct)) + .a("%, allocated=").a(dblFmt.format(offHeapCommSummary / MB)).a("MB]").nl() + .a(" ^-- Page memory [pages=").a(loadedPages).a("]").nl(); + + if (persistenceEnabled) + sb.a(" ^-- Ignite persistence [used=").a(dblFmt.format(pdsUsedSummary / MB)).a("MB]").nl(); + + if (log.isQuiet()) + U.quietMultipleLines(false, sb.toString()); + else if (log.isInfoEnabled()) + log.info(sb.toString()); + } + + /** */ + void ackNodeStopped(IgniteLogger log, IgniteEx ignite, boolean err) { + String igniteInstanceName = ignite.name(); + + // Ack stop. + if (log.isQuiet()) { + String nodeName = igniteInstanceName == null ? "" : "name=" + igniteInstanceName + ", "; + + if (!err) + U.quiet(false, "Ignite node stopped OK [" + nodeName + "uptime=" + + ((IgniteKernal)ignite).upTimeFormatted() + ']'); + else + U.quiet(true, "Ignite node stopped wih ERRORS [" + nodeName + "uptime=" + + ((IgniteKernal)ignite).upTimeFormatted() + ']'); + } + + if (!log.isInfoEnabled()) + return; + + if (!err) { + String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR + + " stopped OK"; + + String dash = U.dash(ack.length()); + + log.info(NL + NL + + ">>> " + dash + NL + + ">>> " + ack + NL + + ">>> " + dash + NL + + (igniteInstanceName == null ? "" : ">>> Ignite instance name: " + igniteInstanceName + NL) + + ">>> Grid uptime: " + ((IgniteKernal)ignite).upTimeFormatted() + + NL + + NL); + } + else { + String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR + + " stopped with ERRORS"; + + String dash = U.dash(ack.length()); + + log.info(NL + NL + + ">>> " + ack + NL + + ">>> " + dash + NL + + (igniteInstanceName == null ? "" : ">>> Ignite instance name: " + igniteInstanceName + NL) + + ">>> Grid uptime: " + ((IgniteKernal)ignite).upTimeFormatted() + + NL + + ">>> See log above for detailed error message." + NL + + ">>> Note that some errors during stop can prevent grid from" + NL + + ">>> maintaining correct topology since this node may have" + NL + + ">>> not exited grid properly." + NL + + NL); + } + } + + /** + * Prints security status. + */ + void ackSecurity(IgniteLogger log, Ignite ignite) { + assert log != null; + + GridKernalContext ctx = ((IgniteEx)ignite).context(); + + U.quietAndInfo(log, "Security status [authentication=" + onOff(ctx.security().enabled()) + + ", sandbox=" + onOff(ctx.security().sandbox().enabled()) + + ", tls/ssl=" + onOff(ctx.config().getSslContextFactory() != null) + ']'); + } + + /** + * Gets "on" or "off" string for given boolean value. + * + * @param b Boolean value to convert. + * @return Result string. + */ + public static String onOff(boolean b) { + return b ? "on" : "off"; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java index 7caaf200a6d..d25458bf116 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java @@ -1551,16 +1551,9 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap dataRegionsStarted = true; - if (log.isQuiet()) { - U.quiet(false, "Data Regions Started: " + dataRegionMap.size()); + U.quietAndInfo(log, "Data Regions Started: " + dataRegionMap.size()); - U.quietMultipleLines(false, IgniteKernal.dataStorageReport(this, false)); - } - else if (log.isInfoEnabled()) { - log.info("Data Regions Started: " + dataRegionMap.size()); - - log.info(IgniteKernal.dataStorageReport(this, false)); - } + ((IgniteKernal)cctx.kernalContext().grid()).dataStorageReport(); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java index 1dfb16975f6..a525ea924df 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java @@ -120,6 +120,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Properties; import java.util.Random; import java.util.ServiceLoader; import java.util.Set; @@ -293,8 +294,10 @@ import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOCAL_HOST; import static org.apache.ignite.IgniteSystemProperties.IGNITE_MBEAN_APPEND_CLASS_LOADER_ID; import static org.apache.ignite.IgniteSystemProperties.IGNITE_MBEAN_APPEND_JVM_ID; import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_DISCO_ORDER; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_REST_START_ON_CLIENT; import static org.apache.ignite.IgniteSystemProperties.IGNITE_SSH_HOST; import static org.apache.ignite.IgniteSystemProperties.IGNITE_SSH_USER_NAME; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_SUCCESS_FILE; import static org.apache.ignite.IgniteSystemProperties.getBoolean; import static org.apache.ignite.events.EventType.EVTS_ALL; import static org.apache.ignite.events.EventType.EVTS_ALL_MINUS_METRIC_UPDATE; @@ -644,6 +647,19 @@ public abstract class IgniteUtils { /** Byte count prefixes. */ private static final String BYTE_CNT_PREFIXES = " KMGTPE"; + /** + * Success file name property. This file is used with auto-restarting functionality when Ignite + * is started by supplied ignite.{bat|sh} scripts. + */ + public static final String IGNITE_SUCCESS_FILE_PROPERTY = System.getProperty(IGNITE_SUCCESS_FILE); + + /** + * JMX remote system property. Setting this property registered the Java VM platform's MBeans and published + * the Remote Method Invocation (RMI) connector via a private interface to allow JMX client applications + * to monitor a local Java platform, that is, a Java VM running on the same machine as the JMX client. + */ + public static final String IGNITE_JMX_REMOTE_PROPERTY = System.getProperty("com.sun.management.jmxremote"); + /* * Initializes enterprise check. */ @@ -1044,16 +1060,25 @@ public abstract class IgniteUtils { * @return Plugins. */ public static List<PluginProvider> allPluginProviders() { - return AccessController.doPrivileged(new PrivilegedAction<List<PluginProvider>>() { - @Override public List<PluginProvider> run() { - List<PluginProvider> providers = new ArrayList<>(); + List<PluginProvider> providers = new ArrayList<>(); - ServiceLoader<PluginProvider> ldr = ServiceLoader.load(PluginProvider.class); + Iterable<PluginProvider> it = loadService(PluginProvider.class); - for (PluginProvider provider : ldr) - providers.add(provider); + for (PluginProvider provider : it) + providers.add(provider); - return providers; + return providers; + } + + /** + * @param svcCls Service class to load. + * @param <S> Type of loaded interfaces. + * @return Lazy iterable structure over loaded class implementations. + */ + public static <S> Iterable<S> loadService(Class<S> svcCls) { + return AccessController.doPrivileged(new PrivilegedAction<Iterable<S>>() { + @Override public Iterable<S> run() { + return ServiceLoader.load(svcCls); } }); } @@ -12316,4 +12341,75 @@ public abstract class IgniteUtils { } } } + + /** + * @return Language runtime. + */ + public static String language(ClassLoader ldr) { + boolean scala = false; + boolean groovy = false; + boolean clojure = false; + + for (StackTraceElement elem : Thread.currentThread().getStackTrace()) { + String s = elem.getClassName().toLowerCase(); + + if (s.contains("scala")) { + scala = true; + + break; + } + else if (s.contains("groovy")) { + groovy = true; + + break; + } + else if (s.contains("clojure")) { + clojure = true; + + break; + } + } + + if (scala) { + try (InputStream in = ldr.getResourceAsStream("/library.properties")) { + Properties props = new Properties(); + + if (in != null) + props.load(in); + + return "Scala ver. " + props.getProperty("version.number", "<unknown>"); + } + catch (Exception ignore) { + return "Scala ver. <unknown>"; + } + } + + // How to get Groovy and Clojure version at runtime?!? + return groovy ? "Groovy" : clojure ? "Clojure" : U.jdkName() + " ver. " + U.jdkVersion(); + } + + /** + * @return {@code True} if remote JMX management is enabled - {@code false} otherwise. + */ + public static boolean isJmxRemoteEnabled() { + return IGNITE_JMX_REMOTE_PROPERTY != null; + } + + /** + * @return {@code true} if the REST processor is enabled, {@code false} the otherwise. + */ + public static boolean isRestEnabled(IgniteConfiguration cfg) { + boolean isClientNode = cfg.isClientMode() || cfg.isDaemon(); + + // By default, rest processor doesn't start on client nodes. + return cfg.getConnectorConfiguration() != null && + (!isClientNode || (isClientNode && IgniteSystemProperties.getBoolean(IGNITE_REST_START_ON_CLIENT))); + } + + /** + * @return {@code True} if restart mode is enabled, {@code false} otherwise. + */ + public static boolean isRestartEnabled() { + return IGNITE_SUCCESS_FILE_PROPERTY != null; + } } diff --git a/modules/core/src/test/java/org/apache/ignite/thread/IgniteThreadPoolSizeTest.java b/modules/core/src/test/java/org/apache/ignite/thread/IgniteThreadPoolSizeTest.java index cc1b25f3aac..21b0fa740ad 100644 --- a/modules/core/src/test/java/org/apache/ignite/thread/IgniteThreadPoolSizeTest.java +++ b/modules/core/src/test/java/org/apache/ignite/thread/IgniteThreadPoolSizeTest.java @@ -18,6 +18,7 @@ package org.apache.ignite.thread; import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteException; import org.apache.ignite.Ignition; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; @@ -76,7 +77,8 @@ public class IgniteThreadPoolSizeTest extends GridCommonAbstractTest { */ @Test public void testRebalanceThreadPoolSize() throws Exception { - testWrongPoolSize(configuration().setRebalanceThreadPoolSize(WRONG_VALUE)); + assertThrowsAnyCause(log, () -> Ignition.start(configuration().setRebalanceThreadPoolSize(WRONG_VALUE)), + IgniteException.class, "thread pool size"); } /** diff --git a/modules/extdata/logo/licenses/apache-2.0.txt b/modules/extdata/logo/licenses/apache-2.0.txt new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/modules/extdata/logo/licenses/apache-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/modules/extdata/logo/pom.xml b/modules/extdata/logo/pom.xml new file mode 100644 index 00000000000..b034378d5b1 --- /dev/null +++ b/modules/extdata/logo/pom.xml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-parent-internal</artifactId> + <version>${revision}</version> + <relativePath>../../../parent-internal/pom.xml</relativePath> + </parent> + + <artifactId>ignite-extdata-logo</artifactId> + <url>https://ignite.apache.org</url> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>ignite-core</artifactId> + </dependency> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>ignite-core</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.ignite</groupId> + <artifactId>ignite-spring</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + <version>${spring.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <version>${spring.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>${spring.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>ignite-tools</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <version>2.8.2</version> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/modules/extdata/logo/src/test/java/org/apache/ignite/internal/IgniteExtendedLogoTest.java b/modules/extdata/logo/src/test/java/org/apache/ignite/internal/IgniteExtendedLogoTest.java new file mode 100644 index 00000000000..497d6202c3f --- /dev/null +++ b/modules/extdata/logo/src/test/java/org/apache/ignite/internal/IgniteExtendedLogoTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal; + +import org.apache.ignite.testframework.ListeningTestLogger; +import org.apache.ignite.testframework.LogListener; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; + +import static org.apache.ignite.testframework.GridTestUtils.waitForCondition; + +/** */ +public class IgniteExtendedLogoTest extends GridCommonAbstractTest { + /** @throws Exception If fails. */ + @Test + public void testExtendedLogo() throws Exception { + ListeningTestLogger testLog = new ListeningTestLogger(log); + + LogListener waitLogoLsnr = LogListener.matches("Ignite IgniteLogInfoProvider is used to customize the logo version output.") + .build(); + testLog.registerListener(waitLogoLsnr); + + startGrid(getConfiguration().setGridLogger(testLog)); + + assertTrue(waitForCondition(waitLogoLsnr::check, 5_000L)); + } +} diff --git a/modules/extdata/logo/src/test/java/org/apache/ignite/internal/plugin/IgniteExtLogInfoProviderImpl.java b/modules/extdata/logo/src/test/java/org/apache/ignite/internal/plugin/IgniteExtLogInfoProviderImpl.java new file mode 100644 index 00000000000..826c7e333a1 --- /dev/null +++ b/modules/extdata/logo/src/test/java/org/apache/ignite/internal/plugin/IgniteExtLogInfoProviderImpl.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.plugin; + +import java.lang.management.RuntimeMXBean; +import org.apache.ignite.IgniteLogger; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.util.typedef.internal.U; + +import static org.apache.ignite.internal.IgniteKernal.NL; +import static org.apache.ignite.internal.IgniteVersionUtils.ACK_VER_STR; +import static org.apache.ignite.internal.IgniteVersionUtils.COPYRIGHT; + +/** + * Change the message output for metrics log. + */ +public class IgniteExtLogInfoProviderImpl extends IgniteLogInfoProviderImpl { + /** {@inheritDoc} */ + @Override void ackAsciiLogo(IgniteLogger log, IgniteConfiguration cfg, RuntimeMXBean rtBean) { + String ver = "ver. " + ACK_VER_STR; + + U.quietAndInfo(log, + NL + NL + + ">>> Ignite IgniteLogInfoProvider is used to customize the logo version output. " + NL + + ">>> " + ver + NL + + ">>> " + cfg.getIgniteHome() + NL + + ">>> " + rtBean.getName() + NL + + ">>> " + COPYRIGHT + NL + + ">>> " + NL + ); + } +} diff --git a/modules/extdata/logo/src/test/java/org/apache/ignite/internal/testsuites/IgniteLogoExtensionTestSuite.java b/modules/extdata/logo/src/test/java/org/apache/ignite/internal/testsuites/IgniteLogoExtensionTestSuite.java new file mode 100644 index 00000000000..36fea9f9d2f --- /dev/null +++ b/modules/extdata/logo/src/test/java/org/apache/ignite/internal/testsuites/IgniteLogoExtensionTestSuite.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.testsuites; + +import org.apache.ignite.internal.IgniteExtendedLogoTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Info provider test suite. + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + IgniteExtendedLogoTest.class +}) +public class IgniteLogoExtensionTestSuite { +} diff --git a/modules/extdata/logo/src/test/resources/META-INF/services/org.apache.ignite.internal.plugin.IgniteLogInfoProvider b/modules/extdata/logo/src/test/resources/META-INF/services/org.apache.ignite.internal.plugin.IgniteLogInfoProvider new file mode 100644 index 00000000000..b38541c6178 --- /dev/null +++ b/modules/extdata/logo/src/test/resources/META-INF/services/org.apache.ignite.internal.plugin.IgniteLogInfoProvider @@ -0,0 +1 @@ +org.apache.ignite.internal.plugin.IgniteExtLogInfoProviderImpl diff --git a/pom.xml b/pom.xml index b2a2ae944e1..d929058f5a1 100644 --- a/pom.xml +++ b/pom.xml @@ -46,6 +46,7 @@ <module>modules/extdata/p2p</module> <module>modules/extdata/uri</module> <module>modules/extdata/platform</module> + <module>modules/extdata/logo</module> <module>modules/clients</module> <module>modules/spring</module> <module>modules/web</module>