From 1e030ca3ecfaf7a3c179978c297a6aa6b31aead3 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Sat, 30 Jul 2011 20:52:42 +0200 Subject: [PATCH] Even more atomic router configuration. Now the XMLRouterConfiguration object encapsulates both config and derived data and provides an API for truly atomic use of the configuration. --- .../impl/RouterConfigServiceImpl.java | 49 +++++++++++++ .../org/wamblee/xmlrouter/impl/XMLRouter.java | 37 ++++++---- .../impl/XMLRouterConfiguration.java | 62 ++++++++++++++++ .../impl/XMLRouterConfigurationImpl.java | 71 +++++++++++++++++++ .../wamblee/xmlrouter/impl/XMLRouterTest.java | 5 +- 5 files changed, 209 insertions(+), 15 deletions(-) create mode 100644 impl/src/main/java/org/wamblee/xmlrouter/impl/RouterConfigServiceImpl.java create mode 100644 impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfiguration.java create mode 100644 impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfigurationImpl.java diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/RouterConfigServiceImpl.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/RouterConfigServiceImpl.java new file mode 100644 index 0000000..76fd26f --- /dev/null +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/RouterConfigServiceImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright 2005-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.xmlrouter.impl; + +import org.wamblee.xmlrouter.common.Id; +import org.wamblee.xmlrouter.config.RouterConfig; +import org.wamblee.xmlrouter.config.RouterConfigService; + +/** + * Router configuration service providing an atomic configuration API for the + * XML router. + * + * @author Erik Brakkee + */ +public class RouterConfigServiceImpl implements RouterConfigService { + + @Override + public RouterConfig emptyConfig() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Id apply(RouterConfig aConfig, + Id aOldConfig) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void clear(Id aConfig) { + // TODO Auto-generated method stub + + } + +} diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouter.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouter.java index d74c93d..637440f 100644 --- a/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouter.java +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouter.java @@ -56,30 +56,38 @@ public class XMLRouter implements Gateway, DestinationRegistry { private Clock clock; private AtomicLong nextEventId; - private ExtendedRouterConfig routerConfig; - private TransformationPaths transformations; + private XMLRouterConfiguration config; private Map, Destination> destinations; - public XMLRouter(Clock aClock, ExtendedRouterConfig aRouterConfig, + public XMLRouter(Clock aClock, XMLRouterConfiguration aConfig, EventListener aListener) { sequenceNumbers = new AtomicLong(1); listener = aListener; clock = aClock; nextEventId = new AtomicLong(clock.currentTimeMillis()); - routerConfig = aRouterConfig; - transformations = new TransformationPaths(); + config = aConfig; destinations = new LinkedHashMap, Destination>(); } @Override public void publish(String aSource, DOMSource aEvent) { + config.startPublishEvent(); + try { + publishImpl(aSource, aEvent); + } finally { + config.endPublishEvent(); + } + } + + private void publishImpl(String aSource, DOMSource aEvent) { long time = clock.currentTimeMillis(); - if (routerConfig.isDirty()) { - transformations.replaceTransformations(routerConfig - .transformationConfig().map()); - routerConfig.resetDirty(); + // TODO dirty flag will become unnecessary in the future. + if (config.routerConfig().isDirty()) { + config.transformations().replaceTransformations( + config.routerConfig().transformationConfig().map()); + config.routerConfig().resetDirty(); } Id id = new Id(nextEventId.getAndIncrement()); @@ -124,7 +132,7 @@ public class XMLRouter implements Gateway, DestinationRegistry { boolean delivered = false; Set possibleTargetTypes = new HashSet(); - possibleTargetTypes.addAll(transformations + possibleTargetTypes.addAll(config.transformations() .getPossibleTargetTypes(aInputType)); // ask each destination what target types, if any they want to have. @@ -137,7 +145,7 @@ public class XMLRouter implements Gateway, DestinationRegistry { if (!requested.isEmpty()) { // Deliver to the destination. for (String targetType : requested) { - TransformationPath path = transformations.getPath( + TransformationPath path = config.transformations().getPath( aInputType, targetType); List ts = path.getTransformations(); int i = 0; @@ -188,7 +196,8 @@ public class XMLRouter implements Gateway, DestinationRegistry { private boolean isAllowedByFilters(String aType, DOMSource aEvent) { boolean allowed = true; - for (Filter filter : routerConfig.filterConfig().map().values()) { + for (Filter filter : config.routerConfig().filterConfig().map() + .values()) { if (!filter.isAllowed(aType, aEvent)) { allowed = false; } @@ -198,8 +207,8 @@ public class XMLRouter implements Gateway, DestinationRegistry { private List determineDocumentTypes(DOMSource aEvent) { List res = new ArrayList(); - for (DocumentType type : routerConfig.documentTypeConfig().map() - .values()) { + for (DocumentType type : config.routerConfig().documentTypeConfig() + .map().values()) { if (type.isInstance(aEvent)) { res.add(type.getName()); } diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfiguration.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfiguration.java new file mode 100644 index 0000000..51c8cc7 --- /dev/null +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfiguration.java @@ -0,0 +1,62 @@ +/* + * Copyright 2005-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.xmlrouter.impl; + +/** + * The XML Router configuration contains both configuration data as well as + * derived data used by the XML router. It is important that all this data is + * consistent. Therefore, this class provides a read-write locking mechanism for + * accessing the data. + * + * @author Erik Brakkee + * + */ +public interface XMLRouterConfiguration { + + /** + * To be called before the configuration is updated. Corresponds to write + * lock acquire. + */ + void startConfigurationChange(); + + /** + * To be called after the configuration is updated. Corresponds to write + * lock acquire. + */ + void endConfigurationChange(); + + /** + * To be called before the configuration is used. Corresponds to read lock + * acquire. + */ + void startPublishEvent(); + + /** + * To be called after the configuration is used. Corresponds to read lock + * release. + */ + void endPublishEvent(); + + /** + * @return Configuration data. + */ + ExtendedRouterConfig routerConfig(); + + /** + * @return Transformation paths (derived data). + */ + TransformationPaths transformations(); +} diff --git a/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfigurationImpl.java b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfigurationImpl.java new file mode 100644 index 0000000..b0b0271 --- /dev/null +++ b/impl/src/main/java/org/wamblee/xmlrouter/impl/XMLRouterConfigurationImpl.java @@ -0,0 +1,71 @@ +/* + * Copyright 2005-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.xmlrouter.impl; + +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Implements the XML Router configuration interface including the required + * locking. + * + * @author Erik Brakkee + */ +public class XMLRouterConfigurationImpl implements XMLRouterConfiguration { + + private final ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock( + true); + private final ReentrantReadWriteLock.ReadLock rlock = rwlock.readLock(); + private final ReentrantReadWriteLock.WriteLock wlock = rwlock.writeLock(); + + private ExtendedRouterConfig config; + private TransformationPaths transformations; + + public XMLRouterConfigurationImpl(ExtendedRouterConfig aConfig, + TransformationPaths aTransformations) { + config = aConfig; + transformations = aTransformations; + } + + @Override + public void startConfigurationChange() { + wlock.lock(); + } + + @Override + public void endConfigurationChange() { + wlock.unlock(); + } + + @Override + public void startPublishEvent() { + rlock.lock(); + } + + @Override + public void endPublishEvent() { + rlock.unlock(); + } + + @Override + public ExtendedRouterConfig routerConfig() { + return config; + } + + @Override + public TransformationPaths transformations() { + return transformations; + } +} diff --git a/impl/src/test/java/org/wamblee/xmlrouter/impl/XMLRouterTest.java b/impl/src/test/java/org/wamblee/xmlrouter/impl/XMLRouterTest.java index eeb05aa..7da3de5 100644 --- a/impl/src/test/java/org/wamblee/xmlrouter/impl/XMLRouterTest.java +++ b/impl/src/test/java/org/wamblee/xmlrouter/impl/XMLRouterTest.java @@ -67,6 +67,7 @@ public class XMLRouterTest { } private ExtendedRouterConfig routerConfig; + private XMLRouterConfiguration config; private XMLRouter router; private DOMSource source1; private DOMSource source2; @@ -79,9 +80,11 @@ public class XMLRouterTest { @Before public void setUp() { routerConfig = new SingleRouterConfig(new AtomicLong(1L)); + config = new XMLRouterConfigurationImpl(routerConfig, + new TransformationPaths()); EventListener logListener = new LoggingEventListener(Level.INFO); listener = spy(logListener); - router = new XMLRouter(new SystemClock(), routerConfig, listener); + router = new XMLRouter(new SystemClock(), config, listener); source1 = mock(DOMSource.class); source2 = mock(DOMSource.class); source3 = mock(DOMSource.class); -- 2.31.1