diff --git a/aeron-client/src/main/java/io/aeron/Aeron.java b/aeron-client/src/main/java/io/aeron/Aeron.java index 3f1601a4c2..2e44453377 100644 --- a/aeron-client/src/main/java/io/aeron/Aeron.java +++ b/aeron-client/src/main/java/io/aeron/Aeron.java @@ -123,6 +123,8 @@ public static Aeron connect() */ public static Aeron connect(final Context ctx) { + ctx.verifyNotAlreadyInUse(); + try { final Aeron aeron = new Aeron(ctx); diff --git a/aeron-client/src/main/java/io/aeron/CommonContext.java b/aeron-client/src/main/java/io/aeron/CommonContext.java index e4aaa03a71..20810f30ba 100644 --- a/aeron-client/src/main/java/io/aeron/CommonContext.java +++ b/aeron-client/src/main/java/io/aeron/CommonContext.java @@ -33,6 +33,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import static io.aeron.Aeron.sleep; @@ -214,6 +215,8 @@ public class CommonContext implements Cloneable */ public static final String TETHER_PARAM_NAME = "tether"; + private final AtomicBoolean inUse = new AtomicBoolean(false); + private long driverTimeoutMs = DRIVER_TIMEOUT_MS; private String aeronDirectoryName = getAeronDirectoryName(); private File aeronDirectory; @@ -310,6 +313,21 @@ public CommonContext concludeAeronDirectory() return this; } + /** + * Checks to see if another instance of the Aeron Client or Media Driver already is already using this + * context. + * + * @throws IllegalStateException if the context is already in use. + */ + public void verifyNotAlreadyInUse() + { + if (!inUse.compareAndSet(false, true)) + { + throw new IllegalStateException( + "Context instances may not be reused, create a new one for each Aeron/MediaDriver instance"); + } + } + /** * Get the top level Aeron directory used for communication between the client and Media Driver, and * the location of the data buffers. diff --git a/aeron-driver/src/main/java/io/aeron/driver/MediaDriver.java b/aeron-driver/src/main/java/io/aeron/driver/MediaDriver.java index 3723a2650d..d5a0df4809 100644 --- a/aeron-driver/src/main/java/io/aeron/driver/MediaDriver.java +++ b/aeron-driver/src/main/java/io/aeron/driver/MediaDriver.java @@ -222,6 +222,7 @@ public static MediaDriver launch() */ public static MediaDriver launch(final Context ctx) { + ctx.verifyNotAlreadyInUse(); return new MediaDriver(ctx).start(); } diff --git a/aeron-driver/src/test/java/io/aeron/driver/DriverContextTest.java b/aeron-driver/src/test/java/io/aeron/driver/DriverContextTest.java new file mode 100644 index 0000000000..5096b07ca9 --- /dev/null +++ b/aeron-driver/src/test/java/io/aeron/driver/DriverContextTest.java @@ -0,0 +1,19 @@ +package io.aeron.driver; + +import org.junit.Test; + +public class DriverContextTest +{ + @Test(expected = IllegalStateException.class) + public void shouldPreventCreatingMultipleDriversWithTheSameContext() + { + final MediaDriver.Context ctx = new MediaDriver.Context(); + + //noinspection EmptyTryBlock + try ( + MediaDriver mediaDriver1 = MediaDriver.launchEmbedded(ctx); + MediaDriver mediaDriver2 = MediaDriver.launchEmbedded(ctx)) + { + } + } +} diff --git a/aeron-system-tests/src/test/java/io/aeron/ClientContextTest.java b/aeron-system-tests/src/test/java/io/aeron/ClientContextTest.java new file mode 100644 index 0000000000..5d6932e97b --- /dev/null +++ b/aeron-system-tests/src/test/java/io/aeron/ClientContextTest.java @@ -0,0 +1,24 @@ +package io.aeron; + +import io.aeron.driver.MediaDriver; +import org.junit.Test; + +public class ClientContextTest +{ + @Test(expected = IllegalStateException.class) + public void shouldPreventCreatingMultipleClientsWithTheSameContext() + { + try (MediaDriver mediaDriver = MediaDriver.launchEmbedded()) + { + final Aeron.Context ctx = new Aeron.Context() + .aeronDirectoryName(mediaDriver.aeronDirectoryName()); + + //noinspection EmptyTryBlock + try ( + Aeron aeron1 = Aeron.connect(ctx); + Aeron aeron2 = Aeron.connect(ctx)) + { + } + } + } +}