Index: ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/GridPluginComponent.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/GridPluginComponent.java (revision aa2d7cb4a5c9f17d6a7a5b739feee7a2b84aad2b) +++ ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/GridPluginComponent.java (revision affce40bed8726388e0b856f696cd61b3273615e) @@ -60,12 +60,12 @@ /** {@inheritDoc} */ @Override public void onKernalStart() throws IgniteCheckedException { - plugin.onIgniteStart(); + plugin.onAfterStart(); } /** {@inheritDoc} */ @Override public void onKernalStop(boolean cancel) { - plugin.onIgniteStop(cancel); + plugin.onBeforeStop(cancel); } /** {@inheritDoc} */ Index: ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeGridTestSuite.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeGridTestSuite.java (revision aa2d7cb4a5c9f17d6a7a5b739feee7a2b84aad2b) +++ ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeGridTestSuite.java (revision affce40bed8726388e0b856f696cd61b3273615e) @@ -94,6 +94,7 @@ suite.addTestSuite(IgniteComputeEmptyClusterGroupTest.class); suite.addTestSuite(IgniteComputeTopologyExceptionTest.class); suite.addTestSuite(GridTaskFailoverAffinityRunTest.class); + suite.addTestSuite(IgnitePluginLifecycleSelfTest.class); return suite; } Index: ../incubator-ignite/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.PluginProvider IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.PluginProvider (revision 37c4bbcd5256b0ea5f4f770ee63a136387f757f2) +++ ../incubator-ignite/modules/core/src/test/java/META-INF/services/org.apache.ignite.plugin.PluginProvider (revision 37c4bbcd5256b0ea5f4f770ee63a136387f757f2) @@ -0,0 +1,18 @@ +# +# 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. +# + +org.apache.ignite.internal.util.TestPluginProvider \ No newline at end of file Index: ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/internal/IgnitePluginLifecycleSelfTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/internal/IgnitePluginLifecycleSelfTest.java (revision 03dd16bc940d9907fdc460f55cdd99d5237baa75) +++ ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/internal/IgnitePluginLifecycleSelfTest.java (revision 03dd16bc940d9907fdc460f55cdd99d5237baa75) @@ -0,0 +1,62 @@ +/* + * 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.internal.util.*; +import org.apache.ignite.testframework.junits.common.*; + +/** + * Testing with {@link TestPluginProvider}. + */ +@GridCommonTest(group = "Kernal Self") +public class IgnitePluginLifecycleSelfTest extends GridCommonAbstractTest { + /** */ + public IgnitePluginLifecycleSelfTest() { + super(false); + } + + /** {@inheritDoc} */ + @Override protected long getTestTimeout() { + return 10000; + } + + /** + * @throws Exception If an error occurs. + */ + public void testStopGrid() throws Exception { + try { + TestPluginProvider.resetState(); + + TestPluginProvider.enableAssert = true; + + startGrid("testGrid"); + } + finally { + try { + stopGrid("testGrid", true); + } + finally { + TestPluginProvider.enableAssert = false; + } + } + + assertTrue(TestPluginProvider.bfStart && TestPluginProvider.start && TestPluginProvider.afStart + && TestPluginProvider.bfStop && TestPluginProvider.stop && TestPluginProvider.afStop + ); + } +} Index: ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java (revision aa2d7cb4a5c9f17d6a7a5b739feee7a2b84aad2b) +++ ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java (revision 0e779a0f77ce8c2970d944aea5ff577e6c6eecfa) @@ -1,0 +1,0 @@ Index: ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/processors/plugin/IgnitePluginProcessor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/processors/plugin/IgnitePluginProcessor.java (revision aa2d7cb4a5c9f17d6a7a5b739feee7a2b84aad2b) +++ ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/internal/processors/plugin/IgnitePluginProcessor.java (revision 0e779a0f77ce8c2970d944aea5ff577e6c6eecfa) @@ -132,7 +132,29 @@ /** {@inheritDoc} */ @Override public void start() throws IgniteCheckedException { + for (Map.Entry e : pluginCtxMap.entrySet()) + e.getKey().onBeforeStart(e.getValue()); + ackPluginsInfo(); + } + + /** {@inheritDoc} */ + @Override public void stop(boolean cancel) throws IgniteCheckedException { + boolean errOnStop = false; + + for (PluginProvider plugin : plugins.values()) { + try { + plugin.onAfterStop(cancel); + } + catch (Exception e) { + errOnStop = true; + + U.error(log, "Failed to invoke afterStop for plugin (ignoring): " + plugin, e); + } + } + + if (errOnStop) + throw new IgniteCheckedException("Failed to stop plugins."); } /** {@inheritDoc} */ Index: ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/plugin/PluginProvider.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/plugin/PluginProvider.java (revision aa2d7cb4a5c9f17d6a7a5b739feee7a2b84aad2b) +++ ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/plugin/PluginProvider.java (revision 0e779a0f77ce8c2970d944aea5ff577e6c6eecfa) @@ -75,6 +75,14 @@ @Nullable public T createComponent(PluginContext ctx, Class cls); /** + * Callback that notifies that Ignite prepares to start plugin. + * + * @param ctx Plugin context. + * @throws IgniteCheckedException Thrown in case of any errors. + */ + public void onBeforeStart(PluginContext ctx) throws IgniteCheckedException; + + /** * Starts grid component. * * @param ctx Plugin context. @@ -83,28 +91,35 @@ public void start(PluginContext ctx) throws IgniteCheckedException; /** - * Stops grid component. + * Callback that notifies that Ignite has successfully started, + * including all internal components. * - * @param cancel If {@code true}, then all ongoing tasks or jobs for relevant - * components need to be cancelled. * @throws IgniteCheckedException Thrown in case of any errors. */ - public void stop(boolean cancel) throws IgniteCheckedException; + public void onAfterStart() throws IgniteCheckedException; /** - * Callback that notifies that Ignite has successfully started, - * including all internal components. + * Callback that notifies that internal components have successfully stopped. * + * @param cancel Flag indicating whether jobs should be canceled. + */ + public void onAfterStop(boolean cancel) throws IgniteCheckedException; + + /** + * Stops grid component. + * + * @param cancel If {@code true}, then all ongoing tasks or jobs for relevant + * components need to be cancelled. * @throws IgniteCheckedException Thrown in case of any errors. */ - public void onIgniteStart() throws IgniteCheckedException; + public void stop(boolean cancel) throws IgniteCheckedException; /** * Callback to notify that Ignite is about to stop. * * @param cancel Flag indicating whether jobs should be canceled. */ - public void onIgniteStop(boolean cancel); + public void onBeforeStop(boolean cancel); /** * Gets plugin discovery data object that will be sent to the new node Index: ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/plugin/PluginProviderAdapter.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/plugin/PluginProviderAdapter.java (revision 0e779a0f77ce8c2970d944aea5ff577e6c6eecfa) +++ ../incubator-ignite/modules/core/src/main/java/org/apache/ignite/plugin/PluginProviderAdapter.java (revision 0e779a0f77ce8c2970d944aea5ff577e6c6eecfa) @@ -0,0 +1,105 @@ +/* + * 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.plugin; + +import org.apache.ignite.*; +import org.apache.ignite.cluster.*; +import org.jetbrains.annotations.*; + +import java.io.*; +import java.util.*; + +/** + * Adapter for {@link PluginProvider}. + */ +public class PluginProviderAdapter implements PluginProvider { + /** {@inheritDoc} */ + @Override public String name() { + return null; + } + + /** {@inheritDoc} */ + @Override public String version() { + return null; + } + + /** {@inheritDoc} */ + @Override public String copyright() { + return null; + } + + /** {@inheritDoc} */ + @Override public T plugin() { + return null; + } + + /** {@inheritDoc} */ + @Override public void initExtensions(PluginContext ctx, ExtensionRegistry registry) { + // No-op. + } + + /** {@inheritDoc} */ + @Nullable @Override public T createComponent(PluginContext ctx, Class cls) { + return null; + } + + /** {@inheritDoc} */ + @Override public void onBeforeStart(PluginContext ctx) throws IgniteCheckedException { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void start(PluginContext ctx) throws IgniteCheckedException { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void onAfterStart() throws IgniteCheckedException { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void onAfterStop(boolean cancel) { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void stop(boolean cancel) throws IgniteCheckedException { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void onBeforeStop(boolean cancel) { + // No-op. + } + + /** {@inheritDoc} */ + @Nullable @Override public Serializable provideDiscoveryData(UUID nodeId) { + return null; + } + + /** {@inheritDoc} */ + @Override public void receiveDiscoveryData(UUID nodeId, Serializable data) { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void validateNewNode(ClusterNode node) throws PluginValidationException { + // No-op. + } +} Index: ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/internal/util/TestPluginProvider.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/internal/util/TestPluginProvider.java (revision 0e779a0f77ce8c2970d944aea5ff577e6c6eecfa) +++ ../incubator-ignite/modules/core/src/test/java/org/apache/ignite/internal/util/TestPluginProvider.java (revision 0e779a0f77ce8c2970d944aea5ff577e6c6eecfa) @@ -0,0 +1,128 @@ +/* + * 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.util; + +import org.apache.ignite.*; +import org.apache.ignite.internal.*; +import org.apache.ignite.plugin.*; +import org.apache.ignite.testframework.*; + +import java.util.concurrent.*; + +import static org.junit.Assert.*; + +/** + * + */ +public class TestPluginProvider extends PluginProviderAdapter { + /** */ + public static boolean bfStart, start, afStart, bfStop, stop, afStop; + + /** */ + public static boolean enableAssert = false; + + /** */ + IgniteKernal ignite; + + /** {@inheritDoc} */ + @Override public String name() { + return "TestPlugin"; + } + + /** {@inheritDoc} */ + @Override public IgnitePlugin plugin() { + return new IgnitePlugin() {}; + } + + /** {@inheritDoc} */ + @Override public void onBeforeStart(PluginContext ctx) throws IgniteCheckedException { + if (enableAssert) { + bfStart = true; + + assertFalse(start || afStart || bfStop || stop || afStop); + } + } + + /** {@inheritDoc} */ + @Override public void start(PluginContext ctx) throws IgniteCheckedException { + if (enableAssert) { + ignite = (IgniteKernal)ctx.grid(); + + start = true; + + assertFalse(afStart || bfStop || stop || afStop); + } + } + + /** {@inheritDoc} */ + @Override public void onAfterStart() throws IgniteCheckedException { + if (enableAssert) { + afStart = true; + + assertFalse(bfStop || stop || afStop); + } + } + + /** {@inheritDoc} */ + @Override public void onBeforeStop(boolean cancel) { + if (enableAssert) { + bfStop = true; + + assertFalse(stop || afStop); + } + } + + /** {@inheritDoc} */ + @Override public void stop(boolean cancel) throws IgniteCheckedException { + if (enableAssert) { + stop = true; + + assertFalse(afStop); + } + } + + /** {@inheritDoc} */ + @Override public void onAfterStop(boolean cancel) { + if (enableAssert) { + GridTestUtils.assertThrows(null, new Callable() { + @Override public Object call() throws Exception { + return ignite.cache(null); + } + }, IllegalStateException.class, null); + + afStop = true; + } + } + + /** {@inheritDoc} */ + @Override public String version() { + return "0.0.1"; + } + + /** + * Reset state. + */ + public static void resetState() { + bfStart = start = afStart = bfStop = stop = afStop = false; + } + + /** */ + public static class TestPluginCfg implements PluginConfiguration { + // No-op. + } +}