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.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