Package cu.ftpd.user.userbases.changetracking

Source Code of cu.ftpd.user.userbases.changetracking.ChangeReceiver

package cu.ftpd.user.userbases.changetracking;

import cu.ftpd.logging.Logging;
import cu.ftpd.user.userbases.local.LocalUserbase;
import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.io.File;
import java.net.URI;

/**
* @author markus@jevring.net
*/
public class ChangeReceiver {
    private final ChangeApplicator changeApplicator;
    private final ChangeParser changeParser = new ChangeParser();
    /**
     * Indicates who this connection is with. This is used when filtering who to propagate the changes to.
     * Obviously, we don't want to propagate changes back to the sender.
     */
    private final String peer;
    private final String myName;
    private final URI broker;
    private final ChangeTracker changeTracker;
    private Connection connection;
    private Session session;
    private MessageConsumer consumer;

    // todo: who runs allotment when we propagate changes?
    // also, what do we do with allotment changes?

    public ChangeReceiver(URI broker, String peer, final String myName, ChangeTracker changeTracker, ChangeApplicator changeApplicator) {
        this.peer = peer;
        this.myName = myName;
        this.broker = broker;
        this.changeTracker = changeTracker;
        this.changeApplicator = changeApplicator;
    }

    public void start() throws JMSException {
        // todo: introduce username/password for the connection and the broker and the connection.

        // Here we can't use JNDI, as we'll be using the broker of the broker.
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(broker);
        connection = connectionFactory.createConnection();
        connection.setExceptionListener(new ExceptionListener() {
            @Override
            public void onException(JMSException exception) {
                Logging.getErrorLog().reportException(myName + ": " + exception.getMessage(), exception);
            }
        });

        session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        final Queue queue = session.createQueue("cu.mq.userbase." + myName);
        consumer = session.createConsumer(queue);
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                if (message instanceof TextMessage) {
                    String text = null;
                    try {
                        text = ((TextMessage) message).getText();
                        Change change = changeParser.parse(text, peer);
                        apply(change);
                        changeTracker.addChange(change); // propagate the change


                        // todo: use a ReentrantReadWriteLock for the userbase initialization.
                        // the normal updaters take read locks, but when someone needs to get a copy of the userbase,
                        // the sender can take a write lock to lock everybody out until it is done.
                    } catch (JMSException e) {
                        Logging.getErrorLog().reportException("Could not get body of userbase message", e);
                    } catch (RuntimeException e) {
                        // just in case something happens, we don't want to break everything
                        Logging.getErrorLog().reportException("Could not apply change: " + text, e);
                    }
                    try {
                        message.acknowledge(); // ideally we'd like some way of rolling back a change if we can't acknowledge because the host goes down
                    } catch (JMSException e) {
                        Logging.getErrorLog().reportException("Failed to acknowledge message regarding change. Possible userbase drift. Change was: " + text, e);
                    }
                }
            }
        });
        connection.start();
    }

    private void apply(Change change) {
        System.out.println("Received change: " + change);
        changeApplicator.apply(change);
    }

    public void stop() throws JMSException {
        consumer.close();
        session.close();
        connection.stop();
    }

    // todo: make a standalone server that does only this... (like the existing RMI server)

    public static void main(String[] args) {
        try {
            final AsynchronousMessageQueueChangeTracker changeTracker = new AsynchronousMessageQueueChangeTracker(URI.create("tcp://localhost:1800"), "master");
            final LocalUserbase userbase = new LocalUserbase(new File("c:/users/captain/desktop/receiver-data"), false, changeTracker);
            ChangeApplicator changeApplicator = new ChangeApplicator(userbase);
            changeTracker.addPeer("cuftpd", URI.create("failover:tcp://localhost:1700"), changeApplicator);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
TOP

Related Classes of cu.ftpd.user.userbases.changetracking.ChangeReceiver

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.