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