From 45e30eb7b15b6c042cd888341e4e8e80fac31209 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sat, 26 Jul 2014 06:18:40 +0200 Subject: [PATCH] Improve RESTCONF thread safety when reconfiguring There is a race which could see us without a populated mapping while a schemacontext change is underway. Use a immutablemap guarded by an atomicreference to allow proper switching. Note that the fix is incomplete, as the schema context needs to be replaced at the same time. Change-Id: I7d64fae99a0bc0f7d1ec19f08450c1954cb7af97 Signed-off-by: Robert Varga --- .../sal/restconf/impl/ControllerContext.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java index ebf0fd896a..671bd6da8a 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java @@ -17,6 +17,7 @@ import com.google.common.base.Strings; import com.google.common.collect.BiMap; import com.google.common.collect.FluentIterable; import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import java.io.UnsupportedEncodingException; @@ -25,13 +26,14 @@ import java.net.URLDecoder; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; import javax.ws.rs.core.Response.Status; @@ -90,7 +92,8 @@ public class ControllerContext implements SchemaContextListener { private final Map moduleNameToUri = uriToModuleName.inverse(); - private final Map qnameToRpc = new ConcurrentHashMap<>(); + private final AtomicReference> qnameToRpc = + new AtomicReference<>(Collections.emptyMap()); private volatile SchemaContext globalSchema; private volatile MountService mountService; @@ -852,20 +855,22 @@ public class ControllerContext implements SchemaContextListener { public RpcDefinition getRpcDefinition(final String name) { final QName validName = this.toQName(name); - return validName == null ? null : this.qnameToRpc.get(validName); + return validName == null ? null : this.qnameToRpc.get().get(validName); } @Override public void onGlobalContextUpdated(final SchemaContext context) { if (context != null) { - this.qnameToRpc.clear(); - this.setGlobalSchema(context); - Set _operations = context.getOperations(); - for (final RpcDefinition operation : _operations) { - { - this.qnameToRpc.put(operation.getQName(), operation); - } + final Collection defs = context.getOperations(); + final Map newMap = new HashMap<>(defs.size()); + + for (final RpcDefinition operation : defs) { + newMap.put(operation.getQName(), operation); } + + // FIXME: still not completely atomic + this.qnameToRpc.set(ImmutableMap.copyOf(newMap)); + this.setGlobalSchema(context); } } -- 2.36.6