All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hornetq.utils.TimeAndCounterIDGenerator Maven / Gradle / Ivy

/*
 * Copyright 2005-2014 Red Hat, Inc.
 * Red Hat licenses this file to you under the Apache License, version
 * 2.0 (the "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *    http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.  See the License for the specific language governing
 * permissions and limitations under the License.
 */
package org.hornetq.utils;

import java.util.concurrent.atomic.AtomicLong;

/**
 * A TimeAndCounterIDGenerator
 * 

* This IDGenerator doesn't support more than 16777215 IDs per 16 millisecond. It would throw an exception if this happens. *

* * @author Clebert Suconic * @author Tim Fox Created Sep 24, 2008 11:54:10 AM */ public class TimeAndCounterIDGenerator implements IDGenerator { // Constants ---------------------------------------------------- /** * Bits to move the date accordingly to MASK_TIME */ private static final int BITS_TO_MOVE = 20; public static final long MASK_TIME = 0x7fffffffff0L; // 44 bits of time and 20 bits of counter public static final long ID_MASK = 0xffffffL; private static final long TIME_ID_MASK = 0x7fffffffff000000L; // Attributes ---------------------------------------------------- private final AtomicLong counter = new AtomicLong(0); private volatile boolean wrapped = false; private volatile long tmMark; // Static -------------------------------------------------------- // Constructors -------------------------------------------------- public TimeAndCounterIDGenerator() { refresh(); } // Public -------------------------------------------------------- // Public -------------------------------------------------------- public long generateID() { long idReturn = counter.incrementAndGet(); if ((idReturn & TimeAndCounterIDGenerator.ID_MASK) == 0) { final long timePortion = idReturn & TimeAndCounterIDGenerator.TIME_ID_MASK; // Wrapping ID logic if (timePortion >= newTM()) { // Unlikely to happen wrapped = true; } else { // Else.. no worry... we will just accept the new time portion being added // This time-mark would have been generated some time ago, so this is ok. // tmMark is just a cache to validate the MaxIDs, so there is no need to make it atomic (synchronized) tmMark = timePortion; } } if (wrapped) { // This will only happen if a computer can generate more than ID_MASK ids (16 million IDs per 16 // milliseconds) // If this wrapping code starts to happen, it needs revision throw new IllegalStateException("The IDGenerator is being overlaped, and it needs revision as the system generated more than " + TimeAndCounterIDGenerator.ID_MASK + " ids per 16 milliseconds which exceeded the IDgenerator limit"); } return idReturn; } public long getCurrentID() { return counter.get(); } // for use in testcases public long getInternalTimeMark() { return tmMark; } // for use in testcases public void setInternalID(final long id) { counter.set(tmMark | id); } // for use in testcases public void setInternalDate(final long date) { tmMark = (date & TimeAndCounterIDGenerator.MASK_TIME) << TimeAndCounterIDGenerator.BITS_TO_MOVE; counter.set(tmMark); } public synchronized void refresh() { long oldTm = tmMark; long newTm = newTM(); while (newTm <= oldTm) { newTm = newTM(); } tmMark = newTm; counter.set(tmMark); } @Override public String toString() { long currentCounter = counter.get(); return "SequenceGenerator(tmMark=" + hex(tmMark) + ", CurrentCounter = " + currentCounter + ", HexCurrentCounter = " + hex(currentCounter) + ")"; } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- // Private ------------------------------------------------------- private long newTM() { return (System.currentTimeMillis() & TimeAndCounterIDGenerator.MASK_TIME) << TimeAndCounterIDGenerator.BITS_TO_MOVE; } private String hex(final long x) { return String.format("%1$X", x); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy