Phil, Tim, et al, I just added the thread lifecycle handling to the *draft* UuidClock.java I'd started For the timestamp of a version 1 uuid.
I'll share it here. I realize it needs more work. I haven't tested it yet, but I wanted to get some feedback before I do more. I'm not a committer on anything... would it be better to open a bugzilla enhancement and add files like this that way? /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.lang.identifier; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * UuidClock.java provides a timing mechanism for returning the current time in * 100-nano second intervals since 00:00:00.00, 15 October 1582 * * As described below this is useful for generating Version 1 UUIDs * * For more information regarding the IETF Draft Uuid specification * @see http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-01.txt * * Selected segements of Draft pertaining to this class: * * ==================================================================== * Timestamp * The timestamp is a 60 bit value. For Uuid version 1, this is * represented by Coordinated Universal Time (UTC) as a count of 100- * nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of * Gregorian reform to the Christian calendar). * * Clock Adjustment * UUIDs may be created at a rate greater than the system clock resolution. * Therefore, the system must also maintain an adjustment value to be added to * the lower-order bits of the time. Logically, each time the system clock * ticks, the adjustment value is cleared. Every time a UUID is generated, * the current adjustment value is read and incremented atomically, then added * to the UTC time field of the UUID. * * Clock Overrun * The 100 nanosecond granularity of time should prove sufficient even for * bursts of UUID creation in the next generation of high-performance * multiprocessors. If a system overruns the clock adjustment by requesting * too many UUIDs within a single system clock tick, the UUID service may * raise an exception, handled in a system or process-dependent manner * either by: * terminating the requester * reissuing the request until it succeeds * stalling the UUID generator until the system clock catches up. * * If the processors overrun the UUID generation frequently, additional node * identifiers and clocks may need to be added. * ==================================================================== */ public class UuidClock extends Thread { /** * Uuid properties file name */ public static final String PROPERTIES_FILE = "uuid.properties"; /** * Properties key for the thread life length */ public static final String THREAD_LIFE_PROPERTY = "uuid.thread.life"; /** * Default life of the UuidClock thread in milliseconds */ public static final long DEFAULT_THREAD_LIFE = 200; /** * Boolean flag indicating if init has occured */ private static boolean isInit = false; /** * Life length of the clock thread the internal thread is perpetual unless * this time expires. This allows the thread to die during low usage but * keeps the thread alive during high usage. */ private static long threadLife; /** * The current time in milliseconds held in this clock thread. */ private long currentTimeMillis; /** * The counter for nanoseconds generated during this system interval (ms) */ private int generatedThisMilli; /** * Offset from GregorianCalendar Change over to Jan 1 1970 00:00:00.00 */ public static final long GREGORIAN_CHANGE_OFFSET = 12219292800000L; /** * Singleton instance of the UuidClock * */ private static UuidClock clock = null; /** * Time when the clock thread should die */ private static long expires; /** * Private constructor for clock implementation. Utilizes a single thread to * increment the clock every milli seconds this should be more * accurate than System.currentTimeMillis() as described in * the javaworld article: * http://www.javaworld.com/javaworld/javaqa/2003-01/01-qa-0110-timing.html */ private UuidClock() { setDaemon(true); setPriority(Thread.MAX_PRIORITY); currentTimeMillis = System.currentTimeMillis(); start(); } private void init() { Properties props = new Properties(); InputStream uuidProps = ClassLoader.getSystemResourceAsStream(PROPERTIES_FILE); try { props.load(uuidProps); UuidClock.threadLife = new Integer(props.getProperty(THREAD_LIFE_PROPERTY)).intValue(); } catch (IOException eio) { UuidClock.threadLife = UuidClock.DEFAULT_THREAD_LIFE; } isInit = true; } /** * Threads run method that increments the clock and resets the generated * nano seconds counter. */ public void run() { try { while (currentTimeMillis <= expires) { Thread.sleep(1); currentTimeMillis++; generatedThisMilli = 0; } } catch (InterruptedException e) { System.out.println("UuidClock thread interrupted"); } } private long currentTime(){ // Stall until counter is reset to limit only 10000 intervals per // millisecond interval while (generatedThisMilli > 10000L) { //wait for thread to reset } // 1 millisecond = 1 000 000 nanoseconds // return interval as 100 nanosecond intervals // 10,000 intervals per millsecond long currentTime = ((currentTimeMillis + GREGORIAN_CHANGE_OFFSET) * 10000); return currentTime + (generatedThisMilli++ * 1L); } public synchronized long getCurrentTime() { if(!isInit){ init(); } if(clock == null || !clock.isAlive()){ clock = null; clock = new UuidClock(); } expires = currentTimeMillis + threadLife; return clock.currentTime(); } /** Main method * * @param args String arrray of program arguements */ public static void main(String[] args) { UuidClock c = new UuidClock(); long[] currentNanos = new long[20000]; int count = 0; try { while (count < 20000) { currentNanos[count] = c.getCurrentTime(); count++; } for (count = 0; count < currentNanos.length; count++) { System.out.println( "CurrentTime as long: " + currentNanos[count]); } } catch (Exception e) { e.printStackTrace(); } } } > -----Original Message----- > From: Tim Anderson [mailto:[EMAIL PROTECTED] > Sent: Tuesday, December 16, 2003 1:18 AM > To: Jakarta Commons Developers List > Subject: RE: UUID Generator? > > > From a licensing perspective, it would be easier > base any commons version on the axis implementation. > The tyrex implementation, while more complete, is > licensed under the Exolab license, and therefore > cannot be hosted in ASF CVS (unless it is donated). > > Also note that the latest draft UUID spec is located > here: http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-01.txt > > -Tim > > > -----Original Message----- > > From: Phil Steitz [mailto:[EMAIL PROTECTED] > > Sent: Tuesday, 16 December 2003 4:29 PM > > To: Jakarta Commons Developers List > > Subject: Re: UUID Generator? > > > > > > Tim Anderson wrote: > > > This question came up earlier this year. > > > Refer to the following thread: > > > http://nagoya.apache.org/eyebrowse/ReadMsg?listId=15&msgNo=32065 > > > > > > Hey Tim, > > > > I recall that we ended up tabling this until after the [lang] 2.0 > > release. > > I am willing to help bring in the axis UUID impl if you are still > > interested in this, or developing a new implementation. > > > > I think that the identifier factory implemented in the unreleased /util > > package contents here: > > http://cvs.apache.org/viewcvs.cgi/jakarta-commons/lang/src/java/or > g/apache/commons/lang/util/ > is a natural place for the UUID generator. I suggest that we replace the > "util" name with "identifier" and add the UUID generator > implementation to > this package, either as an addition to IdentifierUtils or as a separate > implementation. > > Phil > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
