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.IOException;
22 import java.io.ObjectInput;
23
24 import jgroup.relacs.types.MessageId;
25 import jgroup.util.InMessage;
26 import jgroup.util.MsgFactory;
27 import jgroup.util.OutMessage;
28
29 /**
30 * The <code>MsgSYN</code> class is used to synchronize the message
31 * (fragment) identifiers of the different hosts within the distributed
32 * system. This message type is never broadcast, and it will always
33 * fit within a fragment, given that the payload is set above 9.
34 *
35 * Note that this message is currently queued in the MssHost, enabling
36 * us to check the correctness of a ASYN wrt. a previously sent QSYN
37 * message. This prevents us from using a single message instance for
38 * all SYN messages.
39 *
40 * @author Hein Meling
41 * @since Jgroup 1.2
42 */
43 final class MsgSYN
44 implements Msg, MssConstants, MssTag
45 {
46
47 ////////////////////////////////////////////////////////////////////////////////////////////
48 // Size
49 ////////////////////////////////////////////////////////////////////////////////////////////
50
51 /** Message size (1+4+4) bytes */
52 private static final int MSG_SIZE = 9;
53
54
55 ////////////////////////////////////////////////////////////////////////////////////////////
56 // Message Fields (static part)
57 ////////////////////////////////////////////////////////////////////////////////////////////
58
59 /* Type of synchronization message (QSYN, ASYN) */
60 private byte synchType;
61
62 /** Message identifier for this message */
63 private int nonce;
64
65 /** Last message sent by the sender of this synchronization message */
66 private int lastMsgSent;
67
68
69 ////////////////////////////////////////////////////////////////////////////////////////////
70 // Transient fields (recomputed during unmarshalling)
71 ////////////////////////////////////////////////////////////////////////////////////////////
72
73 /** Message to be sent */
74 private transient OutMessage outmsg;
75
76 /** Receiver of this SYN message (not transmitted) */
77 private transient MssHost receiver = null;
78
79 /** The message sender (obtained from the fragment header) */
80 private transient MssHost sender;
81
82
83 ////////////////////////////////////////////////////////////////////////////////////////////
84 // Constructors and marshalling methods
85 ////////////////////////////////////////////////////////////////////////////////////////////
86
87 /**
88 * Used for ASYN
89 */
90 static MsgSYN marshal(byte synchType, MsgSYN msg, int lastMsgSent)
91 throws IOException
92 {
93 return new MsgSYN(synchType, msg.getSender(), msg.nonce, lastMsgSent);
94 }
95
96
97 /**
98 * Used for QSYN
99 */
100 static MsgSYN marshal(byte synchType, MssHost receiver)
101 throws IOException
102 {
103 return new MsgSYN(synchType, receiver, RandomGenerator.newNonce(), UNDEF);
104 }
105
106
107 /**
108 * Marshalling constructor
109 */
110 private MsgSYN(byte synchType, MssHost receiver, int nonce, int lastMsgSent)
111 throws IOException
112 {
113 sender = HostTable.getLocalHost();
114 this.receiver = receiver;
115 outmsg = MsgFactory.get(MSG_SIZE);
116
117 this.synchType = synchType;
118 this.nonce = nonce;
119 this.lastMsgSent = lastMsgSent;
120
121 outmsg.writeByte(synchType);
122 MessageId.marshal(outmsg, nonce);
123 MessageId.marshal(outmsg, lastMsgSent);
124 }
125
126
127 /**
128 *
129 */
130 static MsgSYN unmarshal(ObjectInput inmsg, FragmentHeader header)
131 throws IOException, ClassNotFoundException
132 {
133 return new MsgSYN((InMessage) inmsg, header);
134 }
135
136
137 /**
138 * Unmarshalling contructor
139 */
140 private MsgSYN(InMessage in, FragmentHeader header)
141 throws IOException, ClassNotFoundException
142 {
143 sender = header.getSender();
144 synchType = in.readByte();
145 nonce = MessageId.unmarshal(in);
146 lastMsgSent = MessageId.unmarshal(in);
147 }
148
149
150 ////////////////////////////////////////////////////////////////////////////////////////////
151 // Methods
152 ////////////////////////////////////////////////////////////////////////////////////////////
153
154 byte getSYNType()
155 {
156 return synchType;
157 }
158
159
160 int getLastMsgSent()
161 {
162 return lastMsgSent;
163 }
164
165
166 /**
167 * Returns the receiver of this message. This method should only be
168 * invoked on the sending side, since it does not make sense to query
169 * the receiver at the receiving end (the receiver would be local
170 * host). Therefore the receiver field is not transmitted either.
171 *
172 * @exception IllegalStateException
173 * Thrown if invoked on the receiving side.
174 */
175 MssHost getReceiver()
176 {
177 if (receiver == null)
178 throw new IllegalStateException("Cannot obtain receiver on receiving side (it is the localhost)");
179 return receiver;
180 }
181
182
183 /**
184 * Returns true if the sender of this message is the local host.
185 */
186 public boolean isLocal()
187 {
188 return sender.isLocal();
189 }
190
191
192 ////////////////////////////////////////////////////////////////////////////////////////////
193 // Fragmentation handling (from Msg interface)
194 ////////////////////////////////////////////////////////////////////////////////////////////
195
196 /*
197 * The fragmentation iterator instance for this message; it can be
198 * reused for multiple iterations over this message.
199 */
200 private transient MsgFragmentIterator fragIter = null;
201
202
203 /**
204 * Returns a <code>FragmentIterator</code> for this
205 * <code>MsgSYN</code> object. This iterator allows to send the
206 * entire message as multiple fragments of specified size (payload).
207 * At the same time, it marks each fragment with a tag and message
208 * identifier provided through the <code>next()</code> method of the
209 * iterator.
210 */
211 public FragmentIterator iterator(MsgCntrl msgCntrl)
212 {
213 /* If there is already an iterator for this message, we reuse it. */
214 if (fragIter == null)
215 fragIter = new MsgFragmentIterator(this, msgCntrl);
216 else
217 fragIter.reset(outmsg);
218 return fragIter;
219 }
220
221
222
223 ////////////////////////////////////////////////////////////////////////////////////////////
224 // Msg interface methods
225 ////////////////////////////////////////////////////////////////////////////////////////////
226
227 /**
228 * Returns the tag associated with this message.
229 */
230 public byte getTag()
231 {
232 return SYN;
233 }
234
235
236 /**
237 * Returns the message identifier for this message.
238 */
239 public int getMid()
240 {
241 return nonce;
242 }
243
244
245 /**
246 * Returns the sender of this message.
247 */
248 public MssHost getSender()
249 {
250 return sender;
251 }
252
253
254 /**
255 * Returns false always, since synchronization messages should never
256 * be routed.
257 */
258 public boolean hasToBeRouted()
259 {
260 return false;
261 }
262
263
264 /**
265 * Returns the message flow controller for the sender side.
266 */
267 public MsgFlowSndrSide getMsgFlow()
268 {
269 return sender.getCluster().getMsgFlow();
270 }
271
272
273 /**
274 * Returns the <code>OutMessage</code> associated with this message.
275 */
276 public OutMessage getOutMessage()
277 {
278 return outmsg;
279 }
280
281
282 ////////////////////////////////////////////////////////////////////////////////////////////
283 // Methods from Object
284 ////////////////////////////////////////////////////////////////////////////////////////////
285
286 /**
287 * Returns a string representation of this object
288 */
289 public String toString()
290 {
291 StringBuilder buf = new StringBuilder();
292 switch (synchType) {
293 case QSYN:
294 buf.append("QSYN");
295 break;
296
297 case ASYN:
298 buf.append("ASYN");
299 break;
300
301 default:
302 buf.append("Illegal synchronization type: " + synchType);
303 }
304 buf.append(", sender: ");
305 buf.append(sender);
306 if (receiver != null) {
307 buf.append(", receiver: ");
308 buf.append(receiver);
309 }
310 buf.append(", nonce=");
311 buf.append(nonce);
312 buf.append(", lastMsgSent=");
313 buf.append(lastMsgSent);
314 return buf.toString();
315 }
316
317 } // END MsgSYN