/* * Copyright (c) 2005 - 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package org.wso2.carbon.event.receiver.core.internal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.Logger; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.databridge.commons.Event; import org.wso2.carbon.databridge.commons.StreamDefinition; import org.wso2.carbon.event.input.adapter.core.InputEventAdapterSubscription; import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException; import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException; import org.wso2.carbon.event.processor.manager.core.EventManagementUtil; import org.wso2.carbon.event.processor.manager.core.EventSync; import org.wso2.carbon.event.processor.manager.core.Manager; import org.wso2.carbon.event.processor.manager.core.config.DistributedConfiguration; import org.wso2.carbon.event.processor.manager.core.config.HAConfiguration; import org.wso2.carbon.event.processor.manager.core.config.Mode; import org.wso2.carbon.event.receiver.core.InputMapper; import org.wso2.carbon.event.receiver.core.config.EventReceiverConfiguration; import org.wso2.carbon.event.receiver.core.config.EventReceiverConstants; import org.wso2.carbon.event.receiver.core.exception.EventReceiverConfigurationException; import org.wso2.carbon.event.receiver.core.exception.EventReceiverProcessingException; import org.wso2.carbon.event.receiver.core.internal.ds.EventReceiverServiceValueHolder; import org.wso2.carbon.event.receiver.core.internal.management.AbstractInputEventDispatcher; import org.wso2.carbon.event.receiver.core.internal.management.InputEventDispatcher; import org.wso2.carbon.event.receiver.core.internal.management.QueueInputEventDispatcher; import org.wso2.carbon.event.receiver.core.internal.util.EventReceiverUtil; import org.wso2.carbon.event.receiver.core.internal.util.helper.EventReceiverConfigurationHelper; import org.wso2.carbon.event.stream.core.EventProducer; import org.wso2.carbon.event.stream.core.EventProducerCallback; import org.wso2.carbon.metrics.manager.Counter; import org.wso2.carbon.metrics.manager.Level; import org.wso2.carbon.metrics.manager.MetricManager; import java.util.List; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; public class EventReceiver implements EventProducer { private static final Log log = LogFactory.getLog(EventReceiver.class); private boolean isEventDuplicatedInCluster; private boolean traceEnabled = false; private boolean statisticsEnabled = false; private Counter eventCounter; private boolean customMappingEnabled = false; private boolean isWorkerNode = false; private boolean sufficientToSend = false; private Logger trace = Logger.getLogger(EventReceiverConstants.EVENT_TRACE_LOGGER); private EventReceiverConfiguration eventReceiverConfiguration = null; private StreamDefinition exportedStreamDefinition; private InputMapper inputMapper = null; private String beforeTracerPrefix; private String afterTracerPrefix; private AbstractInputEventDispatcher inputEventDispatcher; private Mode mode; // private volatile AtomicLong totalLatency = new AtomicLong(); // private volatile AtomicLong totalEvents = new AtomicLong(); // private double elapseCount = 10000; // private long tempstartTime = System.currentTimeMillis(); public EventReceiver(EventReceiverConfiguration eventReceiverConfiguration, StreamDefinition exportedStreamDefinition, Mode mode) throws EventReceiverConfigurationException { this.eventReceiverConfiguration = eventReceiverConfiguration; int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); if (this.eventReceiverConfiguration != null) { this.traceEnabled = eventReceiverConfiguration.isTraceEnabled(); this.statisticsEnabled = eventReceiverConfiguration.isStatisticsEnabled() && EventReceiverServiceValueHolder.isGlobalStatisticsEnabled(); this.customMappingEnabled = eventReceiverConfiguration.getInputMapping().isCustomMappingEnabled(); String mappingType = this.eventReceiverConfiguration.getInputMapping().getMappingType(); this.inputMapper = EventReceiverServiceValueHolder.getMappingFactoryMap().get(mappingType) .constructInputMapper(this.eventReceiverConfiguration, exportedStreamDefinition); String metricId = EventReceiverConstants.METRICS_ROOT + EventReceiverConstants.METRIC_DELIMITER + EventReceiverConstants.METRICS_EVENT_RECEIVERS + EventReceiverConstants.METRIC_AGGREGATE_ANNOTATION + EventReceiverConstants.METRIC_DELIMITER + eventReceiverConfiguration.getEventReceiverName() + EventReceiverConstants.METRIC_DELIMITER + EventReceiverConstants.METRICS_RECEIVED_EVENTS; // The input mapper should not be null. For configurations where custom mapping is disabled, // an input mapper would be created without the mapping details. if (this.inputMapper != null) { if (customMappingEnabled) { EventReceiverConfigurationHelper.validateExportedStream( eventReceiverConfiguration, exportedStreamDefinition, this.inputMapper); } this.exportedStreamDefinition = exportedStreamDefinition; } else { throw new EventReceiverConfigurationException("Could not create input mapper for mapping type " + mappingType + " for event receiver :" + eventReceiverConfiguration.getEventReceiverName()); } // Initialize tracer and statistics. if (statisticsEnabled) { this.eventCounter = MetricManager.counter(metricId, Level.INFO, Level.INFO); } if (traceEnabled) { this.beforeTracerPrefix = "TenantId : " + tenantId + ", " + EventReceiverConstants.EVENT_RECEIVER + " : " + eventReceiverConfiguration.getEventReceiverName() + ", before processing " + System.getProperty("line.separator"); this.afterTracerPrefix = "TenantId : " + tenantId + ", " + EventReceiverConstants.EVENT_RECEIVER + " : " + eventReceiverConfiguration.getEventReceiverName() + ", " + EventReceiverConstants.EVENT_STREAM + " : " + EventReceiverUtil.getExportedStreamIdFrom(eventReceiverConfiguration) + ", after processing " + System.getProperty("line.separator"); } String inputEventAdapterName = eventReceiverConfiguration.getFromAdapterConfiguration().getName(); try { InputEventAdapterSubscription inputEventAdapterSubscription; if (this.customMappingEnabled) { inputEventAdapterSubscription = new MappedEventSubscription(); } else { inputEventAdapterSubscription = new TypedEventSubscription(); } EventReceiverServiceValueHolder.getInputEventAdapterService().create( eventReceiverConfiguration.getFromAdapterConfiguration(), inputEventAdapterSubscription); isEventDuplicatedInCluster = EventReceiverServiceValueHolder.getInputEventAdapterService() .isEventDuplicatedInCluster(eventReceiverConfiguration.getFromAdapterConfiguration().getName()); DistributedConfiguration distributedConfiguration = EventReceiverServiceValueHolder .getEventManagementService().getManagementModeInfo().getDistributedConfiguration(); if (distributedConfiguration != null) { this.isWorkerNode = distributedConfiguration.isWorkerNode(); } sufficientToSend = mode != Mode.Distributed || (isWorkerNode && !isEventDuplicatedInCluster); } catch (InputEventAdapterException e) { throw new EventReceiverConfigurationException("Cannot subscribe to input event adapter :" + inputEventAdapterName + ", error in configuration. " + e.getMessage(), e); } catch (InputEventAdapterRuntimeException e) { throw new EventReceiverProcessingException("Cannot subscribe to input event adapter :" + inputEventAdapterName + ", error while connecting by adapter. " + e.getMessage(), e); } this.mode = mode; if (mode == Mode.HA) { HAConfiguration haConfiguration = EventReceiverServiceValueHolder.getEventManagementService() .getManagementModeInfo().getHaConfiguration(); Lock readLock = EventReceiverServiceValueHolder.getCarbonEventReceiverManagementService().getReadLock(); inputEventDispatcher = new QueueInputEventDispatcher(tenantId, EventManagementUtil.constructEventSyncId(tenantId, eventReceiverConfiguration.getEventReceiverName(), Manager.ManagerType.Receiver), readLock, exportedStreamDefinition, haConfiguration.getEventSyncReceiverMaxQueueSizeInMb(), haConfiguration.getEventSyncReceiverQueueSize()); inputEventDispatcher.setSendToOther(!isEventDuplicatedInCluster); EventReceiverServiceValueHolder.getEventManagementService() .registerEventSync((EventSync) inputEventDispatcher, Manager.ManagerType.Receiver); } else { inputEventDispatcher = new InputEventDispatcher(); } if (mode == Mode.HA && isEventDuplicatedInCluster) { EventReceiverServiceValueHolder.getInputEventAdapterService().start(inputEventAdapterName); } } } /** * Returns the stream definition that is exported by this event receiver. * This stream definition will available to any object that consumes the event receiver service * (e.g. EventProcessors) * * @return the {@link StreamDefinition} of the stream that will be * sending out events from this event receiver */ public StreamDefinition getExportedStreamDefinition() { return exportedStreamDefinition; } /** * Returns the event receiver configuration associated with this event receiver * * @return the {@link EventReceiverConfiguration} instance */ public EventReceiverConfiguration getEventReceiverConfiguration() { return this.eventReceiverConfiguration; } protected void processMappedEvent(Object object) { if (traceEnabled) { trace.info(beforeTracerPrefix + object.toString()); } if (object instanceof List) { for (Object obj : (List) object) { try { processMappedEvent(obj); } catch (EventReceiverProcessingException e) { log.error("Dropping event. Error processing event : ", e); } } } else { try { Object convertedEvent = this.inputMapper.convertToMappedInputEvent(object); if (convertedEvent != null) { if (convertedEvent instanceof Event[]) { Event[] arrayOfEvents = (Event[]) convertedEvent; for (Event event : arrayOfEvents) { if (event != null) { sendEvent(event); } } } else { sendEvent((Event) convertedEvent); } } else { log.warn("Dropping the empty/null event, Event does not match with mapping"); } } catch (EventReceiverProcessingException e) { log.error("Dropping event. Error processing event : ", e); } catch (RuntimeException e) { log.error("Dropping event. Unexpected error while processing event : " + e.getMessage(), e); } } } protected void processTypedEvent(Object obj) { if (traceEnabled) { trace.info(beforeTracerPrefix + obj.toString()); } if (obj instanceof List) { for (Object object : (List) obj) { try { processTypedEvent(object); } catch (EventReceiverProcessingException e) { log.error("Dropping event. Error processing event: " + e.getMessage(), e); } } } else { try { Object convertedEvent = this.inputMapper.convertToTypedInputEvent(obj); if (convertedEvent != null) { if (convertedEvent instanceof Event[]) { Event[] arrayOfEvents = (Event[]) convertedEvent; for (Event event : arrayOfEvents) { if (event != null) { sendEvent(event); } } } else { sendEvent((Event) convertedEvent); } } } catch (EventReceiverProcessingException e) { log.error("Dropping event. Error processing event: " + e.getMessage(), e); } } } protected void sendEvent(Event event) { if (traceEnabled) { trace.info(afterTracerPrefix + event); } if (statisticsEnabled) { eventCounter.inc(); } // // long timestamp = event.getTimeStamp(); // long currentTimestamp = System.currentTimeMillis(); // event.setTimeStamp(currentTimestamp); // long eventLatency = currentTimestamp - timestamp; // totalLatency.addAndGet(eventLatency); // totalEvents.incrementAndGet(); // if (totalEvents.get() % elapseCount == 0) { // double avgLatency = (totalLatency.get() * 1.0) / elapseCount; // double throughput = ((elapseCount * 1.0) / (currentTimestamp - tempstartTime + 0.0)) * 1000; // // log.info("Received " + elapseCount + " events with a throughput of " + throughput + // " events per second || and latency: " + avgLatency); // tempstartTime = currentTimestamp; // totalLatency.set(0); // } // In distributed mode if events are duplicated in cluster, send event only if the node is receiver coordinator. // Also do not send if this is a manager node. if (sufficientToSend || EventReceiverServiceValueHolder.getCarbonEventReceiverManagementService().isReceiverCoordinator()) { this.inputEventDispatcher.onEvent(event); } } public AbstractInputEventDispatcher getInputEventDispatcher() { return inputEventDispatcher; } /* protected void defineEventStream(Object definition) throws EventReceiverConfigurationException { if (log.isDebugEnabled()) { log.debug("EventReceiver: " + eventReceiverConfiguration.getEventReceiverName() + ", notifying event definition addition :" + definition.toString()); } if (definition instanceof StreamDefinition) { StreamDefinition inputStreamDefinition = (StreamDefinition) definition; String mappingType = eventReceiverConfiguration.getInputMapping().getMappingType(); this.inputMapper = EventReceiverServiceValueHolder.getMappingFactoryMap().get(mappingType) .constructInputMapper(eventReceiverConfiguration, exportedStreamDefinition); } } protected void removeEventStream(Object definition) { if (log.isDebugEnabled()) { log.debug("EventReceiver: " + eventReceiverConfiguration.getEventReceiverName() + ", notifying event definition addition :" + definition.toString()); } this.inputMapper = null; } */ @Override public String getStreamId() { return exportedStreamDefinition.getStreamId(); } @Override public void setCallBack(EventProducerCallback callBack) { this.inputEventDispatcher.setCallBack(callBack); } public void destroy() { EventReceiverServiceValueHolder.getInputEventAdapterService() .destroy(eventReceiverConfiguration.getFromAdapterConfiguration().getName()); if (mode == Mode.HA && inputEventDispatcher instanceof EventSync) { EventReceiverServiceValueHolder.getEventManagementService().unregisterEventSync( ((EventSync) inputEventDispatcher).getStreamDefinition().getStreamId(), Manager.ManagerType.Receiver); } } public boolean isEventDuplicatedInCluster() { return isEventDuplicatedInCluster; } private class MappedEventSubscription implements InputEventAdapterSubscription { @Override public void onEvent(Object o) { processMappedEvent(o); } } private class TypedEventSubscription implements InputEventAdapterSubscription { @Override public void onEvent(Object o) { processTypedEvent(o); } } }