package com.taobao.tddl.sequence.impl; import java.sql.SQLException; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.lang.StringUtils; import com.taobao.tddl.monitor.eagleeye.EagleeyeHelper; import com.taobao.tddl.sequence.Sequence; import com.taobao.tddl.sequence.SequenceDao; import com.taobao.tddl.sequence.SequenceRange; import com.taobao.tddl.sequence.exception.SequenceException; public class GroupSequence implements Sequence { private final Lock lock = new ReentrantLock(); private SequenceDao sequenceDao; private String name; private volatile SequenceRange currentRange; // 全链路压测需求 private volatile SequenceRange testCurrentRange; /** * 初始化一下,如果name不存在,则给其初始值<br> * * @throws SequenceException * @throws SQLException */ public void init() throws SequenceException, SQLException { if (!(sequenceDao instanceof GroupSequenceDao)) { throw new SequenceException("please use GroupSequenceDao!"); } GroupSequenceDao groupSequenceDao = (GroupSequenceDao) sequenceDao; synchronized (this) // 为了保证安全, { groupSequenceDao.adjust(name); } } public long nextValue() throws SequenceException { boolean isTest = this.isTestSeq(); if (getSequenceRange(isTest) == null) { lock.lock(); try { if (getSequenceRange(isTest) == null) { setSequenceRange(sequenceDao.nextRange(name), isTest); } } finally { lock.unlock(); } } long value = getSequenceRange(isTest).getAndIncrement(); if (value == -1) { lock.lock(); try { for (;;) { if (getSequenceRange(isTest).isOver()) { setSequenceRange(sequenceDao.nextRange(name), isTest); } value = getSequenceRange(isTest).getAndIncrement(); if (value == -1) { continue; } break; } } finally { lock.unlock(); } } if (value < 0) { throw new SequenceException("Sequence value overflow, value = " + value); } return value; } private SequenceRange getSequenceRange(boolean isTest) { if (isTest) { return this.testCurrentRange; } else { return this.currentRange; } } private void setSequenceRange(SequenceRange range, boolean isTest) { if (isTest) { this.testCurrentRange = range; } else { this.currentRange = range; } } private boolean isTestSeq() { String t = EagleeyeHelper.getUserData("t"); if (!StringUtils.isBlank(t) && t.equals("1")) { return true; } else { return false; } } public SequenceDao getSequenceDao() { return sequenceDao; } public void setSequenceDao(SequenceDao sequenceDao) { this.sequenceDao = sequenceDao; } public String getName() { return name; } public void setName(String name) { this.name = name; } }