/* * Copyright (c) 2015, 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.output.adapter.core.internal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.event.output.adapter.core.EventAdapterUtil; import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter; import org.wso2.carbon.event.output.adapter.core.exception.ConnectionUnavailableException; import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException; import java.util.Map; public class OutputAdapterRuntime { private static final Log log = LogFactory.getLog(OutputAdapterRuntime.class); private final OutputEventAdapter outputEventAdapter; private final String name; private volatile boolean connected = false; private final DecayTimer timer = new DecayTimer(); private volatile long nextConnectionTime; public OutputAdapterRuntime(OutputEventAdapter outputEventAdapter, String name) throws OutputEventAdapterException { this.outputEventAdapter = outputEventAdapter; this.name = name; synchronized (this) { outputEventAdapter.init(); // try { // outputEventAdapter.connect(); // connected = true; // } catch (ConnectionUnavailableException e) { // connected = false; // outputEventAdapter.disconnect(); // log.error("Error initializing connecting on " + this.name + ", reconnection will be tried on next event arrival.", e); // } catch (OutputEventAdapterRuntimeException e) { // connected = false; // outputEventAdapter.disconnect(); // log.error("Error initializing connecting on " + this.name + ", reconnection will be tried on next event arrival.", e); // } } } public void publish(Object message, Map<String, String> dynamicProperties) { try { try { if (connected) { outputEventAdapter.publish(message, dynamicProperties); } else { if (nextConnectionTime <= System.currentTimeMillis()) { synchronized (this) { if (!connected) { if (nextConnectionTime <= System.currentTimeMillis()) { outputEventAdapter.connect(); outputEventAdapter.publish(message, dynamicProperties); connected = true; timer.reset(); } else { logAndDrop(message); } } else { outputEventAdapter.publish(message, dynamicProperties); } } } else { logAndDrop(message); } } } catch (ConnectionUnavailableException e) { connected = false; if (nextConnectionTime <= System.currentTimeMillis()) { synchronized (this) { if (nextConnectionTime <= System.currentTimeMillis()) { outputEventAdapter.disconnect(); timer.incrementPosition(); nextConnectionTime = System.currentTimeMillis() + timer.returnTimeToWait(); if (timer.returnTimeToWait() == 0) { log.error("Connection unavailable for Output Adopter '" + name + "' reconnecting.", e); publish(message, dynamicProperties); } else { log.error("Connection unavailable for Output Adopter '" + name + "' reconnection will be retried in " + (timer.returnTimeToWait()) + " milliseconds.", e); } } else { logAndDrop(message); } } } else { logAndDrop(message); } } } catch (Throwable e) { EventAdapterUtil.logAndDrop(name, message, null, e, log, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId()); } } private void logAndDrop(Object message) { log.error("Event dropped, Output Adapter '" + name + "' suspended, Adapter will be active after " + (nextConnectionTime - System.currentTimeMillis()) + " milliseconds."); if (log.isDebugEnabled()) { log.debug("Output Adapter '" + name + "' suspended, dropping event: /n" + message + "/n"); } } public void destroy() { try { outputEventAdapter.disconnect(); } finally { outputEventAdapter.destroy(); } } public boolean isPolled() { return outputEventAdapter.isPolled(); } }