commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Tim Reilly" <tim.rei...@consultant.com>
Subject [lang] UUID Generator - was RE: UUID Generator?
Date Tue, 16 Dec 2003 07:46:25 GMT
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 apache@apache.org.
 *
 * 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:tma@netspace.net.au]
> 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:phil@steitz.com]
> > 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: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message