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.EndPointImpl;
28 import jgroup.relacs.types.GroupIndex;
29 import jgroup.relacs.types.IncarnationId;
30
31 /**
32 * The <code>TopologyEntry</code> class
33 *
34 * @author Salvatore Cammarata
35 * @author Hein Meling
36 * @since Jgroup 1.2
37 */
38 final class TopologyEntry
39 implements Externalizable
40 {
41
42 ////////////////////////////////////////////////////////////////////////////////////////////
43 // Fields
44 ////////////////////////////////////////////////////////////////////////////////////////////
45
46 /** */
47 RoutingTableEntry routing;
48
49 /** */
50 EndPoint[] reachable;
51
52 /** */
53 int[] incarnationId;
54
55 /** The number of bytes required to marshal this topology entry instance */
56 private transient int marshalSize;
57
58
59 ////////////////////////////////////////////////////////////////////////////////////////////
60 // Constructors
61 ////////////////////////////////////////////////////////////////////////////////////////////
62
63 /**
64 * Default constructor for externalization
65 */
66 TopologyEntry()
67 {
68 }
69
70
71 /**
72 *
73 */
74 TopologyEntry(RoutingTableEntry rt, MssHost[] members)
75 {
76 marshalSize = RoutingTableEntry.SIZE + GroupIndex.SIZE
77 + members.length*(EndPointImpl.SIZE + IncarnationId.SIZE);
78 routing = rt;
79 reachable = new EndPoint[members.length];
80 incarnationId = new int[members.length];
81 for (int i = 0; i < members.length; i++) {
82 reachable[i] = members[i].getEndPoint();
83 incarnationId[i] = members[i].getIncarnationId();
84 }
85 }
86
87
88 ////////////////////////////////////////////////////////////////////////////////////////////
89 // Methods
90 ////////////////////////////////////////////////////////////////////////////////////////////
91
92 /**
93 * Returns the number of bytes required to marshal this topology
94 * entry instance.
95 */
96 public int getMarshalSize()
97 {
98 return marshalSize;
99 }
100
101
102 /**
103 * Returns the maximum number of bytes required to marshal a topology
104 * entry instance, when the reachability set includes all hosts in
105 * the system.
106 */
107 public static int getMaxSize(int maxNumOfHosts)
108 {
109 return (RoutingTableEntry.SIZE + GroupIndex.SIZE
110 + maxNumOfHosts*(EndPointImpl.SIZE + IncarnationId.SIZE));
111 }
112
113
114 /**
115 * Updates the reachability information for the cluster associated
116 * with this <code>TopologyEntry</code> object.
117 */
118 public boolean updateReachability(MssHost[] members)
119 {
120 boolean changed = false;
121 /*
122 * This at least avoids creating new arrays, if the new set is the
123 * same size as before.
124 */
125 if (reachable.length != members.length) {
126 reachable = new EndPoint[members.length];
127 incarnationId = new int[members.length];
128 marshalSize = RoutingTableEntry.SIZE + GroupIndex.SIZE
129 + members.length*(EndPointImpl.SIZE + IncarnationId.SIZE);
130 changed = true;
131 }
132 for (int i = 0; i < members.length; i++) {
133 reachable[i] = members[i].getEndPoint();
134 incarnationId[i] = members[i].getIncarnationId();
135 }
136 return changed;
137 }
138
139
140 ////////////////////////////////////////////////////////////////////////////////////////////
141 // Methods for externalization
142 ////////////////////////////////////////////////////////////////////////////////////////////
143
144 /**
145 * Restores the content of this object from the marshalled data contained
146 * in the specified input stream.
147 *
148 * @param in the stream to be read
149 */
150 public void readExternal(ObjectInput in)
151 throws IOException, ClassNotFoundException
152 {
153 routing = new RoutingTableEntry();
154 routing.readExternal(in);
155 int len = GroupIndex.unmarshal(in);
156 reachable = new EndPoint[len];
157 incarnationId = new int[len];
158 for (int i=0; i<len; i++){
159 reachable[i] = new EndPointImpl();
160 reachable[i].readExternal(in);
161 incarnationId[i] = IncarnationId.unmarshal(in);
162 }
163 }
164
165
166 /**
167 * Marshals the content of this object to the specified output stream.
168 *
169 * @param out the stream to be written
170 */
171 public void writeExternal(ObjectOutput out)
172 throws IOException
173 {
174 routing.writeExternal(out);
175 GroupIndex.marshal(out, reachable.length);
176 for (int i=0; i<reachable.length; i++) {
177 reachable[i].writeExternal(out);
178 IncarnationId.marshal(out,incarnationId[i]);
179 }
180 }
181
182
183 ////////////////////////////////////////////////////////////////////////////////////////////
184 // Object methods
185 ////////////////////////////////////////////////////////////////////////////////////////////
186
187 /**
188 * Returns a string representation of this object
189 */
190 public String toString()
191 {
192 StringBuilder buf = new StringBuilder("[TopologyEntry: routing=");
193 buf.append(routing);
194 buf.append(", size=");
195 buf.append(reachable.length);
196 buf.append(", reachable={");
197 for (int i = 0; i < reachable.length; i++) {
198 buf.append((i != 0) ? ", " : "");
199 buf.append(reachable[i]);
200 buf.append(":");
201 buf.append(incarnationId[i]);
202 }
203 buf.append("}]");
204 return buf.toString();
205 }
206
207 } // END TopologyEntry