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;
}
}