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

io.zbus.mq.BrokerRouteTable Maven / Gradle / Ivy

package io.zbus.mq;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import io.zbus.mq.Protocol.ServerInfo;
import io.zbus.mq.Protocol.TopicInfo;
import io.zbus.mq.Protocol.TrackerInfo;
import io.zbus.transport.ServerAddress;
 
public class BrokerRouteTable {    
	private long lastUpdatedTime = System.currentTimeMillis();
	private double voteFactor = 0.5;
	//{ TrackerAddress=>[ServerAddress] }
	private Map votesTable = new ConcurrentHashMap(); 
	//{ ServerAddress=>ServerInfo }
	private Map serverTable = new HashMap();
	//{ TopicName=> { ServerAddress=>TopicInfo } }
	private Map> topicTable = new HashMap>(); 
	
	
	private static class Vote {
		long version; 
		Set trackedServers;
	}
	
	public List updateTracker(TrackerInfo trackerInfo){  
		lastUpdatedTime = System.currentTimeMillis();
		//1) Update Votes
		Vote vote = votesTable.get(trackerInfo.serverAddress);
		if(vote != null && vote.version >= trackerInfo.infoVersion){
			return new ArrayList(); //empty to remove
		}
		
		HashSet trackedServers = new HashSet();
		for(ServerInfo serverInfo : trackerInfo.serverTable.values()){
			trackedServers.add(serverInfo.serverAddress);
		}
		if(vote == null) {
			vote = new Vote();
			vote.version = trackerInfo.infoVersion;  
		}  
		vote.trackedServers = trackedServers;  
		votesTable.put(trackerInfo.serverAddress, vote);
		
		//Update serverTable
		for(Entry e : trackerInfo.serverTable.entrySet()){
			ServerInfo serverInfo = e.getValue();
			ServerInfo oldSeverInfo = this.serverTable.get(serverInfo.serverAddress);
			if(oldSeverInfo != null && oldSeverInfo.infoVersion >= serverInfo.infoVersion) continue; 
			
			this.serverTable.put(serverInfo.serverAddress, serverInfo);
		}
		
		return this.purge(); 
	}
	
	public List removeTracker(ServerAddress trackerAddress){
		lastUpdatedTime = System.currentTimeMillis();
		
		if(!votesTable.containsKey(trackerAddress)) {
			return new ArrayList();
		}
		this.votesTable.remove(trackerAddress);
		
		return this.purge();
	}
	
	
	private List purge(){
		List toRemove = new ArrayList();
		
		Map serverTableLocal = new HashMap(this.serverTable);
		for(ServerAddress serverAddress : serverTableLocal.keySet()) { 
			int count = 0;
			for(Vote vote : this.votesTable.values()){
				if(vote.trackedServers.contains(serverAddress)) count++;
			}
			if(count < votesTable.size()*voteFactor){
				toRemove.add(serverAddress);
			} 
		}
		for(ServerAddress serverAddress : toRemove){
			serverTableLocal.remove(serverAddress);
		}
		
		this.serverTable = serverTableLocal;
		rebuildTopicTable(serverTableLocal); 
		
		return toRemove;
	}
	
	private void rebuildTopicTable(Map serverTableLocal) { 
		Map> table = new ConcurrentHashMap>();
		for (ServerInfo serverInfo : serverTableLocal.values()) {
			for (TopicInfo topicInfo : serverInfo.topicTable.values()) {
				Map server2Topic = table.get(topicInfo.topicName);
				if (server2Topic == null) {
					server2Topic = new HashMap();
					table.put(topicInfo.topicName, server2Topic);
				}
				server2Topic.put(topicInfo.serverAddress, topicInfo);
			}
		}
		this.topicTable = table;
	} 
	
	public Map serverTable() {
		return serverTable;
	} 
 
	public Map> topicTable(){
		return this.topicTable;
	} 
	
	public long getLastUpdatedTime() {
		return lastUpdatedTime;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy