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.daemon;
20
21
22 import java.io.IOException;
23 import java.io.ObjectInput;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import jgroup.core.EndPoint;
28 import jgroup.relacs.mss.MssConstants;
29 import jgroup.relacs.types.EndPointImpl;
30 import jgroup.relacs.types.GroupId;
31 import jgroup.relacs.types.GroupIndex;
32 import jgroup.relacs.types.VersionId;
33 import jgroup.util.MsgFactory;
34 import jgroup.util.OutMessage;
35
36
37 /**
38 * The <code> MsgSymm</code> class
39 *
40 * @author Alberto Montresor
41 * @since Jgroup 0.1
42 */
43 final class MsgSymm
44 implements MssConstants, DaemonMsg
45 {
46
47 ////////////////////////////////////////////////////////////////////////////////////////////
48 // Position constants
49 ////////////////////////////////////////////////////////////////////////////////////////////
50
51 private static final int START = MSS_HEADER_SIZE;
52
53
54 ////////////////////////////////////////////////////////////////////////////////////////////
55 // Unique message instance
56 ////////////////////////////////////////////////////////////////////////////////////////////
57
58 /**
59 * As these messages are never stored by the daemon, a single message
60 * instance is sufficient. In this way, we save the costs of
61 * allocating and garbage collecting messages.
62 */
63 private static MsgSymm msg = new MsgSymm();
64
65 /** The marshalled message data (also static for same reason as above) */
66 private static OutMessage outmsg;
67
68
69 ////////////////////////////////////////////////////////////////////////////////////////////
70 // Fields
71 ////////////////////////////////////////////////////////////////////////////////////////////
72
73 /** Sender version number */
74 int vsend;
75
76 /** Host identifiers */
77 EndPoint[] hosts;
78
79 /** Corresponding version numbers */
80 int[] version;
81
82 /** Reachable set */
83 EndPoint[] rset;
84
85
86 ////////////////////////////////////////////////////////////////////////////////////////////
87 // Decoding methods
88 ////////////////////////////////////////////////////////////////////////////////////////////
89
90 /**
91 * Creates a new instance of MsgSymm starting from a m-received msg
92 * input stream
93 */
94 static MsgSymm unmarshal(ObjectInput msgstream)
95 throws IOException, ClassNotFoundException
96 {
97 /* Read sender version number */
98 msg.vsend = VersionId.unmarshal(msgstream);
99
100 /* Read host identifiers and version numbers of the nrset */
101 int len = GroupIndex.unmarshal(msgstream);
102 msg.version = new int[len];
103 msg.hosts = new EndPoint[len];
104 for (int i=0; i < len; i++) {
105 msg.hosts[i] = new EndPointImpl();
106 msg.hosts[i].readExternal(msgstream);
107 msg.version[i] = VersionId.unmarshal(msgstream);
108 }
109
110 /* Read the rset array */
111 len = GroupIndex.unmarshal(msgstream);
112 msg.rset = new EndPoint[len];
113 for (int i=0; i < len; i++) {
114 msg.rset[i] = new EndPointImpl();
115 msg.rset[i].readExternal(msgstream);
116 }
117 return msg;
118 }
119
120
121 ////////////////////////////////////////////////////////////////////////////////////////////
122 // Encoding methods
123 ////////////////////////////////////////////////////////////////////////////////////////////
124
125 /**
126 * Copies informations into Message structure
127 */
128 static MsgSymm marshal(int gid, int vsend, List nrset, EndPoint[] rset, int nreceivers)
129 throws IOException
130 {
131 /* Allocates data buffer */
132 int size = START + GroupId.SIZE + VersionId.SIZE + 2 * GroupIndex.SIZE + nrset.size() *
133 (VersionId.SIZE + EndPointImpl.SIZE) + rset.length * EndPointImpl.SIZE;
134 outmsg = MsgFactory.get(size, nreceivers);
135 outmsg.seek(START);
136
137 /* Write group identifier and sender version number */
138 GroupId.marshal(outmsg, gid);
139 VersionId.marshal(outmsg, vsend);
140
141 /*
142 * Writes the identifier of the endpoints contained in nrset,
143 * together with their version numbers.
144 */
145 GroupIndex.marshal(outmsg, nrset.size());
146 Iterator iterator = nrset.iterator();
147 while (iterator.hasNext()) {
148 HostData data = (HostData) iterator.next();
149 data.getEndPoint().writeExternal(outmsg);
150 VersionId.marshal(outmsg, data.getVersion());
151 }
152
153 /*
154 * Writes the identifier of the endpoints contained in rset
155 */
156 GroupIndex.marshal(outmsg, rset.length);
157 for (int i=0; i < rset.length; i++)
158 rset[i].writeExternal(outmsg);
159
160 return msg;
161 }
162
163
164 /**
165 * Copies informations into Message structure
166 */
167 static MsgSymm marshal(int gid, int vsend, HostData dest, EndPoint[] rset, int nreceivers)
168 throws IOException
169 {
170 /* Allocates data buffer */
171 int size = START + GroupId.SIZE + VersionId.SIZE + 2 * GroupIndex.SIZE +
172 VersionId.SIZE + EndPointImpl.SIZE + rset.length * EndPointImpl.SIZE;
173 outmsg = MsgFactory.get(size, nreceivers);
174 outmsg.seek(START);
175
176 /* Write group identifier and sender version number */
177 GroupId.marshal(outmsg, gid);
178 VersionId.marshal(outmsg, vsend);
179
180 /* Write dest identifier and version number */
181 GroupIndex.marshal(outmsg, 1);
182 dest.getEndPoint().writeExternal(outmsg);
183 VersionId.marshal(outmsg, dest.getVersion());
184
185 /*
186 * Writes the identifier of the endpoints contained in rset
187 */
188 GroupIndex.marshal(outmsg, rset.length);
189 for (int i=0; i < rset.length; i++)
190 rset[i].writeExternal(outmsg);
191
192 return msg;
193 }
194
195
196 ////////////////////////////////////////////////////////////////////////////////////////////
197 // Methods from DaemonMsg
198 ////////////////////////////////////////////////////////////////////////////////////////////
199
200 public int size()
201 {
202 /* Note; it is ok to use the outmsg size since MsgSymm will never be
203 * forwarded or resent (it is not queued). */
204 return outmsg.size();
205 }
206
207 public OutMessage getOutMessage()
208 {
209 return outmsg;
210 }
211
212
213 ////////////////////////////////////////////////////////////////////////////////////////////
214 // Methods from Object
215 ////////////////////////////////////////////////////////////////////////////////////////////
216
217 /**
218 * Returns a string representation of this object
219 */
220 public String toString()
221 {
222 StringBuilder buffer = new StringBuilder();
223 buffer.append("[MsgSymm: vsend=");
224 buffer.append(vsend);
225 buffer.append(", rset={");
226 for (int i=0; i < rset.length; i++) {
227 buffer.append(rset[i]);
228 if (i < rset.length-1)
229 buffer.append(", ");
230 }
231 buffer.append("}, hosts={");
232 for (int i=0; i < hosts.length; i++) {
233 buffer.append(hosts[i]);
234 if (i < hosts.length-1)
235 buffer.append(", ");
236 }
237 buffer.append("}, versions={");
238 for (int i=0; i < version.length; i++) {
239 buffer.append(version[i]);
240 if (i < version.length-1)
241 buffer.append(", ");
242 }
243 buffer.append("}]");
244 return buffer.toString();
245 }
246
247 } // END MsgSymm