/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.flume.sink.rabbitmq;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.apache.flume.*;
import org.apache.flume.conf.Configurable;
import org.apache.flume.sink.AbstractSink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RabbitMQSink extends AbstractSink implements Configurable {
private static final Logger log = LoggerFactory.getLogger(RabbitMQSink.class);
private CounterGroup _CounterGroup;
private ConnectionFactory _ConnectionFactory;
private Connection _Connection;
private Channel _Channel;
private String _QueueName;
private String _ExchangeName;
public RabbitMQSink(){
_CounterGroup=new CounterGroup();
}
@Override
public void configure(Context context) {
_ConnectionFactory = RabbitMQUtil.getFactory(context);
_QueueName = RabbitMQUtil.getQueueName(context);
_ExchangeName= RabbitMQUtil.getExchangeName(context);
}
@Override
public synchronized void stop() {
RabbitMQUtil.close(_Connection, _Channel);
super.stop();
}
private void resetConnection(){
_CounterGroup.incrementAndGet(RabbitMQConstants.COUNTER_EXCEPTION);
if(log.isWarnEnabled())log.warn(this.getName() + " - Closing RabbitMQ connection and channel due to exception.");
RabbitMQUtil.close(_Connection, _Channel);
_Connection=null;
_Channel=null;
}
@Override
public Status process() throws EventDeliveryException {
if(null==_Connection){
try {
if(log.isInfoEnabled())log.info(this.getName() + " - Opening connection to " + _ConnectionFactory.getHost() + ":" + _ConnectionFactory.getPort());
_Connection = _ConnectionFactory.newConnection();
_CounterGroup.incrementAndGet(RabbitMQConstants.COUNTER_NEW_CONNECTION);
_Channel = null;
} catch(Exception ex) {
if(log.isErrorEnabled()) log.error(this.getName() + " - Exception while establishing connection.", ex);
resetConnection();
return Status.BACKOFF;
}
}
if(null==_Channel){
try {
if(log.isInfoEnabled())log.info(this.getName() + " - creating channel...");
_Channel = _Connection.createChannel();
_CounterGroup.incrementAndGet(RabbitMQConstants.COUNTER_NEW_CHANNEL);
if(log.isInfoEnabled())log.info(this.getName() + " - Connected to " + _ConnectionFactory.getHost() + ":" + _ConnectionFactory.getPort());
} catch(Exception ex) {
if(log.isErrorEnabled()) log.error(this.getName() + " - Exception while creating channel.", ex);
resetConnection();
return Status.BACKOFF;
}
}
Transaction tx = getChannel().getTransaction();
try {
tx.begin();
Event e = getChannel().take();
if(e==null){
tx.rollback();
return Status.BACKOFF;
}
try {
_Channel.basicPublish(_ExchangeName, _QueueName, null, e.getBody());
tx.commit();
_CounterGroup.incrementAndGet(RabbitMQConstants.COUNTER_PUBLISH);
} catch(Exception ex){
resetConnection();
throw ex;
}
return Status.READY;
} catch (Exception ex) {
tx.rollback();
if(log.isErrorEnabled())
log.error(this.getName() + " - Exception while publishing...", ex);
return Status.BACKOFF;
} finally {
tx.close();
}
}
}