You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by kw...@apache.org on 2022/07/15 14:39:27 UTC
[jackrabbit-oak] 01/01: OAK-9840: wait for all required MountInfoConfigs
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch bugfix/mountinfoproviderservice-race-condition
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit d88dab3db5e31fa840ea5f7021f0f3f6101baa59
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Jul 15 16:39:19 2022 +0200
OAK-9840: wait for all required MountInfoConfigs
also consider later configs by making the reference greedy
---
.../oak/composite/MountInfoProviderService.java | 22 ++++++++++++----------
.../composite/MountInfoProviderServiceTest.java | 13 +++++++++++++
2 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/MountInfoProviderService.java b/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/MountInfoProviderService.java
index e163694a42..e70e03071f 100644
--- a/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/MountInfoProviderService.java
+++ b/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/MountInfoProviderService.java
@@ -19,9 +19,10 @@
package org.apache.jackrabbit.oak.composite;
-import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Stream;
import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
@@ -33,14 +34,14 @@ import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
@Component
@Designate(ocd = MountInfoProviderService.Props.class)
@@ -54,7 +55,7 @@ public class MountInfoProviderService {
@AttributeDefinition(
name = "Expected mounts",
- description = "List of all expected read-only mount names"
+ description = "List of all required mount names"
)
String[] expectedMounts() default {};
@@ -90,7 +91,7 @@ public class MountInfoProviderService {
private final List<MountInfoConfig> mountInfoConfigs = new CopyOnWriteArrayList<>();
- private List<String> expectedMounts;
+ private Set<String> expectedMounts;
private ServiceRegistration reg;
private BundleContext context;
@@ -101,9 +102,9 @@ public class MountInfoProviderService {
this.expectedMounts = Stream.of(expectedMounts)
.map(String::trim)
.filter(s -> !s.isEmpty())
- .collect(toList());
+ .collect(toSet());
} else {
- this.expectedMounts = new ArrayList<>();
+ this.expectedMounts = new HashSet<>();
}
context = bundleContext;
addMountInfoConfigFromProperties(props);
@@ -125,7 +126,7 @@ public class MountInfoProviderService {
}
}
- @Reference(cardinality = ReferenceCardinality.MULTIPLE)
+ @Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = ReferencePolicyOption.GREEDY)
protected void bindMountInfoConfig(MountInfoConfig config) {
if (!config.getPaths().isEmpty()) { // Ignore empty configs
mountInfoConfigs.add(config);
@@ -137,9 +138,10 @@ public class MountInfoProviderService {
if (context == null || reg != null) {
return;
}
- if (!mountInfoConfigs.stream().allMatch(mountInfo -> expectedMounts.contains(mountInfo.getMountName()))) {
+ Set<String> providedMounts = mountInfoConfigs.stream().map(MountInfoConfig::getMountName).collect(toSet());
+ if (!providedMounts.containsAll(expectedMounts)) {
LOG.info("Not all expected mounts are present yet (expected: {}, current: {}). Postponing configuration...",
- expectedMounts, mountInfoConfigs.stream().map(MountInfoConfig::getMountName).collect(joining(",", "[", "]")));
+ expectedMounts, providedMounts);
return;
}
diff --git a/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/MountInfoProviderServiceTest.java b/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/MountInfoProviderServiceTest.java
index eff96869a6..08862e78b9 100644
--- a/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/MountInfoProviderServiceTest.java
+++ b/oak-store-composite/src/test/java/org/apache/jackrabbit/oak/composite/MountInfoProviderServiceTest.java
@@ -121,6 +121,19 @@ public class MountInfoProviderServiceTest {
assertEquals(m, provider.getMountByPath("/c"));
}
+ @Test
+ public void mountWithConfig_Multiple_NotAllExpected() {
+ registerActivateMountInfoConfig(propsBuilder().withMountName("foo").withMountPaths("/a").buildMountInfoProps());
+ registerActivateMountInfoConfig(propsBuilder().withMountName("bar").withMountPaths("/b").buildMountInfoProps());
+
+ MockOsgi.injectServices(service, context.bundleContext());
+ service.activate(context.bundleContext(), withExpectedMounts("foo", "bar", "baz"));
+ MockOsgi.activate(service, context.bundleContext(), ImmutableMap.of("expectedMounts", new String[]{"foo", "bar", "baz"}));
+
+ MountInfoProvider provider = context.getService(MountInfoProvider.class);
+ assertNull("Not all expected mounts have been provided", provider);
+ }
+
@Test
public void mountWithConfig_Name() {
registerActivateMountInfoConfig(propsBuilder().withMountName("foo").withMountPaths("/a", "/b").buildMountInfoProps());