view src/org/dancres/blitz/oid/UIDImpl.java @ 27:511648fa4d64 Version 2.1

Version to 2.1
author Dan Creswell <dan.creswell@gmail.com>
date Mon, 04 Jan 2010 13:00:40 +0000
parents 3dc0c5604566
children
line wrap: on
line source

package org.dancres.blitz.oid;

import java.io.Serializable;

import org.dancres.util.BytePacker;

/**
   A unique identifier which can be generated by an Allocator.
 */
final class UIDImpl implements OID {
    static final int KEY_SIZE = 12;

    private transient byte[] theKey;

    private long theId;
    private int theZoneId;

    UIDImpl(byte[] aKey) {
        theKey = aKey;

        BytePacker myPacker = BytePacker.getMSBPacker(theKey);
        theZoneId = myPacker.getInt(0);
        theId = myPacker.getLong(4);
    }

    UIDImpl(int aZoneId, long anId) {
        theId = anId;
        theZoneId = aZoneId;
    }

    public int getZoneId() {
        return theZoneId;
    }

    public long getId() {
        return theId;
    }

    synchronized byte[] getKey() {
        if (theKey == null) {
            theKey = keyFor(theZoneId, theId);
        }

        return theKey;
    }

    public String toString() {
        return " " + theZoneId + "->" + theId;
    }

    public int hashCode() {
        /*
          We include theZoneId to allow for the fact that all allocators for
          a given Entry type will be allocating id's close to each other
          because of the random allocator selection used when an id is
          generated.  Because the id's are allocated evenly, there's a high
          chance of two UID's allocated close together in time colliding unless
          we also factor in theZoneId.
         */
        return theZoneId ^ ((int) (theId ^ (theId >>> 32)));
    }

    public int compareTo(Object anObject) {
        UIDImpl myOther = (UIDImpl) anObject;

        if (theZoneId < myOther.theZoneId)
            return -1;
        else if (theZoneId > myOther.theZoneId)
            return 1;

        if (theId < myOther.theId)
            return -1;
        else if (theId > myOther.theId)
            return 1;
        else
            return 0;
    }

    public boolean equals(Object anObject) {
        if (anObject instanceof UIDImpl) {
            UIDImpl myOther = (UIDImpl) anObject;

            return ((theZoneId == myOther.theZoneId) &&
                    (theId == myOther.theId));
        }
        
        return false;
    }

    private byte[] keyFor(int aZoneId, long anId) {
        byte[] myKey = new byte[12];

        BytePacker myPacker = BytePacker.getMSBPacker(myKey);
        myPacker.putInt(aZoneId, 0);
        myPacker.putLong(anId, 4);

        return myKey;
    }
}