PageRenderTime 68ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/src/groupcomm/net/sf/appia/protocols/group/ViewState.java

https://github.com/navaneethrameshan/appia-byzantine
Java | 481 lines | 269 code | 59 blank | 153 comment | 50 complexity | 9f24ac87e18563f445c95e6df51a3903 MD5 | raw file
  1. /**
  2. * Appia: Group communication and protocol composition framework library
  3. * Copyright 2006 University of Lisbon
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. * Initial developer(s): Alexandre Pinto and Hugo Miranda.
  18. * Contributor(s): See Appia web page for a list of contributors.
  19. */
  20. package net.sf.appia.protocols.group;
  21. import java.io.Externalizable;
  22. import java.io.IOException;
  23. import java.io.ObjectInput;
  24. import java.io.ObjectOutput;
  25. import java.net.InetAddress;
  26. import java.net.InetSocketAddress;
  27. import java.net.SocketAddress;
  28. import java.util.List;
  29. import java.util.ListIterator;
  30. import net.sf.appia.core.message.Message;
  31. import net.sf.appia.core.message.MessageException;
  32. /**
  33. * A <i>view</i>.
  34. * <br>
  35. * The class encapsulates all the attributes of a <i>view</i>.
  36. * <br>
  37. * It also provides some methods to process the <i>view</i>.
  38. *
  39. * @author Alexandre Pinto
  40. * @version 0.1
  41. * @see net.sf.appia.protocols.group.LocalState
  42. * @see net.sf.appia.protocols.group.intra.View
  43. */
  44. public class ViewState implements Externalizable {
  45. private static final long serialVersionUID = 8901541793832881340L;
  46. /**
  47. * The version of the <i>view</i>.
  48. * <br>
  49. * Currently ignored.
  50. */
  51. public String version;
  52. /**
  53. * The {@link net.sf.appia.protocols.group.Group Group} to which the <i>view</i>
  54. * belongs.
  55. */
  56. public Group group;
  57. /**
  58. * The {@link net.sf.appia.protocols.group.ViewID ViewID} of the <i>view</i>.
  59. */
  60. public ViewID id;
  61. /**
  62. * The {@link net.sf.appia.protocols.group.ViewID ViewIDs} of the previous
  63. * <i>views</i>.
  64. */
  65. public ViewID[] previous;
  66. /**
  67. * The view itself, the {@link net.sf.appia.protocols.group.Endpt Endpts} of the
  68. * members.
  69. */
  70. public Endpt[] view;
  71. /**
  72. * The addresses of the members.
  73. */
  74. public SocketAddress[] addresses;
  75. /**
  76. * Calculates the rank of the given member
  77. *
  78. * @param endpt the {@link net.sf.appia.protocols.group.Endpt Endpt} of the member
  79. * @return the rank of the member
  80. */
  81. public int getRank(Endpt endpt) {
  82. int i;
  83. for(i=view.length-1 ; (i >= 0) && !endpt.equals(view[i]) ; i--);
  84. return i;
  85. }
  86. /**
  87. * Calculates the rank of the member with the given address.
  88. *
  89. * @param address the address of the member
  90. * @return the rank of the member
  91. */
  92. public int getRankByAddress(InetSocketAddress address) {
  93. int i;
  94. for(i=addresses.length-1 ; (i >= 0) && !address.equals(addresses[i]) ; i--);
  95. return i;
  96. }
  97. public ViewState() {}
  98. /**
  99. * Constructs a <i>view</i>.
  100. *
  101. * @param version the version of the <i>view</i>
  102. * @param group the {@link net.sf.appia.protocols.group.Group Group} of the <i>view</i>
  103. * @param id the {@link net.sf.appia.protocols.group.ViewID ViewID} of the <i>view</i>
  104. * @param previous the {@link net.sf.appia.protocols.group.ViewID ViewIDs} of the previous
  105. * <i>views</i>
  106. * @param view the {@link net.sf.appia.protocols.group.Endpt Endpts} of the members
  107. * of the <i>view</i>
  108. * @param addresses the addresses of the members of the <i>view</i>
  109. * @throws NullPointerException if group or id or view or addresses are
  110. * <b>null</b>
  111. * @throws AppiaGroupException if the sizes of view and addresses are different
  112. */
  113. public ViewState(
  114. String version,
  115. Group group,
  116. ViewID id,
  117. ViewID[] previous,
  118. Endpt[] view,
  119. SocketAddress[] addresses) throws NullPointerException,AppiaGroupException {
  120. if ( (group==null) || (id==null) || (view==null) || (addresses==null) )
  121. throw new NullPointerException("appia:group:ViewState: group or view_id or view or addresses");
  122. if ( view.length != addresses.length )
  123. throw new AppiaGroupException("ViewState: view.length != addresses.length");
  124. this.version=version;
  125. this.group=group;
  126. this.id=id;
  127. this.previous=previous;
  128. this.view=view;
  129. this.addresses=addresses;
  130. }
  131. /**
  132. * Creates a {@link java.lang.String String} representation of the <i>view</i>.
  133. *
  134. * @return the {@link java.lang.String String} representation
  135. */
  136. public String toString() {
  137. String s="";
  138. int i;
  139. s="\nversion: "+version+"\ngroup: "+group.toString()+"\nid: "+id.toString();
  140. s=s+"\nprevious: [";
  141. for (i=0 ; i < previous.length ; i++) s=s+previous[i].toString()+",";
  142. s=s+"]\nview: [";
  143. for (i=0 ; i < view.length ; i++) s=s+view[i].toString()+",";
  144. s=s+"]\naddresses: [";
  145. for (i=0 ; i < addresses.length ; i++)
  146. s=s+addresses[i].toString()+",";
  147. s=s+"]\n";
  148. return s;
  149. }
  150. /**
  151. * Creates the next ViewState.
  152. * <br>
  153. * The new ViewState mantains the same
  154. * {@link net.sf.appia.protocols.group.ViewState#view view} and
  155. * {@link net.sf.appia.protocols.group.ViewState#addresses addresses}.
  156. * <br>
  157. * The ViewID is generated using the <i>ViewID.next(...)</i> method.
  158. *
  159. * @param coord the Endpoint id of the coordinator of the new ViewState
  160. * @return the next ViewState
  161. */
  162. public ViewState next(Endpt coord) throws NullPointerException,AppiaGroupException {
  163. if (coord == null)
  164. throw new NullPointerException("coord");
  165. ViewID new_id=id.next(coord);
  166. ViewID[] new_previous={id};
  167. return new ViewState(version,group,new_id,new_previous,view,addresses);
  168. }
  169. /**
  170. * Removes the indicated members from the current ViewState.
  171. * <br>
  172. * The members whose index is at true in the remove array, are removed
  173. * from the ViewState.
  174. *
  175. * @param remove the members to remove
  176. */
  177. public void remove(boolean[] remove) {
  178. if (remove.length != view.length)
  179. throw new IllegalArgumentException("different sizes");
  180. int i,j,size;
  181. size=0;
  182. for(i=0 ; i < remove.length ; i++) {
  183. if (!remove[i])
  184. size++;
  185. }
  186. Endpt[] new_view=new Endpt[size];
  187. SocketAddress[] new_addrs=new SocketAddress[size];
  188. j=0;
  189. for(i=0 ; i < remove.length ; i++) {
  190. if (!remove[i]) {
  191. new_view[j]=view[i];
  192. new_addrs[j]=addresses[i];
  193. j++;
  194. }
  195. }
  196. view=new_view;
  197. addresses=new_addrs;
  198. if (new_view.length > 0)
  199. id.coord=new_view[0];
  200. }
  201. /**
  202. * Merges the view states contained in the given list into a single view.
  203. * <br>
  204. * The view is the concatenation of the different views, according to the order provided by the list itself.
  205. * The version is the smallest all the versions.
  206. *
  207. * @param l A list containing the view states to merge
  208. * @return the merged view state.
  209. * @throws AppiaGroupException See {@linkplain ViewState#ViewState(String, Group, ViewID, ViewID[], Endpt[], SocketAddress[])}
  210. * @throws NullPointerException See {@linkplain ViewState#ViewState(String, Group, ViewID, ViewID[], Endpt[], SocketAddress[])}
  211. */
  212. public static ViewState merge(List l) throws NullPointerException, AppiaGroupException {
  213. ListIterator iter=l.listIterator(l.size());
  214. int viewsize=0;
  215. int prevsize=0;
  216. while (iter.hasPrevious()) {
  217. ViewState aux=(ViewState)iter.previous();
  218. viewsize+=aux.view.length;
  219. prevsize+=aux.previous.length;
  220. }
  221. String v=null;
  222. Group g=null;
  223. ViewID vid=null;
  224. ViewID[] prevs=new ViewID[prevsize];
  225. Endpt[] endpts=new Endpt[viewsize];
  226. InetSocketAddress[] addrs=new InetSocketAddress[viewsize];
  227. int iprevs=0,iendpts=0,iaddrs=0;
  228. while (iter.hasNext()) {
  229. ViewState aux=(ViewState)iter.next();
  230. if ((v == null) || (aux.version.compareTo(v) < 0))
  231. v=aux.version;
  232. if (g == null)
  233. g=aux.group;
  234. if (vid == null)
  235. vid=aux.id;
  236. else
  237. if (aux.id.ltime > vid.ltime)
  238. vid.ltime=aux.id.ltime;
  239. System.arraycopy(aux.previous, 0, prevs, iprevs, aux.previous.length);
  240. iprevs+=aux.previous.length;
  241. System.arraycopy(aux.view, 0, endpts, iendpts, aux.view.length);
  242. iendpts+=aux.view.length;
  243. System.arraycopy(aux.addresses, 0, addrs, iaddrs, aux.addresses.length);
  244. iaddrs+=aux.addresses.length;
  245. }
  246. return new ViewState(v,g,vid,prevs,endpts,addrs);
  247. }
  248. /**
  249. * Merges the given ViewState to the current ViewState.
  250. *
  251. * @param vs the ViewState to merge with the current one
  252. */
  253. public void merge(ViewState vs) {
  254. int size=view.length+vs.view.length;
  255. Endpt[] new_view=new Endpt[size];
  256. InetSocketAddress[] new_addrs=new InetSocketAddress[size];
  257. System.arraycopy(view,0,new_view,0,view.length);
  258. System.arraycopy(addresses,0,new_addrs,0,addresses.length);
  259. System.arraycopy(vs.view,0,new_view,view.length,vs.view.length);
  260. System.arraycopy(vs.addresses,0,new_addrs,addresses.length,vs.addresses.length);
  261. ViewID[] new_previous=new ViewID[previous.length+vs.previous.length];
  262. System.arraycopy(previous,0,new_previous,0,previous.length);
  263. System.arraycopy(vs.previous,0,new_previous,previous.length,vs.previous.length);
  264. view=new_view;
  265. addresses=new_addrs;
  266. previous=new_previous;
  267. id.ltime=Math.max(id.ltime,vs.id.ltime);
  268. }
  269. /**
  270. * Compares two ViewState and returns the
  271. * endpoints that were lost during the view change.
  272. * @param v The ViewState to be compared.
  273. * @return Array of lost EndPt.
  274. */
  275. public Endpt[] getDeadMembers(ViewState v){
  276. int current=0;
  277. Endpt[] aux = new Endpt[v.view.length];
  278. Endpt[] deadEnd=null;
  279. boolean found;
  280. for(int i=0; i!=v.view.length; i++){
  281. found = false;
  282. for(int j=0; j!=view.length ; j++)
  283. if(v.view[i].equals(view[j]))
  284. found = true;
  285. if(!found) //doesn't exist in the current view.
  286. aux[current++] = v.view[i];
  287. }
  288. deadEnd = new Endpt[current];
  289. System.arraycopy(aux, 0, deadEnd, 0, deadEnd.length);
  290. return deadEnd;
  291. }
  292. /**
  293. * Compares the current ViewState with the given ViewState and returns the
  294. * endpoints that
  295. * are new in this view.
  296. * @param v The ViewState to be compared.
  297. * @return Array of new EndPt.
  298. */
  299. public Endpt[] getNewMembers(ViewState v){
  300. int current=0;
  301. Endpt[] aux = new Endpt[view.length];
  302. Endpt[] newEnd=null;
  303. boolean found;
  304. for(int i=0; i!=view.length; i++){
  305. found = false;
  306. for(int j=0; j!=v.view.length ; j++)
  307. if(view[i].equals(v.view[j]))
  308. found = true;
  309. if(!found) //doesn't exist in the given view.
  310. aux[current++] = view[i];
  311. }
  312. newEnd = new Endpt[current];
  313. System.arraycopy(aux, 0, newEnd, 0, newEnd.length);
  314. return newEnd;
  315. }
  316. /**
  317. * Compares the current ViewState with the given ViewState and returns the
  318. * endpoints that are in both views.
  319. * @param v The ViewState to be compared.
  320. * @return Array of the common EndPt.
  321. */
  322. public Endpt[] getSurvivingMembers(ViewState v){
  323. int current=0;
  324. Endpt[] aux = new Endpt[v.view.length];
  325. Endpt[] survivorEnd=null;
  326. boolean found;
  327. for(int i=0; i!=view.length; i++){
  328. found = false;
  329. for(int j=0; j!=v.view.length ; j++)
  330. if(view[i].equals(v.view[j]))
  331. found = true;
  332. if(found) //exists in both views
  333. aux[current++] = view[i];
  334. }
  335. survivorEnd = new Endpt[current];
  336. System.arraycopy(aux, 0, survivorEnd, 0, survivorEnd.length);
  337. return survivorEnd;
  338. }
  339. public static void push( ViewState vs, Message message) {
  340. ArrayOptimized.pushArrayInetWithPort(vs.addresses,message);
  341. ArrayOptimized.pushArrayEndpt(vs.view,message);
  342. ArrayOptimized.pushArrayViewID(vs.previous,message);
  343. ViewID.push(vs.id,message);
  344. Group.push(vs.group,message);
  345. message.pushString(vs.version);
  346. }
  347. public static ViewState pop(Message message) {
  348. try {
  349. return new ViewState(
  350. message.popString(),
  351. Group.pop(message),
  352. ViewID.pop(message),
  353. ArrayOptimized.popArrayViewID(message),
  354. ArrayOptimized.popArrayEndpt(message),
  355. ArrayOptimized.popArrayInetWithPort(message));
  356. } catch (AppiaGroupException ex) {
  357. throw new MessageException("Error poping view state.",ex);
  358. }
  359. }
  360. public static ViewState peek(Message message) {
  361. ViewState vs=ViewState.pop(message);
  362. ViewState.push(vs,message);
  363. return vs;
  364. }
  365. public void writeExternal(ObjectOutput out) throws IOException {
  366. // public String version;
  367. byte[] bytes = version.getBytes();
  368. out.writeInt(bytes.length);
  369. out.write(bytes);
  370. // public Group group;
  371. out.writeObject(group);
  372. // public ViewID id;
  373. out.writeObject(id);
  374. // public ViewID[] previous;
  375. out.writeInt(previous.length);
  376. for(int i=0; i<previous.length; i++)
  377. out.writeObject(previous[i]);
  378. // public Endpt[] view;
  379. out.writeInt(view.length);
  380. for(int i=0; i<view.length; i++)
  381. out.writeObject(view[i]);
  382. // public InetWithPort[] addresses;
  383. out.writeInt(addresses.length);
  384. for(int i=0; i<addresses.length; i++){
  385. bytes = ((InetSocketAddress)addresses[i]).getAddress().getAddress();
  386. out.writeInt(bytes.length);
  387. out.write(bytes);
  388. out.writeInt(((InetSocketAddress)addresses[i]).getPort());
  389. }
  390. }
  391. public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
  392. // public String version;
  393. int len = in.readInt();
  394. byte[] bytes = new byte[len];
  395. in.read(bytes);
  396. version = new String(bytes);
  397. // public Group group;
  398. group = (Group) in.readObject();
  399. // public ViewID id;
  400. id = (ViewID) in.readObject();
  401. // public ViewID[] previous;
  402. len = in.readInt();
  403. previous = new ViewID[len];
  404. for(int i=0; i<len; i++)
  405. previous[i] = (ViewID) in.readObject();
  406. // public Endpt[] view;
  407. len = in.readInt();
  408. view = new Endpt[len];
  409. for(int i=0; i<len; i++)
  410. view[i] = (Endpt) in.readObject();
  411. // public InetWithPort[] addresses;
  412. len = in.readInt();
  413. int addrLen = 0;
  414. addresses = new InetSocketAddress[len];
  415. for(int i=0; i<len; i++){
  416. addrLen = in.readInt();
  417. bytes = new byte[addrLen];
  418. in.read(bytes);
  419. addresses[i] = new InetSocketAddress(InetAddress.getByAddress(bytes),in.readInt());
  420. }
  421. }
  422. }