package com.robert.vesta.service.impl; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import com.robert.vesta.service.bean.Id; import com.robert.vesta.service.impl.bean.IdType; import com.robert.vesta.service.intf.IdService; public class IdServiceImpl extends AbstractIdServiceImpl implements IdService { private long sequence = 0; private long lastTimestamp = -1; private Lock lock = new ReentrantLock(); public IdServiceImpl() { super(); } public IdServiceImpl(String type) { super(type); } public IdServiceImpl(IdType type) { super(type); } protected void populateId(Id id) { lock.lock(); try { long timestamp = this.genTime(); validateTimestamp(lastTimestamp, timestamp); if (timestamp == lastTimestamp) { sequence++; sequence &= idMeta.getSeqBitsMask(); if (sequence == 0) { timestamp = this.tillNextTimeUnit(lastTimestamp); } } else { lastTimestamp = timestamp; sequence = 0; } id.setSeq(sequence); id.setTime(timestamp); } finally { lock.unlock(); } } private void validateTimestamp(long lastTimestamp, long timestamp) { if (timestamp < lastTimestamp) { if (log.isErrorEnabled()) log.error(String .format("Clock moved backwards. Refusing to generate id for %d %s.", lastTimestamp - timestamp, idType == IdType.MAX_PEAK ? "second" : "milisecond")); throw new IllegalStateException( String.format( "Clock moved backwards. Refusing to generate id for %d %s.", lastTimestamp - timestamp, idType == IdType.MAX_PEAK ? "second" : "milisecond")); } } protected long tillNextTimeUnit(final long lastTimestamp) { if (log.isInfoEnabled()) log.info(String .format("Ids are used out during %d in machine %d. Waiting till next %s.", lastTimestamp, machineId, idType == IdType.MAX_PEAK ? "second" : "milisecond")); long timestamp = this.genTime(); while (timestamp <= lastTimestamp) { timestamp = this.genTime(); } if (log.isInfoEnabled()) log.info(String.format("Next %s %d is up.", idType == IdType.MAX_PEAK ? "second" : "milisecond", timestamp)); return timestamp; } }