Repository: ignite Updated Branches: refs/heads/master 97b91e9c1 -> a8ac4438f
ignite-6305 Ignite update checker enabled Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a8ac4438 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a8ac4438 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a8ac4438 Branch: refs/heads/master Commit: a8ac4438fd0a0a5d086c5df8872fa0aa97a1360c Parents: 97b91e9 Author: Andrey Gura <ag...@apache.org> Authored: Wed Sep 27 13:50:26 2017 +0300 Committer: Andrey Gura <ag...@apache.org> Committed: Mon Oct 9 17:51:31 2017 +0300 ---------------------------------------------------------------------- .../processors/cluster/ClusterProcessor.java | 39 ++-- .../processors/cluster/GridUpdateNotifier.java | 224 ++++++++----------- .../cluster/HttpIgniteUpdatesChecker.java | 29 ++- .../cluster/GridUpdateNotifierSelfTest.java | 50 +---- 4 files changed, 130 insertions(+), 212 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/a8ac4438/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ClusterProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ClusterProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ClusterProcessor.java index dc503fb..5f2c66c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ClusterProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ClusterProcessor.java @@ -18,7 +18,6 @@ package org.apache.ignite.internal.processors.cluster; import java.io.Serializable; -import java.lang.ref.WeakReference; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -30,6 +29,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteLogger; +import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.events.DiscoveryEvent; import org.apache.ignite.events.Event; @@ -60,6 +60,7 @@ import org.apache.ignite.spi.discovery.DiscoveryDataBag.GridDiscoveryData; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.IgniteSystemProperties.IGNITE_DIAGNOSTIC_ENABLED; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_UPDATE_NOTIFIER; import static org.apache.ignite.IgniteSystemProperties.getBoolean; import static org.apache.ignite.events.EventType.EVT_NODE_FAILED; import static org.apache.ignite.events.EventType.EVT_NODE_LEFT; @@ -84,7 +85,7 @@ public class ClusterProcessor extends GridProcessorAdapter { private IgniteClusterImpl cluster; /** */ - private final AtomicBoolean notifyEnabled = new AtomicBoolean(false); + private final AtomicBoolean notifyEnabled = new AtomicBoolean(); /** */ @GridToStringExclude @@ -107,6 +108,8 @@ public class ClusterProcessor extends GridProcessorAdapter { public ClusterProcessor(GridKernalContext ctx) { super(ctx); + notifyEnabled.set(IgniteSystemProperties.getBoolean(IGNITE_UPDATE_NOTIFIER, true)); + cluster = new IgniteClusterImpl(ctx); } @@ -297,12 +300,13 @@ public class ClusterProcessor extends GridProcessorAdapter { /** * @param vals collection to seek through. */ + @SuppressWarnings("unchecked") private Boolean findLastFlag(Collection<Serializable> vals) { Boolean flag = null; for (Serializable ser : vals) { if (ser != null) { - Map<String, Object> map = (Map<String, Object>) ser; + Map<String, Object> map = (Map<String, Object>)ser; if (map.containsKey(ATTR_UPDATE_NOTIFIER_STATUS)) flag = (Boolean) map.get(ATTR_UPDATE_NOTIFIER_STATUS); @@ -316,11 +320,7 @@ public class ClusterProcessor extends GridProcessorAdapter { @Override public void onKernalStart(boolean active) throws IgniteCheckedException { if (notifyEnabled.get()) { try { - verChecker = new GridUpdateNotifier(ctx.igniteInstanceName(), - VER_STR, - ctx.gateway(), - ctx.plugins().allProviders(), - false); + verChecker = new GridUpdateNotifier(ctx.igniteInstanceName(), VER_STR, false); updateNtfTimer = new Timer("ignite-update-notifier-timer", true); @@ -473,9 +473,6 @@ public class ClusterProcessor extends GridProcessorAdapter { * Update notifier timer task. */ private static class UpdateNotifierTimerTask extends GridTimerTask { - /** Reference to kernal. */ - private final WeakReference<IgniteKernal> kernalRef; - /** Logger. */ private final IgniteLogger log; @@ -494,10 +491,11 @@ public class ClusterProcessor extends GridProcessorAdapter { * @param kernal Kernal. * @param verChecker Version checker. */ - private UpdateNotifierTimerTask(IgniteKernal kernal, GridUpdateNotifier verChecker, - AtomicBoolean notifyEnabled) { - kernalRef = new WeakReference<>(kernal); - + private UpdateNotifierTimerTask( + IgniteKernal kernal, + GridUpdateNotifier verChecker, + AtomicBoolean notifyEnabled + ) { log = kernal.context().log(UpdateNotifierTimerTask.class); this.verChecker = verChecker; @@ -509,14 +507,7 @@ public class ClusterProcessor extends GridProcessorAdapter { if (!notifyEnabled.get()) return; - if (!first) { - IgniteKernal kernal = kernalRef.get(); - - if (kernal != null) - verChecker.topologySize(kernal.cluster().nodes().size()); - } - - verChecker.checkForNewVersion(log); + verChecker.checkForNewVersion(log, first); // Just wait for 10 secs. Thread.sleep(PERIODIC_VER_CHECK_CONN_TIMEOUT); @@ -530,7 +521,7 @@ public class ClusterProcessor extends GridProcessorAdapter { // No-op if status is NOT available. verChecker.reportStatus(log); - if (first) { + if (first && verChecker.error() == null) { first = false; verChecker.reportOnlyNew(true); http://git-wip-us.apache.org/repos/asf/ignite/blob/a8ac4438/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifier.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifier.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifier.java index eacc42f..ff834f6 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifier.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifier.java @@ -17,34 +17,17 @@ package org.apache.ignite.internal.processors.cluster; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLConnection; -import java.util.Collection; +import java.util.Comparator; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicReference; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteLogger; -import org.apache.ignite.IgniteSystemProperties; -import org.apache.ignite.internal.GridKernalGateway; import org.apache.ignite.internal.IgniteKernal; -import org.apache.ignite.internal.IgniteProperties; -import org.apache.ignite.internal.util.typedef.F; -import org.apache.ignite.internal.util.typedef.internal.SB; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.internal.util.worker.GridWorker; -import org.apache.ignite.plugin.PluginProvider; import org.jetbrains.annotations.Nullable; -import static java.net.URLEncoder.encode; - /** * This class is responsible for notification about new version availability. * <p> @@ -55,8 +38,8 @@ class GridUpdateNotifier { /** Default encoding. */ private static final String CHARSET = "UTF-8"; - /** Access URL to be used to access latest version data. */ - private final String UPD_STATUS_PARAMS = IgniteProperties.get("ignite.update.status.params"); + /** Version comparator. */ + private static final VersionComparator VER_COMPARATOR = new VersionComparator(); /** Throttling for logging out. */ private static final long THROTTLE_PERIOD = 24 * 60 * 60 * 1000; // 1 day. @@ -64,12 +47,18 @@ class GridUpdateNotifier { /** Sleep milliseconds time for worker thread. */ private static final int WORKER_THREAD_SLEEP_TIME = 5000; - /** Default url for request Ignite updates. */ - private final static String DEFAULT_IGNITE_UPDATES_URL = "https://ignite.run/update_status_ignite-plain-text.php"; + /** Default URL for request Ignite updates. */ + private final static String DEFAULT_IGNITE_UPDATES_URL = "https://ignite.apache.org/latest"; + + /** Default HTTP parameter for request Ignite updates. */ + private final static String DEFAULT_IGNITE_UPDATES_PARAMS = "?ver="; /** Grid version. */ private final String ver; + /** Error during obtaining data. */ + private volatile Exception err; + /** Latest version. */ private volatile String latestVer; @@ -83,18 +72,6 @@ class GridUpdateNotifier { private volatile boolean reportOnlyNew; /** */ - private volatile int topSize; - - /** System properties */ - private final String vmProps; - - /** Plugins information for request */ - private final String pluginsVers; - - /** Kernal gateway */ - private final GridKernalGateway gw; - - /** */ private long lastLog = -1; /** Command for worker thread. */ @@ -111,88 +88,50 @@ class GridUpdateNotifier { * * @param igniteInstanceName igniteInstanceName * @param ver Compound Ignite version. - * @param gw Kernal gateway. - * @param pluginProviders Kernal gateway. * @param reportOnlyNew Whether or not to report only new version. * @param updatesChecker Service for getting Ignite updates * @throws IgniteCheckedException If failed. */ - GridUpdateNotifier(String igniteInstanceName, String ver, GridKernalGateway gw, Collection<PluginProvider> pluginProviders, - boolean reportOnlyNew, HttpIgniteUpdatesChecker updatesChecker) throws IgniteCheckedException { - try { - this.ver = ver; - this.igniteInstanceName = igniteInstanceName == null ? "null" : igniteInstanceName; - this.gw = gw; - this.updatesChecker = updatesChecker; - - SB pluginsBuilder = new SB(); - - for (PluginProvider provider : pluginProviders) - pluginsBuilder.a("&").a(provider.name() + "-plugin-version").a("="). - a(encode(provider.version(), CHARSET)); - - pluginsVers = pluginsBuilder.toString(); - - this.reportOnlyNew = reportOnlyNew; - - vmProps = getSystemProperties(); + GridUpdateNotifier( + String igniteInstanceName, + String ver, + boolean reportOnlyNew, + HttpIgniteUpdatesChecker updatesChecker + ) throws IgniteCheckedException { + this.ver = ver; + this.igniteInstanceName = igniteInstanceName == null ? "null" : igniteInstanceName; + this.updatesChecker = updatesChecker; + this.reportOnlyNew = reportOnlyNew; - workerThread = new Thread(new Runnable() { - @Override public void run() { - try { - while(!Thread.currentThread().isInterrupted()) { - Runnable cmd0 = cmd.getAndSet(null); + workerThread = new Thread(new Runnable() { + @Override public void run() { + try { + while(!Thread.currentThread().isInterrupted()) { + Runnable cmd0 = cmd.getAndSet(null); - if (cmd0 != null) - cmd0.run(); - else - Thread.sleep(WORKER_THREAD_SLEEP_TIME); - } - } - catch (InterruptedException ignore) { - // No-op. + if (cmd0 != null) + cmd0.run(); + else + Thread.sleep(WORKER_THREAD_SLEEP_TIME); } } - }, "upd-ver-checker"); + catch (InterruptedException ignore) { + // No-op. + } + } + }, "upd-ver-checker"); - workerThread.setDaemon(true); + workerThread.setDaemon(true); - workerThread.start(); - } - catch (UnsupportedEncodingException e) { - throw new IgniteCheckedException("Failed to encode.", e); - } + workerThread.start(); } /** * Creates new notifier with default Ignite updates URL */ - GridUpdateNotifier(String igniteInstanceName, String ver, GridKernalGateway gw, Collection<PluginProvider> pluginProviders, - boolean reportOnlyNew) throws IgniteCheckedException { - this(igniteInstanceName, ver, gw, pluginProviders, reportOnlyNew, new HttpIgniteUpdatesChecker(DEFAULT_IGNITE_UPDATES_URL, CHARSET)); - } - - /** - * Gets system properties. - * - * @return System properties. - */ - private static String getSystemProperties() { - try { - StringWriter sw = new StringWriter(); - - try { - IgniteSystemProperties.safeSnapshot().store(new PrintWriter(sw), ""); - } - catch (IOException ignore) { - return null; - } - - return sw.toString(); - } - catch (SecurityException ignore) { - return null; - } + GridUpdateNotifier(String igniteInstanceName, String ver, boolean reportOnlyNew) throws IgniteCheckedException { + this(igniteInstanceName, ver, reportOnlyNew, + new HttpIgniteUpdatesChecker(DEFAULT_IGNITE_UPDATES_URL, DEFAULT_IGNITE_UPDATES_PARAMS + ver, CHARSET)); } /** @@ -203,31 +142,32 @@ class GridUpdateNotifier { } /** - * @param topSize Size of topology for license verification purpose. + * @return Latest version. */ - void topologySize(int topSize) { - this.topSize = topSize; + String latestVersion() { + return latestVer; } /** - * @return Latest version. + * @return Error. */ - String latestVersion() { - return latestVer; + Exception error() { + return err; } /** * Starts asynchronous process for retrieving latest version data. * * @param log Logger. + * @param first First checking. */ - void checkForNewVersion(IgniteLogger log) { + void checkForNewVersion(IgniteLogger log, boolean first) { assert log != null; log = log.getLogger(getClass()); try { - cmd.set(new UpdateChecker(log)); + cmd.set(new UpdateChecker(log, first)); } catch (RejectedExecutionException e) { U.error(log, "Failed to schedule a thread due to execution rejection (safely ignoring): " + @@ -250,13 +190,16 @@ class GridUpdateNotifier { downloadUrl = downloadUrl != null ? downloadUrl : IgniteKernal.SITE; - if (latestVer != null) - if (latestVer.equals(ver)) { + if (latestVer != null) { + int cmp = VER_COMPARATOR.compare(latestVer, ver); + + if (cmp == 0) { if (!reportOnlyNew) throttle(log, false, "Your version is up to date."); } - else + else if (cmp > 0) throttle(log, true, "New version is available at " + downloadUrl + ": " + latestVer); + } else if (!reportOnlyNew) throttle(log, false, "Update status is not available."); @@ -302,35 +245,29 @@ class GridUpdateNotifier { /** Logger. */ private final IgniteLogger log; + /** First. */ + private final boolean first; + /** * Creates checked with given logger. * * @param log Logger. */ - UpdateChecker(IgniteLogger log) { + UpdateChecker(IgniteLogger log, boolean first) { super(igniteInstanceName, "grid-version-checker", log); this.log = log.getLogger(getClass()); + this.first = first; } /** {@inheritDoc} */ @Override protected void body() throws InterruptedException { try { - String stackTrace = gw != null ? gw.userStackTrace() : null; - - String postParams = - "igniteInstanceName=" + encode(igniteInstanceName, CHARSET) + - (!F.isEmpty(UPD_STATUS_PARAMS) ? "&" + UPD_STATUS_PARAMS : "") + - (topSize > 0 ? "&topSize=" + topSize : "") + - (!F.isEmpty(stackTrace) ? "&stackTrace=" + encode(stackTrace, CHARSET) : "") + - (!F.isEmpty(vmProps) ? "&vmProps=" + encode(vmProps, CHARSET) : "") + - pluginsVers; - if (!isCancelled()) { try { - String updatesResponse = updatesChecker.getUpdates(postParams); + String updatesRes = updatesChecker.getUpdates(first); - String[] lines = updatesResponse.split("\n"); + String[] lines = updatesRes.split("\n"); for (String line : lines) { if (line.contains("version")) @@ -338,14 +275,20 @@ class GridUpdateNotifier { else if (line.contains("downloadUrl")) downloadUrl = obtainDownloadUrlFrom(line); } + + err = null; } catch (IOException e) { + err = e; + if (log.isDebugEnabled()) log.debug("Failed to connect to Ignite update server. " + e.getMessage()); } } } catch (Exception e) { + err = e; + if (log.isDebugEnabled()) log.debug("Unexpected exception in update checker. " + e.getMessage()); } @@ -385,4 +328,35 @@ class GridUpdateNotifier { return obtainMeta("downloadUrl=", line); } } + + /** + * Ignite version comparator. + */ + private static final class VersionComparator implements Comparator<String> { + /** Dot pattern. */ + private static final String DOT_PATTERN = "\\."; + + /** Dash pattern. */ + private static final String DASH_PATTERN = "-"; + + /** {@inheritDoc} */ + @Override public int compare(String o1, String o2) { + if (o1.equals(o2)) + return 0; + + String[] ver1 = o1.split(DOT_PATTERN, 3); + String[] ver2 = o2.split(DOT_PATTERN, 3); + + assert ver1.length == 3; + assert ver2.length == 3; + + if (Integer.valueOf(ver1[0]) >= Integer.valueOf(ver2[0]) && + Integer.valueOf(ver1[1]) >= Integer.valueOf(ver2[1]) && + Integer.valueOf(ver1[2].split(DASH_PATTERN)[0]) >= Integer.valueOf(ver2[2].split(DASH_PATTERN)[0])) + + return 1; + else + return -1; + } + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/a8ac4438/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java index 2b93ceb..5d6732e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/HttpIgniteUpdatesChecker.java @@ -21,7 +21,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; import java.net.URL; import java.net.URLConnection; @@ -32,6 +31,9 @@ public class HttpIgniteUpdatesChecker { /** Url for request updates. */ private final String url; + /** Params. */ + private final String params; + /** Charset for encoding requests/responses */ private final String charset; @@ -40,43 +42,38 @@ public class HttpIgniteUpdatesChecker { * @param url URL for getting Ignite updates information * @param charset Charset for encoding */ - HttpIgniteUpdatesChecker(String url, String charset) { + HttpIgniteUpdatesChecker(String url, String params, String charset) { this.url = url; + this.params = params; this.charset = charset; } /** * Gets information about Ignite updates via HTTP - * @param updateRequest HTTP Request parameters * @return Information about Ignite updates separated by line endings * @throws IOException If HTTP request was failed */ - public String getUpdates(String updateRequest) throws IOException { - URLConnection conn = new URL(url).openConnection(); - conn.setDoOutput(true); + public String getUpdates(boolean first) throws IOException { + String addr = first ? url + params : url; + + URLConnection conn = new URL(addr).openConnection(); conn.setRequestProperty("Accept-Charset", charset); - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset); conn.setConnectTimeout(3000); conn.setReadTimeout(3000); - try (OutputStream os = conn.getOutputStream()) { - os.write(updateRequest.getBytes(charset)); - } - try (InputStream in = conn.getInputStream()) { if (in == null) return null; BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset)); - StringBuilder response = new StringBuilder(); + StringBuilder res = new StringBuilder(); - for (String line; (line = reader.readLine()) != null; ) { - response.append(line).append('\n'); - } + for (String line; (line = reader.readLine()) != null; ) + res.append(line).append('\n'); - return response.toString(); + return res.toString(); } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/a8ac4438/modules/core/src/test/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifierSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifierSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifierSelfTest.java index 1a20f26..f295b2b 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifierSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cluster/GridUpdateNotifierSelfTest.java @@ -17,19 +17,13 @@ package org.apache.ignite.internal.processors.cluster; -import java.util.Collections; import java.util.Properties; import org.apache.ignite.IgniteSystemProperties; -import org.apache.ignite.internal.GridKernalGateway; -import org.apache.ignite.internal.GridKernalState; import org.apache.ignite.internal.IgniteProperties; -import org.apache.ignite.internal.util.future.GridFutureAdapter; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteProductVersion; -import org.apache.ignite.plugin.PluginProvider; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.apache.ignite.testframework.junits.common.GridCommonTest; -import org.mockito.Matchers; import org.mockito.Mockito; /** @@ -78,13 +72,12 @@ public class GridUpdateNotifierSelfTest extends GridCommonAbstractTest { HttpIgniteUpdatesChecker updatesCheckerMock = Mockito.mock(HttpIgniteUpdatesChecker.class); // Return current node version and some other info - Mockito.when(updatesCheckerMock.getUpdates(Matchers.anyString())) + Mockito.when(updatesCheckerMock.getUpdates(true)) .thenReturn("meta=meta" + "\n" + "version=" + nodeVer + "\n" + "downloadUrl=url"); - GridUpdateNotifier ntf = new GridUpdateNotifier(null, nodeVer, - TEST_GATEWAY, Collections.<PluginProvider>emptyList(), false, updatesCheckerMock); + GridUpdateNotifier ntf = new GridUpdateNotifier(null, nodeVer, false, updatesCheckerMock); - ntf.checkForNewVersion(log); + ntf.checkForNewVersion(log, true); String ver = ntf.latestVersion(); @@ -108,41 +101,4 @@ public class GridUpdateNotifierSelfTest extends GridCommonAbstractTest { ntf.reportStatus(log); } - - /** - * Test kernal gateway that always return uninitialized user stack trace. - */ - private static final GridKernalGateway TEST_GATEWAY = new GridKernalGateway() { - @Override public void readLock() throws IllegalStateException {} - - @Override public void readLockAnyway() {} - - @Override public void setState(GridKernalState state) {} - - @Override public GridKernalState getState() { - return null; - } - - @Override public void readUnlock() {} - - @Override public void writeLock() {} - - @Override public void writeUnlock() {} - - @Override public String userStackTrace() { - return null; - } - - @Override public boolean tryWriteLock(long timeout) { - return false; - } - - @Override public GridFutureAdapter<?> onDisconnected() { - return null; - } - - @Override public void onReconnected() { - // No-op. - } - }; }