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.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