Package com.arjuna.ats.arjuna.common

Source Code of com.arjuna.ats.arjuna.common.Uid

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*
* (C) 2005-2006,
* @author JBoss Inc.
*/
/*
* Copyright (C) 1998, 1999, 2000, 2001,
*
* Arjuna Solutions Limited,
* Newcastle upon Tyne,
* Tyne and Wear,
* UK. 
*
* $Id: Uid.java 2342 2006-03-30 13:06:17Z  $
*/

package com.arjuna.ats.arjuna.common;

import com.arjuna.ats.arjuna.state.InputBuffer;
import com.arjuna.ats.arjuna.state.OutputBuffer;
import com.arjuna.ats.arjuna.utils.Utility;

import java.lang.Cloneable;
import java.io.Serializable;
import java.io.PrintStream;

import com.arjuna.ats.arjuna.exceptions.FatalError;
import java.io.IOException;
import java.net.UnknownHostException;
import java.lang.StringIndexOutOfBoundsException;
import java.lang.NumberFormatException;
import java.lang.CloneNotSupportedException;
import java.util.concurrent.atomic.AtomicInteger;

import com.arjuna.ats.arjuna.logging.tsLogger;

/**
* Implements a unique identity class.
*
* @author Mark Little (mark@arjuna.com)
* @version $Id: Uid.java 2342 2006-03-30 13:06:17Z  $
* @since 1.0.
*
* @message com.arjuna.ats.arjuna.common.Uid_1
*          [com.arjuna.ats.arjuna.common.Uid_1] - cannot get local host.
* @message com.arjuna.ats.arjuna.common.Uid_2
*          [com.arjuna.ats.arjuna.common.Uid_2] - Uid.Uid string constructor
*          could not create nullUid
* @message com.arjuna.ats.arjuna.common.Uid_3
*          [com.arjuna.ats.arjuna.common.Uid_3] - Uid general parsing error:
*          {0}
* @message com.arjuna.ats.arjuna.common.Uid_4
*          [com.arjuna.ats.arjuna.common.Uid_4] - Uid.Uid string constructor
*          could not create nullUid for incorrect string: {0}
* @message com.arjuna.ats.arjuna.common.Uid_5
*          [com.arjuna.ats.arjuna.common.Uid_5] - Uid.Uid string constructor
*          incorrect: {0}
* @message com.arjuna.ats.arjuna.common.Uid_6
*          [com.arjuna.ats.arjuna.common.Uid_6] - Uid.generateHash called for
*          invalid Uid. Will ignore.
* @message com.arjuna.ats.arjuna.common.Uid_7
*          [com.arjuna.ats.arjuna.common.Uid_7] - nullUid error for
* @message com.arjuna.ats.arjuna.common.Uid_8
*          [com.arjuna.ats.arjuna.common.Uid_8] - Invalid string:
* @message com.arjuna.ats.arjuna.common.Uid_9
*          [com.arjuna.ats.arjuna.common.Uid_9] - Invalid Uid object.
* @message com.arjuna.ats.arjuna.common.Uid_10
*          [com.arjuna.ats.arjuna.common.Uid_10] - Cannot unpack into nullUid!
*/

public class Uid implements Cloneable, Serializable
{
  private static final long serialVersionUID = 7808395904206530189L;

  /**
   * Create a new instance.
   */

  public Uid ()
  {
    hostAddr = -1;
    process = 0;
    sec = 0;
    other = 0;
    _hashValue = -1;
    _valid = true;

    try
    {
      hostAddr = Utility.hostInetAddr(); /* calculated only once */
      process = Utility.getpid();

      if (Uid.initTime == 0)
        Uid.initTime = (int) (System.currentTimeMillis() / 1000);

      sec = Uid.initTime;

      other = Uid.getValue();
    }
    catch (UnknownHostException e)
    {
      if (tsLogger.arjLoggerI18N.isWarnEnabled())
        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.common.Uid_1");
      _valid = false;
    }
  }

  /**
   * Create a copy of the specified identifier.
   */

  public Uid (Uid copyFrom)
  {
    copy(copyFrom);
  }

  /**
   * Create Uid from string representation. If the string does not represent a
   * valid Uid then the instance will be set to nullUid.
   */

  public Uid (String uidString)
  {
    this(uidString, true);
  }

  /**
   * Create Uid from string representation. boolean arg says whether to give
   * up if an error is detected or to simply replace with nullUid.
   */

  public Uid (String uidString, boolean errsOk)
  {
    char theBreakChar = Uid.getBreakChar(uidString);

    hostAddr = -1;
    process = 0;
    sec = 0;
    other = 0;
    _hashValue = -1;
    _valid = false;

    if (uidString.length() > 0)
    {
      int startIndex = 0;
      int endIndex = 0;
      String s = null;

      try
      {
        while (uidString.charAt(endIndex) != theBreakChar)
          endIndex++;

        s = uidString.substring(startIndex, endIndex);
        hostAddr = (int) Utility.hexStringToLong(s);

        startIndex = endIndex + 1;
        endIndex++;

        while (uidString.charAt(endIndex) != theBreakChar)
          endIndex++;

        s = uidString.substring(startIndex, endIndex);
        process = (int) Utility.hexStringToLong(s);

        startIndex = endIndex + 1;
        endIndex++;

        while (uidString.charAt(endIndex) != theBreakChar)
          endIndex++;

        s = uidString.substring(startIndex, endIndex);
        sec = (int) Utility.hexStringToLong(s);

        s = uidString.substring(endIndex + 1, uidString.length());
        other = (int) Utility.hexStringToLong(s);

        _valid = true;
      }
      catch (NumberFormatException e)
      {
        if (!errsOk)
        {
          if (tsLogger.arjLoggerI18N.isWarnEnabled())
          {
            tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.common.Uid_3", new Object[]
            { uidString });
          }
        }

        _valid = false;
      }
      catch (StringIndexOutOfBoundsException e)
      {
        _valid = false;
      }
    }
    else
    {
      this.copy(Uid.nullUid());
    }

    if (!_valid)
    {
      if (errsOk)
      {
        try
        {
          this.copy(Uid.nullUid());
        }
        catch (Exception e)
        {
          if (tsLogger.arjLoggerI18N.isFatalEnabled())
          {
            tsLogger.arjLoggerI18N.fatal("com.arjuna.ats.arjuna.common.Uid_4", new Object[]
            { uidString });
          }

          throw new FatalError(
              tsLogger.log_mesg.getString("com.arjuna.ats.arjuna.common.Uid_2"));
        }
      }
      else
      {
        if (tsLogger.arjLoggerI18N.isFatalEnabled())
        {
          tsLogger.arjLoggerI18N.fatal("com.arjuna.ats.arjuna.common.Uid_5", new Object[]
          { uidString });
        }

        throw new FatalError(
            tsLogger.log_mesg.getString("com.arjuna.ats.arjuna.common.Uid_3")
                + uidString);
      }
    }
  }

  /**
   * Override Object.hashCode. We always return a positive value.
   */

  /*
   * generateHash should have been called by now.
   */

  public int hashCode ()
  {
    if (_hashValue == -1)
      generateHash();

    return _hashValue;
  }

  /**
   * Routines to pack and unpack Uids into Buffers (for RPC, storage etc)
   */

  public synchronized void pack (OutputBuffer packInto) throws IOException
  {
    if (_valid)
    {
      packInto.packInt(hostAddr);
      packInto.packInt(process);
      packInto.packInt(sec);
      packInto.packInt(other);
    }
    else
      throw new IOException(
          tsLogger.log_mesg.getString("com.arjuna.ats.arjuna.common.Uid_9"));
  }

  public synchronized void unpack (InputBuffer unpackFrom) throws IOException
  {
    /*
     * Prevent nullUid being overwritten by unpack.
     */

    if (this == Uid.nullUid())
      throw new IOException(
          tsLogger.log_mesg.getString("com.arjuna.ats.arjuna.common.Uid_10"));

    _valid = true; // should not be able to pack an invalid Uid.

    try
    {
      hostAddr = unpackFrom.unpackInt();
      process = unpackFrom.unpackInt();
      sec = unpackFrom.unpackInt();
      other = unpackFrom.unpackInt();

      _hashValue = -1;
    }
    catch (IOException e)
    {
      _valid = false;

      throw e;
    }
  }

  /**
   * Print a human-readable form of the Uid.
   */

  public void print (PrintStream strm)
  {
    strm.print("<Uid:" + this.toString() + ">");
  }

  public String stringForm ()
  {
    return Utility.intToHexString(hostAddr) + Uid.breakChar
        + Utility.intToHexString(process) + Uid.breakChar
        + Utility.intToHexString(sec) + Uid.breakChar
        + Utility.intToHexString(other);
  }

  /**
   * @return a string representation of the Uid with all : replaced by _ so
   *         that the name may be used as a file name.
   */

  public String fileStringForm ()
  {
    return Utility.intToHexString(hostAddr) + Uid.fileBreakChar
        + Utility.intToHexString(process) + Uid.fileBreakChar
        + Utility.intToHexString(sec) + Uid.fileBreakChar
        + Utility.intToHexString(other);
  }

  /**
   * Same as stringForm()
   */

  public String toString ()
  {
    return stringForm();
  }

  /**
   * Create a copy of this instance.
   */

  public Object clone () throws CloneNotSupportedException
  {
    return new Uid(this);
  }

  /**
   * Copy the specified Uid over this instance.
   */

  public synchronized void copy (Uid toCopy)
  {
    if (toCopy == this)
      return;

    hostAddr = toCopy.hostAddr;
    process = toCopy.process;
    sec = toCopy.sec;
    other = toCopy.other;
    _hashValue = toCopy._hashValue;
    _valid = toCopy._valid;
  }

  /**
   * Uid comparisons.
   */

  /**
   * Override Object.equals
   */

  public boolean equals (Object o)
  {
    if (o instanceof Uid)
      return this.equals((Uid) o);
    else
      return false;
  }

  public boolean equals (Uid u)
  {
    if (u == null)
      return false;

    if (u == this)
      return true;

    return ((other == u.other) && (sec == u.sec) && (process == u.process) && (hostAddr == u.hostAddr));
  }

  public boolean notEquals (Uid u)
  {
    if (u == null)
      return true;

    if (u == this)
      return false;

    return ((other != u.other) || (sec != u.sec) || (process != u.process) || (hostAddr != u.hostAddr));
  }

  public boolean lessThan (Uid u)
  {
    if (u == null)
      return false;

    if (u == this)
      return false;

    if (this.equals(u))
      return false ;
   
    if (LAST_RESOURCE_UID.equals(this))
      return false ;
   
    if (LAST_RESOURCE_UID.equals(u))
      return true ;
   
    if (hostAddr < u.hostAddr)
      return true;
    else
      if (hostAddr == u.hostAddr)
      {
        if (process < u.process)
          return true;
        else
          if (process == u.process)
          {
            if (sec < u.sec)
              return true;
            else
              if ((sec == u.sec) && (other < u.other))
                return true;
          }
      }
    return false;
  }

  public boolean greaterThan (Uid u)
  {
    if (u == null)
      return false;

    if (u == this)
      return false;

    if (this.equals(u))
      return false ;
   
    if (LAST_RESOURCE_UID.equals(this))
      return true ;
   
    if (LAST_RESOURCE_UID.equals(u))
      return false ;

    if (hostAddr > u.hostAddr)
      return true;
    else
      if (hostAddr == u.hostAddr)
      {
        if (process > u.process)
          return true;
        else
          if (process == u.process)
          {
            if (sec > u.sec)
              return true;
            else
              if ((sec == u.sec) && (other > u.other))
                return true;
          }
      }
    return false;
  }

  /**
   * Is the Uid valid?
   */

  public synchronized final boolean valid ()
  {
    return _valid;
  }

  /**
   * Return a null Uid (0:0:0:0)
   */

  public static final Uid nullUid ()
  {
    return NIL_UID;
  }

  /**
   * Return a last resource Uid (0:0:0:1)
   */
  public static final Uid lastResourceUid ()
  {
    return LAST_RESOURCE_UID;
  }

  /**
   * Return the maximum Uid (7fffffff:7fffffff:7fffffff:7fffffff)
   */
  public static final Uid maxUid ()
  {
    return MAX_UID;
  }
 
  /**
   * Return the minimum Uid (-80000000:-80000000:-80000000:-80000000)
   */
  public static final Uid minUid ()
  {
    return MIN_UID;
  }

  /*
   * Serialization methods. Similar to buffer packing. If the Uid is invalid
   * the an IOException is thrown.
   *
   * @since JTS 2.1.
   */

  private void writeObject (java.io.ObjectOutputStream out)
      throws IOException
  {
    if (_valid)
    {
      out.writeInt(hostAddr);
      out.writeInt(process);
      out.writeInt(sec);
      out.writeInt(other);
    }
    else
      throw new IOException("Invalid Uid object.");
  }

  /*
   * Serialization methods. Similar to buffer unpacking. If the
   * unserialization fails then an IOException is thrown.
   *
   * @since JTS 2.1.
   */

  private void readObject (java.io.ObjectInputStream in) throws IOException,
      ClassNotFoundException
  {
    _valid = true; // should not be able to pack an invalid Uid.

    try
    {
      hostAddr = in.readInt();
      process = in.readInt();
      sec = in.readInt();
      other = in.readInt();
      _hashValue = -1; // Set hashvalue to -1 to force a regeneration
                // of the hashcode
    }
    catch (IOException e)
    {
      _valid = false;

      throw e;
    }
  }

    private static final int MAX_SEQ_VALUE = 0x40000000; // 2^30, which is a bit conservative.

  private static int getValue ()
  {
        int value = 0;
        do {
            value = uidsCreated.getAndIncrement();
            if(value == MAX_SEQ_VALUE) {
                uidsCreated.set(0);
                initTime = (int) (System.currentTimeMillis() / 1000);
            }
        } while(value >= MAX_SEQ_VALUE);

        return value;
  }

  /*
   * Is an idempotent operation, so can be called more than once without
   * adverse effect.
   */

  private final synchronized void generateHash ()
  {
    if (_valid)
    {
      if (true)
        _hashValue = hostAddr ^ process ^ sec ^ other;
      else
      {
        int g = 0;
        String p = toString();
        int len = p.length();
        int index = 0;

        if (len > 0)
        {
          while (len-- > 0)
          {
            _hashValue = (_hashValue << 4)
                + (int) (p.charAt(index));
            g = _hashValue & 0xf0000000;

            if (g > 0)
            {
              _hashValue = _hashValue ^ (g >> 24);
              _hashValue = _hashValue ^ g;
            }

            index++;
          }
        }
      }

      /*
       * Integers are signed in Java, so we have to be careful and only
       * return a signed value.
       */

      if (_hashValue < 0)
        _hashValue = -_hashValue;
    }
    else
    {
      if (tsLogger.arjLoggerI18N.isWarnEnabled())
        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.common.Uid_6");
    }
  }

  /*
   * Since we may be given a Uid from the file system (which uses '_' to
   * separate fields, we need to be able to convert.
   */

  private static final char getBreakChar (String uidString)
  {
    if (uidString == null)
      return Uid.breakChar;

    if (uidString.indexOf(fileBreakChar) != -1)
      return Uid.fileBreakChar;
    else
      return Uid.breakChar;
  }

  // use ints rather than longs for interoperability with C++ version

  private volatile int hostAddr;

  private volatile int process;

  private volatile int sec;

  private volatile int other;

  private volatile int _hashValue;

  private volatile boolean _valid;
 
  private static final AtomicInteger uidsCreated = new AtomicInteger();

  private static volatile int initTime ;

  private static final char breakChar = ':';

  private static final char fileBreakChar = '_';

  private static final Uid NIL_UID = new Uid("0:0:0:0") ;

  private static final Uid LAST_RESOURCE_UID = new Uid("0:0:0:1") ;
 
  private static final Uid MAX_UID = new Uid("7fffffff:7fffffff:7fffffff:7fffffff") ;
 
  private static final Uid MIN_UID = new Uid("-80000000:-80000000:-80000000:-80000000") ;
}
TOP

Related Classes of com.arjuna.ats.arjuna.common.Uid

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.