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