improvements for very occasional test failures
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/store/WorkflowStateActiveInMemory.java b/core/src/main/java/org/apache/brooklyn/core/workflow/store/WorkflowStateActiveInMemory.java
index af6ef21..762b26e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/store/WorkflowStateActiveInMemory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/store/WorkflowStateActiveInMemory.java
@@ -18,6 +18,9 @@
*/
package org.apache.brooklyn.core.workflow.store;
+import java.util.Map;
+import java.util.Set;
+
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.config.ConfigKey;
@@ -25,11 +28,10 @@
import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.MutableSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Map;
-
public class WorkflowStateActiveInMemory {
private static final Logger log = LoggerFactory.getLogger(WorkflowStateActiveInMemory.class);
@@ -64,14 +66,20 @@
public void expireAbsentEntities() {
lastInMemClear = System.currentTimeMillis();
- MutableMap.copyOf(data).forEach( (entityId, mapByWorkflowId) -> {
- if (mgmt.getEntityManager().getEntity(entityId)==null) data.remove(entityId);
+ Set<String> copy;
+ synchronized (data) {
+ copy = MutableSet.copyOf(data.keySet());
+ }
+ copy.forEach(entityId -> {
+ if (mgmt.getEntityManager().getEntity(entityId) == null) {
+ data.remove(entityId);
+ }
});
}
public void checkpoint(WorkflowExecutionContext context) {
// keep active workflows in memory, even if disabled
- Map<String, WorkflowExecutionContext> entityActiveWorkflows = data.get(context.getEntity().getId());
+ Map<String, WorkflowExecutionContext> entityActiveWorkflows = getSynchronizedForWorkflowId(context.getEntity().getId());
if (context.getStatus().expirable) {
if (entityActiveWorkflows!=null) entityActiveWorkflows.remove(context.getWorkflowId());
} else {
@@ -94,19 +102,25 @@
}
public Map<String,WorkflowExecutionContext> getWorkflows(Entity entity) {
- return MutableMap.copyOf(data.get(entity.getId()));
+ return getSynchronizedForWorkflowId(entity.getId());
}
boolean deleteWorkflow(WorkflowExecutionContext context) {
- Map<String, WorkflowExecutionContext> entityActiveWorkflows = data.get(context.getEntity().getId());
+ Map<String, WorkflowExecutionContext> entityActiveWorkflows = getSynchronizedForWorkflowId(context.getEntity().getId());
if (entityActiveWorkflows!=null) {
return entityActiveWorkflows.remove(context.getWorkflowId()) != null;
}
return false;
}
+ private Map<String, WorkflowExecutionContext> getSynchronizedForWorkflowId(String entityId) {
+ synchronized (data) {
+ return data.get(entityId);
+ }
+ }
+
public WorkflowExecutionContext getFromTag(BrooklynTaskTags.WorkflowTaskTag tag) {
- Map<String, WorkflowExecutionContext> activeForEntity = data.get(tag.getEntityId());
+ Map<String, WorkflowExecutionContext> activeForEntity = getSynchronizedForWorkflowId(tag.getEntityId());
if (activeForEntity!=null) {
return activeForEntity.get(tag.getWorkflowId());
}
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/EntityExecutionManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/EntityExecutionManagerTest.java
index 1073578..cb6cbd8 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/EntityExecutionManagerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/internal/EntityExecutionManagerTest.java
@@ -353,6 +353,7 @@
return e;
}
+ // non-det failure, see below
public void testUnmanagedEntityCanBeGcedEvenIfPreviouslyTagged() throws Exception {
TestEntity e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
String eId = e.getId();
@@ -376,6 +377,7 @@
}
if ((tag instanceof WrappedEntity) && ((WrappedEntity) tag).unwrap().getId().equals(eId)
&& ((WrappedItem<?>) tag).getWrappingType().equals(BrooklynTaskTags.CONTEXT_ENTITY)) {
+ // non-deterministic failure observed here; only once so far, so might simply be GC being ignored
fail("tags contains unmanaged entity (wrapped) " + tag + "; tasks: " + app.getManagementContext().getExecutionManager().getTasksWithTag(tag));
}
}