All Downloads are FREE. Search and download functionalities are using the official Maven repository.

co.edu.uniquindio.chord.node.NodeEnvironment Maven / Gradle / Ivy

There is a newer version: 2.0.2
Show newest version
/*
 *  Chord project implement of lookup algorithm Chord
 *  Copyright (C) 2010 - 2018  Daniel Pelaez
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see .
 *
 */

package co.edu.uniquindio.chord.node;

import co.edu.uniquindio.chord.ChordKey;
import co.edu.uniquindio.chord.protocol.Protocol;
import co.edu.uniquindio.chord.protocol.Protocol.*;
import co.edu.uniquindio.overlay.Key;
import co.edu.uniquindio.overlay.KeyFactory;
import co.edu.uniquindio.utils.communication.message.Address;
import co.edu.uniquindio.utils.communication.message.Message;
import co.edu.uniquindio.utils.communication.message.Message.SendType;
import co.edu.uniquindio.utils.communication.message.SequenceGenerator;
import co.edu.uniquindio.utils.communication.transfer.CommunicationManager;
import co.edu.uniquindio.utils.communication.transfer.MessageProcessor;
import org.apache.log4j.Logger;

import java.math.BigInteger;

/**
 * The NodeEnvironment class is the node responsible for handling
 * with the messages. This class is notified when a message arrives and decides
 * what the chord node must do. This class also initializes and starts the
 * {@link StableRing} of the node.
 *
 * @author Daniel Pelaez
 * @author Hector Hurtado
 * @author Daniel Lopez
 * @version 1.0, 17/06/2010
 * @see ChordNode
 * @since 1.0
 */
class NodeEnvironment implements MessageProcessor {

    /**
     * Logger
     */
    private static final Logger logger = Logger
            .getLogger(NodeEnvironment.class);

    /**
     * Communication manager
     */
    private final CommunicationManager communicationManager;

    /**
     * Defines if an arrive message must be process.
     */
    private boolean process = true;

    /**
     * The reference of the chord node.
     */
    private final ChordNode chordNode;

    /**
     * The thread that uses the commands for stabilizing the node.
     */
    private final KeyFactory keyFactory;
    private final SequenceGenerator sequenceGenerator;

    NodeEnvironment(CommunicationManager communicationManager, ChordNode chordNode, KeyFactory keyFactory, SequenceGenerator sequenceGenerator) {
        this.communicationManager = communicationManager;
        this.chordNode = chordNode;
        this.keyFactory = keyFactory;
        this.sequenceGenerator = sequenceGenerator;
    }

    @Override
    /**
     * This method is called when a new message has arrived.
     *
     * @param message  The income message.
     */
    public Message process(Message message) {

        logger.debug("Message to '" + chordNode.getKey().getValue() + "', ["
                + message.toString());

        Message response = null;

        /*
         * Discards the message that comes if process==false
         */
        if (!process) {
            return null;
        }

        if (message.getMessageType().equals(Protocol.LOOKUP)) {
            response = processLookUp(message);
        }
        if (message.getMessageType().equals(Protocol.PING)) {
            response = processPing(message);
        }
        if (message.getMessageType().equals(Protocol.NOTIFY)) {
            response = processNotify(message);
        }
        if (message.getMessageType().equals(Protocol.GET_PREDECESSOR)) {
            response = processGetPredecessor(message);
        }
        if (message.getMessageType().equals(Protocol.BOOTSTRAP)) {
            response = processBootStrap(message);
        }
        if (message.getMessageType().equals(Protocol.SET_PREDECESSOR)) {
            response = processSetPredecessor(message);
        }
        if (message.getMessageType().equals(Protocol.SET_SUCCESSOR)) {
            response = processSetSuccessor(message);
        }
        if (message.getMessageType().equals(Protocol.GET_SUCCESSOR_LIST)) {
            response = processGetSuccessorList(message);
        }

        return response;

    }

    /**
     * Process message of type is GET_SUCCESSOR_LIST
     *
     * @param message Message GET_SUCCESSOR_LIST
     */
    private Message processGetSuccessorList(Message message) {
        String successorList;
        Message getSuccesorListResponseMessage;

        successorList = chordNode.getSuccessorList().toString();

        getSuccesorListResponseMessage = Message.builder()
                .sequenceNumber(message.getSequenceNumber())
                .sendType(SendType.RESPONSE)
                .messageType(Protocol.GET_SUCCESSOR_LIST_RESPONSE)
                .address(Address.builder()
                        .destination(message.getAddress().getSource())
                        .source(chordNode.getKey().getValue())
                        .build())
                .param(GetSuccessorListResponseParams.SUCCESSOR_LIST.name(), successorList)
                .build();

        return getSuccesorListResponseMessage;
    }

    /**
     * Process message of type is SET_SUCCESSOR
     *
     * @param message Message SET_SUCCESSOR
     */
    private Message processSetSuccessor(Message message) {
        ChordKey nodeSucessor;

        nodeSucessor = (ChordKey) keyFactory.newKey(message.getParam(SetSuccessorParams.SUCCESSOR
                .name()));

        chordNode.setSuccessor(nodeSucessor);

        return null;
    }

    /**
     * Process message of type is SET_PREDECESSOR
     *
     * @param message Message SET_PREDECESSOR
     */
    private Message processSetPredecessor(Message message) {
        ChordKey nodePredecessor;

        nodePredecessor = (ChordKey) keyFactory.newKey(message
                .getParam(SetPredecessorParams.PREDECESSOR.name()));

        chordNode.setPredecessor(nodePredecessor);

        return null;
    }

    /**
     * Process message of type is LEAVE
     *
     * @param message Message LEAVE
     */
    private Message processLeave(Message message) {

        Message setSuccessorMessage;
        Message setPredecessorMessage;

        process = false;

        if (!chordNode.getSuccessor().equals(chordNode.getKey())) {

            setSuccessorMessage = Message.builder()
                    .sequenceNumber(sequenceGenerator.getSequenceNumber())
                    .sendType(SendType.REQUEST)
                    .messageType(Protocol.SET_SUCCESSOR)
                    .address(Address.builder()
                            .destination(chordNode.getPredecessor().getValue())
                            .source(chordNode.getKey().getValue())
                            .build())
                    .param(SetSuccessorParams.SUCCESSOR.name(), chordNode.getSuccessor().getValue())
                    .build();

            communicationManager.sendMessageUnicast(setSuccessorMessage);

            setPredecessorMessage = Message.builder()
                    .sequenceNumber(sequenceGenerator.getSequenceNumber())
                    .sendType(SendType.REQUEST)
                    .messageType(Protocol.SET_PREDECESSOR)
                    .address(Address.builder()
                            .destination(chordNode.getSuccessor().getValue())
                            .source(chordNode.getKey().getValue())
                            .build())
                    .param(SetPredecessorParams.PREDECESSOR.name(), chordNode.getPredecessor().toString())
                    .build();

            communicationManager.sendMessageUnicast(setPredecessorMessage);
        }

        communicationManager.removeMessageProcessor(this.chordNode.getKey().getValue());

        return null;
    }

    /**
     * Process message of type is BOOTSTRAP
     *
     * @param message Message BOOTSTRAP
     */
    private Message processBootStrap(Message message) {

        Message bootstrapResponseMessage = null;

        if (message.getAddress().getSource().equals(chordNode.getKey().getValue())) {
            return bootstrapResponseMessage;
        }

        bootstrapResponseMessage = Message.builder()
                .sequenceNumber(message.getSequenceNumber())
                .sendType(SendType.RESPONSE)
                .messageType(Protocol.BOOTSTRAP_RESPONSE)
                .address(Address.builder()
                        .destination(message.getAddress().getSource())
                        .source(chordNode.getKey().getValue())
                        .build())
                .param(BootStrapResponseParams.NODE_FIND.name(), chordNode.getKey().toString())
                .build();

        return bootstrapResponseMessage;
    }

    /**
     * Process message of type is GET_PREDECESSOR
     *
     * @param message Message GET_PREDECESSOR
     */
    private Message processGetPredecessor(Message message) {

        Message.MessageBuilder getPredecessorResponseMessage;

        getPredecessorResponseMessage = Message.builder()
                .sequenceNumber(message.getSequenceNumber())
                .sendType(SendType.RESPONSE)
                .messageType(Protocol.GET_PREDECESSOR_RESPONSE)
                .address(Address.builder()
                        .destination(message.getAddress().getSource())
                        .source(chordNode.getKey().getValue())
                        .build());

        if (chordNode.getPredecessor() == null) {
            getPredecessorResponseMessage.param(GetPredecessorResponseParams.PREDECESSOR.name(), null);
        } else {
            getPredecessorResponseMessage.param(GetPredecessorResponseParams.PREDECESSOR.name(), chordNode
                    .getPredecessor().toString());
        }

        return getPredecessorResponseMessage.build();
    }

    /**
     * Process message of type is NOTIFY
     *
     * @param message Message NOTIFY
     */
    private Message processNotify(Message message) {
        if (!message.isMessageFromMySelf()) {
            ChordKey node;

            node = (ChordKey) keyFactory.newKey(message.getAddress().getSource());

            chordNode.notify(node);
        }
        return null;
    }

    /**
     * Process message of type is PING
     *
     * @param message Message PING
     */
    private Message processPing(Message message) {

        Message pingMessage;

        pingMessage = Message.builder()
                .sequenceNumber(message.getSequenceNumber())
                .sendType(SendType.RESPONSE)
                .messageType(Protocol.PING_RESPONSE)
                .address(Address.builder()
                        .destination(message.getAddress().getSource())
                        .source(chordNode.getKey().getValue())
                        .build())
                .param(PingResponseParams.PING.name(), Boolean.TRUE.toString())
                .build();

        return pingMessage;
    }

    /**
     * Process message of type is LOOKUP
     *
     * @param message Message LOOKUP
     */
    private Message processLookUp(Message message) {

        Message.MessageBuilder lookupResponseMessage;

        lookupResponseMessage = Message.builder()
                .sequenceNumber(message.getSequenceNumber())
                .sendType(SendType.RESPONSE)
                .messageType(Protocol.LOOKUP_RESPONSE)
                .address(Address.builder()
                        .destination(message.getAddress().getSource())
                        .source(chordNode.getKey().getValue())
                        .build())
                .param(LookupResponseParams.TYPE.name(), message.getParam(LookupParams.TYPE.name()));

        /* Discards the message that comes from the same node */
        if (message.isMessageFromMySelf()) {
            lookupResponseMessage.param(LookupResponseParams.NODE_FIND
                    .name(), chordNode.getKey().toString());

        } else {

            ChordKey response;
            ChordKey id;

            id = (ChordKey) keyFactory.newKey(new BigInteger(message.getParam(LookupParams.HASHING
                    .name())));

            response = chordNode.findSuccessor(id, LookupType.valueOf(message
                    .getParam(LookupParams.TYPE.name())));

            if (response == null) {
                lookupResponseMessage.param(LookupResponseParams.NODE_FIND
                        .name(), chordNode.getKey().toString());
            } else {
                lookupResponseMessage.param(LookupResponseParams.NODE_FIND
                        .name(), response.toString());
            }

        }

        return lookupResponseMessage.build();
    }

    /**
     * Gets the reference of the chordNode
     *
     * @return The {@link ChordNode} reference
     */
    public ChordNode getChordNode() {
        return chordNode;
    }

    /**
     * Gets chord node name from key value
     */
    /*public String getName() {
        return chordNode.getKey().getValue();
    }*/

    void setProcess(boolean process) {
        this.process = process;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy