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  import java.util.Iterator;
25  import java.util.List;
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  /**
38   * The <code> MsgSymm</code> class
39   *
40   * @author  Alberto Montresor
41   * @since   Jgroup 0.1
42   */
43  final class MsgSymm
44    implements MssConstants, DaemonMsg
45  {
46  
47    ////////////////////////////////////////////////////////////////////////////////////////////
48    // Position constants
49    ////////////////////////////////////////////////////////////////////////////////////////////
50  
51    private static final int START  = MSS_HEADER_SIZE;
52  
53  
54    ////////////////////////////////////////////////////////////////////////////////////////////
55    // Unique message instance
56    ////////////////////////////////////////////////////////////////////////////////////////////
57  
58    /**
59     * As these messages are never stored by the daemon, a single message
60     * instance is sufficient.  In this way, we save the costs of
61     * allocating and garbage collecting messages.
62     */
63    private static MsgSymm msg = new MsgSymm();
64  
65    /** The marshalled message data (also static for same reason as above) */
66    private static OutMessage outmsg;
67  
68  
69    ////////////////////////////////////////////////////////////////////////////////////////////
70    // Fields
71    ////////////////////////////////////////////////////////////////////////////////////////////
72  
73    /** Sender version number */
74    int vsend;
75  
76    /** Host identifiers */
77    EndPoint[] hosts;
78  
79    /** Corresponding version numbers */
80    int[] version;
81  
82    /** Reachable set */
83    EndPoint[] rset;
84  
85  
86    ////////////////////////////////////////////////////////////////////////////////////////////
87    // Decoding methods
88    ////////////////////////////////////////////////////////////////////////////////////////////
89  
90    /**
91     * Creates a new instance of MsgSymm starting from a m-received msg
92     * input stream
93     */
94    static MsgSymm unmarshal(ObjectInput msgstream)
95      throws IOException, ClassNotFoundException
96    {
97      /* Read sender version number */
98      msg.vsend = VersionId.unmarshal(msgstream);
99      
100     /* Read host identifiers and version numbers of the nrset */
101     int len  = GroupIndex.unmarshal(msgstream);
102     msg.version = new int[len];
103     msg.hosts   = new EndPoint[len];
104     for (int i=0; i < len; i++) {   
105       msg.hosts[i] = new EndPointImpl();
106       msg.hosts[i].readExternal(msgstream);
107       msg.version[i] = VersionId.unmarshal(msgstream);
108     }
109     
110     /* Read the rset array */
111     len = GroupIndex.unmarshal(msgstream);
112     msg.rset = new EndPoint[len];
113     for (int i=0; i < len; i++) {
114       msg.rset[i] = new EndPointImpl();
115       msg.rset[i].readExternal(msgstream);
116     }
117     return msg;
118   }
119 
120 
121   ////////////////////////////////////////////////////////////////////////////////////////////
122   // Encoding methods
123   ////////////////////////////////////////////////////////////////////////////////////////////
124 
125   /**
126    * Copies informations into Message structure
127    */
128   static MsgSymm marshal(int gid, int vsend, List nrset, EndPoint[] rset, int nreceivers)
129     throws IOException
130   {
131     /* Allocates data buffer */
132     int size = START + GroupId.SIZE + VersionId.SIZE + 2 * GroupIndex.SIZE + nrset.size() * 
133                (VersionId.SIZE + EndPointImpl.SIZE) + rset.length * EndPointImpl.SIZE;
134     outmsg = MsgFactory.get(size, nreceivers);
135     outmsg.seek(START);
136 
137     /* Write group identifier and sender version number */
138     GroupId.marshal(outmsg, gid);
139     VersionId.marshal(outmsg, vsend);
140 
141     /*
142      * Writes the identifier of the endpoints contained in nrset,
143      * together with their version numbers.
144      */
145     GroupIndex.marshal(outmsg, nrset.size());
146     Iterator iterator = nrset.iterator();
147     while (iterator.hasNext()) {
148       HostData data = (HostData) iterator.next();
149       data.getEndPoint().writeExternal(outmsg);
150       VersionId.marshal(outmsg, data.getVersion());
151     }
152 
153     /*
154      * Writes the identifier of the endpoints contained in rset
155      */
156     GroupIndex.marshal(outmsg, rset.length);
157     for (int i=0; i < rset.length; i++)
158       rset[i].writeExternal(outmsg);
159 
160     return msg;
161   }
162 
163 
164   /**
165    * Copies informations into Message structure
166    */
167   static MsgSymm marshal(int gid, int vsend, HostData dest, EndPoint[] rset, int nreceivers)
168     throws IOException
169   {
170     /* Allocates data buffer */
171     int size = START + GroupId.SIZE + VersionId.SIZE + 2 * GroupIndex.SIZE +
172                VersionId.SIZE + EndPointImpl.SIZE + rset.length * EndPointImpl.SIZE;
173     outmsg = MsgFactory.get(size, nreceivers);
174     outmsg.seek(START);
175 
176     /* Write group identifier and sender version number */
177     GroupId.marshal(outmsg, gid);
178     VersionId.marshal(outmsg, vsend);
179 
180     /* Write dest identifier and version number */
181     GroupIndex.marshal(outmsg, 1);
182     dest.getEndPoint().writeExternal(outmsg);
183     VersionId.marshal(outmsg, dest.getVersion());
184 
185     /*
186      * Writes the identifier of the endpoints contained in rset
187      */
188     GroupIndex.marshal(outmsg, rset.length);
189     for (int i=0; i < rset.length; i++)
190       rset[i].writeExternal(outmsg);
191 
192     return msg;
193   }
194 
195 
196   ////////////////////////////////////////////////////////////////////////////////////////////
197   // Methods from DaemonMsg
198   ////////////////////////////////////////////////////////////////////////////////////////////
199 
200   public int size()
201   {
202     /* Note; it is ok to use the outmsg size since MsgSymm will never be
203      * forwarded or resent (it is not queued). */
204     return outmsg.size();
205   }
206 
207   public OutMessage getOutMessage()
208   {
209     return outmsg;
210   }
211 
212 
213   ////////////////////////////////////////////////////////////////////////////////////////////
214   // Methods from Object
215   ////////////////////////////////////////////////////////////////////////////////////////////
216 
217   /**
218    *  Returns a string representation of this object
219    */
220   public String toString()
221   {
222     StringBuilder buffer = new StringBuilder();
223     buffer.append("[MsgSymm: vsend=");
224     buffer.append(vsend);
225     buffer.append(", rset={");
226     for (int i=0; i < rset.length; i++) {
227       buffer.append(rset[i]);
228       if (i < rset.length-1)
229         buffer.append(", ");
230     }
231     buffer.append("}, hosts={");
232     for (int i=0; i < hosts.length; i++) {
233       buffer.append(hosts[i]);
234       if (i < hosts.length-1)
235         buffer.append(", ");
236     }
237     buffer.append("}, versions={");
238     for (int i=0; i < version.length; i++) {
239       buffer.append(version[i]);
240       if (i < version.length-1)
241         buffer.append(", ");
242     }
243     buffer.append("}]");
244     return buffer.toString();
245   }
246 
247 } // END MsgSymm