package engine; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import com.github.ddth.id.SnowflakeIdGenerator; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; /** * Snowflake-implementation of {@link IIdEngine}. * * <p> * IDs generated by this engine are: * <ul> * <li>Unique: Unique across all nodes (each node must be assigned a unique * node-id).</li> * <li>Ascending: Next generated ID is larger than previous ones.</li> * <li>Time-based: Each generated ID is associated with a timestamp.</li> * <li>Non-serial: {@code next-id} is NOT equal to {@code previous-id + 1}!</li> * <li>No-current: {@link IIdEngine#currentId(String)} is NOT supported!</li> * </ul> * <p/> * * @author ThanhNB * @since 0.1.0 */ public class SnowflakeIdEngine implements IIdEngine { private LoadingCache<String, SnowflakeIdGenerator> _cache; private long nodeId = -1; protected long getNodeId() { return nodeId; } public SnowflakeIdEngine setNodeId(long nodeId) { this.nodeId = nodeId; return this; } /** * Init method * * @return */ public SnowflakeIdEngine init() { if (nodeId < 0) { nodeId = 0; try { InetAddress ip = InetAddress.getLocalHost(); NetworkInterface network = NetworkInterface.getByInetAddress(ip); byte[] mac = network.getHardwareAddress(); for (byte temp : mac) { nodeId = (nodeId << 8) | ((int) temp & 0xFF); } } catch (Exception e) { nodeId = System.currentTimeMillis(); } } _cache = CacheBuilder.newBuilder() .removalListener(new RemovalListener<String, SnowflakeIdGenerator>() { @Override public void onRemoval(RemovalNotification<String, SnowflakeIdGenerator> entry) { // EMPTY } }).expireAfterAccess(3600, TimeUnit.SECONDS) .build(new CacheLoader<String, SnowflakeIdGenerator>() { @Override public SnowflakeIdGenerator load(String namespace) throws Exception { return SnowflakeIdGenerator.getInstance(nodeId); } }); return this; } /** * Destroy method. */ public void destroy() { if (_cache != null) { _cache.invalidateAll(); _cache = null; } } /** * {@inheritDoc} */ @Override public long nextId(String namespace) throws ExecutionException { return _cache.get(namespace).generateId64(); } /** * {@inheritDoc} */ @Override public long currentId(String namespace) throws Exception { return -2; } /** * {@inheritDoc} */ @Override public boolean setValue(String namespace, long value) throws Exception { // operation is not supported return false; } }