Package com.ning.metrics.meteo.publishers

Source Code of com.ning.metrics.meteo.publishers.AMQSession

/*
* Copyright 2010-2013 Ning, Inc.
*
* Ning 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 com.ning.metrics.meteo.publishers;

import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.TimerMetric;
import org.apache.activemq.AlreadyClosedException;
import org.apache.activemq.ConnectionFailedException;
import org.apache.log4j.Logger;

import javax.jms.BytesMessage;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class AMQSession
{
    private static final Logger logger = Logger.getLogger(AMQSession.class);

    private static final Charset UTF8 = Charset.forName("UTF-8");

    private final TimerMetric timer;

    private final AMQPublisherConfig config;
    private final AMQConnection connection;
    private final String topic;
    private final AtomicBoolean isRunning = new AtomicBoolean(false);

    // Configuration flag that indicates we should use BytesMessage (not TextMessage)
    // for sending notifications
    private final AtomicBoolean useBytesMessage;

    private final Object sessionMonitor = new Object();
    private TopicSession session = null;
    private TopicPublisher publisher;

    public AMQSession(final AMQPublisherConfig config, final AMQConnection connection, final String topic,
                      final AtomicBoolean useBytesMessage)
    {
        this.config = config;
        this.connection = connection;
        this.topic = topic;
        this.useBytesMessage = useBytesMessage;

        timer = Metrics.newTimer(AMQSession.class, topic, TimeUnit.MILLISECONDS, TimeUnit.SECONDS);

        reinit();
    }

    public void close()
    {
        if (isRunning.get()) {
            synchronized (sessionMonitor) {
                isRunning.set(false);
                if (publisher != null) {
                    try {
                        publisher.close();
                    }
                    catch (JMSException ex) {
                        logger.warn(String.format("Got error while trying to close a producer for topic %s", topic), ex);
                    }
                    publisher = null;
                }
                if (session != null) {
                    try {
                        session.close();
                    }
                    catch (JMSException ex) {
                        logger.warn(String.format("Got error while trying to close a session for topic %s", topic), ex);
                    }
                    session = null;
                }
            }
        }
    }

    private void reinit()
    {
        final long startTime = System.currentTimeMillis();

        synchronized (sessionMonitor) {
            close();
            while (!isRunning.get()) {
                try {
                    session = connection.createTopicSession();
                    publisher = session.createPublisher(session.createTopic(topic));
                    publisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
                    publisher.setTimeToLive(config.getMessagesTTLMilliseconds());
                    isRunning.set(true);
                }
                catch (JMSException ex) {
                    logger.debug(String.format("Got error while trying to get a session for topic %s", topic));
                }
            }
        }

        final long secondsToRecreate = (System.currentTimeMillis() - startTime) / 1000;
        logger.info(String.format("Recreated topic [%s] in %d seconds", topic, secondsToRecreate));
    }

    private boolean shouldReinit(final JMSException ex)
    {
        return ex instanceof AlreadyClosedException ||
            ex instanceof javax.jms.IllegalStateException ||
            ex instanceof ConnectionFailedException ||
            ex.getCause() instanceof IOException;
    }

    public void send(final Object event)
    {
        if (isRunning.get()) {
            try {
                final long startTime = System.nanoTime();
                publisher.send(createMessage(event));
                timer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
            }
            catch (JMSException ex) {
                if (shouldReinit(ex)) {
                    reinit();
                }
                else {
                    logger.debug(String.format("Got error while trying to send a message to topic %s", topic));
                }
            }
        }
    }

    protected Message createMessage(final Object event) throws JMSException
    {
        final String eventStr = event.toString();
        if (useBytesMessage.get()) {
            final BytesMessage msg = session.createBytesMessage();
            msg.writeBytes(eventStr.getBytes(UTF8));
            return msg;
        }
        return session.createTextMessage(eventStr);
    }
}
TOP

Related Classes of com.ning.metrics.meteo.publishers.AMQSession

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.