Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/main/java/com/yetanalytics/hlaxapi/AppConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.yetanalytics.hlaxapi.cache.FomCatalog;
import com.yetanalytics.hlaxapi.cache.ObjectCache;
import com.yetanalytics.hlaxapi.config.ConfigParser;
import com.yetanalytics.hlaxapi.config.XapiConfig;

Expand Down Expand Up @@ -40,6 +42,15 @@ public HLADecoderRegistry hlaDecoderRegistry(EncoderFactory encoderFactory) {
return new HLADecoderRegistry(encoderFactory);
}

@Bean(destroyMethod = "close")
public ObjectCache objectCache(
XapiConfig xapiConfig,
FomCatalog fomCatalog,
FOMXML fomXml,
HLADecoderRegistry decoderRegistry) {
return new ObjectCache(xapiConfig, fomCatalog, fomXml, decoderRegistry);
}

@Bean
public XapiConfig xapiConfig() {
XapiConfig xapiConfig;
Expand Down
43 changes: 9 additions & 34 deletions src/main/java/com/yetanalytics/hlaxapi/HlaInterfaceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
Expand All @@ -13,8 +12,7 @@
import org.apache.logging.log4j.Logger;

import com.yetanalytics.hlaxapi.cache.FomCatalog;
import com.yetanalytics.hlaxapi.cache.HlaObjectCache;
import com.yetanalytics.hlaxapi.cache.QueryReferenceCollector;
import com.yetanalytics.hlaxapi.cache.ObjectCache;
import com.yetanalytics.hlaxapi.config.XapiConfig;
import com.yetanalytics.hlaxapi.config.model.StatementTrigger;
import com.yetanalytics.hlaxapi.injection.InteractionInjectionContext;
Expand Down Expand Up @@ -87,23 +85,11 @@ public class HlaInterfaceImpl extends NullFederateAmbassador implements HlaInter
@Autowired
private SimulationConfig simulationConfig;

@Autowired
private FOMXML fomXml;

@Autowired
private HLADecoderRegistry decoderRegistry;

@Autowired
private TriggerProcessor triggerProcessor;

@Autowired
private InjectionHandler injectionHandler;

private FomCatalog fomCatalog;

private HlaObjectCache objectCache;

private Map<String, Set<String>> objectCacheSubscriptions = Collections.emptyMap();
private ObjectCache objectCache;

public void start()
throws ConnectionFailed, InvalidLocalSettingsDesignator, RTIinternalError, NotConnected, ErrorReadingFDD,
Expand All @@ -112,14 +98,8 @@ public void start()
RtiFactory rtiFactory = RtiFactoryFactory.getRtiFactory();
ambassador = rtiFactory.getRtiAmbassador();

fomCatalog = FomCatalog.fromFomXml(fomXml);
objectCacheSubscriptions = QueryReferenceCollector.collect(xapiConfig.statementTriggers);
if (objectCacheSubscriptions.isEmpty()) {
injectionHandler.setQueryService(null);
if (!objectCache.isEnabled()) {
logger.info("No query injections configured; object cache is disabled");
} else {
objectCache = new HlaObjectCache(HlaObjectCache.defaultJdbcUrl(), fomCatalog, fomXml, decoderRegistry);
injectionHandler.setQueryService(objectCache.queryService());
}

try {
Expand Down Expand Up @@ -194,11 +174,6 @@ public void stop() throws RTIinternalError {
} catch (FederateIsExecutionMember | CallNotAllowedFromWithinCallback e) {
throw new RTIinternalError("HlaInterfaceFailure", e);
}
injectionHandler.setQueryService(null);
if (objectCache != null) {
objectCache.close();
objectCache = null;
}
} catch (NotConnected ignored) {
}
}
Expand All @@ -214,12 +189,12 @@ public void connectionLost(String faultDescription) throws FederateInternalError

private void subscribeObjectClasses()
throws FederateNotExecutionMember, RestoreInProgress, SaveInProgress, NotConnected, RTIinternalError {
if (objectCacheSubscriptions.isEmpty()) {
if (!objectCache.isEnabled()) {
return;
}
for (Map.Entry<String, Set<String>> subscription : objectCacheSubscriptions.entrySet()) {
for (Map.Entry<String, Set<String>> subscription : objectCache.subscriptions().entrySet()) {
try {
FomCatalog.ObjectClassDef clazz = fomCatalog.objectClass(subscription.getKey()).orElseThrow(
FomCatalog.ObjectClassDef clazz = objectCache.catalog().objectClass(subscription.getKey()).orElseThrow(
() -> new IllegalArgumentException("No FOM object class " + subscription.getKey()));
ObjectClassHandle classHandle = ambassador.getObjectClassHandle(clazz.localName());
AttributeHandleSet attributeHandles = ambassador.getAttributeHandleSetFactory().create();
Expand Down Expand Up @@ -251,7 +226,7 @@ public void discoverObjectInstance(
ObjectClassHandle theObjectClass,
String objectName,
hla.rti1516e.FederateHandle producingFederate) throws FederateInternalError {
if (objectCache == null) {
if (!objectCache.isEnabled()) {
return;
}
try {
Expand Down Expand Up @@ -303,7 +278,7 @@ public void reflectAttributeValues(
}

private void reflectAttributeValues(ObjectInstanceHandle theObject, AttributeHandleValueMap theAttributes) {
if (objectCache == null) {
if (!objectCache.isEnabled()) {
return;
}
try {
Expand Down Expand Up @@ -356,7 +331,7 @@ public void removeObjectInstance(
}

private void removeCachedObject(ObjectInstanceHandle theObject) {
if (objectCache == null) {
if (!objectCache.isEnabled()) {
return;
}
try {
Expand Down
17 changes: 10 additions & 7 deletions src/main/java/com/yetanalytics/hlaxapi/InjectionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import org.springframework.stereotype.Component;

import com.yetanalytics.hlaxapi.FOMXML.PathCheckResult;
import com.yetanalytics.hlaxapi.cache.CacheQueryService;
import com.yetanalytics.hlaxapi.cache.ObjectCache;
import com.yetanalytics.hlaxapi.config.model.Criterion;
import com.yetanalytics.hlaxapi.config.model.Expression;
import com.yetanalytics.hlaxapi.config.model.LogicalExpression;
Expand All @@ -36,16 +36,16 @@ public class InjectionHandler {

private static final Logger logger = LogManager.getLogger(InjectionHandler.class);

private volatile CacheQueryService queryService;
@Autowired
private ObjectCache objectCache;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird that we would do constructor injection when there are already wired beans. just change to autowired and kill the 1-arg constructor OR make it a 3-arg constructor to not mix DI methodologies.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and fef0683


@Autowired
private FOMXML fomXml;

@Autowired
private HLADecoderRegistry hlaDecoderRegistry;

public void setQueryService(CacheQueryService cacheQueryService) {
this.queryService = cacheQueryService;
public InjectionHandler() {
}

public Object handleThis(Target t, InjectionContext context) {
Expand Down Expand Up @@ -225,13 +225,12 @@ public Object handleQuery(String clazz, Target attrTarget, Expression criteria)
}

public Object handleQuery(String clazz, Target attrTarget, Expression criteria, InjectionContext context) {
CacheQueryService service = queryService;
if (service == null) {
if (objectCache == null) {
return null;
}

Expression resolvedCriteria = resolveThisExpressions(criteria, context);
Optional<Object> value = service.findFirstValue(clazz, attrTarget, resolvedCriteria);
Optional<Object> value = objectCache.findFirstValue(clazz, attrTarget, resolvedCriteria);
return value.orElse(null);
}

Expand Down Expand Up @@ -266,4 +265,8 @@ public void setFomXml(FOMXML fomXml) {
public void setHLADecoderRegistry(HLADecoderRegistry hdr) {
this.hlaDecoderRegistry = hdr;
}

ObjectCache objectCache() {
return objectCache;
}
}
29 changes: 14 additions & 15 deletions src/main/java/com/yetanalytics/hlaxapi/cache/FomCatalog.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.Optional;
import java.util.Set;
import javax.xml.xpath.XPathExpressionException;

import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
Expand All @@ -20,14 +22,24 @@
/**
* FOM-derived object metadata used by the SQLite cache.
*/
@Component
public final class FomCatalog {

private final Map<String, ObjectClassDef> classesByName;
private final Map<Integer, ObjectClassDef> classesById;
private final Map<Integer, FomAttribute> attributesById;

private FomCatalog(Map<String, ObjectClassDef> classesByName) {
this.classesByName = Collections.unmodifiableMap(classesByName);
public FomCatalog(FOMXML fomXml) {
Objects.requireNonNull(fomXml, "fomXml");
CatalogBuilder builder = new CatalogBuilder(fomXml);
Document document = fomXml.getDoc();
Element objects = firstElement(document.getDocumentElement(), "objects");
if (objects != null) {
for (Element objectClass : childElements(objects, "objectClass")) {
builder.parseObjectClass(objectClass, null, new ArrayList<>());
}
}
this.classesByName = builder.classesByName;

Map<Integer, ObjectClassDef> byId = new LinkedHashMap<>();
Map<Integer, FomAttribute> attrsById = new LinkedHashMap<>();
Expand All @@ -41,19 +53,6 @@ private FomCatalog(Map<String, ObjectClassDef> classesByName) {
this.attributesById = Collections.unmodifiableMap(attrsById);
}

public static FomCatalog fromFomXml(FOMXML fomXml) {
Objects.requireNonNull(fomXml, "fomXml");
CatalogBuilder builder = new CatalogBuilder(fomXml);
Document document = fomXml.getDoc();
Element objects = firstElement(document.getDocumentElement(), "objects");
if (objects != null) {
for (Element objectClass : childElements(objects, "objectClass")) {
builder.parseObjectClass(objectClass, null, new ArrayList<>());
}
}
return new FomCatalog(builder.classesByName);
}

public Collection<ObjectClassDef> objectClasses() {
return classesByName.values();
}
Expand Down
79 changes: 79 additions & 0 deletions src/main/java/com/yetanalytics/hlaxapi/cache/ObjectCache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.yetanalytics.hlaxapi.cache;

import com.yetanalytics.hlaxapi.FOMXML;
import com.yetanalytics.hlaxapi.HLADecoderRegistry;
import com.yetanalytics.hlaxapi.config.XapiConfig;
import com.yetanalytics.hlaxapi.config.model.Expression;
import com.yetanalytics.hlaxapi.config.model.Target;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

public class ObjectCache implements AutoCloseable {

private final FomCatalog catalog;
private final Map<String, Set<String>> subscriptions;
private HlaObjectCache delegate;

public ObjectCache(XapiConfig xapiConfig, FomCatalog catalog, FOMXML fomXml, HLADecoderRegistry decoderRegistry) {
this(xapiConfig, catalog, fomXml, decoderRegistry, HlaObjectCache.defaultJdbcUrl());
}

ObjectCache(
XapiConfig xapiConfig,
FomCatalog catalog,
FOMXML fomXml,
HLADecoderRegistry decoderRegistry,
String jdbcUrl) {
this.catalog = catalog;
this.subscriptions = QueryReferenceCollector.collect(xapiConfig.statementTriggers);
if (!subscriptions.isEmpty()) {
this.delegate = new HlaObjectCache(jdbcUrl, catalog, fomXml, decoderRegistry);
}
}

public boolean isEnabled() {
return delegate != null;
}

public Map<String, Set<String>> subscriptions() {
return subscriptions;
}

public FomCatalog catalog() {
return catalog;
}

public Optional<Object> findFirstValue(String clazz, Target attrTarget, Expression criteria) {
if (delegate == null) {
return Optional.empty();
}
return delegate.queryService().findFirstValue(clazz, attrTarget, criteria);
}

public void discoverObject(String objectHandle, String objectName, String className) {
if (delegate != null) {
delegate.discoverObject(objectHandle, objectName, className);
}
}

public void reflectAttributeValue(String objectHandle, String className, String attributeName, byte[] bytes) {
if (delegate != null) {
delegate.reflectAttributeValue(objectHandle, className, attributeName, bytes);
}
}

public void removeObject(String objectHandle) {
if (delegate != null) {
delegate.removeObject(objectHandle);
}
}

@Override
public synchronized void close() {
if (delegate != null) {
delegate.close();
delegate = null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.yetanalytics.hlaxapi;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;

import com.yetanalytics.hlaxapi.cache.FomCatalog;
import com.yetanalytics.hlaxapi.cache.ObjectCache;
import com.yetanalytics.hlaxapi.config.XapiConfig;
import hla.rti1516e.encoding.EncoderFactory;
import org.junit.jupiter.api.Test;
import org.portico.impl.hla1516e.types.encoding.HLA1516eEncoderFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

class ObjectCacheSpringContextTest {

@Test
void springWiresObjectCacheIntoConsumers() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
context.register(
TestConfig.class,
FOMXML.class,
FomCatalog.class,
HlaInterfaceImpl.class,
InjectionHandler.class,
TriggerProcessor.class);
context.refresh();

FomCatalog fomCatalog = context.getBean(FomCatalog.class);
ObjectCache objectCache = context.getBean(ObjectCache.class);
InjectionHandler injectionHandler = context.getBean(InjectionHandler.class);
HlaInterfaceImpl hlaInterface = context.getBean(HlaInterfaceImpl.class);

assertNotNull(hlaInterface);
assertSame(fomCatalog, objectCache.catalog());
assertSame(objectCache, injectionHandler.objectCache());
}
}

@Configuration
static class TestConfig extends AppConfig {

@Override
@Bean
public EncoderFactory encoderFactory() {
return new HLA1516eEncoderFactory();
}

@Override
@Bean
public XapiConfig xapiConfig() {
return new XapiConfig();
}

@Override
@Bean
public SimulationConfig simulationConfig() {
return new SimulationConfig(null, null, null, null, "config/HlaFedereplFOM.xml");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ void convertsTargetsToPathKeys() {
private FomCatalog catalog(String fomPath) {
SimulationConfig simConfig = new SimulationConfig(null, null, null, null, fomPath);
HLADecoderRegistry decoderRegistry = new HLADecoderRegistry(new HLA1516eEncoderFactory());
return FomCatalog.fromFomXml(new FOMXML(simConfig, decoderRegistry));
return new FomCatalog(new FOMXML(simConfig, decoderRegistry));
}
}
Loading
Loading