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]

Reply via email to