package org.distributeme.core.routing;
import org.distributeme.core.ClientSideCallContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.atomic.AtomicLong;
/**
* This router sends each call to another instance. It is useful if you want to cluster a service
*
* @author lrosenberg
* @version $Id: $Id
*/
public class FairRoundRobinRouter extends AbstractRouter implements Router{
/**
* Max mod parameter. It is used to scale up the range of instances, and to prevent the counter from too many overflows, thus allowing the distribution be more fair.
*/
private long MAX = 0;
/**
* Number of instances.
*/
private int MOD = 0;
/**
* Call counter.
*/
private AtomicLong callCounter = new AtomicLong(0);
/**
* Logger.
*/
private static Logger log = LoggerFactory.getLogger(FairRoundRobinRouter.class);
/** {@inheritDoc} */
@Override
public void customize(String parameter) {
try{
MOD = Integer.parseInt(parameter);
MAX = 1000L*MOD;
}catch(NumberFormatException e){
log.error("Can't set customization parameter "+parameter+", send all traffic to default instance");
}
}
/** {@inheritDoc} */
@Override
public String getServiceIdForCall(ClientSideCallContext callContext) {
if (MAX==0)
return callContext.getServiceId();
long fromCounter = callCounter.incrementAndGet();
if (fromCounter>=MAX){
long oldCounter = fromCounter;
fromCounter = 0;
callCounter.compareAndSet(oldCounter, 0);
}
return callContext.getServiceId()+"_"+(fromCounter%MOD);
}
}