001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.l2.state;
006:
007: import com.tc.logging.TCLogger;
008: import com.tc.logging.TCLogging;
009: import com.tc.net.groups.NodeID;
010: import com.tc.util.Assert;
011:
012: import java.io.Externalizable;
013: import java.io.IOException;
014: import java.io.ObjectInput;
015: import java.io.ObjectOutput;
016: import java.util.Arrays;
017:
018: public class Enrollment implements Externalizable {
019:
020: private static final TCLogger logger = TCLogging
021: .getLogger(Enrollment.class);
022: private NodeID nodeID;
023: private long[] weights;
024: private boolean isNew;
025:
026: public Enrollment() {
027: // To make serialization happy
028: }
029:
030: public Enrollment(NodeID nodeID, boolean isNew, long[] weights) {
031: this .nodeID = nodeID;
032: this .isNew = isNew;
033: Assert.assertNotNull(weights);
034: this .weights = weights;
035: }
036:
037: public NodeID getNodeID() {
038: return nodeID;
039: }
040:
041: public boolean isANewCandidate() {
042: return isNew;
043: }
044:
045: public boolean wins(Enrollment other) {
046: if (isNew != other.isNew) {
047: // an old candidate always wins over a new candidate
048: return !isNew;
049: }
050: int myLength = weights.length;
051: int otherLength = other.weights.length;
052: if (myLength > otherLength) {
053: return true;
054: } else if (myLength < otherLength) {
055: return false;
056: } else {
057: for (int i = 0; i < myLength; i++) {
058: if (weights[i] > other.weights[i]) {
059: // wins
060: return true;
061: } else if (weights[i] < other.weights[i]) {
062: // loses
063: return false;
064: }
065: }
066:
067: // XXX:: Both are the same weight. This shouldn't happen once we fix the weights to
068: // be unique (based on hardware,ip,process id etc.) But now it is possible and we
069: // handle it. If two nodes dont agree because of this there will be a re-election
070: logger.warn("Two Enrollments with same weights : " + this
071: + " == " + other);
072: return false;
073: }
074: }
075:
076: public void readExternal(ObjectInput in) throws IOException,
077: ClassNotFoundException {
078: this .nodeID = (NodeID) in.readObject();
079: this .isNew = in.readBoolean();
080: this .weights = new long[in.readInt()];
081: for (int i = 0; i < weights.length; i++) {
082: weights[i] = in.readLong();
083: }
084: }
085:
086: public void writeExternal(ObjectOutput out) throws IOException {
087: out.writeObject(this .nodeID);
088: out.writeBoolean(this .isNew);
089: out.writeInt(weights.length);
090: for (int i = 0; i < weights.length; i++) {
091: out.writeLong(weights[i]);
092: }
093: }
094:
095: public boolean equals(Object o) {
096: if (o instanceof Enrollment) {
097: Enrollment oe = (Enrollment) o;
098: return nodeID.equals(oe.nodeID)
099: && Arrays.equals(weights, oe.weights)
100: && isNew == oe.isNew;
101: }
102: return false;
103: }
104:
105: public String toString() {
106: StringBuffer sb = new StringBuffer("Enrollment [ ");
107: sb.append(nodeID).append(", isNew = ").append(isNew);
108: sb.append(", weights = ");
109: int length = weights.length;
110: for (int i = 0; i < length; i++) {
111: sb.append(weights[i]);
112: if (i < length - 1) {
113: sb.append(",");
114: }
115: }
116: sb.append(" ]");
117: return sb.toString();
118: }
119:
120: }
|