package eu.play_project.dcep.distributedetalis; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import jpl.PrologException; import org.objectweb.proactive.Body; import org.objectweb.proactive.Service; import org.objectweb.proactive.core.component.body.ComponentEndActive; import org.objectweb.proactive.core.component.body.ComponentInitActive; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.bridge.SLF4JBridgeHandler; import com.jtalis.core.JtalisContextImpl; import eu.play_project.dcep.api.DcepManagementException; import eu.play_project.dcep.api.DcepManagmentApi; import eu.play_project.dcep.api.DcepMonitoringApi; import eu.play_project.dcep.api.measurement.MeasurementConfig; import eu.play_project.dcep.api.measurement.NodeMeasurementResult; import eu.play_project.dcep.distributedetalis.api.ConfigApi; import eu.play_project.dcep.distributedetalis.api.Configuration; import eu.play_project.dcep.distributedetalis.api.DEtalisConfigApi; import eu.play_project.dcep.distributedetalis.api.DistributedEtalisException; import eu.play_project.dcep.distributedetalis.api.DistributedEtalisTestApi; import eu.play_project.dcep.distributedetalis.api.EcConnectionManager; import eu.play_project.dcep.distributedetalis.api.EcConnectionmanagerException; import eu.play_project.dcep.distributedetalis.api.SimplePublishApi; import eu.play_project.dcep.distributedetalis.measurement.MeasurementUnit; import eu.play_project.play_platformservices.api.BdplQuery; import fr.inria.eventcloud.api.CompoundEvent; /** * Distributed Etalis component. This component is a standalone event processing * agent which can be instantiated multiple times to create a distributed * network. * * @author Stefan Obermeier * @author Roland Stühmer */ public class DistributedEtalis implements DcepMonitoringApi, DcepManagmentApi, DistributedEtalisTestApi, ComponentInitActive, ComponentEndActive, ConfigApi, DEtalisConfigApi, Serializable { private static final long serialVersionUID = 100L; private String name; private JtalisContextImpl etalis; // ETALIS Object private JtalisOutputProvider eventOutputProvider; private JtalisInputProvider eventInputProvider; private final Logger logger = LoggerFactory.getLogger(DistributedEtalis.class); private Map<String, BdplQuery> registeredQueries = Collections.synchronizedMap(new HashMap<String, BdplQuery>()); private EcConnectionManager ecConnectionManager; private MeasurementUnit measurementUnit; private PrologSemWebLib semWebLib; private boolean init = false; private final Set<SimplePublishApi> eventSinks = Collections .synchronizedSet(new HashSet<SimplePublishApi>()); Service service; { /* * Set up logging for jtalis (using JUL -> slf4j) */ // Optionally remove existing handlers attached to j.u.l root logger SLF4JBridgeHandler.removeHandlersForRootLogger(); // add SLF4JBridgeHandler to j.u.l's root logger, should be done once // during the initialization phase of your application SLF4JBridgeHandler.install(); } // Only for ProActive public DistributedEtalis() { } // Only for local use (testing) public DistributedEtalis(String name) { this.name = name; this.initComponentActivity(null); } @Override public void initComponentActivity(Body body) { logger.info("Initialising {} component.", this.getClass().getSimpleName()); } @Override public void endComponentActivity(Body arg0) { logger.info("Terminating {} component.", this.getClass() .getSimpleName()); if (init) { if(ecConnectionManager!=null) this.ecConnectionManager.destroy(); this.etalis.shutdown(); this.eventSinks.clear(); this.init = false; } } @Override public void registerEventPattern(BdplQuery bdplQuery) throws DcepManagementException { if (!init) { throw new IllegalStateException(this.getClass().getSimpleName()+ " has not been initialized."); } if (bdplQuery.getDetails() == null) { throw new IllegalArgumentException("QueryDetails is not set"); } logger.info("New event pattern is being registered at {} with queryId = {}", this.getClass().getSimpleName(), bdplQuery .getDetails().getQueryId()); logger.debug("ELE: " + bdplQuery.getEleQuery()); if(this.registeredQueries.containsKey(bdplQuery.getDetails().getQueryId())) { String error = "Pattern ID already exists: " + bdplQuery.getDetails().getQueryId(); logger.error(error); throw new DcepManagementException(error); } try { this.registeredQueries.put(bdplQuery.getDetails().getQueryId(), bdplQuery); logger.debug("Register query: " + bdplQuery.getEleQuery()); etalis.addDynamicRuleWithId("'" + bdplQuery.getDetails().getQueryId() + "'" + bdplQuery.getDetails().getEtalisProperty(), bdplQuery.getEleQuery()); // Start tumbling window. (If a tumbling window was defined.) etalis.getEngineWrapper().executeGoal(bdplQuery.getDetails().getTumblingWindow()); //Register db queries. for (String dbQuerie : bdplQuery.getDetails().getRdfDbQueries()) { etalis.getEngineWrapper().executeGoal("assert(" + dbQuerie + ")"); } // Configure ETALIS to inform output listener if complex event of new type appeared. etalis.addEventTrigger(bdplQuery.getDetails().getComplexType() + "/_"); // Make subscriptions. this.ecConnectionManager.registerEventPattern(bdplQuery); } catch (PrologException e) { this.unregisterEventPattern(bdplQuery.getDetails().getQueryId()); throw new DcepManagementException(e.getMessage()); } catch (EcConnectionmanagerException e) { this.unregisterEventPattern(bdplQuery.getDetails().getQueryId()); throw new DcepManagementException(e.getMessage()); } catch (Exception e) { this.unregisterEventPattern(bdplQuery.getDetails().getQueryId()); throw new DcepManagementException(e.getMessage()); } } @Override public BdplQuery getRegisteredEventPattern(String queryId) throws DcepManagementException { if (!init) { throw new IllegalStateException(this.getClass().getSimpleName() + " has not been initialized."); } if (this.registeredQueries.get(queryId) != null) { return this.registeredQueries.get(queryId); } else { throw new DcepManagementException("No event pattern is registered with id: " + queryId); } } @Override public Map<String, BdplQuery> getRegisteredEventPatterns() { if (!init) { throw new IllegalStateException(this.getClass().getSimpleName() + " has not been initialized."); } return this.registeredQueries; } @Override public void unregisterEventPattern(String queryId) { if (!init) { throw new IllegalStateException(this.getClass().getSimpleName() + " has not been initialized."); } if (this.registeredQueries.containsKey(queryId)) { logger.info("Removing event pattern at 'DistributedEtalis' Rule ID = " + queryId); try { etalis.removeDynamicRule(queryId); } catch (PrologException e) { logger.warn(String.format("Problem removing event pattern '%s': %s: %s", queryId, e.getClass().getSimpleName(), e.getMessage())); } this.ecConnectionManager.unregisterEventPattern(registeredQueries .get(queryId)); this.registeredQueries.remove(queryId); } else { logger.warn("Event pattern to be removed was not found at 'DistributedEtalis' Rule ID = " + queryId); } } @Override public NodeMeasurementResult getMeasuredData(String queryId) { if (!init) { throw new IllegalStateException(this.getClass().getSimpleName() + " has not been initialized."); } return measurementUnit.getMeasuringResults(); } @Override public void setConfig(Configuration configuration) throws DistributedEtalisException { configuration.configure(this); init = true; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Service getService() { return service; } public void setService(Service service) { this.service = service; } @Override public JtalisInputProvider getEventInputProvider() { return eventInputProvider; } @Override public void publish(CompoundEvent event) { eventInputProvider.notify(event); } @Override public void attach(SimplePublishApi subscriber) { logger.debug("New subscriber."); this.eventSinks.add(subscriber); } @Override public void detach(SimplePublishApi subscriber) { this.eventSinks.remove(subscriber); } @Override public void setEcConnectionManager(EcConnectionManager ecConnectionManager) { this.ecConnectionManager = ecConnectionManager; } @Override public void setEventOutputProvider(JtalisOutputProvider eventOutputProvider) { this.eventOutputProvider = eventOutputProvider; } @Override public void setEventInputProvider(JtalisInputProvider eventInputProvider) { this.eventInputProvider = eventInputProvider; } @Override public void setSemWebLib(PrologSemWebLib semWebLib) { this.semWebLib = semWebLib; } @Override public void setEtalis(JtalisContextImpl etalis) { this.etalis = etalis; } @Override public DistributedEtalis getDistributedEtalis(){ return this; } @Override public Map<String, BdplQuery> getRegisteredQueries() { return registeredQueries; } @Override public void setRegisteredQueries(Map<String, BdplQuery> registeredQueries) { this.registeredQueries = registeredQueries; } @Override public EcConnectionManager getEcConnectionManager() { return ecConnectionManager; } @Override public Set<SimplePublishApi> getEventSinks() { return eventSinks; } @Override public JtalisContextImpl getEtalis() { return etalis; } @Override public JtalisOutputProvider getEventOutputProvider() { return eventOutputProvider; } @Override public void measurePerformance(MeasurementConfig config) { if (!init) { throw new IllegalStateException(this.getClass().getSimpleName() + " has not been initialized."); } measurementUnit.startMeasurement(config.getMeasurementPeriod()); } @Override public void setMeasurementUnit(MeasurementUnit measurementUnit) { this.measurementUnit = measurementUnit; } }