Author: rgoers
Date: Wed Oct 21 05:41:59 2009
New Revision: 827888

URL: http://svn.apache.org/viewvc?rev=827888&view=rev
Log:
Default file won't reload if it is being accessed from a second thread.

Added:
    commons/proper/configuration/trunk/conf/testMultiDynamic_default.xml
      - copied, changed from r823891, 
commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml
    commons/proper/configuration/trunk/conf/testMultiDynamic_default2.xml
    
commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder5.xml
      - copied, changed from r823891, 
commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder3.xml
Modified:
    
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java
    
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java

Copied: commons/proper/configuration/trunk/conf/testMultiDynamic_default.xml 
(from r823891, 
commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml)
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/testMultiDynamic_default.xml?p2=commons/proper/configuration/trunk/conf/testMultiDynamic_default.xml&p1=commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml&r1=823891&r2=827888&rev=827888&view=diff
==============================================================================
--- commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml 
(original)
+++ commons/proper/configuration/trunk/conf/testMultiDynamic_default.xml Wed 
Oct 21 05:41:59 2009
@@ -8,6 +8,13 @@
     <link normal="#040404" visited="#404040"/>
     <default>${colors.default}</default>
   </colors>
+  <Product>
+    <FIIndex>
+        <FI id="123456781">ID0001</FI>
+        <FI id="AUTO01">IDAUTO01</FI>
+        <FI id="AUTO02">IDAUTO02</FI>
+    </FIIndex>
+  </Product>
   <rowsPerPage>50</rowsPerPage>
   <buttons>
     <name>OK-4,Cancel-4,Help-4</name>

Added: commons/proper/configuration/trunk/conf/testMultiDynamic_default2.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/testMultiDynamic_default2.xml?rev=827888&view=auto
==============================================================================
--- commons/proper/configuration/trunk/conf/testMultiDynamic_default2.xml 
(added)
+++ commons/proper/configuration/trunk/conf/testMultiDynamic_default2.xml Wed 
Oct 21 05:41:59 2009
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+           
xsi:noNamespaceSchemaLocation="http://commons.apache.org/testMultiConfiguration.xsd";>
+  <colors>
+    <background>#40404040</background>
+    <text>#000000</text>
+    <header>#444444</header>
+    <link normal="#040404" visited="#404040"/>
+    <default>${colors.default}</default>
+  </colors>
+  <Product>
+    <FIIndex>
+        <FI id="123456781">ID0001</FI>
+        <FI id="123456782">ID0002</FI>
+        <FI id="AUTO01">IDAUTO01</FI>
+        <FI id="AUTO02">IDAUTO02</FI>
+    </FIIndex>
+  </Product>
+  <rowsPerPage>25</rowsPerPage>
+  <buttons>
+    <name>OK-4,Cancel-4,Help-4</name>
+  </buttons>
+  <numberFormat pattern="###\,###.##"/>
+  <!-- Comma delimited lists -->
+  <split>
+    <list1>a,b,c</list1>
+    <list2>a\,b\,c</list2>
+    <list3 values="a,b,c"/>
+    <list4 values="a\,b\,c"/>
+  </split>
+  <Channels>
+    <Channel id="1">
+      <Name>Channel 1</Name>
+      <ChannelData>test 1 data</ChannelData>
+    </Channel>
+    <Channel id="2">
+      <Name>Channel 2</Name>
+      <ChannelData>test 2 data</ChannelData>
+    </Channel>
+  </Channels>
+</configuration>
\ No newline at end of file

Copied: 
commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder5.xml
 (from r823891, 
commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder3.xml)
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder5.xml?p2=commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder5.xml&p1=commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder3.xml&r1=823891&r2=827888&rev=827888&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder3.xml
 (original)
+++ 
commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder5.xml
 Wed Oct 21 05:41:59 2009
@@ -18,14 +18,14 @@
   </header>
   <override>
     <multifile filePattern="testwrite/testMultiConfiguration_$$${sys:Id}.xml"
-               config-name="clientConfig" delimiterParsingDisabled="true" 
schemaValidation="true">
+               config-name="clientConfig" delimiterParsingDisabled="true" 
schemaValidation="false">
        <expressionEngine
           
config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
        <reloadingStrategy refreshDelay="500"
           
config-class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy"/>
     </multifile>
-    <xml fileName="testMultiConfiguration_default.xml"
-         config-name="defaultConfig" delimiterParsingDisabled="true" 
schemaValidation="true">
+    <xml fileName="testwrite/testMultiDynamic_default.xml"
+         config-name="defaultConfig" delimiterParsingDisabled="true" 
schemaValidation="false">
       <expressionEngine
           
config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
       <reloadingStrategy refreshDelay="500"

Modified: 
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java?rev=827888&r1=827887&r2=827888&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java
 (original)
+++ 
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java
 Wed Oct 21 05:41:59 2009
@@ -302,14 +302,17 @@
 
     private boolean reload(boolean checkReload)
     {
-        setDetailEvents(false);
-        try
-        {
-            return delegate.reload(checkReload);
-        }
-        finally
+        synchronized(delegate.getReloadLock())
         {
-            setDetailEvents(true);
+            setDetailEvents(false);
+            try
+            {
+                return delegate.reload(checkReload);
+            }
+            finally
+            {
+                setDetailEvents(true);
+            }
         }
     }
 

Modified: 
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java?rev=827888&r1=827887&r2=827888&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java
 (original)
+++ 
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java
 Wed Oct 21 05:41:59 2009
@@ -18,6 +18,11 @@
 package org.apache.commons.configuration;
 
 import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.FileReader;
+import java.io.Writer;
+import java.io.FileWriter;
 
 import junit.framework.TestCase;
 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
@@ -30,7 +35,9 @@
     private static String DEFAULT_FILE = 
"target/test-classes/testMultiConfiguration_default.xml";
     private static final File MULTI_TENENT_FILE = new File(
             "conf/testMultiTenentConfigurationBuilder4.xml");
-
+     private static final File MULTI_DYNAMIC_FILE = new File(
+            "conf/testMultiTenentConfigurationBuilder5.xml");
+    
     public void testConfiguration() throws Exception
     {
         DynamicCombinedConfiguration config = new 
DynamicCombinedConfiguration();
@@ -158,6 +165,55 @@
         assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
     }
 
+  public void testConcurrentGetAndReloadFile() throws Exception
+    {
+        final int threadCount = 25;
+        System.getProperties().remove("Id");
+        // create a new configuration
+        File input = new 
File("target/test-classes/testMultiDynamic_default.xml");
+        File output = new 
File("target/test-classes/testwrite/testMultiDynamic_default.xml");
+        output.delete();
+        output.getParentFile().mkdir();
+        copyFile(input, output);
+
+        DefaultConfigurationBuilder factory = new 
DefaultConfigurationBuilder();
+        factory.setFile(MULTI_DYNAMIC_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+
+        assertEquals(config.getString("Product/FIIndex/f...@id='123456781']"), 
"ID0001");
+
+        ReaderThread testThreads[] = new ReaderThread[threadCount];
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i] = new ReaderThread(config);
+            testThreads[i].start();
+        }
+
+        Thread.sleep(2000);
+
+        input = new File("target/test-classes/testMultiDynamic_default2.xml");
+        copyFile(input, output);
+
+        Thread.sleep(2000);
+        String id = config.getString("Product/FIIndex/f...@id='123456782']");
+        assertNotNull("File did not reload, id is null", id);
+        String rows = config.getString("rowsPerPage");
+        assertTrue("Incorrect value for rowsPerPage", "25".equals(rows));
+
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i].shutdown();
+            testThreads[i].join();
+        }
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            assertFalse(testThreads[i].failed());
+        }
+        assertEquals("ID0002", 
config.getString("Product/FIIndex/f...@id='123456782']"));
+        output.delete();
+    }
+
+
     private class ReloadThread extends Thread
     {
         CombinedConfiguration combined;
@@ -205,12 +261,69 @@
         }
     }
 
+    private class ReaderThread extends Thread
+    {
+        private boolean running = true;
+        private boolean failed = false;
+        CombinedConfiguration combined;
+
+        public ReaderThread(CombinedConfiguration c)
+        {
+            combined = c;
+        }
+
+        public void run()
+        {
+            while (running)
+            {
+                String bcId = 
combined.getString("Product/FIIndex/f...@id='123456781']");
+                if ("ID0001".equalsIgnoreCase(bcId))
+                {
+                    if (failed)
+                    {
+                        System.out.println("Thread failed, but recovered");
+                    }
+                    failed = false;
+                }
+                else
+                {
+                    failed = true;
+                }
+            }
+        }
+
+        public boolean failed()
+        {
+            return failed;
+        }
+
+        public void shutdown()
+        {
+            running = false;
+        }
+
+    }
+
     private void verify(String key, DynamicCombinedConfiguration config, int 
rows)
     {
         System.setProperty("Id", key);
         assertTrue(config.getInt("rowsPerPage") == rows);
     }
 
+    private void copyFile(File input, File output) throws IOException
+    {
+        Reader reader = new FileReader(input);
+        Writer writer = new FileWriter(output);
+        char[] buffer = new char[4096];
+        int n = 0;
+        while (-1 != (n = reader.read(buffer)))
+        {
+            writer.write(buffer, 0, n);
+        }
+        reader.close();
+        writer.close();
+    }
+
     public static class ThreadLookup extends StrLookup
     {
         private static ThreadLocal id = new ThreadLocal();


Reply via email to