Repository: activemq-artemis Updated Branches: refs/heads/master 6c6568b76 -> 1d407c2c3
ARTEMIS-187 hold lock between live server and tools This should avoid users damaging data while the server is running (by for instance running compact while the server is running) https://issues.apache.org/jira/browse/ARTEMIS-187 Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/f0f4f168 Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/f0f4f168 Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/f0f4f168 Branch: refs/heads/master Commit: f0f4f1684d083170764f7bd3a273c60f44aaa464 Parents: 6c6568b Author: Clebert Suconic <clebertsuco...@apache.org> Authored: Thu Aug 13 23:40:24 2015 -0400 Committer: Clebert Suconic <clebertsuco...@apache.org> Committed: Thu Aug 13 23:57:49 2015 -0400 ---------------------------------------------------------------------- .../cli/commands/tools/CompactJournal.java | 2 ++ .../cli/commands/tools/DataAbstract.java | 31 ++++++++++++++++++++ .../artemis/cli/commands/tools/PrintData.java | 2 ++ .../cli/commands/tools/XmlDataExporter.java | 2 ++ .../apache/activemq/cli/test/ArtemisTest.java | 9 ++++++ .../artemis/core/server/NodeManager.java | 3 ++ .../core/server/impl/ActiveMQServerImpl.java | 5 ++-- .../core/server/impl/FileLockNodeManager.java | 9 ++++++ .../core/server/impl/InVMNodeManager.java | 7 +++++ .../core/server/impl/LiveOnlyActivation.java | 15 ++++++---- .../discovery/DiscoveryBaseTest.java | 6 ++++ 11 files changed, 84 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/CompactJournal.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/CompactJournal.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/CompactJournal.java index af55345..ba0e9ce 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/CompactJournal.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/CompactJournal.java @@ -33,12 +33,14 @@ public final class CompactJournal extends DataAbstract implements Action { public Object execute(ActionContext context) throws Exception { super.execute(context); try { + testLock(); Configuration configuration = getFileConfiguration(); compactJournal(new File(getJournal()), "activemq-data", "amq", configuration.getJournalMinFiles(), configuration.getJournalFileSize(), null); compactJournal(new File(getBinding()), "activemq-bindings", "bindings", 2, 1048576, null); } catch (Exception e) { treatError(e, "data", "compact"); + return e; } return null; } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java index c08dd44..47edaee 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java @@ -18,9 +18,15 @@ package org.apache.activemq.artemis.cli.commands.tools; import java.io.File; +import java.nio.channels.FileLock; import io.airlift.airline.Option; import org.apache.activemq.artemis.cli.commands.Configurable; +import org.apache.activemq.artemis.core.config.Configuration; +import org.apache.activemq.artemis.core.server.JournalType; +import org.apache.activemq.artemis.core.server.impl.AIOFileLockNodeManager; +import org.apache.activemq.artemis.core.server.impl.FileLockNodeManager; +import org.apache.activemq.artemis.jlibaio.LibaioContext; /** * Abstract class for places where you need bindings, journal paging and large messages configuration @@ -39,6 +45,31 @@ public abstract class DataAbstract extends Configurable { @Option(name = "--large-messages", description = "The folder used for large-messages (default from broker.xml)") public String largeMessges; + + protected void testLock() throws Exception { + + FileLockNodeManager fileLockNodeManager; + Configuration configuration = getFileConfiguration(); + if (getFileConfiguration().getJournalType() == JournalType.ASYNCIO && LibaioContext.isLoaded()) { + fileLockNodeManager = new AIOFileLockNodeManager(new File(getJournal()), false, configuration.getJournalLockAcquisitionTimeout()); + } + else { + fileLockNodeManager = new FileLockNodeManager(new File(getJournal()), false, configuration.getJournalLockAcquisitionTimeout()); + } + + fileLockNodeManager.start(); + + try (FileLock lock = fileLockNodeManager.tryLockLive()) { + if (lock == null) { + throw new RuntimeException("Server is locked!"); + } + } + finally { + fileLockNodeManager.stop(); + } + + } + public String getLargeMessages() throws Exception { if (largeMessges == null) { largeMessges = getFileConfiguration().getLargeMessagesLocation().getAbsolutePath(); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java index 68dc5dc..0802b13 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java @@ -63,10 +63,12 @@ public class PrintData extends DataAbstract implements Action { public Object execute(ActionContext context) throws Exception { super.execute(context); try { + testLock(); printData(new File(getBinding()), new File(getJournal()), new File(getPaging())); } catch (Exception e) { treatError(e, "data", "print"); + return e; } return null; } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/XmlDataExporter.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/XmlDataExporter.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/XmlDataExporter.java index 0d96aae..66101b9 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/XmlDataExporter.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/XmlDataExporter.java @@ -129,10 +129,12 @@ public final class XmlDataExporter extends DataAbstract implements Action { super.execute(context); try { + testLock(); process(context.out, getBinding(), getJournal(), getPaging(), getLargeMessages()); } catch (Exception e) { treatError(e, "data", "exp"); + return e; } return null; } http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java index cfcc53f..b6b5ac7 100644 --- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java +++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java @@ -93,6 +93,15 @@ public class ArtemisTest { // Some exceptions may happen on the initialization, but they should be ok on start the basic core protocol Artemis.execute("run"); + Object object = Artemis.execute("data", "print"); + Assert.assertTrue("An error was expected", object != null && object instanceof Throwable); + + object = Artemis.execute("data", "compact"); + Assert.assertTrue("An error was expected", object != null && object instanceof Throwable); + + object = Artemis.execute("data", "exp"); + Assert.assertTrue("An error was expected", object != null && object instanceof Throwable); + try (ServerLocator locator = ServerLocatorImpl.newLocator("tcp://localhost:61616"); ClientSessionFactory factory = locator.createSessionFactory(); ClientSession coreSession = factory.createSession()) { http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/NodeManager.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/NodeManager.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/NodeManager.java index 421daaa..222f0ce 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/NodeManager.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/NodeManager.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; import org.apache.activemq.artemis.api.core.ActiveMQIllegalStateException; import org.apache.activemq.artemis.api.core.SimpleString; @@ -130,6 +131,8 @@ public abstract class NodeManager implements ActiveMQComponent { releaseBackup(); } + public abstract FileLock tryLockLive(); + /** * Ensures existence of persistent information about the server's nodeID. * <p> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java index 8853154..de19512 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java @@ -347,9 +347,10 @@ public class ActiveMQServerImpl implements ActiveMQServer { protected NodeManager createNodeManager(final File directory, boolean replicatingBackup) { NodeManager manager; if (!configuration.isPersistenceEnabled()) { - manager = new InVMNodeManager(replicatingBackup); + return new InVMNodeManager(replicatingBackup); } - else if (configuration.getJournalType() == JournalType.ASYNCIO && LibaioContext.isLoaded()) { + + if (configuration.getJournalType() == JournalType.ASYNCIO && LibaioContext.isLoaded()) { manager = new AIOFileLockNodeManager(directory, replicatingBackup, configuration.getJournalLockAcquisitionTimeout()); } else { http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/FileLockNodeManager.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/FileLockNodeManager.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/FileLockNodeManager.java index acb431d..4b4134b 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/FileLockNodeManager.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/FileLockNodeManager.java @@ -73,6 +73,15 @@ public class FileLockNodeManager extends NodeManager { super.start(); } + public FileLock tryLockLive() { + try { + return tryLock(FileLockNodeManager.LIVE_LOCK_POS); + } + catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + @Override public boolean isAwaitingFailback() throws Exception { return getState() == FileLockNodeManager.FAILINGBACK; http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/InVMNodeManager.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/InVMNodeManager.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/InVMNodeManager.java index 726cb50..c11c810 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/InVMNodeManager.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/InVMNodeManager.java @@ -18,6 +18,7 @@ package org.apache.activemq.artemis.core.server.impl; import java.io.File; import java.io.IOException; +import java.nio.channels.FileLock; import java.util.concurrent.Semaphore; import org.apache.activemq.artemis.api.core.ActiveMQIllegalStateException; @@ -96,6 +97,12 @@ public final class InVMNodeManager extends NodeManager { } @Override + public FileLock tryLockLive() { + // no op.. doesn't make sense on InVM + return null; + } + + @Override public void startLiveNode() throws Exception { state = FAILING_BACK; liveLock.acquire(); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LiveOnlyActivation.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LiveOnlyActivation.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LiveOnlyActivation.java index 1c82bbf..11f860c 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LiveOnlyActivation.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LiveOnlyActivation.java @@ -16,6 +16,11 @@ */ package org.apache.activemq.artemis.core.server.impl; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; + import org.apache.activemq.artemis.api.core.ActiveMQException; import org.apache.activemq.artemis.api.core.Pair; import org.apache.activemq.artemis.api.core.SimpleString; @@ -32,11 +37,6 @@ import org.apache.activemq.artemis.core.server.cluster.ActiveMQServerSideProtoco import org.apache.activemq.artemis.core.server.cluster.ha.LiveOnlyPolicy; import org.apache.activemq.artemis.core.server.cluster.ha.ScaleDownPolicy; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentMap; - public class LiveOnlyActivation extends Activation { //this is how we act when we initially start as live @@ -55,6 +55,11 @@ public class LiveOnlyActivation extends Activation { public void run() { try { + + /* We will hold a lock here so print-data and other tools + * won't be able to run */ + activeMQServer.getNodeManager().startLiveNode(); + activeMQServer.initialisePart1(false); activeMQServer.initialisePart2(false); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/f0f4f168/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/discovery/DiscoveryBaseTest.java ---------------------------------------------------------------------- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/discovery/DiscoveryBaseTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/discovery/DiscoveryBaseTest.java index 06bc14e..e2e450b 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/discovery/DiscoveryBaseTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/discovery/DiscoveryBaseTest.java @@ -17,6 +17,7 @@ package org.apache.activemq.artemis.tests.integration.discovery; import java.net.InetAddress; +import java.nio.channels.FileLock; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -177,6 +178,11 @@ public class DiscoveryBaseTest extends ActiveMQTestBase { } @Override + public FileLock tryLockLive() { + return null; + } + + @Override public void awaitLiveNode() throws Exception { }