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 20 package jgroup.relacs.daemon; 21 22 import java.io.IOException; 23 import java.io.ObjectInput; 24 25 import jgroup.core.MemberId; 26 import jgroup.relacs.mss.MssConstants; 27 import jgroup.relacs.types.Flag; 28 import jgroup.relacs.types.GroupId; 29 import jgroup.relacs.types.GroupIndex; 30 import jgroup.relacs.types.MemberIdImpl; 31 import jgroup.relacs.types.MessageId; 32 import jgroup.relacs.types.ViewId; 33 import jgroup.util.MsgFactory; 34 import jgroup.util.OutMessage; 35 36 /** 37 * 38 * @author Alberto Montresor 39 * @since Jgroup 0.8 40 */ 41 final class MsgResult 42 implements MssConstants, DaemonMsg 43 { 44 45 //////////////////////////////////////////////////////////////////////////////////////////// 46 // Position constants 47 //////////////////////////////////////////////////////////////////////////////////////////// 48 49 private static final int START = MSS_HEADER_SIZE; 50 51 52 //////////////////////////////////////////////////////////////////////////////////////////// 53 // Fields 54 //////////////////////////////////////////////////////////////////////////////////////////// 55 56 /** Group identifier */ 57 int gid; 58 59 /** View identifier */ 60 long vid; 61 62 /** Message identifier */ 63 int mid; 64 65 /** 66 * Identifier of the sender of the message to which this message is a 67 * response. 68 */ 69 MemberId sender; 70 71 /** Number of messages delivered by all local members */ 72 int dlvr; 73 74 /** Host index in the view */ 75 int hpos; 76 77 /** Member index in the view */ 78 int vpos; 79 80 /** Result value */ 81 Object result; 82 83 /** The marshalled message stream for this object */ 84 private OutMessage outmsg; 85 86 87 //////////////////////////////////////////////////////////////////////////////////////////// 88 // Constructors 89 //////////////////////////////////////////////////////////////////////////////////////////// 90 91 /** 92 * Default constructors used to create an empty ResultMessage in the 93 * decoding process. 94 */ 95 MsgResult() 96 { 97 } 98 99 /** 100 * Default constructors used to create an empty ResultMessage in the 101 * decoding process. 102 */ 103 MsgResult(int gid, long vid, int mid, MemberId sender, int dlvr, int hpos, int vpos, 104 Object result) 105 { 106 this.gid = gid; 107 this.vid = vid; 108 this.mid = mid; 109 this.sender = sender; 110 this.dlvr = dlvr; 111 this.hpos = hpos; 112 this.vpos = vpos; 113 this.result = result; 114 } 115 116 117 //////////////////////////////////////////////////////////////////////////////////////////// 118 // Methods 119 //////////////////////////////////////////////////////////////////////////////////////////// 120 121 /** 122 * Returns an output stream containing the encoding of this message. 123 */ 124 MsgResult marshal(int nreceivers) 125 throws IOException 126 { 127 outmsg = marshal(gid, vid, mid, sender, dlvr, hpos, vpos, result, nreceivers); 128 return this; 129 } 130 131 132 //////////////////////////////////////////////////////////////////////////////////////////// 133 // Static methods 134 //////////////////////////////////////////////////////////////////////////////////////////// 135 136 /** 137 * Returns a <code>MsgResult</code> object that contains the decoding 138 * of an m-received input stream. 139 * 140 * @param stream the message input stream to decode 141 */ 142 static MsgResult unmarshal(ObjectInput stream) 143 throws IOException, ClassNotFoundException 144 { 145 /* 146 * Currently, this message type cannot be a singleton since the 147 * SendBuffer class stores instances of MsgResult in its ackbuffer. 148 */ 149 MsgResult msg = new MsgResult(); 150 151 msg.vid = ViewId.unmarshal(stream); 152 msg.mid = MessageId.unmarshal(stream); 153 msg.sender = new MemberIdImpl(); 154 msg.sender.readExternal(stream); 155 msg.dlvr = MessageId.unmarshal(stream); 156 msg.hpos = GroupIndex.unmarshal(stream); 157 msg.vpos = GroupIndex.unmarshal(stream); 158 // check if stream contains a result object. 159 if (Flag.unmarshal(stream)) { 160 msg.result = stream.readObject(); 161 } 162 return msg; 163 } 164 165 /** 166 * Returns a output stream containing the encoding of a 167 * <code>MsgResult</code> message. 168 * 169 * @param gid group identifier 170 * @param vid current view identifier 171 * @param mid identifier of the original message to which this message is a response 172 * @param sender identifier of the sender of the original message to which this message is 173 * a response 174 * @param hpos host index in the view 175 * @param mpos member index in the view 176 * @param result result value 177 */ 178 private static OutMessage marshal(int gid, long vid, int mid, MemberId sender, int dlvr, int hpos, 179 int vpos, Object result, int nreceivers) 180 throws IOException 181 { 182 OutMessage stream; 183 184 // Allocates data buffer 185 if (result == null) { 186 int size = START + GroupId.SIZE + ViewId.SIZE + MessageId.SIZE * 2 + 187 GroupIndex.SIZE*2 + MemberIdImpl.SIZE + Flag.SIZE; 188 stream = MsgFactory.get(size, nreceivers); 189 } else { 190 stream = MsgFactory.get(); 191 } 192 stream.seek(START); 193 194 // Writes single data 195 GroupId.marshal(stream, gid); 196 ViewId.marshal(stream, vid); 197 MessageId.marshal(stream, mid); 198 sender.writeExternal(stream); 199 MessageId.marshal(stream, dlvr); 200 GroupIndex.marshal(stream, hpos); 201 GroupIndex.marshal(stream, vpos); 202 boolean hasResult = (result != null); 203 Flag.marshal(stream, hasResult); 204 if (hasResult) { 205 stream.writeObject(result); 206 } 207 return stream; 208 } 209 210 211 //////////////////////////////////////////////////////////////////////////////////////////// 212 // Methods from DaemonMsg 213 //////////////////////////////////////////////////////////////////////////////////////////// 214 215 public int size() 216 { 217 /* Note; it is ok to use the outmsg size since MsgResult will never be 218 * forwarded or resent (it is queued, but only to deliver later, I think). */ 219 return outmsg.size(); 220 } 221 222 public OutMessage getOutMessage() 223 { 224 return outmsg; 225 } 226 227 228 //////////////////////////////////////////////////////////////////////////////////////////// 229 // Methods from Object 230 //////////////////////////////////////////////////////////////////////////////////////////// 231 232 /** 233 * Returns a string representation of this object 234 */ 235 public String toString() 236 { 237 StringBuilder buf = new StringBuilder(); 238 buf.append("[MsgResult: gid="); 239 buf.append(gid); 240 buf.append(", vid="); 241 buf.append(vid); 242 buf.append(", mid="); 243 buf.append(mid); 244 buf.append(", sender="); 245 buf.append(sender); 246 buf.append(", dlvr="); 247 buf.append(dlvr); 248 buf.append(", hpos="); 249 buf.append(hpos); 250 buf.append(", vpos="); 251 buf.append(vpos); 252 buf.append(", result="); 253 buf.append(result); 254 return buf.toString(); 255 } 256 257 } // END MsgResult