001: // $Id: View.java,v 1.12.2.1 2006/12/09 21:56:31 belaban Exp $
002:
003: package org.jgroups;
004:
005: import org.jgroups.util.Streamable;
006: import org.jgroups.util.Util;
007:
008: import java.io.*;
009: import java.util.Vector;
010:
011: /**
012: * A view is a local representation of the current membership of a group.
013: * Only one view is installed in a channel at a time.
014: * Views contain the address of its creator, an ID and a list of member addresses.
015: * These adresses are ordered, and the first address is always the coordinator of the view.
016: * This way, each member of the group knows who the new coordinator will be if the current one
017: * crashes or leaves the group.
018: * The views are sent between members using the VIEW_CHANGE event.
019: */
020: public class View implements Externalizable, Cloneable, Streamable {
021: /* A view is uniquely identified by its ViewID
022: * The view id contains the creator address and a Lamport time.
023: * The Lamport time is the highest timestamp seen or sent from a view.
024: * if a view change comes in with a lower Lamport time, the event is discarded.
025: */
026: protected ViewId vid = null;
027:
028: /**
029: * A list containing all the members of the view
030: * This list is always ordered, with the coordinator being the first member.
031: * the second member will be the new coordinator if the current one disappears
032: * or leaves the group.
033: */
034: protected Vector members = null;
035:
036: /**
037: * creates an empty view, should not be used
038: */
039: public View() {
040: }
041:
042: /**
043: * Creates a new view
044: *
045: * @param vid The view id of this view (can not be null)
046: * @param members Contains a list of all the members in the view, can be empty but not null.
047: */
048: public View(ViewId vid, Vector members) {
049: this .vid = vid;
050: this .members = members;
051: }
052:
053: /**
054: * Creates a new view
055: *
056: * @param creator The creator of this view (can not be null)
057: * @param id The lamport timestamp of this view
058: * @param members Contains a list of all the members in the view, can be empty but not null.
059: */
060: public View(Address creator, long id, Vector members) {
061: this (new ViewId(creator, id), members);
062: }
063:
064: /**
065: * returns the view ID of this view
066: * if this view was created with the empty constructur, null will be returned
067: *
068: * @return the view ID of this view
069: */
070: public ViewId getVid() {
071: return vid;
072: }
073:
074: /**
075: * returns the creator of this view
076: * if this view was created with the empty constructur, null will be returned
077: *
078: * @return the creator of this view in form of an Address object
079: */
080: public Address getCreator() {
081: return vid != null ? vid.getCoordAddress() : null;
082: }
083:
084: /**
085: * Returns a reference to the List of members (ordered)
086: * Do NOT change this list, hence your will invalidate the view
087: * Make a copy if you have to modify it.
088: *
089: * @return a reference to the ordered list of members in this view
090: */
091: public Vector getMembers() {
092: return Util.unmodifiableVector(members);
093: }
094:
095: /**
096: * returns true, if this view contains a certain member
097: *
098: * @param mbr - the address of the member,
099: * @return true if this view contains the member, false if it doesn't
100: * if the argument mbr is null, this operation returns false
101: */
102: public boolean containsMember(Address mbr) {
103: if (mbr == null || members == null) {
104: return false;
105: }
106: return members.contains(mbr);
107: }
108:
109: public boolean equals(Object obj) {
110: if (obj == null)
111: return false;
112: if (!(obj instanceof View))
113: throw new ClassCastException(obj.getClass().getName()
114: + " is not a View");
115: if (vid != null) {
116: int rc = vid.compareTo(((View) obj).vid);
117: if (rc != 0)
118: return false;
119: if (members != null && ((View) obj).members != null) {
120: return members.equals(((View) obj).members);
121: }
122: } else {
123: if (((View) obj).vid == null)
124: return true;
125: }
126: return false;
127: }
128:
129: /**
130: * returns the number of members in this view
131: *
132: * @return the number of members in this view 0..n
133: */
134: public int size() {
135: return members == null ? 0 : members.size();
136: }
137:
138: /**
139: * creates a copy of this view
140: *
141: * @return a copy of this view
142: */
143: public Object clone() {
144: ViewId vid2 = vid != null ? (ViewId) vid.clone() : null;
145: Vector members2 = members != null ? (Vector) members.clone()
146: : null;
147: return new View(vid2, members2);
148: }
149:
150: /**
151: * debug only
152: */
153: public String printDetails() {
154: StringBuffer ret = new StringBuffer();
155: ret.append(vid).append("\n\t");
156: if (members != null) {
157: for (int i = 0; i < members.size(); i++) {
158: ret.append(members.elementAt(i)).append("\n\t");
159: }
160: ret.append('\n');
161: }
162: return ret.toString();
163: }
164:
165: public String toString() {
166: StringBuffer ret = new StringBuffer(64);
167: ret.append(vid).append(" ").append(members);
168: return ret.toString();
169: }
170:
171: public void writeExternal(ObjectOutput out) throws IOException {
172: out.writeObject(vid);
173: out.writeObject(members);
174: }
175:
176: public void readExternal(ObjectInput in) throws IOException,
177: ClassNotFoundException {
178: vid = (ViewId) in.readObject();
179: members = (Vector) in.readObject();
180: }
181:
182: public void writeTo(DataOutputStream out) throws IOException {
183: // vid
184: if (vid != null) {
185: out.writeBoolean(true);
186: vid.writeTo(out);
187: } else
188: out.writeBoolean(false);
189:
190: // members:
191: Util.writeAddresses(members, out);
192: }
193:
194: public void readFrom(DataInputStream in) throws IOException,
195: IllegalAccessException, InstantiationException {
196: boolean b;
197: // vid:
198: b = in.readBoolean();
199: if (b) {
200: vid = new ViewId();
201: vid.readFrom(in);
202: }
203:
204: // members:
205: members = (Vector) Util.readAddresses(in, Vector.class);
206: }
207:
208: public int serializedSize() {
209: int retval = Global.BYTE_SIZE; // presence for vid
210: if (vid != null)
211: retval += vid.serializedSize();
212: retval += Util.size(members);
213: return retval;
214: }
215:
216: }
|