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
22 import java.io.IOException;
23 import java.io.ObjectInput;
24 import java.util.Collection;
25 import java.util.Iterator;
26
27 import jgroup.core.EndPoint;
28 import jgroup.relacs.mss.MssConstants;
29 import jgroup.relacs.types.EndPointImpl;
30 import jgroup.relacs.types.GroupId;
31 import jgroup.relacs.types.GroupIndex;
32 import jgroup.relacs.types.VersionId;
33 import jgroup.util.MsgFactory;
34 import jgroup.util.OutMessage;
35
36 /**
37 * <code>MsgEstim</code> messages are used during the ee-phase (estimate exchange) of
38 * the view agreement algorithm. They are sent to daemons belonging to the current
39 * estimate whenever this estimate changes.
40 *
41 * @author Alberto Montresor
42 * @since Jgroup 0.1
43 */
44 final class MsgEstim
45 implements MssConstants, DaemonMsg
46 {
47
48 ////////////////////////////////////////////////////////////////////////////////////////////
49 // Position constants
50 ////////////////////////////////////////////////////////////////////////////////////////////
51
52 private static final int START = MSS_HEADER_SIZE;
53
54
55 ////////////////////////////////////////////////////////////////////////////////////////////
56 // Unique message instance
57 ////////////////////////////////////////////////////////////////////////////////////////////
58
59 /**
60 * As these messages are never stored by the daemon, a single message instance is
61 * sufficient. In this way, we save the costs of allocating and garbage collecting
62 * messages.
63 */
64 private static MsgEstim msg = new MsgEstim();
65
66 /** The marshalled message data (also static for same reason as above) */
67 private static OutMessage outmsg;
68
69
70 ////////////////////////////////////////////////////////////////////////////////////////////
71 // Fields
72 ////////////////////////////////////////////////////////////////////////////////////////////
73
74 /** Agreed version number of the sender */
75 int vsend;
76
77 /** Agreed version number table of next view estimate */
78 int[] agreed;
79
80 /** Next view estimate */
81 EndPoint[] hosts;
82
83
84 ////////////////////////////////////////////////////////////////////////////////////////////
85 // Message to send
86 ////////////////////////////////////////////////////////////////////////////////////////////
87
88 /**
89 * Returns a <code>MsgEstim</code> object that contains the decoding
90 * of the m-received input stream.
91 *
92 * @param stream the message input stream to decode
93 */
94 static MsgEstim unmarshal(ObjectInput stream)
95 throws IOException, ClassNotFoundException
96 {
97 msg.vsend = VersionId.unmarshal(stream);
98 int len = GroupIndex.unmarshal(stream); // Read length of agreed and hosts
99 msg.agreed = new int[len];
100 msg.hosts = new EndPoint[len];
101 for (int i=0; i<len; i++) { // Read agreed and hosts
102 msg.agreed[i] = VersionId.unmarshal(stream);
103 msg.hosts[i] = new EndPointImpl();
104 msg.hosts[i].readExternal(stream);
105 }
106 return msg;
107 }
108
109 /**
110 * Returns a output stream containing the encoding of a
111 * <code>MsgEstim</code> message.
112 *
113 * @param gid group identifier
114 * @param vsend version number of the sender
115 * @param estimate current estimate
116 * @param elen actual length of estimate (estimate.length >= elen)
117 */
118 static MsgEstim marshal(int gid, int vsend, Collection estimate)
119 throws IOException
120 {
121 // Allocates data buffer
122 int size = START + GroupId.SIZE + VersionId.SIZE + GroupIndex.SIZE +
123 (VersionId.SIZE + EndPointImpl.SIZE) * estimate.size();
124 outmsg = MsgFactory.get(size, estimate.size());
125 outmsg.seek(START);
126
127 GroupId.marshal(outmsg, gid);
128 VersionId.marshal(outmsg, vsend);
129
130 // Write length of agreed and hosts
131 GroupIndex.marshal(outmsg, estimate.size());
132
133 // Write agreed and hosts
134 Iterator iterator = estimate.iterator();
135 while (iterator.hasNext()) {
136 HostData scan = (HostData) iterator.next();
137 VersionId.marshal(outmsg, scan.getAgreed());
138 scan.getEndPoint().writeExternal(outmsg);
139 }
140 return msg;
141 }
142
143
144 ////////////////////////////////////////////////////////////////////////////////////////////
145 // Methods from DaemonMsg
146 ////////////////////////////////////////////////////////////////////////////////////////////
147
148 public int size()
149 {
150 /* Note; it is ok to use the outmsg size since MsgEstim will never be
151 * forwarded or resent (it is not queued). */
152 return outmsg.size();
153 }
154
155 public OutMessage getOutMessage()
156 {
157 return outmsg;
158 }
159
160
161 ////////////////////////////////////////////////////////////////////////////////////////////
162 // Methods from Object
163 ////////////////////////////////////////////////////////////////////////////////////////////
164
165 /**
166 * Returns a string representation of this object
167 */
168 public String toString()
169 {
170 StringBuilder buffer = new StringBuilder();
171 buffer.append("[MsgEstim: vsend=");
172 buffer.append(vsend);
173 buffer.append(", hosts={");
174 for (int i=0; i < hosts.length; i++) {
175 buffer.append(hosts[i]);
176 if (i < hosts.length-1)
177 buffer.append(", ");
178 }
179 buffer.append("}, agreed={");
180 for (int i=0; i < agreed.length; i++) {
181 buffer.append(agreed[i]);
182 if (i < agreed.length-1)
183 buffer.append(", ");
184 }
185 buffer.append("}]");
186 return buffer.toString();
187 }
188
189 } // END MsgEstim