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 import java.io.IOException; 22 import java.io.ObjectInput; 23 24 import jgroup.relacs.mss.MssConstants; 25 import jgroup.relacs.types.GroupId; 26 import jgroup.relacs.types.GroupIndex; 27 import jgroup.relacs.types.MessageId; 28 import jgroup.relacs.types.ViewId; 29 import jgroup.util.MsgFactory; 30 import jgroup.util.OutMessage; 31 32 /** 33 * The <code>MsgAck</code> class contain methods to encode and decode 34 * ACK messages from remote hosts. The ACK message structure is the 35 * following: 36 * <p> 37 * <code> 38 * +-------+-------+-------+-------+-------+ ....... +-------+ 39 * | GID | VID | HPOS | VLEN | ACK | | ACK | 40 * | | | | | 1 | | VLEN | 41 * +-------+-------+-------+-------+-------+ ....... +-------+ 42 * </code> 43 * 44 * @author Alberto Montresor 45 * @since Jgroup 0.1 46 */ 47 final class MsgAck 48 implements MssConstants, DaemonMsg 49 { 50 51 //////////////////////////////////////////////////////////////////////////////////////////// 52 // Position constants 53 //////////////////////////////////////////////////////////////////////////////////////////// 54 55 private static final int START = MSS_HEADER_SIZE; 56 57 58 //////////////////////////////////////////////////////////////////////////////////////////// 59 // Unique message instance 60 //////////////////////////////////////////////////////////////////////////////////////////// 61 62 /** 63 * As these messages are never stored by the daemon, a single message 64 * instance is sufficient. In this way, we save the costs of 65 * allocating and garbage collecting messages. 66 */ 67 private static MsgAck msg = new MsgAck(); 68 69 /** The marshalled message data (also static for same reason as above) */ 70 private static OutMessage outmsg; 71 72 73 //////////////////////////////////////////////////////////////////////////////////////////// 74 // Fields 75 //////////////////////////////////////////////////////////////////////////////////////////// 76 77 /** View identifier */ 78 long vid; 79 80 /** Host index in the view */ 81 int hpos; 82 83 /** Acknowledgement numbers for each host in the current view */ 84 int[] ack; 85 86 87 //////////////////////////////////////////////////////////////////////////////////////////// 88 // Methods 89 //////////////////////////////////////////////////////////////////////////////////////////// 90 91 /** 92 * Returns a <code>MsgAck</code> object that contains the decoding of 93 * the m-received input stream. 94 * 95 * @param stream the message input stream to decode 96 */ 97 static MsgAck unmarshal(ObjectInput stream) 98 throws IOException 99 { 100 msg.vid = ViewId.unmarshal(stream); 101 msg.hpos = GroupIndex.unmarshal(stream); 102 103 /* Read length and content of the ack array */ 104 int len = GroupIndex.unmarshal(stream); 105 msg.ack = new int[len]; 106 for (int i=0; i < len; i++) // Read ack fields 107 msg.ack[i] = MessageId.unmarshal(stream); 108 109 return msg; 110 } 111 112 113 /** 114 * Returns a output stream containing the encoding of a 115 * <code>MsgAck</code> message. 116 * 117 * @param gid group identifier 118 * @param vid view identifier 119 * @param hpos host index in the view 120 */ 121 static MsgAck marshal(int gid, long vid, int hpos, int[] acks, int nreceivers) 122 throws IOException 123 { 124 // Allocates data buffer 125 int size = START + GroupId.SIZE + ViewId.SIZE + GroupIndex.SIZE*2 + MessageId.SIZE*acks.length; 126 outmsg = MsgFactory.get(size, nreceivers); 127 outmsg.seek(START); 128 129 GroupId.marshal(outmsg, gid); 130 ViewId.marshal(outmsg, vid); 131 GroupIndex.marshal(outmsg, hpos); 132 GroupIndex.marshal(outmsg, acks.length); 133 for (int i=0; i < acks.length; i++) 134 MessageId.marshal(outmsg, acks[i]); 135 136 return msg; 137 } 138 139 140 //////////////////////////////////////////////////////////////////////////////////////////// 141 // Methods from DaemonMsg 142 //////////////////////////////////////////////////////////////////////////////////////////// 143 144 public int size() 145 { 146 /* Note; it is ok to use the outmsg size since MsgAck will never be 147 * forwarded or resent. */ 148 return outmsg.size(); 149 } 150 151 public OutMessage getOutMessage() 152 { 153 return outmsg; 154 } 155 156 157 //////////////////////////////////////////////////////////////////////////////////////////// 158 // Methods from Object 159 //////////////////////////////////////////////////////////////////////////////////////////// 160 161 /** 162 * Returns a string representation of this object 163 */ 164 public String toString() 165 { 166 StringBuilder buffer = new StringBuilder(); 167 buffer.append("[MsgAck: vid="); 168 buffer.append(vid); 169 buffer.append(", hpos="); 170 buffer.append(hpos); 171 buffer.append(", ack={"); 172 for (int i=0; i < ack.length; i++) { 173 buffer.append(ack[i]); 174 if (i != ack.length-1) 175 buffer.append(", "); 176 } 177 buffer.append("}]"); 178 return buffer.toString(); 179 } 180 181 } // END MsgAck