aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core/src
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-02-11 18:14:52 +0100
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-02-11 18:15:47 +0100
commit54cdd41e77bf99b81134435499219eaef4862525 (patch)
tree6b301d2bcd29166b9edc6d005c1c6a84bfc6ddf0 /sonar-core/src
parentdf6129a0913277db1ec8f8ac4b9cc0303b8c9c25 (diff)
downloadsonarqube-54cdd41e77bf99b81134435499219eaef4862525.tar.gz
sonarqube-54cdd41e77bf99b81134435499219eaef4862525.zip
Fix shutdown of server after DB migration
When a DB migration is required, two containers are up at the same time ("safemode" and "level 2"). This is not handled by ComponentContainer, so one of the two children is badly dereferenced and can't be stopped.
Diffstat (limited to 'sonar-core/src')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java40
-rw-r--r--sonar-core/src/test/java/org/sonar/core/platform/ComponentContainerTest.java26
2 files changed, 47 insertions, 19 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java b/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java
index 8db0da8cd58..3d01d8f482e 100644
--- a/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java
+++ b/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java
@@ -21,6 +21,7 @@ package org.sonar.core.platform;
import com.google.common.collect.Iterables;
import java.lang.annotation.Annotation;
+import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import org.picocontainer.Characteristics;
@@ -71,12 +72,11 @@ public class ComponentContainer implements ContainerPopulator.Container {
}
}
- // no need for multiple children
- ComponentContainer parent;
- ComponentContainer child;
- MutablePicoContainer pico;
- PropertyDefinitions propertyDefinitions;
- ComponentKeys componentKeys;
+ private ComponentContainer parent;
+ private final List<ComponentContainer> children = new ArrayList<>();
+ private MutablePicoContainer pico;
+ private PropertyDefinitions propertyDefinitions;
+ private ComponentKeys componentKeys;
/**
* Create root container
@@ -87,7 +87,6 @@ public class ComponentContainer implements ContainerPopulator.Container {
protected ComponentContainer(MutablePicoContainer picoContainer) {
this.parent = null;
- this.child = null;
this.pico = picoContainer;
this.componentKeys = new ComponentKeys();
propertyDefinitions = new PropertyDefinitions();
@@ -101,7 +100,7 @@ public class ComponentContainer implements ContainerPopulator.Container {
protected ComponentContainer(ComponentContainer parent) {
this.parent = parent;
this.pico = parent.pico.makeChildContainer();
- this.parent.child = this;
+ this.parent.children.add(this);
this.propertyDefinitions = parent.propertyDefinitions;
this.componentKeys = new ComponentKeys();
addSingleton(this);
@@ -168,9 +167,9 @@ public class ComponentContainer implements ContainerPopulator.Container {
throw PicoUtils.propagate(e);
}
} finally {
- removeChild();
+ removeChildren();
if (parent != null) {
- parent.removeChild();
+ parent.removeChild(this);
}
}
return this;
@@ -270,11 +269,22 @@ public class ComponentContainer implements ContainerPopulator.Container {
return pico.getComponents(tClass);
}
- public ComponentContainer removeChild() {
- if (child != null) {
+ public ComponentContainer removeChild(ComponentContainer childToBeRemoved) {
+ for (ComponentContainer child : children) {
+ if (child == childToBeRemoved) {
+ pico.removeChildContainer(child.pico);
+ children.remove(child);
+ break;
+ }
+ }
+ return this;
+ }
+
+ private ComponentContainer removeChildren() {
+ for (ComponentContainer child : children) {
pico.removeChildContainer(child.pico);
- child = null;
}
+ children.clear();
return this;
}
@@ -299,8 +309,8 @@ public class ComponentContainer implements ContainerPopulator.Container {
return parent;
}
- public ComponentContainer getChild() {
- return child;
+ public List<ComponentContainer> getChildren() {
+ return children;
}
public MutablePicoContainer getPicoContainer() {
diff --git a/sonar-core/src/test/java/org/sonar/core/platform/ComponentContainerTest.java b/sonar-core/src/test/java/org/sonar/core/platform/ComponentContainerTest.java
index f3aaeddc1bd..4de73a5e9c9 100644
--- a/sonar-core/src/test/java/org/sonar/core/platform/ComponentContainerTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/platform/ComponentContainerTest.java
@@ -116,7 +116,7 @@ public class ComponentContainerTest {
child.startComponents();
assertThat(child.getParent()).isSameAs(parent);
- assertThat(parent.getChild()).isSameAs(child);
+ assertThat(parent.getChildren()).containsOnly(child);
assertThat(child.getComponentByType(ComponentContainer.class)).isSameAs(child);
assertThat(parent.getComponentByType(ComponentContainer.class)).isSameAs(parent);
assertThat(child.getComponentByType(StartableComponent.class)).isNotNull();
@@ -131,13 +131,31 @@ public class ComponentContainerTest {
parent.startComponents();
ComponentContainer child = parent.createChild();
- assertThat(parent.getChild()).isSameAs(child);
+ assertThat(parent.getChildren()).containsOnly(child);
- parent.removeChild();
- assertThat(parent.getChild()).isNull();
+ parent.removeChild(child);
+ assertThat(parent.getChildren()).isEmpty();
}
@Test
+ public void support_multiple_children() {
+ ComponentContainer parent = new ComponentContainer();
+ parent.startComponents();
+ ComponentContainer child1 = parent.createChild();
+ child1.startComponents();
+ ComponentContainer child2 = parent.createChild();
+ child2.startComponents();
+ assertThat(parent.getChildren()).containsOnly(child1, child2);
+
+ child1.stopComponents();
+ assertThat(parent.getChildren()).containsOnly(child2);
+
+ parent.stopComponents();
+ assertThat(parent.getChildren()).isEmpty();
+ }
+
+
+ @Test
public void shouldForwardStartAndStopToDescendants() {
ComponentContainer grandParent = new ComponentContainer();
ComponentContainer parent = grandParent.createChild();