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