Package lupos.event.broker.distributed

Source Code of lupos.event.broker.distributed.MasterBroker

/**
* Copyright (c) 2013, Institute of Information Systems (Sven Groppe and contributors of LUPOSDATE), University of Luebeck
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
*   - Redistributions of source code must retain the above copyright notice, this list of conditions and the following
*     disclaimer.
*   - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
*     following disclaimer in the documentation and/or other materials provided with the distribution.
*   - Neither the name of the University of Luebeck nor the names of its contributors may be used to endorse or promote
*     products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lupos.event.broker.distributed;

import java.io.IOException;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;

import lupos.event.broker.distributed.model.BConsumer;
import lupos.event.broker.distributed.model.BProducer;
import lupos.event.broker.distributed.model.SubBrokerData;
import lupos.event.communication.BrokerNetworkUpdateMessage;
import lupos.event.communication.BrokerUpdateMessage;
import lupos.event.communication.BrokerUpdateMessageCollector;
import lupos.event.communication.IDisconnectedHandler;
import lupos.event.communication.IMessageReceivedHandler;
import lupos.event.communication.ConnectionRequest;
import lupos.event.communication.ModelUpdateMessage;
import lupos.event.communication.SerializingMessageService;
import lupos.event.communication.TcpConnectInfo;
import lupos.event.communication.TcpMessageTransport;

/**
* This class represents the single master broker which
* only handles management of severeal connecting producers,
* brokers and consumers
* @author Kevin
*
*/
public class MasterBroker implements IMessageReceivedHandler<Serializable>, Runnable, IDisconnectedHandler{

  private Hashtable<Integer, SubBrokerData> subBrokers;
 
  private boolean threadToggle = false;
 
  public MasterBroker(){
    this.subBrokers = new Hashtable<Integer, SubBrokerData>();
  }
 
  private void start() throws Exception{
    new Thread(this).start();
    System.out.println("Master Broker started. Waiting for incoming services...");
    while (true){
      // create communication endpoint and wait for an incoming connection
      SerializingMessageService msgService = new SerializingMessageService(TcpMessageTransport.class);
      msgService.addHandler2(this);
      msgService.waitForConnection();
     
    }
  }
 
  /**
   * This thread method is the main calculating thread
   * in this master broker which does all networking
   * updates
   */
  @Override
  public void run(){
    while (true){
      if (this.threadToggle){
        // send forwarding table to all subbrokers
        updateBrokerNetwork();
        this.threadToggle = false;
      } else{
        // Drop disconnected brokers
        updateConnectedBrokers();
        // look for connection network
        distributeConsumers();
        this.threadToggle = true;
      }
      try{
        // this sleep or in general this thread
        // could be optimized for faster reaction times
        Thread.sleep(4000);
      } catch (InterruptedException ie){
        System.err.println("Warning: MasterBroker - Sleep time has been interrupted");
      }
    }
  }
 
  /**
   * Iterates through all sub brokers and
   * pings them with a dummy message to
   * force a disconnected()-call on this broker
   */
  private void updateConnectedBrokers(){
    for (SubBrokerData subBroker : this.subBrokers.values()){
      try {
        subBroker.getMessageService().sendMessage(0);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
 
  /**
   * updates Broker Network connections
   */
  private void updateBrokerNetwork(){   
    for(SubBrokerData sub : this.subBrokers.values()){
      Hashtable<String, List<TcpConnectInfo>> table = new Hashtable<String, List<TcpConnectInfo>>();
      for(String produced : sub.getProducedEvents()){
        List<TcpConnectInfo> receiverBroker = new LinkedList<TcpConnectInfo>();
        for(SubBrokerData sub2 : this.subBrokers.values()){
          if(!sub.equals(sub2)){
            for(String consumed : sub2.getConsumedEvents()){
              if(produced.equals(consumed)){
                receiverBroker.add(sub2.getMessageService().getConnectionInfo());
              }
            }
          }
        }
        table.put(produced, receiverBroker);
      }
      BrokerNetworkUpdateMessage bnum = new BrokerNetworkUpdateMessage(table);
      try {
        sub.getMessageService().sendMessage(bnum);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    System.out.println("Sent a network update to all SubBrokers");
  }
 
  /**
   * Gets the connection info for a requesting producer
   * to connect to a appropriate sub broker
   * @return connection info to the free or least used broker
   */
  private TcpConnectInfo getProducerConnectBroker(){
   
    int temp = Integer.MAX_VALUE;
    SubBrokerData broker = null;
    for (SubBrokerData subBroker : this.subBrokers.values()){
      int size = subBroker.getRegisteredProducers().size();
      if(size<temp){
        temp = size;
        broker = subBroker; 
      }
    }
   
    return broker.getMessageService().getConnectionInfo();
  }
 
  public static void main(String[] args){
    MasterBroker master = new MasterBroker();
    try{
      master.start();
    } catch (Exception e){
      e.printStackTrace();
    }
  }

  @Override
  public void messageReceived(Object src, Serializable msg) {
    if (msg instanceof ConnectionRequest){
      SerializingMessageService msgService = (SerializingMessageService) src;
      msgService.setConnectionPort(((ConnectionRequest)msg).getPort());
     
      switch (((ConnectionRequest) msg).getRequestType()){
     
      case ConnectionRequest.REQUESTTYPE_PRODUCER:
        TcpConnectInfo tcpInfo = getProducerConnectBroker();
        try {
          msgService.sendMessage(tcpInfo);
          System.out.println("Producer redirected to "+tcpInfo.getHost()+":"+tcpInfo.getPort());
        } catch (IOException e) {
          e.printStackTrace();
        }
        break;
       
      case ConnectionRequest.REQUESTTYPE_BROKER:
        // put this sub broker in a hashtable
        SubBrokerData subBroker = new SubBrokerData(msgService);
        this.subBrokers.put(subBroker.getID(), subBroker);
        subBroker.getMessageService().addDisconnectHandler(this);
        System.out.println("Registered a SubBroker connection: "+msgService.getConnectionInfo().getHost()+":"+msgService.getConnectionInfo().getPort());
       
        break;
       
      case ConnectionRequest.REQUESTTYPE_CONSUMER:
        TcpConnectInfo tcpInfo2 = getConsumerConnectBroker();
        try {
          msgService.sendMessage(tcpInfo2);
          System.out.println("Consumer redirected to "+tcpInfo2.getHost()+":"+tcpInfo2.getPort());
        } catch (IOException e) {
          e.printStackTrace();
        }
        break
      }
     
    }
   
    else if (msg instanceof ModelUpdateMessage){
      TcpConnectInfo tcpInfo = ((SerializingMessageService)src).getConnectionInfo();
      SubBrokerData subBroker = null;
      for (SubBrokerData sub : this.subBrokers.values()){
        if (sub.getMessageService().getConnectionInfo().equals(tcpInfo)){
          subBroker = sub;
          break;
        }
      }
      if (subBroker != null){
        // update model of this sub broker
        ModelUpdateMessage message = (ModelUpdateMessage)msg;
        subBroker.setRegisteredProducers(message.getProducers());
        subBroker.setRegisteredConsumers(message.getConsumers());
        System.out.println("Recieved and stored update from SubBroker "+tcpInfo.getHost()+":"+tcpInfo.getPort());
      }
    }
  }
 

 
  /**
   * Gets the connection info for a requesting consumer
   * to connect to a appropriate sub broker
   * @return connection info for the broker with most producers and least consumers
   */
  private TcpConnectInfo getConsumerConnectBroker(){
    int tempProd = 0;
    int tempCons = Integer.MAX_VALUE;
    SubBrokerData broker = null;
    for (SubBrokerData subBroker : this.subBrokers.values()){
      int sizeCons = subBroker.getRegisteredConsumers().size();
      int sizeProd = subBroker.getRegisteredProducers().size();
      if((sizeCons<=tempCons && sizeProd>tempProd)||(sizeCons<tempCons && sizeProd>=tempProd)){
        tempCons = sizeCons;
        tempProd = sizeProd;
        broker = subBroker; 
      }
    }
   
    return broker.getMessageService().getConnectionInfo();
  }
 

  /**
   * distribute the consumers to brokers for efficient transmission
   */
  public void distributeConsumers(){ 
   
    for (SubBrokerData subBroker : this.subBrokers.values()){
      List<BConsumer> regCon = subBroker.getRegisteredConsumers();
      BrokerUpdateMessageCollector messageList = new BrokerUpdateMessageCollector();
     
      for(BConsumer curCon : regCon){
        int sum = 0;
        int ownSum = 0;
        SubBrokerData chosenBroker = null;
       
        for (SubBrokerData subBroker2 : this.subBrokers.values()){
          int tempSum=0;
          List<BProducer> regPro = subBroker2.getRegisteredProducers();
          for(BProducer curPro : regPro){
            for(String curConEvent : curCon.getWantedEvents()){
              if(curPro.getProducedEvent().equals(curConEvent)){
                if(!subBroker.equals(subBroker2)){
                  tempSum++;
                } else{
                  ownSum++;
                }
              }
            }
           
          }
          if(tempSum>sum){
            sum = tempSum;
            chosenBroker = subBroker2;
          }
        }
               
        if(sum>ownSum){
          BrokerUpdateMessage message = new BrokerUpdateMessage(chosenBroker.getMessageService().getConnectionInfo(),curCon);
          messageList.addMessage(message);
          System.out.println("Forwarded Consumer from "+subBroker.getMessageService().getConnectionInfo().getHost()
              +":"+subBroker.getMessageService().getConnectionInfo().getPort()+" to "
              +chosenBroker.getMessageService().getConnectionInfo().getHost()+":"
              +chosenBroker.getMessageService().getConnectionInfo().getPort());
        }
      }
      try {
        subBroker.getMessageService().sendMessage(messageList);
      } catch (IOException e) {
        e.printStackTrace();
      }
     
    }
   
  }

  /**
   * This method will be called after a client has been
   * disconnected. In fact this method will only handle
   * disconnects by subbroker and will remove them from
   * the connected list
   */
  @Override
  public void disconnected() {
    List<SubBrokerData> toDrop = new LinkedList<SubBrokerData>();
    for (SubBrokerData subBroker : this.subBrokers.values()){
      if (!subBroker.getMessageService().isConnected()){
        toDrop.add(subBroker);
      }
    }
    for (SubBrokerData drop : toDrop){
      this.subBrokers.remove(drop);
      System.out.println("Dropped a SubBroker");
    }
  }
}
TOP

Related Classes of lupos.event.broker.distributed.MasterBroker

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.