001: // $Id: Xid.java,v 1.5 2005/07/17 11:36:40 chrislott Exp $
002:
003: package org.jgroups.blocks;
004:
005: import org.jgroups.Address;
006:
007: import java.io.Externalizable;
008: import java.io.IOException;
009: import java.io.ObjectInput;
010: import java.io.ObjectOutput;
011:
012: /**
013: * Distributed transaction ID modeled after the JTA spec. This is used to
014: * identify entities of work, with which resources are associated. A transaction
015: * will thus trigger the creation of an associated entry on each receiver, which
016: * keeps track of resources acquired and their locks, operations to be committed
017: * in case {@link ReplicationReceiver#commit(Xid)}is called.
018: * <p>
019: * A transaction is identified by its creator and a transaction ID. The creator
020: * is currently a <a href="http://www.jgroups.com">JGroups</a> address,
021: * consisting of the IP address and port of the member.
022: * <p>
023: * <em>Note that this class might be replaced in the future with the real
024: * JTA counterpart.</em>
025: *
026: * @author <a href="mailto:belaban@yahoo.com">Bela Ban</a>.
027: * @version $Revision: 1.5 $
028: *
029: * <p><b>Revisions:</b>
030: *
031: * <p>Dec 28 2002 Bela Ban: first implementation
032: */
033: public class Xid implements Externalizable {
034: protected Address creator = null;
035: protected long id = 0;
036: protected int mode = DIRTY_READS;
037: protected static transient long next_id = 0;
038: public static final String XID = "xid";
039:
040: /**
041: * Writes are serialized, but reads can be dirty; e.g., a data might have
042: * been changed while we read it. This is fast because we don't need to
043: * acquire locks for reads.
044: */
045: public static final int DIRTY_READS = 1;
046:
047: /**
048: * Reads are dirty until another transaction actually commits; at that
049: * points the modified data will be reflected here.
050: */
051: public static final int READ_COMMITTED = 2;
052:
053: /**
054: * Each read causes the data read to be copied to the private workspace, so
055: * subsequent reads always read the private data.
056: */
057: public static final int REPEATABLE_READ = 3;
058:
059: /**
060: * Reads and writes require locks. This is very costly, and is not
061: * recommended (and currently not implemented either :-)).
062: */
063: public static final int SERIALIZABLE = 4;
064:
065: public Xid() {
066: ; // used by externalization
067: }
068:
069: private Xid(Address creator, long id) {
070: this .creator = creator;
071: this .id = id;
072: }
073:
074: private Xid(Address creator, long id, int mode) {
075: this .creator = creator;
076: this .id = id;
077: this .mode = mode;
078: }
079:
080: public Address getCreator() {
081: return creator;
082: }
083:
084: public long getId() {
085: return id;
086: }
087:
088: public long getMode() {
089: return mode;
090: }
091:
092: public static Xid create(Address creator) throws Exception {
093: if (creator == null)
094: throw new Exception("Xid.create(): creator == null");
095: synchronized (Xid.class) {
096: return new Xid(creator, ++next_id);
097: }
098: }
099:
100: public static Xid create(Address creator, int mode)
101: throws Exception {
102: if (creator == null)
103: throw new Exception("Xid.create(): creator == null");
104: synchronized (Xid.class) {
105: return new Xid(creator, ++next_id, mode);
106: }
107: }
108:
109: public static String modeToString(int m) {
110: switch (m) {
111: case DIRTY_READS:
112: return "DIRTY_READS";
113: case READ_COMMITTED:
114: return "READ_COMMITTED";
115: case REPEATABLE_READ:
116: return "REPEATABLE_READ";
117: case SERIALIZABLE:
118: return "SERIALIZABLE";
119: default:
120: return "<unknown>";
121: }
122: }
123:
124: public boolean equals(Object other) {
125: return compareTo(other) == 0;
126: }
127:
128: public int hashCode() {
129: return creator.hashCode() + (int) id;
130: }
131:
132: public int compareTo(Object o) {
133: Xid other;
134: int comp;
135: if (o == null || !(o instanceof Xid))
136: throw new ClassCastException(
137: "Xid.compareTo(): comparison between different classes");
138: other = (Xid) o;
139: comp = creator.compareTo(other.getCreator());
140: if (comp != 0)
141: return comp;
142: if (id < other.getId())
143: return -1;
144: if (id > other.getId())
145: return 1;
146: return 0;
147: }
148:
149: public String toString() {
150: StringBuffer sb = new StringBuffer();
151: sb.append('<').append(creator).append(">:").append(id);
152: return sb.toString();
153: }
154:
155: public void writeExternal(ObjectOutput out) throws IOException {
156: out.writeObject(creator);
157: out.writeLong(id);
158: out.writeInt(mode);
159: }
160:
161: public void readExternal(ObjectInput in) throws IOException,
162: ClassNotFoundException {
163: creator = (Address) in.readObject();
164: id = in.readLong();
165: mode = in.readInt();
166: }
167:
168: }
|