View Javadoc

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  
25  import jgroup.core.EndPoint;
26  import jgroup.relacs.mss.MssConstants;
27  import jgroup.relacs.types.EndPointImpl;
28  import jgroup.relacs.types.GroupId;
29  import jgroup.relacs.types.GroupIndex;
30  import jgroup.relacs.types.IncarnationId;
31  import jgroup.relacs.types.LocalId;
32  import jgroup.relacs.types.MessageLen;
33  import jgroup.relacs.types.VersionId;
34  import jgroup.relacs.types.ViewId;
35  import jgroup.util.InMessage;
36  import jgroup.util.MsgFactory;
37  import jgroup.util.OutMessage;
38  
39  
40  /**
41   * The <code> MsgView</code> class
42   *
43   * @author  Alberto Montresor
44   * @since  Jgroup 0.1
45   */
46  final class MsgView
47    implements MssConstants, DaemonMsg
48  {
49  
50    ////////////////////////////////////////////////////////////////////////////////////////////
51    // Position constants
52    ////////////////////////////////////////////////////////////////////////////////////////////
53  
54    private static final int START  = MSS_HEADER_SIZE;
55  
56  
57    ////////////////////////////////////////////////////////////////////////////////////////////
58    // Unique message instance
59    ////////////////////////////////////////////////////////////////////////////////////////////
60  
61    /**
62     * As these messages are never stored by the daemon, a single message
63     * instance is sufficient.  In this way, we save the costs of
64     * allocating and garbage collecting messages.
65     */
66    private static MsgView msg = new MsgView();
67  
68    /** The marshalled message data (also static for same reason as above) */
69    private static OutMessage outmsg;
70  
71  
72    ////////////////////////////////////////////////////////////////////////////////////////////
73    // Fields
74    ////////////////////////////////////////////////////////////////////////////////////////////
75  
76    /** Original stream received from a coordinator, used to resend messages. */
77    InMessage stream;
78    
79    /** New complete view identifier */
80    long cvid;
81    
82    /** New compete view composition */
83    EndPoint[] cvcomp;
84    
85    /** */                                  
86    int[] incarns;
87    
88    /** Agreed version numbers */          
89    int[] agreed;
90    
91    /** Partial view identifiers */         
92    int[] pvids;
93    
94    /** Members tables */
95    LocalId[][] members;
96  
97    /** MsgView message size (excluding the mss header) */
98    private int size;
99  
100 
101   ////////////////////////////////////////////////////////////////////////////////////////////
102   // Decoding methods
103   ////////////////////////////////////////////////////////////////////////////////////////////
104 
105   /**
106    *  Returns a <code>MsgView</code> object that contains the decoding
107    *  of the m-received input stream.
108    *
109    *  @param stream    the message input stream to decode
110    */
111   static MsgView unmarshal(ObjectInput stream)
112     throws IOException, ClassNotFoundException
113   {
114     msg.stream = (InMessage) stream;
115     msg.cvid = ViewId.unmarshal(stream);
116     msg.size = MessageLen.unmarshal(stream);
117     int len  = GroupIndex.unmarshal(stream);
118     msg.cvcomp  = new EndPoint[len];
119     msg.incarns = new int[len];
120     msg.agreed  = new int[len];
121     msg.pvids   = new int[len];
122     msg.members = new LocalId[len][];
123     for (int i=0; i < len; i++) {
124       msg.cvcomp[i] = new EndPointImpl();
125       msg.cvcomp[i].readExternal(stream);
126     }
127     for (int i=0; i < len; i++) 
128       msg.incarns[i] = IncarnationId.unmarshal(stream);
129     for (int i=0; i < len; i++) 
130       msg.agreed[i]  = VersionId.unmarshal(stream);
131     for (int i=0; i < len; i++) 
132       msg.pvids[i]   = GroupIndex.unmarshal(stream);
133     for (int i=0; i < len; i++) {
134       msg.members[i] = new LocalId[GroupIndex.unmarshal(stream)];
135       for (int j=0; j < msg.members[i].length; j++) {
136         msg.members[i][j] = new LocalId();
137         msg.members[i][j].readExternal(stream);
138       }
139     }
140     return msg;
141   }
142 
143   ////////////////////////////////////////////////////////////////////////////////////////////
144   // Message to send
145   ////////////////////////////////////////////////////////////////////////////////////////////
146 
147   /**
148    *  Encode a message starting from a previously received message.
149    */
150   MsgView marshal()
151   {
152     outmsg = new OutMessage(stream);
153     return msg;
154   }
155 
156 
157   /**
158    *  Returns a output stream containing the encoding of a
159    *  <code>MsgView</code> message.
160    *
161    *  @param     gid     group identifier
162    *  @param     cvid    identifier of the current complete view
163    *  @param     prop    proposal on which the agreement has been reached
164    *  @param     pvids   identifiers of previous partial views (needed to compute new partial
165    *                     views
166    *  @param     props   proposal array (containing members lists)
167    */
168   static MsgView marshal(int gid, long cvid, MsgProp prop, int[] pvids,
169                          MsgProp[] props, int nreceivers)
170     throws IOException
171   {
172     // Allocates data buffer
173     msg.size = GroupId.SIZE + ViewId.SIZE + MessageLen.SIZE + GroupIndex.SIZE
174       + prop.host_plen + pvids.length * GroupIndex.SIZE;
175     for (int i=0; i < props.length; i++)
176       msg.size += props[i].memb_plen;
177     outmsg = MsgFactory.get(START + msg.size, nreceivers);
178     outmsg.seek(START);
179 
180     // Writes single data
181     GroupId.marshal(outmsg, gid);
182     /*
183      * There should've been a GroupIndex.marshal() here, but this is
184      * instead in MsgProp.encodeHostProp().
185      */
186     ViewId.marshal(outmsg, cvid);
187     MessageLen.marshal(outmsg, msg.size);
188 
189     // Copies composition and agreed values
190     prop.stream.seek(prop.host_start);
191     byte[] tempbuffer = new byte[prop.host_plen];
192     prop.stream.read(tempbuffer);
193     outmsg.write(tempbuffer);
194 
195     // Writes coordinator table informations
196     for (int i=0; i < pvids.length; i++)
197       GroupIndex.marshal(outmsg, pvids[i]);
198     for (int i=0; i < props.length; i++) {
199       props[i].stream.seek(props[i].memb_start);
200       tempbuffer = new byte[props[i].memb_plen];
201       props[i].stream.read(tempbuffer);
202       outmsg.write(tempbuffer);
203     }
204     return msg;
205   }
206 
207 
208   ////////////////////////////////////////////////////////////////////////////////////////////
209   // Methods from DaemonMsg
210   ////////////////////////////////////////////////////////////////////////////////////////////
211 
212   public int size()
213   {
214     return size;
215   }
216 
217   public OutMessage getOutMessage()
218   {
219     return outmsg;
220   }
221 
222 
223   ////////////////////////////////////////////////////////////////////////////////////////////
224   // Methods from Object
225   ////////////////////////////////////////////////////////////////////////////////////////////
226 
227   /**
228    *  Returns a string representation of this object
229    */
230   public String toString()
231   {
232     StringBuilder buffer = new StringBuilder();
233     buffer.append("[MsgView: cvid=");
234     buffer.append(cvid);
235     buffer.append(", cvcomp={");
236     for (int i=0; i < cvcomp.length; i++) {
237       buffer.append(cvcomp[i]);
238       if (i < cvcomp.length-1)
239         buffer.append(", ");
240     }
241     buffer.append("}, agreed={");
242     for (int i=0; i < agreed.length; i++) {
243       buffer.append(agreed[i]);
244       if (i < agreed.length-1)
245         buffer.append(", ");
246     }
247     buffer.append("}, pvids={");
248     for (int i=0; i < pvids.length; i++) {
249       buffer.append(pvids[i]);
250       if (i < pvids.length-1)
251         buffer.append(", ");
252     }
253     buffer.append("}, members={");
254     for (int i=0; i < members.length; i++) {
255       buffer.append("{");
256       for (int j=0; j < members[i].length; j++) {
257         buffer.append(members[i][j]);
258         if (j < members[i].length-1)
259           buffer.append(",");
260       }
261       buffer.append("}");
262       if (i < members.length-1)
263         buffer.append(",");
264     }
265     buffer.append("}]");
266     return buffer.toString();
267   }
268   
269 } // END MsgView
270