org.mule.modules.loggly.async.AsyncWorkManager.java Source code

Java tutorial

Introduction

Here is the source code for org.mule.modules.loggly.async.AsyncWorkManager.java

Source

/**
 * Mule Loggly Connector
 *
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package org.mule.modules.loggly.async;

import org.apache.commons.collections.Buffer;
import org.apache.commons.collections.BufferUnderflowException;
import org.apache.commons.collections.buffer.CircularFifoBuffer;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class AsyncWorkManager implements WorkManager {
    private static final Logger LOGGER = Logger.getLogger(AsyncWorkManager.class);
    public static final long PATIENCE = 300;

    private final Buffer buffer;

    private Thread thread;

    private String inputKey;
    private String inputsURL;
    private String tags;

    private ReentrantReadWriteLock lock;

    private volatile boolean end = false;

    public AsyncWorkManager(String inputsURL, String inputKey, String tags) {
        this.buffer = new CircularFifoBuffer();
        this.inputKey = inputKey;
        this.inputsURL = inputKey;
        this.tags = tags;

        lock = new ReentrantReadWriteLock();

        thread = new Thread(new MessageConsumer());
        thread.start();
    }

    @Override
    public void send(String message) throws InterruptedException {
        if (lock.writeLock().tryLock()) {
            try {
                this.buffer.add(message);
            } finally {
                lock.writeLock().unlock();
            }
        } else {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Unable to get a hold of a write lock");
            }
        }
    }

    @Override
    public void stop() {
        end = true;

        LOGGER.debug("Waiting for MessageLoop thread to finish");
        if (thread.isAlive()) {

            try {
                thread.join(PATIENCE);
            } catch (InterruptedException e) {
                LOGGER.error(e);
            }

            LOGGER.debug("Still waiting...");
            if (thread.isAlive()) {
                thread.interrupt();
            }
        }
        LOGGER.debug("Finally!");
    }

    private class MessageConsumer implements Runnable {
        /*
        * We are using a different HttpClient in order to avoid
        * concurrency issues with the rest of the Loggly RestCall API.
        */
        private HttpClient httpClient = new HttpClient();

        @Override
        public void run() {
            while (!end) {
                int i = -1;
                try {
                    String message = null;
                    if (lock.readLock().tryLock()) {
                        try {
                            message = (String) buffer.get();
                        } finally {
                            lock.readLock().unlock();
                        }
                    } else {
                        Thread.sleep(100);
                    }

                    if (message != null) {
                        RequestEntity entity;
                        entity = new StringRequestEntity(message, "application/text", "UTF-8");

                        /* Tried to recycle the PostMethod but that kind of usage
                         * is deprecated.
                         */

                        String URI = inputsURL + inputKey + "/" + tags;
                        LOGGER.error("Using URL " + URI);
                        PostMethod postMethod = new PostMethod(inputsURL + inputKey + "/" + tags);
                        postMethod.setRequestEntity(entity);

                        try {
                            i = httpClient.executeMethod(postMethod);
                        } catch (HttpException e) {
                            LOGGER.error(e);
                        } catch (IOException e) {
                            LOGGER.error(e);
                        } finally {
                            postMethod.releaseConnection();
                        }

                        /* Log only when no 2xx HTTP status codes was returned */
                        if (i - 200 > 100 || i - 200 < 0) {
                            LOGGER.error("Message [" + message + "] logged with HTTP Status code " + i + ".");
                        } else {
                            if (lock.writeLock().tryLock()) {
                                try {
                                    buffer.remove();
                                } finally {
                                    lock.writeLock().unlock();
                                }
                            } else {
                                Thread.sleep(100);
                            }
                        }
                    }
                } catch (BufferUnderflowException bue) {
                    //LOGGER.error(bue);
                    // do nothing
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        return;
                    }
                } catch (UnsupportedEncodingException e) {
                    LOGGER.error(e);
                } catch (InterruptedException e) {
                    return;
                }

            }

        }
    }
}