View Javadoc

1   /*
2    * Copyright (c) 1998-2002 The Jgroup Team.
3    *
4    * This program is free software; you can redistribute it and/or modify
5    * it under the terms of the GNU Lesser General Public License version 2 as
6    * published by the Free Software Foundation.
7    *
8    * This program is distributed in the hope that it will be useful,
9    * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   * GNU Lesser General Public License for more details.
12   *
13   * You should have received a copy of the GNU Lesser General Public License
14   * along with this program; if not, write to the Free Software
15   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16   *
17   */
18  
19  package jgroup.relacs.types;
20  
21  import java.io.IOException;
22  import java.io.ObjectInput;
23  import java.io.ObjectOutput;
24  import java.net.InetAddress;
25  import java.net.UnknownHostException;
26  
27  import jgroup.core.VMID;
28  import jgroup.util.Abort;
29  import jgroup.util.Network;
30  
31  /**
32   *  The <code>VMIDImpl</code> class implements the <code>VMID</code>
33   *  interface to uniquely identify a Java Virtual Machine.
34   *
35   *  @author Alberto Montresor
36   *  @author Hein Meling
37   *  @since Jgroup 0.7
38   */
39  public final class VMIDImpl
40    implements VMID
41  {
42  
43    ////////////////////////////////////////////////////////////////////////////////////////////
44    // Fields
45    ////////////////////////////////////////////////////////////////////////////////////////////
46  
47    private static final long serialVersionUID = 6243630502385386084L;
48  
49    /** IP address of the generating host */
50    private InetAddress inetAddress;
51  
52    /** Integer representation of the above IP address */
53    private int address;
54  
55    /** Random number to distinguish concurrent JVMs on the same host */
56    private int hash;
57  
58    /** Time when this <code>VMID</code> was generated */
59    private long time;
60  
61  
62    ////////////////////////////////////////////////////////////////////////////////////////////
63    // Static section
64    ////////////////////////////////////////////////////////////////////////////////////////////
65  
66    /** Unique virtual machine identifier for the local host */
67    private static VMID vmid;
68  
69    /*
70     *  Create a virtual machine identifier for the local host.
71     */
72    static {
73      try {
74        InetAddress inetAddress = Network.getLocalHost();
75        long time = System.currentTimeMillis();
76        int hash = (new Object()).hashCode();
77        vmid = new VMIDImpl(inetAddress, time, hash);
78      } catch (Exception e) {
79        Abort.exit("Failed to generate an identifier for the virtual machine", e, 1);
80      }
81    }
82  
83  
84    /**
85     *  Returns the <code>VMID</code> for the local Java Virtual Machine.
86     */
87    public static VMID getLocalVMID()
88    {
89      return vmid;
90    }
91  
92  
93    ////////////////////////////////////////////////////////////////////////////////////////////
94    // Constructors
95    ////////////////////////////////////////////////////////////////////////////////////////////
96  
97    /**
98     *  Public default constructor for externalization.
99     */
100   public VMIDImpl()
101   {
102   }
103 
104   /**
105    *  Private constructor.
106    */
107   private VMIDImpl(InetAddress inetAddress, long time, int hash)
108   {
109     this.inetAddress = inetAddress;
110     this.time = time;
111     this.hash = hash;
112     this.address = Network.translate(inetAddress);
113   }
114 
115 
116   ////////////////////////////////////////////////////////////////////////////////////////////
117   // Methods from the VMID interface
118   ////////////////////////////////////////////////////////////////////////////////////////////
119 
120   /**
121    *  Returns the address of the host in which the virtual machine
122    *  identified by this <code>VMID</code> is executed.
123    */
124   public InetAddress getAddress()
125     throws UnknownHostException
126   {
127     /*
128      * If the inetAddress is null it means that this object must have
129      * been serialized, and thus we only have an integer representation
130      * of this JVMs internet address.  Thus, we convert the int
131      * representation to an InetAddress representation.
132      */
133     if (inetAddress == null)
134       inetAddress = Network.translate(address);
135     return inetAddress;
136   }
137 
138 
139   /**
140    *  Returns the time at which this <code>VMID</code> has been created.
141    */
142   public long getTime()
143   {
144     return time;
145   }
146 
147 
148   ////////////////////////////////////////////////////////////////////////////////////////////
149   // Methods from Object
150   ////////////////////////////////////////////////////////////////////////////////////////////
151 
152   /**
153    *  Returns a string representation of this object.
154    */
155   public String toString()
156   {
157     StringBuilder buf = new StringBuilder();
158     buf.append("[VMID: ");
159     buf.append(Network.translateToString(address));
160     buf.append(", ");
161     buf.append(time);
162     buf.append(", ");
163     buf.append(hash);
164     buf.append("]");
165     return buf.toString();
166   }
167 
168 
169   /**
170    *  Returns a hashcode for the <code>VMIDImpl</code>.  Two
171    *  <code>VMIDImpl</code>s will have the same hashcode if they are
172    *  equal with respect to their content.
173    */
174   public int hashCode()
175   {
176     return address + (int) time + hash;
177   }
178 
179 
180   /**
181    *  Compares two objects for content equality.
182    *
183    *  @param obj the object to compare with
184    *  @return true if these objects are equal; false otherwise.
185    */
186   public boolean equals(Object obj)
187   {
188     if (!(obj instanceof VMIDImpl))
189       return false;
190     VMIDImpl vmid = (VMIDImpl) obj;
191     return (hash == vmid.hash && address == vmid.address && time == vmid.time);
192   }
193 
194 
195   ////////////////////////////////////////////////////////////////////////////////////////////
196   // Methods from Externalizable
197   ////////////////////////////////////////////////////////////////////////////////////////////
198 
199   /**
200    *  Write the content of this VMID on stream <tt>out</tt>.  Note that
201    *  the InetAddress is not serialized, because too inefficient.  If
202    *  requested, the InetAddress is retrieved through DNS lookup in
203    *  method <tt>getAddress</tt>.
204    * 
205    *  @param out the stream to be written
206    */
207   public void writeExternal(ObjectOutput out)
208     throws IOException
209   {
210     out.writeInt(hash);
211     out.writeLong(time);
212     out.writeInt(address);
213   }
214 
215   /**
216    *  Restores the content of this object from the marshalled data contained
217    *  in the specified input stream.
218    * 
219    *  @param in the stream to be read
220    */
221   public void readExternal(ObjectInput in)
222     throws IOException
223   {
224     hash = in.readInt();
225     time = in.readLong();
226     address = in.readInt();
227   }
228 
229 } // END VMIDImpl