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.mss;
20  
21  import java.io.Externalizable;
22  import java.io.IOException;
23  import java.io.ObjectInput;
24  import java.io.ObjectOutput;
25  
26  import jgroup.core.EndPoint;
27  import jgroup.relacs.types.GroupIndex;
28  
29  /**
30   *  The <code>RoutingTable</code> class
31   *
32   *  @author Salvatore Cammarata
33   *  @author Hein Meling
34   *  @since Jgroup 1.2
35   */
36  public final class RoutingTable 
37    implements MssConstants, Externalizable
38  {
39  
40    ////////////////////////////////////////////////////////////////////////////////////////////
41    // Fields
42    ////////////////////////////////////////////////////////////////////////////////////////////
43  
44    /** Table with topology information */
45    TopologyEntry[] table;
46  
47    /** The number of bytes required to marshal this routing table instance */
48    private transient int marshalSize;
49  
50    /** The reachability threshold for the hosts to include in the routing table. */
51    private transient int threshold;
52  
53    /** The clusters in this system */
54    private transient ClusterTable clustertable;
55  
56  
57    ////////////////////////////////////////////////////////////////////////////////////////////
58    // Constructors
59    ////////////////////////////////////////////////////////////////////////////////////////////
60  
61    /** 
62     *  Default constructor for externalization
63     */
64    public RoutingTable()
65    {
66    }
67  
68    /** 
69     *  
70     */
71    public RoutingTable(ClusterTable ct, int threshold)
72    {
73      marshalSize = GroupIndex.SIZE;
74      this.clustertable = ct;
75      this.threshold = threshold;
76  
77      table = new TopologyEntry[ct.size()];
78      for (int i=0; i<table.length; i++) {
79        Cluster cluster = ct.get(i);
80        table[i] = new TopologyEntry(cluster.getRoutingEntry(), cluster.getReachable(threshold));
81        marshalSize += table[i].getMarshalSize();
82      }
83    }
84  
85  
86    ////////////////////////////////////////////////////////////////////////////////////////////
87    // Methods
88    ////////////////////////////////////////////////////////////////////////////////////////////
89  
90    /**
91     *  Returns the number of bytes required to marshal this routing table
92     *  instance.
93     */
94    public int getMarshalSize()
95    {
96      return marshalSize;
97    }
98  
99  
100   /**
101    *  Returns the maximum number of bytes required to marshal a routing
102    *  table instance, when the reachability set includes all hosts in
103    *  the system.
104    */
105   public static int getMaxSize(int numOfHosts, int numOfClusters)
106   {
107     return GroupIndex.SIZE + (numOfClusters*TopologyEntry.getMaxSize(numOfHosts));
108   }
109 
110 
111   /**
112    *  Updates the reachability information for all clusters in the
113    *  clustertable.
114    *
115    *  @return 
116    *    true if the reachability information in the routing table was
117    *    changed as a consequence of this invocation; false otherwise.
118    */
119   public boolean updateReachability()
120   {
121     marshalSize = GroupIndex.SIZE;
122     boolean changed = false;
123 
124     /*
125      * This at least avoids creating a new array, given that there is no
126      * new clusters in the system.  New clusters should not occur very
127      * often, at least not until we implement dynamic system
128      * configuration.
129      */
130     if (table.length != clustertable.size()) {
131       table = new TopologyEntry[clustertable.size()];
132       for (int i = 0; i < table.length; i++) {
133         Cluster cluster = clustertable.get(i);
134         table[i] = new TopologyEntry(cluster.getRoutingEntry(), cluster.getReachable(threshold));
135         marshalSize += table[i].getMarshalSize();
136       }
137       changed = true;
138     } else {
139       for (int i = 0; i < table.length; i++) {
140         Cluster cluster = clustertable.get(i);
141         /*
142          * Note the compound assignment operator below; used to ensure
143          * that we reflect a change in any one of the clusters.
144          */
145         changed |= table[i].updateReachability(cluster.getReachable(threshold));
146         marshalSize += table[i].getMarshalSize();
147       }
148     }
149     return changed;
150   }
151 
152 
153   /** 
154    *  Negate the cost as reverse poison 
155    */
156   public void splitHorizonOn(EndPoint key) 
157   {
158     for (int i=0; i < table.length; i++)
159       if (table[i].routing.route.equals(key))
160         table[i].routing.cost = -table[i].routing.cost;
161   }
162 
163 
164   /** 
165    *  Reverts all negative routing costs to positive.
166    */
167   public void splitHorizonOff() 
168   {
169     for (int i=0; i < table.length; i++)
170       if (table[i].routing.cost < 0)
171         table[i].routing.cost = -table[i].routing.cost;
172   }
173 
174 
175   ////////////////////////////////////////////////////////////////////////////////////////////
176   // Methods from Externalizable
177   ////////////////////////////////////////////////////////////////////////////////////////////
178   
179   /**
180    *  Restores the content of this object from the marshalled data contained
181    *  in the specified input stream.
182    * 
183    *  @param in the stream to be read
184    */
185   public void readExternal(ObjectInput in)
186     throws IOException, ClassNotFoundException
187   {
188     /* Read the number of entries in the stream */
189     int entries = GroupIndex.unmarshal(in);
190     table = new TopologyEntry[entries];
191     for (int i=0; i < entries; i++) {
192       table[i] = new TopologyEntry();
193       table[i].readExternal(in);
194     }
195   }
196   
197   
198   /**
199    *  Marshals the content of this object to the specified output stream.
200    * 
201    *  @param out the stream to be written
202    */
203   public void writeExternal(ObjectOutput out)
204     throws IOException
205   {
206     GroupIndex.marshal(out, table.length);
207     for (int i=0; i<table.length; i++)
208       table[i].writeExternal(out);
209   }
210 
211   
212   ////////////////////////////////////////////////////////////////////////////////////////////
213   // Methods from Object
214   ////////////////////////////////////////////////////////////////////////////////////////////
215 
216   /**
217    *  Returns a string representation of this object
218    */
219   public String toString() 
220   {
221     StringBuilder buf = new StringBuilder("[RoutingTable: length=");
222     buf.append(table.length);
223     buf.append(", {");
224     for (int i = 0; i < table.length; i++) {
225       buf.append((i != 0) ? ", " : "");
226       buf.append(table[i].toString());
227     }
228     buf.append("}]");
229     return buf.toString();
230   }
231 
232 } // END RoutingTable
233