Skip to content

Commit a79b19c

Browse files
committed
SPI Queue/QE
1 parent 92b3c50 commit a79b19c

File tree

5 files changed

+75
-31
lines changed

5 files changed

+75
-31
lines changed

src/main/java/net/openhft/chronicle/queue/impl/single/SingleChronicleQueueBuilder.java

+7-31
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import net.openhft.chronicle.queue.impl.table.ReadonlyTableStore;
3838
import net.openhft.chronicle.queue.impl.table.SingleTableBuilder;
3939
import net.openhft.chronicle.queue.internal.domestic.QueueOffsetSpec;
40+
import net.openhft.chronicle.queue.providers.EnterpriseQueueFactories;
4041
import net.openhft.chronicle.threads.MediumEventLoop;
4142
import net.openhft.chronicle.threads.Pauser;
4243
import net.openhft.chronicle.threads.TimeoutPauser;
@@ -47,7 +48,6 @@
4748

4849
import javax.crypto.spec.SecretKeySpec;
4950
import java.io.File;
50-
import java.lang.reflect.Constructor;
5151
import java.nio.file.Path;
5252
import java.time.LocalTime;
5353
import java.time.ZoneId;
@@ -68,7 +68,6 @@ public class SingleChronicleQueueBuilder extends SelfDescribingMarshallable impl
6868
public static final long SMALL_BLOCK_SIZE = OS.isWindows() ? OS.SAFE_PAGE_SIZE : OS.pageSize(); // the smallest safe block size on Windows 8+
6969

7070
public static final long DEFAULT_SPARSE_CAPACITY = 512L << 30;
71-
private static final Constructor ENTERPRISE_QUEUE_CONSTRUCTOR;
7271
private static final WireStoreFactory storeFactory = SingleChronicleQueueBuilder::createStore;
7372
private static final Supplier<TimingPauser> TIMING_PAUSER_SUPPLIER = DefaultPauserSupplier.INSTANCE;
7473

@@ -78,17 +77,6 @@ public class SingleChronicleQueueBuilder extends SelfDescribingMarshallable impl
7877
CLASS_ALIASES.addAlias(SCQRoll.class, "SCQSRoll");
7978
CLASS_ALIASES.addAlias(SCQIndexing.class, "SCQSIndexing");
8079
CLASS_ALIASES.addAlias(SingleChronicleQueueStore.class, "SCQStore");
81-
82-
{
83-
Constructor co;
84-
try {
85-
co = ((Class) Class.forName("software.chronicle.enterprise.queue.EnterpriseSingleChronicleQueue")).getDeclaredConstructors()[0];
86-
Jvm.setAccessible(co);
87-
} catch (Exception e) {
88-
co = null;
89-
}
90-
ENTERPRISE_QUEUE_CONSTRUCTOR = co;
91-
}
9280
}
9381

9482
private BufferMode writeBufferMode = BufferMode.None;
@@ -235,7 +223,7 @@ static SingleChronicleQueueStore createStore(@NotNull RollingChronicleQueue queu
235223
}
236224

237225
public static boolean areEnterpriseFeaturesAvailable() {
238-
return ENTERPRISE_QUEUE_CONSTRUCTOR != null;
226+
return EnterpriseQueueFactories.get().areEnterpriseFeaturesAvailable();
239227
}
240228

241229
private static RollCycle loadDefaultRollCycle() {
@@ -300,10 +288,10 @@ public SingleChronicleQueue build() {
300288

301289
// It is important to check enterprise features after preBuild()
302290
// Enterprise-only config options can be loaded from the metadata
303-
if (checkEnterpriseFeaturesRequested())
304-
chronicleQueue = buildEnterprise();
305-
else
306-
chronicleQueue = new SingleChronicleQueue(this);
291+
if (checkEnterpriseFeaturesRequested() && !areEnterpriseFeaturesAvailable()) {
292+
throw new IllegalStateException("Enterprise features requested but Chronicle Queue Enterprise is not in the class path!");
293+
}
294+
chronicleQueue = EnterpriseQueueFactories.get().newInstance(this);
307295

308296
postBuild(chronicleQueue);
309297

@@ -342,23 +330,11 @@ private boolean checkEnterpriseFeaturesRequested() {
342330
}
343331

344332
public static boolean onlyAvailableInEnterprise(final String feature) {
345-
if (ENTERPRISE_QUEUE_CONSTRUCTOR == null)
333+
if (!areEnterpriseFeaturesAvailable())
346334
Jvm.warn().on(SingleChronicleQueueBuilder.class, feature + " is only supported in Chronicle Queue Enterprise. If you would like to use this feature, please contact sales@chronicle.software for more information.");
347335
return true;
348336
}
349337

350-
@NotNull
351-
private SingleChronicleQueue buildEnterprise() {
352-
if (ENTERPRISE_QUEUE_CONSTRUCTOR == null)
353-
throw new IllegalStateException("Enterprise features requested but Chronicle Queue Enterprise is not in the class path!");
354-
355-
try {
356-
return (SingleChronicleQueue) ENTERPRISE_QUEUE_CONSTRUCTOR.newInstance(this);
357-
} catch (Exception e) {
358-
throw new IllegalStateException("Couldn't create an instance of Enterprise queue", e);
359-
}
360-
}
361-
362338
public SingleChronicleQueueBuilder aesEncryption(@Nullable byte[] keyBytes) {
363339
if (keyBytes == null) {
364340
codingSuppliers(null, null);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package net.openhft.chronicle.queue.impl.single;
2+
3+
import net.openhft.chronicle.queue.providers.QueueFactory;
4+
5+
public class SingleChronicleQueueFactory implements QueueFactory {
6+
7+
@Override
8+
public boolean areEnterpriseFeaturesAvailable() {
9+
return false;
10+
}
11+
12+
@Override
13+
public SingleChronicleQueue newInstance(SingleChronicleQueueBuilder queueBuilder) {
14+
return new SingleChronicleQueue(queueBuilder);
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package net.openhft.chronicle.queue.providers;
2+
3+
import net.openhft.chronicle.core.Jvm;
4+
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueueFactory;
5+
import org.jetbrains.annotations.NotNull;
6+
7+
import java.util.ServiceLoader;
8+
9+
public class EnterpriseQueueFactories {
10+
11+
private static final String PREFERRED_FACTORY_CLASS_NAME = Jvm.getProperty("net.openhft.chronicle.queue.providers.EnterpriseQueueWrapper",
12+
"software.chronicle.enterprise.queue.EnterpriseQueueFactory");
13+
14+
private static QueueFactory queueFactory;
15+
16+
/**
17+
* Get the {@link QueueFactory}
18+
*
19+
* @return the active queue wrapper
20+
*/
21+
@NotNull
22+
public static QueueFactory get() {
23+
if (queueFactory == null) {
24+
final ServiceLoader<QueueFactory> load = ServiceLoader.load(QueueFactory.class);
25+
for (QueueFactory factory : load) {
26+
// last one in wins, unless we encounter the "preferred" one
27+
queueFactory = factory;
28+
if (PREFERRED_FACTORY_CLASS_NAME.equals(factory.getClass().getName())) {
29+
break;
30+
}
31+
}
32+
if (queueFactory == null) {
33+
Jvm.error().on(EnterpriseQueueFactories.class, "There's no queue wrapper factory configured, this shouldn't happen. ");
34+
queueFactory = new SingleChronicleQueueFactory();
35+
}
36+
}
37+
return queueFactory;
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package net.openhft.chronicle.queue.providers;
2+
3+
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueue;
4+
import net.openhft.chronicle.queue.impl.single.SingleChronicleQueueBuilder;
5+
6+
public interface QueueFactory {
7+
8+
// SPI for SingleChronicleQueueBuilder
9+
boolean areEnterpriseFeaturesAvailable();
10+
11+
SingleChronicleQueue newInstance(SingleChronicleQueueBuilder queueBuilder);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
net.openhft.chronicle.queue.impl.single.SingleChronicleQueueFactory

0 commit comments

Comments
 (0)