You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kw...@apache.org on 2014/08/05 15:33:01 UTC

svn commit: r1615928 - in /qpid/trunk/qpid/java/bdbstore/src: main/java/org/apache/qpid/server/store/berkeleydb/ main/java/org/apache/qpid/server/store/berkeleydb/replication/ test/java/org/apache/qpid/server/store/berkeleydb/

Author: kwall
Date: Tue Aug  5 13:33:00 2014
New Revision: 1615928

URL: http://svn.apache.org/r1615928
Log:
QPID-5962: [Java Broker] Prevent two or more BDB virtual host or virtual hosts nodes sharing the same JE environment path

Added:
    qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistry.java
    qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistryTest.java
Modified:
    qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java
    qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
    qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java

Added: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistry.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistry.java?rev=1615928&view=auto
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistry.java (added)
+++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistry.java Tue Aug  5 13:33:00 2014
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.qpid.server.store.berkeleydb;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.qpid.server.store.StoreException;
+
+/**
+ * JE permits the same environment to opened for write many times from within the same JVM.
+ * The Java Broker needs to disallow this as the stores of many VHNs or many VH
+ */
+public class EnvHomeRegistry
+{
+    private static final EnvHomeRegistry _instance = new EnvHomeRegistry();
+    private final Set<String> _canonicalNames = new HashSet<>();
+
+    public static final EnvHomeRegistry getInstance()
+    {
+        return _instance;
+    }
+
+    // default for unit testing
+    EnvHomeRegistry()
+    {
+        super();
+    }
+
+    public synchronized void registerHome(final File home) throws StoreException
+    {
+        if (home == null)
+        {
+            throw new IllegalArgumentException("home parameter cannot be null");
+        }
+
+        String canonicalForm = getCanonicalForm(home);
+        if (_canonicalNames.contains(canonicalForm))
+        {
+            throw new IllegalArgumentException("JE Home " + home + " is already in use");
+        }
+        _canonicalNames.add(canonicalForm);
+    }
+
+
+    public synchronized void deregisterHome(final File home) throws StoreException
+    {
+        if (home == null)
+        {
+            throw new IllegalArgumentException("home parameter cannot be null");
+        }
+
+        String canonicalForm = getCanonicalForm(home);
+        _canonicalNames.remove(canonicalForm);
+    }
+
+    private String getCanonicalForm(final File home)
+    {
+        try
+        {
+            return home.getCanonicalPath();
+        }
+        catch (IOException e)
+        {
+            throw new StoreException("Failed to resolve " + home + " into canonical form", e);
+        }
+    }
+
+}

Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java?rev=1615928&r1=1615927&r2=1615928&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java Tue Aug  5 13:33:00 2014
@@ -49,6 +49,7 @@ public class StandardEnvironmentFacade i
 
     private Environment _environment;
     private final Committer _committer;
+    private final File _environmentPath;
 
     public StandardEnvironmentFacade(StandardEnvironmentConfiguration configuration)
     {
@@ -59,12 +60,12 @@ public class StandardEnvironmentFacade i
             LOGGER.info("Creating environment at environment path " + _storePath);
         }
 
-        File environmentPath = new File(_storePath);
-        if (!environmentPath.exists())
+        _environmentPath = new File(_storePath);
+        if (!_environmentPath.exists())
         {
-            if (!environmentPath.mkdirs())
+            if (!_environmentPath.mkdirs())
             {
-                throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. "
+                throw new IllegalArgumentException("Environment path " + _environmentPath + " could not be read or created. "
                                                    + "Ensure the path is correct and that the permissions are correct.");
             }
         }
@@ -92,7 +93,20 @@ public class StandardEnvironmentFacade i
 
         envConfig.setExceptionListener(new LoggingAsyncExceptionListener());
 
-        _environment = new Environment(environmentPath, envConfig);
+        EnvHomeRegistry.getInstance().registerHome(_environmentPath);
+        boolean success = false;
+        try
+        {
+            _environment = new Environment(_environmentPath, envConfig);
+            success = true;
+        }
+        finally
+        {
+            if (!success)
+            {
+                EnvHomeRegistry.getInstance().deregisterHome(_environmentPath);
+            }
+        }
 
         _committer =  new CoalescingCommiter(name, this);
         _committer.start();
@@ -135,7 +149,14 @@ public class StandardEnvironmentFacade i
         }
         finally
         {
-            closeEnvironment();
+            try
+            {
+                closeEnvironment();
+            }
+            finally
+            {
+                EnvHomeRegistry.getInstance().deregisterHome(_environmentPath);
+            }
         }
     }
 

Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java?rev=1615928&r1=1615927&r2=1615928&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java Tue Aug  5 13:33:00 2014
@@ -57,7 +57,23 @@ import com.sleepycat.je.Sequence;
 import com.sleepycat.je.SequenceConfig;
 import com.sleepycat.je.Transaction;
 import com.sleepycat.je.TransactionConfig;
-import com.sleepycat.je.rep.*;
+import com.sleepycat.je.rep.AppStateMonitor;
+import com.sleepycat.je.rep.InsufficientAcksException;
+import com.sleepycat.je.rep.InsufficientLogException;
+import com.sleepycat.je.rep.InsufficientReplicasException;
+import com.sleepycat.je.rep.NetworkRestore;
+import com.sleepycat.je.rep.NetworkRestoreConfig;
+import com.sleepycat.je.rep.NodeState;
+import com.sleepycat.je.rep.NodeType;
+import com.sleepycat.je.rep.RepInternal;
+import com.sleepycat.je.rep.ReplicatedEnvironment;
+import com.sleepycat.je.rep.ReplicationConfig;
+import com.sleepycat.je.rep.ReplicationGroup;
+import com.sleepycat.je.rep.ReplicationMutableConfig;
+import com.sleepycat.je.rep.ReplicationNode;
+import com.sleepycat.je.rep.RestartRequiredException;
+import com.sleepycat.je.rep.StateChangeEvent;
+import com.sleepycat.je.rep.StateChangeListener;
 import com.sleepycat.je.rep.util.DbPing;
 import com.sleepycat.je.rep.util.ReplicationGroupAdmin;
 import com.sleepycat.je.rep.utilint.HostPortPair;
@@ -71,6 +87,7 @@ import org.codehaus.jackson.map.ObjectMa
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.store.StoreFuture;
 import org.apache.qpid.server.store.berkeleydb.CoalescingCommiter;
+import org.apache.qpid.server.store.berkeleydb.EnvHomeRegistry;
 import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade;
 import org.apache.qpid.server.store.berkeleydb.LoggingAsyncExceptionListener;
 import org.apache.qpid.server.util.DaemonThreadFactory;
@@ -132,7 +149,6 @@ public class ReplicatedEnvironmentFacade
         put(ReplicationConfig.LOG_FLUSH_TASK_INTERVAL, "1 min");
     }});
 
-    public static final String TYPE = "BDB-HA";
     private static final String PERMITTED_NODE_LIST = "permittedNodes";
 
     private final ReplicatedEnvironmentConfiguration _configuration;
@@ -183,7 +199,20 @@ public class ReplicatedEnvironmentFacade
         _groupChangeExecutor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() + 1, new DaemonThreadFactory("Group-Change-Learner:" + _prettyGroupNodeName));
 
         // create environment in a separate thread to avoid renaming of the current thread by JE
-        _environment = createEnvironment(true);
+        EnvHomeRegistry.getInstance().registerHome(_environmentDirectory);
+        boolean success = false;
+        try
+        {
+            _environment = createEnvironment(true);
+            success = true;
+        }
+        finally
+        {
+            if (!success)
+            {
+                EnvHomeRegistry.getInstance().deregisterHome(_environmentDirectory);
+            }
+        }
         populateExistingRemoteReplicationNodes();
         _groupChangeExecutor.submit(new RemoteNodeStateLearner());
     }
@@ -234,8 +263,8 @@ public class ReplicatedEnvironmentFacade
     public void close()
     {
         if (_state.compareAndSet(State.OPENING, State.CLOSING) ||
-                _state.compareAndSet(State.OPEN, State.CLOSING) ||
-                _state.compareAndSet(State.RESTARTING, State.CLOSING) )
+            _state.compareAndSet(State.OPEN, State.CLOSING) ||
+            _state.compareAndSet(State.RESTARTING, State.CLOSING) )
         {
             try
             {
@@ -258,7 +287,14 @@ public class ReplicatedEnvironmentFacade
                 }
                 finally
                 {
-                    closeEnvironment();
+                    try
+                    {
+                        closeEnvironment();
+                    }
+                    finally
+                    {
+                        EnvHomeRegistry.getInstance().deregisterHome(_environmentDirectory);
+                    }
                 }
             }
             finally
@@ -714,13 +750,13 @@ public class ReplicatedEnvironmentFacade
                     String newMaster = admin.transferMaster(Collections.singleton(nodeName), MASTER_TRANSFER_TIMEOUT, TimeUnit.MILLISECONDS, true);
                     if (LOGGER.isDebugEnabled())
                     {
-                        LOGGER.debug("The mastership has been transfered to " + newMaster);
+                        LOGGER.debug("The mastership has been transferred to " + newMaster);
                     }
                 }
                 catch (DatabaseException e)
                 {
-                    LOGGER.warn("Exception on transfering the mastership to " + _prettyGroupNodeName
-                            + " Master transfer timeout : " + MASTER_TRANSFER_TIMEOUT, e);
+                    LOGGER.warn("Exception on transferring the mastership to " + _prettyGroupNodeName
+                                + " Master transfer timeout : " + MASTER_TRANSFER_TIMEOUT, e);
                     throw e;
                 }
                 return null;

Added: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistryTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistryTest.java?rev=1615928&view=auto
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistryTest.java (added)
+++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/EnvHomeRegistryTest.java Tue Aug  5 13:33:00 2014
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.qpid.server.store.berkeleydb;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class EnvHomeRegistryTest extends TestCase
+{
+
+    private final EnvHomeRegistry _ehr = new EnvHomeRegistry();
+
+    public void testDuplicateEnvHomeRejected() throws Exception
+    {
+        File home = new File(QpidTestCase.TMP_FOLDER, getName());
+
+        _ehr.registerHome(home);
+        try
+        {
+            _ehr.registerHome(home);
+            fail("Exception not thrown");
+        }
+        catch (IllegalArgumentException iae)
+        {
+            // PASS
+        }
+    }
+
+    public void testUniqueEnvHomesAllowed() throws Exception
+    {
+        File home1 = new File(QpidTestCase.TMP_FOLDER, getName() + "1");
+        File home2 = new File(QpidTestCase.TMP_FOLDER, getName() + "2");
+
+        _ehr.registerHome(home1);
+        _ehr.registerHome(home2);
+    }
+
+    public void testReuseOfEnvHomesAllowed() throws Exception
+    {
+        File home = new File(QpidTestCase.TMP_FOLDER, getName() + "1");
+
+        _ehr.registerHome(home);
+
+        _ehr.deregisterHome(home);
+
+        _ehr.registerHome(home);
+    }
+}
\ No newline at end of file

Modified: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java?rev=1615928&r1=1615927&r2=1615928&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacadeTest.java Tue Aug  5 13:33:00 2014
@@ -73,6 +73,26 @@ public class StandardEnvironmentFacadeTe
         assertTrue("Environment is not valid", e.isValid());
     }
 
+    public void testSecondEnvironmentFacadeUsingSamePathRejected() throws Exception
+    {
+        EnvironmentFacade ef = createEnvironmentFacade();
+        assertNotNull("Environment should not be null", ef);
+        try
+        {
+            createEnvironmentFacade();
+            fail("Exception not thrown");
+        }
+        catch (IllegalArgumentException iae)
+        {
+            // PASS
+        }
+
+        ef.close();
+
+        EnvironmentFacade ef2 = createEnvironmentFacade();
+        assertNotNull("Environment should not be null", ef2);
+    }
+
     public void testClose() throws Exception
     {
         EnvironmentFacade ef = createEnvironmentFacade();



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org