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  import java.io.IOException;
22  import java.io.ObjectInput;
23  
24  import jgroup.relacs.mss.MssConstants;
25  import jgroup.relacs.types.GroupId;
26  import jgroup.relacs.types.GroupIndex;
27  import jgroup.relacs.types.MessageId;
28  import jgroup.relacs.types.ViewId;
29  import jgroup.util.MsgFactory;
30  import jgroup.util.OutMessage;
31  
32  /**
33   *  The <code>MsgAck</code> class contain methods to encode and decode
34   *  ACK messages from remote hosts.  The ACK message structure is the
35   *  following:
36   *  <p>
37   *  <code>
38   *  +-------+-------+-------+-------+-------+ ....... +-------+
39   *  |  GID  |  VID  |  HPOS | VLEN  |  ACK  |         |  ACK  |
40   *  |       |       |       |       |   1   |         |  VLEN |
41   *  +-------+-------+-------+-------+-------+ ....... +-------+
42   *  </code>
43   *
44   *  @author  Alberto Montresor
45   *  @since   Jgroup 0.1
46   */
47  final class MsgAck 
48    implements MssConstants, DaemonMsg
49  {
50  
51    ////////////////////////////////////////////////////////////////////////////////////////////
52    // Position constants
53    ////////////////////////////////////////////////////////////////////////////////////////////
54  
55    private static final int START       = MSS_HEADER_SIZE;
56  
57  
58    ////////////////////////////////////////////////////////////////////////////////////////////
59    // Unique message instance
60    ////////////////////////////////////////////////////////////////////////////////////////////
61  
62    /**
63     * As these messages are never stored by the daemon, a single message
64     * instance is sufficient.  In this way, we save the costs of
65     * allocating and garbage collecting messages.
66     */
67    private static MsgAck msg = new MsgAck();
68  
69    /** The marshalled message data (also static for same reason as above) */
70    private static OutMessage outmsg;
71  
72  
73    ////////////////////////////////////////////////////////////////////////////////////////////
74    // Fields
75    ////////////////////////////////////////////////////////////////////////////////////////////
76  
77    /** View identifier */            
78    long vid;      
79  
80    /** Host index in the view */
81    int hpos;     
82  
83    /** Acknowledgement numbers for each host in the current view */
84    int[] ack;      
85  
86  
87    ////////////////////////////////////////////////////////////////////////////////////////////
88    // Methods
89    ////////////////////////////////////////////////////////////////////////////////////////////
90  
91    /**
92     *  Returns a <code>MsgAck</code> object that contains the decoding of
93     *  the m-received input stream.
94     *
95     *  @param stream    the message input stream to decode
96     */
97    static MsgAck unmarshal(ObjectInput stream)
98      throws IOException
99    {
100     msg.vid  = ViewId.unmarshal(stream);
101     msg.hpos = GroupIndex.unmarshal(stream);
102 
103     /* Read length and content of the ack array */
104     int len  = GroupIndex.unmarshal(stream);
105     msg.ack  = new int[len];
106     for (int i=0; i < len; i++)   // Read ack fields
107       msg.ack[i] = MessageId.unmarshal(stream);
108 
109     return msg;
110   }
111 
112 
113   /**
114    *  Returns a output stream containing the encoding of a
115    *  <code>MsgAck</code> message.
116    *
117    *  @param     gid     group identifier
118    *  @param     vid     view identifier
119    *  @param     hpos    host index in the view
120    */
121   static MsgAck marshal(int gid, long vid, int hpos, int[] acks, int nreceivers)
122     throws IOException
123   {
124     // Allocates data buffer
125     int size = START + GroupId.SIZE + ViewId.SIZE + GroupIndex.SIZE*2 + MessageId.SIZE*acks.length;
126     outmsg = MsgFactory.get(size, nreceivers);
127     outmsg.seek(START);
128 
129     GroupId.marshal(outmsg, gid);
130     ViewId.marshal(outmsg, vid);
131     GroupIndex.marshal(outmsg, hpos);
132     GroupIndex.marshal(outmsg, acks.length);
133     for (int i=0; i < acks.length; i++)
134       MessageId.marshal(outmsg, acks[i]);
135 
136     return msg;
137   }
138 
139 
140   ////////////////////////////////////////////////////////////////////////////////////////////
141   // Methods from DaemonMsg
142   ////////////////////////////////////////////////////////////////////////////////////////////
143 
144   public int size()
145   {
146     /* Note; it is ok to use the outmsg size since MsgAck will never be
147      * forwarded or resent. */
148     return outmsg.size();
149   }
150 
151   public OutMessage getOutMessage()
152   {
153     return outmsg;
154   }
155 
156 
157   ////////////////////////////////////////////////////////////////////////////////////////////
158   // Methods from Object
159   ////////////////////////////////////////////////////////////////////////////////////////////
160 
161   /**
162    *  Returns a string representation of this object
163    */
164   public String toString()
165   {
166     StringBuilder buffer = new StringBuilder();
167     buffer.append("[MsgAck: vid=");
168     buffer.append(vid);
169     buffer.append(", hpos=");
170     buffer.append(hpos);
171     buffer.append(", ack={");
172     for (int i=0; i < ack.length; i++) {
173       buffer.append(ack[i]);
174       if (i != ack.length-1)
175         buffer.append(", ");
176     }
177     buffer.append("}]");
178     return buffer.toString();
179   }
180 
181 } // END MsgAck