This is an automated email from the ASF dual-hosted git repository.
heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
The following commit(s) were added to refs/heads/master by this push:
new da1653b try to clean osgi so launcher build doesn't break FS limits
da1653b is described below
commit da1653b660334660dbf1334a179d92f0d7da65d7
Author: Alex Heneveld <[email protected]>
AuthorDate: Sat Aug 7 03:33:43 2021 +0100
try to clean osgi so launcher build doesn't break FS limits
OSGi cycles leak a few hundred open files; can't solve it, though code in
here tries to;
ultimately just enable osgi reuse for the test...
---
.../apache/brooklyn/core/mgmt/ha/OsgiManager.java | 41 +++++++++++++++++
.../BrooklynLauncherUpgradeCatalogOsgiTest.java | 6 +--
.../java/org/apache/brooklyn/util/guava/Maybe.java | 53 ++++++++++++++++++++++
3 files changed, 97 insertions(+), 3 deletions(-)
diff --git
a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index 85418e9..835ae44 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -29,6 +29,9 @@ import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
@@ -59,6 +62,7 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.exceptions.ReferenceWithError;
import org.apache.brooklyn.util.exceptions.UserFacingException;
import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.Reflections;
import org.apache.brooklyn.util.os.Os;
import org.apache.brooklyn.util.os.Os.DeletionResult;
import org.apache.brooklyn.util.osgi.VersionedName;
@@ -70,6 +74,7 @@ import org.apache.commons.lang3.tuple.Pair;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.launch.Framework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -296,7 +301,43 @@ public class OsgiManager {
}
if (!reuseFramework || !REUSED_FRAMEWORKS_ARE_KEPT_RUNNING) {
+ try {
+ for (Bundle b: framework.getBundleContext().getBundles()) {
+ if ((bundlesAtStartup==null ||
!bundlesAtStartup.contains(b)) && (b!=framework)) {
+ try {
+ log.info("Uninstalling "+b+" from OSGi container");
+ b.uninstall();
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ log.warn("Unable to uninstall "+b+": "+e, e);
+ }
+ }
+ }
+
+ framework.stop();
+ final FrameworkEvent fe =
framework.waitForStop(Duration.seconds(30).toMilliseconds());
+ log.debug("Stopped OSGi framework: "+fe);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
Osgis.ungetFramework(framework);
+
+ // aggressively clean up, as Felix leaks threadpools and other
objects;
+ // but even with this _something_ is clogging up the app
classloader
+ // which is causing file handles to leak badly;
+
+ Reflections.getFieldValueMaybe(framework, "m_resolver")
+ .mapMaybe(resolver -> Reflections.getFieldValueMaybe(resolver,
"m_executor"))
+ .transformNow(ex -> {
+ if (ex instanceof ExecutorService) {
+ return ((ExecutorService) ex).shutdownNow();
+ }
+ return null;
+ });
+
+ System.gc(); System.gc();
+ System.runFinalization(); System.runFinalization();
+ System.gc(); System.gc();
}
if (reuseFramework) {
diff --git
a/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherUpgradeCatalogOsgiTest.java
b/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherUpgradeCatalogOsgiTest.java
index c7cc83d..a3f4c32 100644
---
a/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherUpgradeCatalogOsgiTest.java
+++
b/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherUpgradeCatalogOsgiTest.java
@@ -61,7 +61,7 @@ public class BrooklynLauncherUpgradeCatalogOsgiTest extends
AbstractBrooklynLaun
@Override
protected boolean reuseOsgi() {
- return false;
+ return true;
}
private BrooklynLauncher newLauncherForTests(String catalogInitial) {
@@ -216,7 +216,7 @@ public class BrooklynLauncherUpgradeCatalogOsgiTest extends
AbstractBrooklynLaun
public void testForciblyRemovedBundleNotAdded() throws Exception {
runForciblyRemovedBundleNotAdded(true);
}
-
+
@Test
public void testForciblyRemovedBundleNotAddedWithNoUpgradeTarget() throws
Exception {
runForciblyRemovedBundleNotAdded(false);
@@ -295,7 +295,7 @@ public class BrooklynLauncherUpgradeCatalogOsgiTest extends
AbstractBrooklynLaun
launcher.terminate();
}
-
+
@Test
public void testForciblyRemovedBundleNotAddedWhenReferencedByName() throws
Exception {
VersionedName one_1_0_0 = VersionedName.fromString("one:1.0.0");
diff --git
a/utils/common/src/main/java/org/apache/brooklyn/util/guava/Maybe.java
b/utils/common/src/main/java/org/apache/brooklyn/util/guava/Maybe.java
index e319503..5649f88 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/guava/Maybe.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/Maybe.java
@@ -403,6 +403,10 @@ public abstract class Maybe<T> implements Serializable,
Supplier<T> {
return new MaybeTransforming(this, f);
}
+ public <V> Maybe<V> mapMaybe(final Function<? super T, Maybe<V>> f) {
+ return new MaybeTransformingMaybe(this, f);
+ }
+
private <V> Maybe<V> mapKeptForDeserializingOld(final Function<? super T,
V> f) {
if (isPresent()) return new AbstractPresent<V>() {
private static final long serialVersionUID = 325089324325L;
@@ -440,6 +444,55 @@ public abstract class Maybe<T> implements Serializable,
Supplier<T> {
}
}
+ public static class MaybeTransformingMaybe<T,V> extends Maybe<V> {
+ private static final long serialVersionUID = 325089324325L;
+ private final Maybe<T> input;
+ private final Function<? super T, Maybe<V>> f;
+ private boolean gotten = false;
+ private Maybe<V> gottenObject;
+
+ public MaybeTransformingMaybe(Maybe<T> input, Function<? super
T,Maybe<V>> f) {
+ this.input = input;
+ this.f = f;
+ }
+
+ @Override
+ public boolean isPresent() {
+ if (!input.isPresent()) return false;
+ evaluate();
+ return gottenObject.isPresent();
+ }
+
+ public void evaluate() {
+ if (!gotten) {
+ synchronized (this) {
+ if (!gotten) {
+ gotten = true;
+ if (!input.isPresent()) {
+ gottenObject = Maybe.castAbsent(input);
+ return;
+ }
+ gottenObject = f.apply(input.get());
+ if (gottenObject==null) {
+ gottenObject = Maybe.absent("transformation
yielded null rather than a maybe");
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public V get() {
+ evaluate();
+ return gottenObject.get();
+ }
+
+ @Override
+ public boolean isNull() {
+ return isPresent() ? get()==null : input.isNull();
+ }
+ }
+
/** applies a function immediately if a value is present and returns the
transformed object,
* or returns the original absence */
public <V> Maybe<V> transformNow(final Function<? super T, V> f) {