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

net.sf.hajdbc.state.distributed.DistributedStateManager Maven / Gradle / Ivy

There is a newer version: 3.6.61
Show newest version
package net.sf.hajdbc.state.distributed;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import java.util.concurrent.CopyOnWriteArrayList;
import net.sf.hajdbc.Database;
import net.sf.hajdbc.DatabaseCluster;
import net.sf.hajdbc.Messages;
import net.sf.hajdbc.distributed.Command;
import net.sf.hajdbc.distributed.CommandDispatcher;
import net.sf.hajdbc.distributed.CommandDispatcherFactory;
import net.sf.hajdbc.distributed.Member;
import net.sf.hajdbc.distributed.MembershipListener;
import net.sf.hajdbc.distributed.Remote;
import net.sf.hajdbc.distributed.Stateful;
import net.sf.hajdbc.distributed.jgroups.AddressMember;
import net.sf.hajdbc.durability.InvocationEvent;
import net.sf.hajdbc.durability.InvokerEvent;
import net.sf.hajdbc.logging.Level;
import net.sf.hajdbc.logging.Logger;
import net.sf.hajdbc.logging.LoggerFactory;
import net.sf.hajdbc.state.*;
import net.sf.hajdbc.state.health.ClusterHealth;
import net.sf.hajdbc.state.health.ClusterHealthImpl;
import net.sf.hajdbc.state.sync.SyncMgr;
import net.sf.hajdbc.state.sync.SyncMgrImpl;
import net.sf.hajdbc.util.StopWatch;

/**
 * @author Paul Ferraro
 */
public class DistributedStateManager> implements StateManager, DistributedManager, StateCommandContext, MembershipListener, Stateful
{
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	private final DatabaseCluster cluster;
	private final StateManager stateManager;


  public CommandDispatcher> getDispatcher() {
    return dispatcher;
  }

  private final CommandDispatcher> dispatcher;
	private final ConcurrentMap>> remoteInvokerMap = new ConcurrentHashMap>>();
	private final Set members = Collections.newSetFromMap(new ConcurrentHashMap());
  private final List membershipListeners = new CopyOnWriteArrayList<>();
  private final Map extContexts = new HashMap<>();
	private final ClusterHealth health;
	private final SyncMgr syncMgr;


	public DistributedStateManager(DatabaseCluster cluster, CommandDispatcherFactory dispatcherFactory) throws Exception {
		this.cluster = cluster;
		this.stateManager = cluster.getStateManager();
		StateCommandContext context = this;
		this.dispatcher = dispatcherFactory.createCommandDispatcher(cluster.getId() + ".state", context, this, this);
		this.health = new ClusterHealthImpl(this);
		this.syncMgr = new SyncMgrImpl(this);
		this.addMembershipListener(this.health);
	}

  public ClusterHealth getHealth() {
    return health;
  }

	public SyncMgr getSyncMgr() {
		return syncMgr;
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.state.StateManager#getActiveDatabases()
	 */
	@Override
	public Set getActiveDatabases()
	{
		return this.stateManager.getActiveDatabases();
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.state.StateManager#setActiveDatabases(java.util.Set)
	 */
	@Override
	public void setActiveDatabases(Set databases)
	{
		this.stateManager.setActiveDatabases(databases);
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterListener#activated(net.sf.hajdbc.state.DatabaseEvent)
	 */
	@Override
	public void activated(DatabaseEvent event)
	{
		this.stateManager.activated(event);
		this.dispatcher.executeAll(new ActivationCommand(event), this.dispatcher.getLocal());
		Set activeDatabases = getActiveDatabases();
		logger.log(Level.INFO,"sync activeDatabases={0}", activeDatabases);
		DatabasesEvent event2 = new DatabasesEvent(activeDatabases);
		this.dispatcher.executeAll(new SyncActiveDbsCommand(event2), this.dispatcher.getLocal());

	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.DatabaseClusterListener#deactivated(net.sf.hajdbc.state.DatabaseEvent)
	 */
	@Override
	public void deactivated(DatabaseEvent event)
	{
		StopWatch stopWatch = StopWatch.createStarted();
		this.stateManager.deactivated(event);
		this.dispatcher.executeAll(new DeactivationCommand(event), this.dispatcher.getLocal());
		logger.log(Level.INFO,"{0} deactivated cost time:{1}", event.getSource(), stopWatch.toString());
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.durability.DurabilityListener#afterInvocation(net.sf.hajdbc.durability.InvocationEvent)
	 */
	@Override
	public void afterInvocation(InvocationEvent event)
	{
		this.dispatcher.executeAll(new PostInvocationCommand(this.getRemoteDescriptor(event)));
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.durability.DurabilityListener#afterInvoker(net.sf.hajdbc.durability.InvokerEvent)
	 */
	@Override
	public void afterInvoker(InvokerEvent event)
	{
		this.dispatcher.executeAll(new InvokerCommand(this.getRemoteDescriptor(event)));
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.durability.DurabilityListener#beforeInvocation(net.sf.hajdbc.durability.InvocationEvent)
	 */
	@Override
	public void beforeInvocation(InvocationEvent event)
	{
		this.dispatcher.executeAll(new PreInvocationCommand(this.getRemoteDescriptor(event)));
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.durability.DurabilityListener#beforeInvoker(net.sf.hajdbc.durability.InvokerEvent)
	 */
	@Override
	public void beforeInvoker(InvokerEvent event)
	{
		this.dispatcher.executeAll(new InvokerCommand(this.getRemoteDescriptor(event)));
	}

	private RemoteInvocationDescriptor getRemoteDescriptor(InvocationEvent event)
	{
		return new RemoteInvocationDescriptorImpl(event, this.dispatcher.getLocal());
	}
	
	private RemoteInvokerDescriptor getRemoteDescriptor(InvokerEvent event)
	{
		return new RemoteInvokerDescriptorImpl(event, this.dispatcher.getLocal());
	}
	
	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.Lifecycle#start()
	 */
	@Override
	public void start() throws Exception
	{
		this.stateManager.start();
		this.dispatcher.start();
		this.health.start();

	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.Lifecycle#stop()
	 */
	@Override
	public void stop()
	{
    this.health.stop();
		this.dispatcher.stop();
		this.stateManager.stop();
	}


	@Override
	public boolean isEnabled()
	{
		return this.stateManager.isEnabled() && dispatcher.getLocal().equals(dispatcher.getCoordinator());
	}


  /**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.state.distributed.StateCommandContext#getDatabaseCluster()
	 */
	@Override
	public DatabaseCluster getDatabaseCluster()
	{
		return this.cluster;
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.state.distributed.StateCommandContext#getLocalStateManager()
	 */
	@Override
	public StateManager getLocalStateManager()
	{
		return this.stateManager;
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.state.distributed.StateCommandContext#getRemoteInvokers(net.sf.hajdbc.distributed.Remote)
	 */
	@Override
	public Map> getRemoteInvokers(Remote remote)
	{
		return this.remoteInvokerMap.get(remote.getMember());
	}

	@Override
	public  Map executeAll(Command> command,
			Member... excludedMembers) {
		return dispatcher.executeAll(command, excludedMembers);
	}


	@Override
	public  R execute(Command> command, Member member) {
		return dispatcher.execute(command, member);
	}

	@Override
	public  C getExtContext(String key) {
		return (C)extContexts.get(key);
	}

	@Override
	public  C removeExtContext(String key) {
		return (C)extContexts.remove(key);
	}

	@Override
	public  void setExtContext(String key,C context) {
		if(context!=null){
			extContexts.put(key,context);
		}
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.distributed.Stateful#readState(java.io.ObjectInput)
	 */
	@Override
	public void readState(ObjectInput input) throws IOException
	{
		if (input.available() > 0)
		{
			Set databases = new TreeSet();
			
			int size = input.readInt();
			
			for (int i = 0; i < size; ++i)
			{
				databases.add(input.readUTF());
			}
			
			this.logger.log(Level.INFO, Messages.INITIAL_CLUSTER_STATE_REMOTE.getMessage(databases, this.dispatcher.getCoordinator()));
			
			this.stateManager.setActiveDatabases(databases);


    }
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.distributed.Stateful#writeState(java.io.ObjectOutput)
	 */
	@Override
	public void writeState(ObjectOutput output) throws IOException
	{
		Set databases = this.cluster.getBalancer();
		output.writeInt(databases.size());
		
		for (D database: databases)
		{
			output.writeUTF(database.getId());
		}
	}



	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.distributed.MembershipListener#added(net.sf.hajdbc.distributed.Member)
	 */
	@Override
	public void added(Member member)
	{
		this.remoteInvokerMap.putIfAbsent(member, new HashMap>());
		members.add(member);
		checkMemberDatabaseConfig(member);

		Iterator iterator = membershipListeners.iterator();
    while(iterator.hasNext()){
      try {
        iterator.next().added(member);
      }catch (Exception e){
        logger.log(Level.WARN,e);
      }
    }

	}

	/*
	public void checkDatabaseConfig() {
		Iterator iterator = members.iterator();
		while(iterator.hasNext()){
			Member member = iterator.next();
			checkMemberDatabaseConfig(member);
		}
	}//*/
	GetDatabaseCommand getDatabaseCommand = new GetDatabaseCommand();
	private void checkMemberDatabaseConfig(Member member) {
		if(!member.equals(getLocal())){
			String ip = getIp(member);
			if(ip!=null) {
				D database = cluster.getDatabaseByIp(ip);
				if (database == null) {
					logger.log(Level.INFO, "checkMemberDatabaseConfig member={0}, ip={1}", member, ip);
					D db = (D) execute(getDatabaseCommand, member);
					if (db != null) {
						db.setLocal(false);
						cluster.addDatabase(db);
					}
				}
			}
		}
	}


	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.distributed.MembershipListener#removed(net.sf.hajdbc.distributed.Member)
	 */
	@Override
	public void removed(Member member)
	{
		logger.log(Level.INFO,"DSM member removed:"+member);

		if (this.dispatcher.getLocal().equals(this.dispatcher.getCoordinator()))
		{
			Map> invokers = this.remoteInvokerMap.remove(member);
			
			if (invokers != null)
			{
				this.cluster.getDurability().recover(invokers);
			}
		}

		members.remove(member);

		Iterator iterator = membershipListeners.iterator();
    while(iterator.hasNext()){
      try {
        iterator.next().removed(member);
      }catch (Exception e){
        logger.log(Level.WARN,e);
      }
    }

  }

	private void removeNodeDatabase(Member member) {
		StopWatch stopWatch = StopWatch.createStarted();
		D database = this.cluster.getDatabaseByIp(getIp(member));
		try {
			this.cluster.deactivate(database, this.cluster.getStateManager());
			logger.log(Level.INFO, "remove NodeDatabase, cost time: {0}", stopWatch.toString());
		} catch (Exception e) {
			logger.log(Level.WARN, e, "remove NodeDatabase fail, cost time {0}:", stopWatch.toString());
		}
	}

	/**
	 * {@inheritDoc}
	 * @see net.sf.hajdbc.state.StateManager#recover()
	 */
	@Override
	public Map> recover()
	{
		return this.stateManager.recover();
	}

	@Override
	public boolean isValid(Database database) {
		Set ips = getIps();
		if(ips.contains(database.getIp())){
     return true;
		}
		return false;
	}

  public Member getMember(String ip) {
    Member find = null;
    Iterator iterator = members.iterator();
    while(iterator.hasNext()){
      Member next = iterator.next();
      if(getIp(next).equals(ip)){
        find = next;
        break;
      }
    }
    return find;
  }

	private Set getIps() {
		Set ips = new HashSet<>();
		for(Member m:this.members){
      ips.add(getIp(m));

		}
		return ips;
	}


	private String getIp(Member local) {
		return org.jgroups.util.UUID.get(((AddressMember)local).getAddress());
	}

  public Member getCoordinator() {
    return this.dispatcher.getCoordinator();
  }

	@Override
	public List getMembers() {
		return new ArrayList<>(members);
	}

  @Override
  public void addMembershipListener(MembershipListener listener) {
    membershipListeners.add(listener);
  }

  @Override
  public void removeMembershipListener(MembershipListener listener) {
    membershipListeners.remove(listener);
  }

  public Member getLocal() {
    return this.dispatcher.getLocal();
  }

  public String getLocalIp() {
    return getIp(getLocal());
  }


	private static class RemoteDescriptor implements Remote, Serializable
	{
		private static final long serialVersionUID = 3717630867671175936L;
		
		private final Member member;
		
		RemoteDescriptor(Member member)
		{
			this.member = member;
		}

		@Override
		public Member getMember()
		{
			return this.member;
		}
	}
	
	private static class RemoteInvocationDescriptorImpl extends RemoteDescriptor implements RemoteInvocationDescriptor
	{
		private static final long serialVersionUID = 7782082258670023082L;
		
		private final InvocationEvent event;
		
		RemoteInvocationDescriptorImpl(InvocationEvent event, Member member)
		{
			super(member);
			
			this.event = event;
		}
		
		@Override
		public InvocationEvent getEvent()
		{
			return this.event;
		}

		/**
		 * {@inheritDoc}
		 * @see java.lang.Object#toString()
		 */
		@Override
		public String toString()
		{
			return this.event.toString();
		}
	}
	
	private static class RemoteInvokerDescriptorImpl extends RemoteDescriptor implements RemoteInvokerDescriptor
	{
		private static final long serialVersionUID = 6991831573393882786L;
		
		private final InvokerEvent event;
		
		RemoteInvokerDescriptorImpl(InvokerEvent event, Member member)
		{
			super(member);
			
			this.event = event;
		}
		
		@Override
		public InvokerEvent getEvent()
		{
			return this.event;
		}

		/**
		 * {@inheritDoc}
		 * @see java.lang.Object#toString()
		 */
		@Override
		public String toString()
		{
			return this.event.toString();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy