From 5531f0c01a1bd7070bb9372b589641efcb6f0544 Mon Sep 17 00:00:00 2001 From: Aleksey Plekhanov Date: Fri, 6 Nov 2020 16:46:12 +0300 Subject: [PATCH 1/6] IGNITE-13633 Fix ServiceDescriptor.serviceClass failure in case of deployed via DeploymentSPI service --- .../service/GridServiceProcessor.java | 2 +- .../service/IgniteServiceProcessor.java | 4 +- .../service/ServiceDescriptorImpl.java | 27 +++++- .../processors/service/ServiceInfo.java | 32 ++++++- ...ceHotRedeploymentViaDeploymentSpiTest.java | 94 ++++++++++++++++--- .../service/ServiceInfoSelfTest.java | 4 +- 6 files changed, 139 insertions(+), 24 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java index c0f624f67d887..d064a052ce206 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java @@ -945,7 +945,7 @@ private static Map serviceTopology(IgniteInternalCache top; + /** Service class. */ + private volatile Class srvcCls; + /** * @param originNodeId Initiating node id. * @param srvcId Service id. * @param cfg Service configuration. */ - public ServiceInfo(@NotNull UUID originNodeId, @NotNull IgniteUuid srvcId, @NotNull ServiceConfiguration cfg) { - this(originNodeId, srvcId, cfg, false); + public ServiceInfo(GridKernalContext ctx, @NotNull UUID originNodeId, @NotNull IgniteUuid srvcId, @NotNull ServiceConfiguration cfg) { + this(ctx, originNodeId, srvcId, cfg, false); } /** @@ -68,8 +76,9 @@ public ServiceInfo(@NotNull UUID originNodeId, @NotNull IgniteUuid srvcId, @NotN * @param cfg Service configuration. * @param staticCfg Statically configured flag. */ - public ServiceInfo(@NotNull UUID originNodeId, @NotNull IgniteUuid srvcId, @NotNull ServiceConfiguration cfg, + public ServiceInfo(@NotNull GridKernalContext ctx, @NotNull UUID originNodeId, @NotNull IgniteUuid srvcId, @NotNull ServiceConfiguration cfg, boolean staticCfg) { + this.ctx = ctx; this.originNodeId = originNodeId; this.srvcId = srvcId; this.cfg = cfg; @@ -116,15 +125,28 @@ public IgniteUuid serviceId() { } /** {@inheritDoc} */ - @SuppressWarnings("unchecked") @Override public Class serviceClass() { if (cfg instanceof LazyServiceConfiguration) { + if (srvcCls != null) + return srvcCls; + String clsName = ((LazyServiceConfiguration)cfg).serviceClassName(); try { - return (Class)Class.forName(clsName); + srvcCls = (Class)Class.forName(clsName); + + return srvcCls; } catch (ClassNotFoundException e) { + GridDeployment srvcDep = ctx.deploy().getDeployment(clsName); + + if (srvcDep != null) { + srvcCls = (Class)srvcDep.deployedClass(clsName); + + if (srvcCls != null) + return srvcCls; + } + throw new IgniteException("Failed to find service class: " + clsName, e); } } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceHotRedeploymentViaDeploymentSpiTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceHotRedeploymentViaDeploymentSpiTest.java index 7ac558a72e9d8..aeeeadbf11a90 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceHotRedeploymentViaDeploymentSpiTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceHotRedeploymentViaDeploymentSpiTest.java @@ -24,19 +24,24 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.function.ToIntFunction; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteException; +import org.apache.ignite.Ignition; +import org.apache.ignite.client.IgniteClient; +import org.apache.ignite.configuration.ClientConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.services.Service; +import org.apache.ignite.services.ServiceDescriptor; import org.apache.ignite.spi.deployment.DeploymentSpi; import org.apache.ignite.spi.deployment.local.LocalDeploymentSpi; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.junit.After; import org.junit.Assume; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; /** @@ -61,12 +66,6 @@ public class ServiceHotRedeploymentViaDeploymentSpiTest extends GridCommonAbstra return cfg; } - /** */ - @BeforeClass - public static void check() { - Assume.assumeTrue(isEventDrivenServiceProcessorEnabled()); - } - /** */ @Before public void prepare() throws IOException { @@ -79,11 +78,64 @@ public void cleanup() { U.delete(srcTmpDir); } + /** */ + @Test + public void testServiceDeploymentViaDeploymentSpi() throws Exception { + URLClassLoader clsLdr = prepareClassLoader(1); + Class cls = clsLdr.loadClass("MyRenewServiceImpl"); + + MyRenewService srvc = (MyRenewService)cls.newInstance(); + + assertEquals(1, srvc.version()); + + try { + Ignite ignite = startGrid(0); + + final DeploymentSpi depSpi = ignite.configuration().getDeploymentSpi(); + + depSpi.register(clsLdr, srvc.getClass()); + + ignite.services().deployClusterSingleton(SERVICE_NAME, srvc); + + Class srvcCls = serviceClass(ignite, SERVICE_NAME); + + assertSame(cls, srvcCls); + + assertEquals(1, ignite.services().serviceProxy(SERVICE_NAME, MyRenewService.class, false) + .version()); + } + finally { + stopAllGrids(); + } + } + + /** */ + @Test + public void testServiceHotRedeploymentNode() throws Exception { + serviceHotRedeploymentTest( + ignite -> ignite.services().serviceProxy(SERVICE_NAME, MyRenewService.class, false).version()); + } + + /** */ + @Test + public void testServiceHotRedeploymentThinClient() throws Exception { + serviceHotRedeploymentTest(ignite -> { + try (IgniteClient client = Ignition.startClient(new ClientConfiguration().setAddresses("127.0.0.1:10800"))) { + return client.services().serviceProxy(SERVICE_NAME, MyRenewService.class).version(); + } + catch (Exception e) { + throw new IgniteException(e); + } + }); + } + /** * @throws Exception If failed. */ - @Test - public void serviceHotRedeploymentTest() throws Exception { + private void serviceHotRedeploymentTest(ToIntFunction srvcFunc) throws Exception { + Assume.assumeTrue("Hot redeployment supported only by event driven service processor", + isEventDrivenServiceProcessorEnabled()); + URLClassLoader clsLdr = prepareClassLoader(1); Class cls = clsLdr.loadClass("MyRenewServiceImpl"); @@ -99,8 +151,12 @@ public void serviceHotRedeploymentTest() throws Exception { depSpi.register(clsLdr, srvc.getClass()); ignite.services().deployClusterSingleton(SERVICE_NAME, srvc); - MyRenewService proxy = ignite.services().serviceProxy(SERVICE_NAME, MyRenewService.class, false); - assertEquals(1, proxy.version()); + + Class srvcCls = serviceClass(ignite, SERVICE_NAME); + + assertSame(cls, srvcCls); + + assertEquals(1, srvcFunc.applyAsInt(ignite)); ignite.services().cancel(SERVICE_NAME); depSpi.unregister(srvc.getClass().getName()); @@ -111,14 +167,26 @@ public void serviceHotRedeploymentTest() throws Exception { depSpi.register(clsLdr, srvc.getClass()); ignite.services().deployClusterSingleton(SERVICE_NAME, srvc); - proxy = ignite.services().serviceProxy(SERVICE_NAME, MyRenewService.class, false); - assertEquals(2, proxy.version()); + + assertNotSame(srvcCls, serviceClass(ignite, SERVICE_NAME)); + + assertEquals(2, srvcFunc.applyAsInt(ignite)); } finally { stopAllGrids(); } } + /** */ + private Class serviceClass(Ignite ignite, String srvcName) { + for (ServiceDescriptor desc : ignite.services().serviceDescriptors()) { + if (srvcName.equals(desc.name())) + return desc.serviceClass(); + } + + return null; + } + /** */ public interface MyRenewService extends Service { /** diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java index 4d557f5e2b7b6..4abe4c438640c 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java @@ -24,6 +24,8 @@ import org.apache.ignite.services.Service; import org.apache.ignite.services.ServiceConfiguration; import org.apache.ignite.services.ServiceContext; +import org.apache.ignite.testframework.junits.GridTestKernalContext; +import org.apache.ignite.testframework.junits.logger.GridTestLog4jLogger; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -44,7 +46,7 @@ public class ServiceInfoSelfTest { private ServiceConfiguration cfg = configuration(); /** Subject under test. */ - private ServiceInfo sut = new ServiceInfo(nodeId, srvcId, cfg); + private ServiceInfo sut = new ServiceInfo(new GridTestKernalContext(new GridTestLog4jLogger()), nodeId, srvcId, cfg); /** * Tests {@link ServiceInfo#configuration()}. From 9245c9ba23d85e42eade478c774510505ccaf436 Mon Sep 17 00:00:00 2001 From: Aleksey Plekhanov Date: Thu, 19 Nov 2020 18:06:47 +0300 Subject: [PATCH 2/6] IGNITE-13633 Review fixes --- .../service/ServiceDescriptorImpl.java | 16 +++++++------ .../processors/service/ServiceInfo.java | 16 +++++++------ .../service/ServiceInfoSelfTest.java | 23 +++++++++++++++++++ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDescriptorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDescriptorImpl.java index 805a8b642edd6..4b57ab47eecea 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDescriptorImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceDescriptorImpl.java @@ -41,7 +41,7 @@ public class ServiceDescriptorImpl implements ServiceDescriptor { private static final long serialVersionUID = 0L; /** Kernel context. */ - private final GridKernalContext ctx; + private final transient GridKernalContext ctx; /** Configuration. */ @GridToStringInclude @@ -52,7 +52,7 @@ public class ServiceDescriptorImpl implements ServiceDescriptor { private Map top; /** Service class. */ - private volatile Class srvcCls; + private transient volatile Class srvcCls; /** * @param dep Deployment. @@ -83,13 +83,15 @@ public ServiceDescriptorImpl(GridKernalContext ctx, GridServiceDeployment dep) { return srvcCls; } catch (ClassNotFoundException e) { - GridDeployment srvcDep = ctx.deploy().getDeployment(clsName); + if (ctx != null) { + GridDeployment srvcDep = ctx.deploy().getDeployment(clsName); - if (srvcDep != null) { - srvcCls = (Class)srvcDep.deployedClass(clsName); + if (srvcDep != null) { + srvcCls = (Class)srvcDep.deployedClass(clsName); - if (srvcCls != null) - return srvcCls; + if (srvcCls != null) + return srvcCls; + } } throw new IgniteException("Failed to find service class: " + clsName, e); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceInfo.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceInfo.java index 2a2b668e2ceca..dcb7521e32da0 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceInfo.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceInfo.java @@ -40,7 +40,7 @@ public class ServiceInfo implements ServiceDescriptor { private static final long serialVersionUID = 0L; /** Context. */ - private final GridKernalContext ctx; + private final transient GridKernalContext ctx; /** Origin node ID. */ private final UUID originNodeId; @@ -59,7 +59,7 @@ public class ServiceInfo implements ServiceDescriptor { private volatile Map top; /** Service class. */ - private volatile Class srvcCls; + private transient volatile Class srvcCls; /** * @param originNodeId Initiating node id. @@ -138,13 +138,15 @@ public IgniteUuid serviceId() { return srvcCls; } catch (ClassNotFoundException e) { - GridDeployment srvcDep = ctx.deploy().getDeployment(clsName); + if (ctx != null) { + GridDeployment srvcDep = ctx.deploy().getDeployment(clsName); - if (srvcDep != null) { - srvcCls = (Class)srvcDep.deployedClass(clsName); + if (srvcDep != null) { + srvcCls = (Class)srvcDep.deployedClass(clsName); - if (srvcCls != null) - return srvcCls; + if (srvcCls != null) + return srvcCls; + } } throw new IgniteException("Failed to find service class: " + clsName, e); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java index 4abe4c438640c..51f6f919a2620 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java @@ -17,6 +17,10 @@ package org.apache.ignite.internal.processors.service; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.HashMap; import java.util.UUID; import org.apache.ignite.cluster.ClusterNode; @@ -100,6 +104,25 @@ public void testTopologySnapshotEquality() { assertNotSame(top, sut.topologySnapshot()); } + /** + * Tests serialization/deserialization of ServiceInfo. + */ + @Test + public void testSerializeDeserialize() throws Exception { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + new ObjectOutputStream(os).writeObject(sut); + + ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(os.toByteArray())); + + ServiceInfo srvcInfo = (ServiceInfo)is.readObject(); + + assertEquals(sut.name(), srvcInfo.name()); + assertEquals(sut.originNodeId(), srvcInfo.originNodeId()); + assertEquals(sut.serviceId(), srvcInfo.serviceId()); + assertEquals(sut.serviceClass(), srvcInfo.serviceClass()); + } + /** * @return Service configuration. */ From 1144b052f3ac4be2fbd97c37cc53c25f701e5051 Mon Sep 17 00:00:00 2001 From: Aleksey Plekhanov Date: Wed, 2 Dec 2020 12:48:17 +0300 Subject: [PATCH 3/6] IGNITE-13663 Review fixes, partial revert --- .../service/GridServiceProcessor.java | 2 +- .../service/IgniteServiceProcessor.java | 18 +++++++++--- .../service/ServiceDescriptorImpl.java | 29 ++----------------- .../processors/service/ServiceInfo.java | 18 ++++++++---- ...ceHotRedeploymentViaDeploymentSpiTest.java | 25 ++++++++++++---- .../service/ServiceInfoSelfTest.java | 2 +- 6 files changed, 50 insertions(+), 44 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java index d064a052ce206..c0f624f67d887 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java @@ -945,7 +945,7 @@ private static Map serviceTopology(IgniteInternalCache srvcFunc) throws Exception { - Assume.assumeTrue("Hot redeployment supported only by event driven service processor", - isEventDrivenServiceProcessorEnabled()); - URLClassLoader clsLdr = prepareClassLoader(1); Class cls = clsLdr.loadClass("MyRenewServiceImpl"); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java index 51f6f919a2620..02ad376e277da 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java @@ -50,7 +50,7 @@ public class ServiceInfoSelfTest { private ServiceConfiguration cfg = configuration(); /** Subject under test. */ - private ServiceInfo sut = new ServiceInfo(new GridTestKernalContext(new GridTestLog4jLogger()), nodeId, srvcId, cfg); + private ServiceInfo sut = new ServiceInfo(nodeId, srvcId, cfg); /** * Tests {@link ServiceInfo#configuration()}. From 1ce95c603e15aa81d665c0be5b2b89466982d0fb Mon Sep 17 00:00:00 2001 From: Aleksey Plekhanov Date: Wed, 2 Dec 2020 13:43:15 +0300 Subject: [PATCH 4/6] IGNITE-13663 Unused imports removed --- .../ignite/internal/processors/service/ServiceInfoSelfTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java index 02ad376e277da..6233168a6e7dc 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/ServiceInfoSelfTest.java @@ -28,8 +28,6 @@ import org.apache.ignite.services.Service; import org.apache.ignite.services.ServiceConfiguration; import org.apache.ignite.services.ServiceContext; -import org.apache.ignite.testframework.junits.GridTestKernalContext; -import org.apache.ignite.testframework.junits.logger.GridTestLog4jLogger; import org.junit.Test; import static org.junit.Assert.assertEquals; From 880b49754dfdd14fb9dbdd1c63bc22ae88a8d49f Mon Sep 17 00:00:00 2001 From: Aleksey Plekhanov Date: Wed, 2 Dec 2020 15:58:17 +0300 Subject: [PATCH 5/6] IGNITE-13663 Review fixes --- .../service/IgniteServiceProcessor.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java index db649210b1133..03b57774594d8 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java @@ -349,11 +349,8 @@ private void cancelDeployedServices() { ServiceProcessorCommonDiscoveryData clusterData = (ServiceProcessorCommonDiscoveryData)data.commonData(); - for (ServiceInfo desc : clusterData.registeredServices()) { - desc.context(ctx); - - registeredServices.put(desc.serviceId(), desc); - } + for (ServiceInfo desc : clusterData.registeredServices()) + registerService(desc); } /** {@inheritDoc} */ @@ -386,7 +383,7 @@ private void cancelDeployedServices() { oldDesc = lookupInRegisteredServices(desc.name()); if (oldDesc == null) { - registeredServices.put(desc.serviceId(), desc); + registerService(desc); continue; } @@ -1623,9 +1620,7 @@ else if (req instanceof ServiceUndeploymentRequest) else { ServiceInfo desc = new ServiceInfo(snd.id(), reqSrvcId, cfg); - desc.context(ctx); - - registeredServices.put(reqSrvcId, desc); + registerService(desc); toDeploy.put(reqSrvcId, desc); } @@ -1679,6 +1674,15 @@ else if (req instanceof ServiceUndeploymentRequest) { } } + /** + * @param desc Service descriptor. + */ + private void registerService(ServiceInfo desc) { + desc.context(ctx); + + registeredServices.put(desc.serviceId(), desc); + } + /** * @param msg Message. */ From b37d9802d1be71efa74a8e243fbd2493b1f2a6cc Mon Sep 17 00:00:00 2001 From: Aleksey Plekhanov Date: Wed, 2 Dec 2020 16:00:32 +0300 Subject: [PATCH 6/6] IGNITE-13663 Review fixes --- .../internal/processors/service/IgniteServiceProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java index 03b57774594d8..e3ad553720f38 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java @@ -1513,7 +1513,7 @@ private boolean isLocalNodeCoordinator() { // First node start, method onGridDataReceived(DiscoveryDataBag.GridDiscoveryData) has not been called. ArrayList staticServicesInfo = staticallyConfiguredServices(false); - staticServicesInfo.forEach(desc -> registeredServices.put(desc.serviceId(), desc)); + staticServicesInfo.forEach(this::registerService); } ServiceDeploymentActions depActions = null;