Skip to content

Commit 18255ad

Browse files
authored
IGNITE-26536 Extract code deployment class loader to separate module (#7083)
1 parent 4ce319e commit 18255ad

File tree

36 files changed

+374
-232
lines changed

36 files changed

+374
-232
lines changed

modules/client/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ dependencies {
5757
testImplementation project(':ignite-cluster-management')
5858
testImplementation project(':ignite-compute')
5959
testImplementation project(':ignite-code-deployment')
60+
testImplementation project(':ignite-code-deployment-classloader')
6061
testImplementation project(':ignite-eventlog')
6162
testImplementation testFixtures(project(':ignite-api'))
6263
testImplementation testFixtures(project(':ignite-core'))

modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCompute.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
import org.apache.ignite.internal.compute.TaskStateImpl;
6969
import org.apache.ignite.internal.compute.events.ComputeEventMetadata;
7070
import org.apache.ignite.internal.compute.events.ComputeEventMetadataBuilder;
71-
import org.apache.ignite.internal.compute.loader.JobClassLoader;
71+
import org.apache.ignite.internal.deployunit.loader.UnitsClassLoader;
7272
import org.apache.ignite.internal.hlc.HybridTimestamp;
7373
import org.apache.ignite.internal.network.ClusterNodeImpl;
7474
import org.apache.ignite.internal.network.InternalClusterNode;
@@ -132,7 +132,7 @@ public CompletableFuture<JobExecution<ComputeJobDataHolder>> executeAsyncWithFai
132132
}
133133

134134
if (jobClassName.startsWith("org.apache.ignite")) {
135-
JobClassLoader jobClassLoader = new JobClassLoader(List.of(), this.getClass().getClassLoader());
135+
UnitsClassLoader jobClassLoader = new UnitsClassLoader(List.of(), this.getClass().getClassLoader());
136136
Class<ComputeJob<Object, Object>> jobClass = ComputeUtils.jobClass(jobClassLoader, jobClassName);
137137
ComputeJob<Object, Object> job = ComputeUtils.instantiateJob(jobClass);
138138
CompletableFuture<Object> jobFut = job.executeAsync(
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
apply from: "$rootDir/buildscripts/java-core.gradle"
19+
apply from: "$rootDir/buildscripts/publishing.gradle"
20+
apply from: "$rootDir/buildscripts/java-junit5.gradle"
21+
apply from: 'jobs.gradle'
22+
23+
description = 'ignite-code-deployment-classloader'
24+
25+
dependencies {
26+
implementation libs.jetbrains.annotations
27+
28+
implementation project(':ignite-core')
29+
implementation project(':ignite-api')
30+
implementation project(':ignite-code-deployment')
31+
32+
testImplementation project(':ignite-core')
33+
testImplementation testFixtures(project(':ignite-core'))
34+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
sourceSets {
19+
jobs
20+
unit1
21+
unit2
22+
}
23+
24+
def registerJarTask(SourceSet sourceSet, String baseName) {
25+
tasks.register(sourceSet.jarTaskName, Jar) {
26+
group = 'build'
27+
archiveBaseName = baseName
28+
archiveVersion = '1.0-SNAPSHOT'
29+
from sourceSet.output
30+
}
31+
}
32+
33+
registerJarTask(sourceSets.unit1, 'ignite-unit-test-job1')
34+
registerJarTask(sourceSets.unit2, 'ignite-unit-test-job2')
35+
36+
processTestResources {
37+
into('units/unit1') {
38+
into('1.0.0') {
39+
from unit1Jar
40+
}
41+
into('2.0.0') {
42+
from unit2Jar
43+
}
44+
into('3.0.1') {
45+
from unit1Jar
46+
from unit2Jar
47+
}
48+
into('3.0.2') {
49+
into('subdir') {
50+
from unit2Jar
51+
}
52+
from unit1Jar
53+
}
54+
}
55+
into('units/unit2') {
56+
into('1.0.0') {
57+
from unit1Jar
58+
}
59+
into('2.0.0') {
60+
from unit2Jar
61+
}
62+
}
63+
64+
File corruptedJarFile = file("$destinationDir/units/unit1/4.0.0/unit1-1.0-corrupted.jar")
65+
doLast {
66+
// Generate a 100 bytes long file with random contents to simulate corrupted jar
67+
byte[] randomBytes = new byte[100]
68+
new Random().nextBytes(randomBytes)
69+
corruptedJarFile.parentFile.mkdirs()
70+
corruptedJarFile.bytes = randomBytes
71+
}
72+
}
73+
74+
dependencies {
75+
jobsImplementation project(':ignite-api')
76+
jobsImplementation project(':ignite-core')
77+
unit1Implementation project(':ignite-api')
78+
unit2Implementation project(':ignite-api')
79+
}

modules/compute/src/main/java/org/apache/ignite/internal/compute/ClassLoaderExceptionsMapper.java renamed to modules/code-deployment-classloader/src/main/java/org/apache/ignite/internal/deployunit/loader/ClassLoaderExceptionsMapper.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@
1515
* limitations under the License.
1616
*/
1717

18-
package org.apache.ignite.internal.compute;
18+
package org.apache.ignite.internal.deployunit.loader;
1919

2020
import static org.apache.ignite.internal.util.ExceptionUtils.unwrapCompletionThrowable;
2121

2222
import java.util.concurrent.CompletableFuture;
2323
import java.util.concurrent.CompletionException;
24-
import org.apache.ignite.internal.compute.loader.JobContext;
2524
import org.apache.ignite.internal.deployunit.exception.DeploymentUnitNotFoundException;
2625
import org.apache.ignite.internal.deployunit.exception.DeploymentUnitUnavailableException;
2726

@@ -34,20 +33,20 @@ class ClassLoaderExceptionsMapper {
3433
private static final String DEPLOYMENT_UNIT_NOT_AVAILABLE_MSG = "%s. Deployment unit %s:%s can't be used: "
3534
+ "[clusterStatus = %s, nodeStatus = %s]";
3635

37-
static CompletableFuture<JobContext> mapClassLoaderExceptions(
38-
CompletableFuture<JobContext> future,
39-
String jobClassName
36+
static CompletableFuture<UnitsClassLoaderContext> mapClassLoaderExceptions(
37+
CompletableFuture<UnitsClassLoaderContext> future,
38+
String acquireId
4039
) {
4140
return future.handle((v, e) -> {
42-
if (e instanceof Exception) {
43-
throw new CompletionException(mapException((Exception) unwrapCompletionThrowable((Exception) e), jobClassName));
41+
if (e != null) {
42+
throw new CompletionException(mapException(unwrapCompletionThrowable(e), acquireId));
4443
} else {
4544
return v;
4645
}
4746
});
4847
}
4948

50-
private static Exception mapException(Exception e, String jobClassName) {
49+
private static Throwable mapException(Throwable e, String jobClassName) {
5150
if (e instanceof DeploymentUnitNotFoundException) {
5251
return new ClassNotFoundException(
5352
String.format(

modules/compute/src/main/java/org/apache/ignite/internal/compute/loader/JobClassLoader.java renamed to modules/code-deployment-classloader/src/main/java/org/apache/ignite/internal/deployunit/loader/UnitsClassLoader.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
package org.apache.ignite.internal.compute.loader;
18+
package org.apache.ignite.internal.deployunit.loader;
1919

2020
import java.net.URL;
2121
import java.security.AccessController;
@@ -32,22 +32,22 @@
3232
/**
3333
* Implementation of {@link ClassLoader} that loads classes from specified component directories.
3434
*/
35-
public class JobClassLoader implements AutoCloseable {
36-
private static final IgniteLogger LOG = Loggers.forClass(JobClassLoader.class);
35+
public class UnitsClassLoader implements AutoCloseable {
36+
private static final IgniteLogger LOG = Loggers.forClass(UnitsClassLoader.class);
3737

3838
private final List<DisposableDeploymentUnit> units;
3939

4040
private final ClassLoader parent;
4141

42-
private volatile JobClassLoaderImpl impl;
42+
private volatile UnitsClassLoaderImpl impl;
4343

4444
/**
45-
* Creates new instance of {@link JobClassLoader}.
45+
* Creates new instance of {@link UnitsClassLoader}.
4646
*
4747
* @param units Units to load classes from.
4848
* @param parent Parent class loader.
4949
*/
50-
public JobClassLoader(List<DisposableDeploymentUnit> units, ClassLoader parent) {
50+
public UnitsClassLoader(List<DisposableDeploymentUnit> units, ClassLoader parent) {
5151
this.units = units;
5252
this.parent = parent;
5353
}
@@ -77,18 +77,18 @@ public ClassLoader classLoader() {
7777
return impl;
7878
}
7979

80-
private JobClassLoaderImpl createClassLoader() {
81-
return AccessController.doPrivileged((PrivilegedAction<JobClassLoaderImpl>) () -> {
80+
private UnitsClassLoaderImpl createClassLoader() {
81+
return AccessController.doPrivileged((PrivilegedAction<UnitsClassLoaderImpl>) () -> {
8282
URL[] classpath = units.stream()
8383
.map(DisposableDeploymentUnit::path)
84-
.flatMap(JobClasspath::collectClasspath)
84+
.flatMap(UnitsClasspath::collectClasspath)
8585
.toArray(URL[]::new);
8686

8787
if (LOG.isDebugEnabled()) {
8888
LOG.debug("Created class loader with classpath: {}", Arrays.toString(classpath));
8989
}
9090

91-
return new JobClassLoaderImpl(units, classpath, parent);
91+
return new UnitsClassLoaderImpl(units, classpath, parent);
9292
});
9393
}
9494

@@ -105,7 +105,7 @@ public void close() {
105105
}
106106

107107
try {
108-
JobClassLoaderImpl impl0 = impl;
108+
UnitsClassLoaderImpl impl0 = impl;
109109

110110
if (impl0 != null) {
111111
impl0.close();

modules/compute/src/main/java/org/apache/ignite/internal/compute/loader/JobContext.java renamed to modules/code-deployment-classloader/src/main/java/org/apache/ignite/internal/deployunit/loader/UnitsClassLoaderContext.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,25 @@
1515
* limitations under the License.
1616
*/
1717

18-
package org.apache.ignite.internal.compute.loader;
18+
package org.apache.ignite.internal.deployunit.loader;
1919

2020
import java.util.function.Consumer;
2121

2222
/**
2323
* Job context.
2424
*/
25-
public class JobContext implements AutoCloseable {
25+
public class UnitsClassLoaderContext implements AutoCloseable {
2626

27-
private final JobClassLoader classLoader;
27+
private final UnitsClassLoader classLoader;
2828

29-
private final Consumer<JobContext> onClose;
29+
private final Consumer<UnitsClassLoaderContext> onClose;
3030

31-
public JobContext(JobClassLoader classLoader, Consumer<JobContext> onClose) {
31+
public UnitsClassLoaderContext(UnitsClassLoader classLoader, Consumer<UnitsClassLoaderContext> onClose) {
3232
this.classLoader = classLoader;
3333
this.onClose = onClose;
3434
}
3535

36-
public JobClassLoader classLoader() {
36+
public UnitsClassLoader classLoader() {
3737
return classLoader;
3838
}
3939

modules/compute/src/main/java/org/apache/ignite/internal/compute/loader/JobClassLoaderFactory.java renamed to modules/code-deployment-classloader/src/main/java/org/apache/ignite/internal/deployunit/loader/UnitsClassLoaderFactory.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,22 @@
1515
* limitations under the License.
1616
*/
1717

18-
package org.apache.ignite.internal.compute.loader;
18+
package org.apache.ignite.internal.deployunit.loader;
1919

2020
import java.util.List;
2121
import org.apache.ignite.internal.deployunit.DisposableDeploymentUnit;
2222

2323
/**
24-
* Creates a class loader for a job.
24+
* Deployment units classloader factory.
2525
*/
26-
public class JobClassLoaderFactory {
26+
public class UnitsClassLoaderFactory {
2727
/**
2828
* Create a class loader for the specified units.
2929
*
3030
* @param units The units of the job.
3131
* @return The class loader.
3232
*/
33-
public JobClassLoader createClassLoader(List<DisposableDeploymentUnit> units) {
34-
return new JobClassLoader(units, getClass().getClassLoader());
33+
public UnitsClassLoader createClassLoader(List<DisposableDeploymentUnit> units) {
34+
return new UnitsClassLoader(units, getClass().getClassLoader());
3535
}
3636
}

modules/compute/src/main/java/org/apache/ignite/internal/compute/loader/JobClassLoaderImpl.java renamed to modules/code-deployment-classloader/src/main/java/org/apache/ignite/internal/deployunit/loader/UnitsClassLoaderImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
package org.apache.ignite.internal.compute.loader;
18+
package org.apache.ignite.internal.deployunit.loader;
1919

2020
import java.net.URL;
2121
import java.net.URLClassLoader;
@@ -24,7 +24,7 @@
2424
import java.util.regex.Pattern;
2525
import org.apache.ignite.internal.deployunit.DisposableDeploymentUnit;
2626

27-
class JobClassLoaderImpl extends URLClassLoader {
27+
class UnitsClassLoaderImpl extends URLClassLoader {
2828
/**
2929
* Pattern to match system packages.
3030
*/
@@ -38,13 +38,13 @@ class JobClassLoaderImpl extends URLClassLoader {
3838
private final ClassLoader parent;
3939

4040
/**
41-
* Creates new instance of {@link JobClassLoader}.
41+
* Creates new instance of {@link UnitsClassLoader}.
4242
*
4343
* @param urls URLs to load classes from.
4444
* @param units Units to load classes from.
4545
* @param parent Parent class loader.
4646
*/
47-
JobClassLoaderImpl(List<DisposableDeploymentUnit> units, URL[] urls, ClassLoader parent) {
47+
public UnitsClassLoaderImpl(List<DisposableDeploymentUnit> units, URL[] urls, ClassLoader parent) {
4848
super("compute-job", urls, parent);
4949
this.units = units;
5050
this.parent = parent;

modules/compute/src/main/java/org/apache/ignite/internal/compute/loader/JobClasspath.java renamed to modules/code-deployment-classloader/src/main/java/org/apache/ignite/internal/deployunit/loader/UnitsClasspath.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
package org.apache.ignite.internal.compute.loader;
18+
package org.apache.ignite.internal.deployunit.loader;
1919

2020
import java.io.IOException;
2121
import java.net.MalformedURLException;
@@ -31,7 +31,7 @@
3131
import org.apache.ignite.compute.ComputeException;
3232
import org.apache.ignite.lang.ErrorGroups.Compute;
3333

34-
class JobClasspath {
34+
class UnitsClasspath {
3535
static Stream<URL> collectClasspath(Path unitDir) {
3636
if (Files.notExists(unitDir)) {
3737
throw new IllegalArgumentException("Unit does not exist: " + unitDir);

0 commit comments

Comments
 (0)