001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.transaction;
030:
031: import com.caucho.util.Alarm;
032: import com.caucho.util.CharBuffer;
033: import com.caucho.util.L10N;
034:
035: import javax.transaction.xa.Xid;
036:
037: /**
038: * Transaction identifier implementation.
039: */
040: public class XidImpl implements Xid {
041: private static L10N L = new L10N(XidImpl.class);
042:
043: public static final int GLOBAL_LENGTH = 28;
044:
045: private byte[] _global;
046: private byte[] _local;
047:
048: /**
049: * Creates a new transaction id.
050: *
051: * @param id the 64 bit number for the id.
052: */
053: public XidImpl(long serverId, long randomId) {
054: _global = new byte[GLOBAL_LENGTH];
055: _local = new byte[4];
056: _local[0] = 1;
057:
058: // the global id has the requirement of being globally unique
059:
060: // first 4 identify as Resin.
061: _global[0] = 'R';
062: _global[1] = 'e';
063: _global[2] = 's';
064: _global[3] = 'n';
065:
066: // next 8 is the crc64 of the caucho.server-id
067: _global[4] = (byte) (serverId >> 56);
068: _global[5] = (byte) (serverId >> 48);
069: _global[6] = (byte) (serverId >> 40);
070: _global[7] = (byte) (serverId >> 32);
071: _global[8] = (byte) (serverId >> 24);
072: _global[9] = (byte) (serverId >> 16);
073: _global[10] = (byte) (serverId >> 8);
074: _global[11] = (byte) (serverId);
075:
076: // next 8 is the current timestamp
077: long timestamp = Alarm.getCurrentTime();
078:
079: _global[12] = (byte) (timestamp >> 56);
080: _global[13] = (byte) (timestamp >> 48);
081: _global[14] = (byte) (timestamp >> 40);
082: _global[15] = (byte) (timestamp >> 32);
083: _global[16] = (byte) (timestamp >> 24);
084: _global[17] = (byte) (timestamp >> 16);
085: _global[18] = (byte) (timestamp >> 8);
086: _global[19] = (byte) (timestamp);
087:
088: // next 8 is a 64-bit random long
089: _global[20] = (byte) (randomId >> 56);
090: _global[21] = (byte) (randomId >> 48);
091: _global[22] = (byte) (randomId >> 40);
092: _global[23] = (byte) (randomId >> 32);
093: _global[24] = (byte) (randomId >> 24);
094: _global[25] = (byte) (randomId >> 16);
095: _global[26] = (byte) (randomId >> 8);
096: _global[27] = (byte) (randomId);
097: }
098:
099: XidImpl(XidImpl base, int branch) {
100: _global = new byte[base._global.length];
101: _local = new byte[4];
102: _local[0] = (byte) (branch);
103:
104: System.arraycopy(base._global, 0, _global, 0, _global.length);
105: }
106:
107: public XidImpl(byte[] global, byte[] local) {
108: _global = new byte[global.length];
109: _local = new byte[local.length];
110:
111: System.arraycopy(global, 0, _global, 0, global.length);
112: System.arraycopy(local, 0, _local, 0, local.length);
113: }
114:
115: XidImpl(byte[] global) {
116: _global = new byte[global.length];
117: _local = new byte[4];
118:
119: System.arraycopy(global, 0, _global, 0, global.length);
120: _local[0] = 1;
121: }
122:
123: XidImpl(byte[] global, int length) {
124: _global = new byte[length];
125: _local = new byte[4];
126:
127: System.arraycopy(global, 0, _global, 0, length);
128: _local[0] = 1;
129: }
130:
131: public int getFormatId() {
132: return 1234;
133: }
134:
135: public byte[] getBranchQualifier() {
136: return _local;
137: }
138:
139: public byte[] getGlobalTransactionId() {
140: return _global;
141: }
142:
143: /**
144: * Clones the xid.
145: */
146: public Object clone() {
147: return new XidImpl(_global, _local);
148: }
149:
150: /**
151: * Returns hashCode.
152: */
153: public int hashCode() {
154: byte[] global = _global;
155:
156: int hash = 37;
157:
158: for (int i = global.length - 1; i >= 0; i--)
159: hash = 65521 * hash + global[i];
160:
161: return hash;
162: }
163:
164: /**
165: * Returns equality.
166: */
167: public boolean equals(Object o) {
168: if (!(o instanceof Xid))
169: return false;
170:
171: Xid xid = (Xid) o;
172:
173: byte[] global = xid.getGlobalTransactionId();
174: byte[] local = xid.getBranchQualifier();
175:
176: if (global.length != _global.length)
177: return false;
178:
179: byte[] selfGlobal = _global;
180: byte[] selfLocal = _local;
181:
182: for (int i = global.length - 1; i >= 0; i--) {
183: if (global[i] != selfGlobal[i])
184: return false;
185: }
186:
187: for (int i = local.length - 1; i >= 0; i--) {
188: if (local[i] != selfLocal[i])
189: return false;
190: }
191:
192: return true;
193: }
194:
195: /**
196: * Printable version of the transaction id.
197: */
198: public String toString() {
199: CharBuffer cb = CharBuffer.allocate();
200:
201: cb.append("Xid[");
202:
203: byte[] branch = getBranchQualifier();
204:
205: addByte(cb, branch[0]);
206:
207: cb.append(":");
208:
209: byte[] global = getGlobalTransactionId();
210: for (int i = 24; i < 28; i++)
211: addByte(cb, global[i]);
212:
213: cb.append("]");
214:
215: return cb.close();
216: }
217:
218: /**
219: * Adds hex for debug
220: *
221: * @param cb the character buffer for the new value
222: * @param b the byte value
223: */
224: static private void addByte(CharBuffer cb, int b) {
225: int h = (b / 16) & 0xf;
226: int l = b & 0xf;
227:
228: if (h >= 10)
229: cb.append((char) ('a' + h - 10));
230: else
231: cb.append((char) ('0' + h));
232:
233: if (l >= 10)
234: cb.append((char) ('a' + l - 10));
235: else
236: cb.append((char) ('0' + l));
237: }
238: }
|