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