Author: oheger
Date: Mon Feb 8 21:03:02 2010
New Revision: 907793
URL: http://svn.apache.org/viewvc?rev=907793&view=rev
Log:
[CONFIGURATION-407] Synchronized access to nodes when constructing the global
section configuration. Applied a fix to configuration2 branch.
Modified:
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
Modified:
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/INIConfiguration.java?rev=907793&r1=907792&r2=907793&view=diff
==============================================================================
---
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
(original)
+++
commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
Mon Feb 8 21:03:02 2010
@@ -32,7 +32,6 @@
import org.apache.commons.configuration2.expr.ExpressionEngine;
import org.apache.commons.configuration2.tree.ConfigurationNode;
import org.apache.commons.configuration2.tree.DefaultConfigurationNode;
-import org.apache.commons.configuration2.tree.ViewNode;
import org.apache.commons.lang.StringUtils;
/**
@@ -690,7 +689,26 @@
*/
private SubConfiguration<ConfigurationNode> getGlobalSection()
{
- ViewNode parent = new ViewNode();
+ ConfigurationNode parent = new DefaultConfigurationNode()
+ {
+ /**
+ * Adds the specified child node to this node. This implementation
+ * does not change the parent node of the child. So the child node
+ * remains in its original hierarchy.
+ *
+ * @param child the child node to be added
+ */
+ @Override
+ public void addChild(ConfigurationNode child)
+ {
+ synchronized (child)
+ {
+ ConfigurationNode parent = child.getParentNode();
+ super.addChild(child);
+ child.setParentNode(parent);
+ }
+ }
+ };
for (ConfigurationNode node : getRootNode().getChildren())
{
Modified:
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java?rev=907793&r1=907792&r2=907793&view=diff
==============================================================================
---
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
(original)
+++
commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
Mon Feb 8 21:03:02 2010
@@ -27,6 +27,8 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
import junit.framework.TestCase;
@@ -516,6 +518,72 @@
}
/**
+ * Tests concurrent access to the global section.
+ */
+ public void testGetSectionGloabalMultiThreaded()
+ throws ConfigurationException, InterruptedException
+ {
+ final INIConfiguration config = setUpConfig(INI_DATA_GLOBAL);
+ final int threadCount = 12;
+ final int loopCount = 350;
+ final CountDownLatch syncLatch = new CountDownLatch(1);
+ final AtomicBoolean errorFlag = new AtomicBoolean();
+
+ Thread[] threads = new Thread[threadCount];
+ for (int i = 0; i < threadCount; i++)
+ {
+ threads[i] = new Thread()
+ {
+ /**
+ * Accesses the global section of the test configuration in a
+ * loop and checks whether this causes an exception.
+ */
+ @Override
+ public void run()
+ {
+ boolean error = false;
+
+ try
+ {
+ // wait on the latch to increase parallelism
+ syncLatch.await();
+ }
+ catch (InterruptedException iex)
+ {
+ error = true;
+ }
+
+ // access the configuration, check for errors
+ for (int i = 0; i < loopCount && !error; i++)
+ {
+ try
+ {
+ config.getSection(null);
+ }
+ catch (IllegalStateException istex)
+ {
+ error = true;
+ }
+ }
+
+ if (error)
+ {
+ errorFlag.set(true);
+ }
+ };
+ };
+ threads[i].start();
+ }
+
+ syncLatch.countDown(); // start all test threads
+ for (int i = 0; i < threadCount; i++)
+ {
+ threads[i].join();
+ }
+ assertFalse("Exception occurred", errorFlag.get());
+ }
+
+ /**
* Tests querying the content of the global section if there is none.
*/
public void testGetSectionGlobalNonExisting() throws ConfigurationException
Modified:
commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml?rev=907793&r1=907792&r2=907793&view=diff
==============================================================================
---
commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
(original)
+++
commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
Mon Feb 8 21:03:02 2010
@@ -79,6 +79,10 @@
</release>
<release version="1.7" date="in SVN" description="">
+ <action dev="oheger" type="fix" issue="CONFIGURATION-407">
+ Fixed a potential IllegalStateException in HierarchicalINIConfiguration
+ that can be thrown when the global section is requested concurrently.
+ </action>
<action dev="oheger" type="fix" issue="CONFIGURATION-405">
XMLPropertyListConfiguration no longer throws a ConfigurationException
if the file to be loaded does not have an outer dict element.