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

com.bagri.server.hazelcast.impl.HealthManagementImpl Maven / Gradle / Ivy

The newest version!
package com.bagri.server.hazelcast.impl;

import static com.bagri.core.server.api.CacheConstants.*;

import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bagri.core.DocumentKey;
import com.bagri.core.api.HealthState;
import com.bagri.core.model.Counter;
import com.bagri.core.model.Document;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.core.ITopic;
import com.hazelcast.core.Message;
import com.hazelcast.core.MessageListener;
import com.hazelcast.partition.PartitionLostEvent;
import com.hazelcast.partition.PartitionLostListener;

public class HealthManagementImpl implements MessageListener, PartitionLostListener {
	//, XDMHealthManagement{ 

    private static final Logger logger = LoggerFactory.getLogger(HealthManagementImpl.class);

	private HazelcastInstance hzInstance;
	private ITopic hTopic;
	private IMap xddCache;
	
	private HealthState healthState = HealthState.good; 
	
	private int thLow = 10;
	private int thHigh = 0;
	
	// TODO: would be better to have an internal atomic structure 
	// which will update both fields in one atomic operation
	private AtomicLong cntActive = new AtomicLong(0);
	private AtomicLong cntInactive = new AtomicLong(0);
	
	public HealthManagementImpl() {
		//super();
	}
	
	public HealthManagementImpl(HazelcastInstance hzInstance) {
		initialize(hzInstance);
	}
	
	public void setLowThreshold(int thLow) {
		this.thLow = thLow;
	}
	
	public void setHighThreshold(int thHigh) {
		this.thHigh = thHigh;
	}

	private void initialize(HazelcastInstance hzInstance) {
		this.hzInstance = hzInstance;
		ITopic cTopic = hzInstance.getTopic(TPN_XDM_COUNTERS);
		cTopic.addMessageListener(this);
		ITopic pTopic = hzInstance.getTopic(TPN_XDM_POPULATION);
		pTopic.addMessageListener(new PopulationStateListener());
		hTopic = hzInstance.getTopic(TPN_XDM_HEALTH);
		xddCache = hzInstance.getMap(CN_XDM_DOCUMENT);
		hzInstance.getPartitionService().addPartitionLostListener(this);
	}
	
	private void updateState(Counter counter) {
		if (counter.isCommit()) {
			cntActive.addAndGet(counter.getCreated() - counter.getDeleted());
			cntInactive.addAndGet(counter.getUpdated() + counter.getDeleted()); 
		} else {
			// nothing will change, all garbage will be compensated
		}
		checkState();
	}
	
	private void checkState() {
		int docSize = xddCache.size();
		logger.trace("checkState; active count: {}; inactive count: {}; cache size: {}", cntActive, cntInactive, docSize);
		long fullSize = cntActive.get() + cntInactive.get();
		HealthState hState;
		if (fullSize < docSize - thLow) {
			hState = HealthState.bad;
		} else if (fullSize > docSize + thHigh) {
			hState = HealthState.ugly;
		} else {
			hState = HealthState.good; 
		} 
		if (healthState != hState) {
			healthState = hState;
			hTopic.publish(hState);
			if (healthState != HealthState.good) { 			
				logger.info("checkState; the state is: {}; expected size: {}; cache size: {}", hState, fullSize, docSize);
			}
		}
	}
	
	public void clearState() {
		cntActive = new AtomicLong(0);
		cntInactive = new AtomicLong(0);
		hTopic.publish(HealthState.good);
	}

	public int[] getCounters() {
		return new int[] {cntActive.intValue(), cntInactive.intValue()};
	}
	
	public HealthState getHealthState() {
		return healthState;
	}

	public void initState(int docActive, int docInactive) {
		cntActive = new AtomicLong(docActive);
		cntInactive = new AtomicLong(docInactive);
		checkState();
	}
	
	@Override
	public void onMessage(Message message) {
		logger.trace("onMessage; {}", message); 
		updateState(message.getMessageObject());
	}

	@Override
	public void partitionLost(PartitionLostEvent event) {
		logger.debug("partitionLost; event: {}", event); 
		checkState();
	}
	
	private class PopulationStateListener implements MessageListener {

		@Override
		public void onMessage(Message message) {
			int lo = (int) message.getMessageObject().longValue();
			int hi = (int) (message.getMessageObject().longValue() >> 32);
			initState(lo, hi);
			// now we can disconnect, actually..
		}
		
	}
	
/*		
	@Override
	public void checkClusterState() throws XDMException {
		// TODO Auto-generated method stub
	}

	@Override
	public boolean isClusterSafe() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public int getClusterSize() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public XDMHealthState getHealthState() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void addHealthChangeListener(XDMHealthChangeListener listener) {
		// TODO Auto-generated method stub
	}

	@Override
	public void removeHealthChangeListener(XDMHealthChangeListener listener) {
		// TODO Auto-generated method stub
	}
*/
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy