001: /*
002: * @(#) XidImpl.java
003: *
004: * JOTM: Java Open Transaction Manager
005: *
006: *
007: * This module was originally developed by
008: *
009: * - Bull S.A. as part of the JOnAS application server code released in
010: * July 1999 (www.bull.com)
011: *
012: * --------------------------------------------------------------------------
013: * The original code and portions created by Bull SA are
014: * Copyright (c) 1999 BULL SA
015: * All rights reserved.
016: *
017: * Redistribution and use in source and binary forms, with or without
018: * modification, are permitted provided that the following conditions are met:
019: *
020: * -Redistributions of source code must retain the above copyright notice, this
021: * list of conditions and the following disclaimer.
022: *
023: * -Redistributions in binary form must reproduce the above copyright notice,
024: * this list of conditions and the following disclaimer in the documentation
025: * and/or other materials provided with the distribution.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
028: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
029: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
030: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
031: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
032: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
033: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
034: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
035: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
036: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
037: * POSSIBILITY OF SUCH DAMAGE.
038: *
039: * --------------------------------------------------------------------------
040: * $Id: XidImpl.java,v 1.28 2005/04/22 17:53:46 tonyortiz Exp $
041: * --------------------------------------------------------------------------
042: */
043: package org.objectweb.jotm;
044:
045: import java.io.Serializable;
046: import java.nio.ByteBuffer;
047: import java.security.SecureRandom;
048:
049: import org.objectweb.howl.log.xa.XACommittingTx;
050:
051: /**
052: * Xid implementation for JTA
053: *
054: * XID has the following format as defined by X/Open Specification:
055: *
056: * XID
057: * long formatId format identifier
058: * long gtrid_length value 1-64
059: * long bqual_length value 1-64
060: * byte data [XIDDATASIZE] where XIDDATASIZE = 128
061: *
062: * The data field comprises at most two contiguous components:
063: * a global transaction identifier (gtrid) and a branch qualifier (bqual)
064: * which are defined as:
065: *
066: * byte gtrid [1-64] global transaction identfier
067: * byte bqual [1-64] branch qualifier
068: *
069: */
070: public class XidImpl implements Xid, Serializable {
071:
072: public static final int JOTM_FORMAT_ID = 0xBB14;
073:
074: // these cells are gated by this.getClass()
075: private static SecureRandom rand = null; // (also used as first-time flag)
076: private final byte internalVersId = 1;
077: private static int count = 1;
078: private static long uuid0;
079: private static long uuid1;
080: private static boolean uuidsRecovered = false;
081: private static byte[] gtrid_base = null; // created by makeGtridBase()
082: private static String host, server;
083:
084: private String fullString = "";
085: private String shortString = "";
086:
087: private boolean hashcodevalid = false;
088: private int myhashcode;
089:
090: static String HexDigits[] = { "00", "01", "02", "03", "04", "05",
091: "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
092: "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
093: "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23",
094: "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d",
095: "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37",
096: "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41",
097: "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b",
098: "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55",
099: "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
100: "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
101: "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73",
102: "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d",
103: "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87",
104: "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91",
105: "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b",
106: "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5",
107: "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
108: "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9",
109: "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3",
110: "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd",
111: "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
112: "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1",
113: "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb",
114: "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5",
115: "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" };
116:
117: /**
118: * format id
119: * @serial
120: */
121: private int formatId;
122:
123: /**
124: * gtrid length
125: * @serial
126: */
127: private int gtrid_length;
128:
129: /**
130: * bqual length
131: * @serial
132: */
133: private int bqual_length;
134:
135: /**
136: * global transaction id
137: * @serial
138: */
139: private byte[] gtrid;
140:
141: /**
142: * branch qualifier
143: * @serial
144: */
145: private byte[] bqual;
146:
147: // -------------------------------------------------------------------
148: // Constructors
149: // -------------------------------------------------------------------
150:
151: /**
152: * Build an Xid for a local transaction
153: */
154: public XidImpl(String serverName, int ipAddr) {
155:
156: if (TraceTm.jotm.isDebugEnabled()) {
157: TraceTm.jotm.debug("serverName=" + serverName + ", ipAddr="
158: + ipAddr);
159: }
160:
161: formatId = JOTM_FORMAT_ID;
162: byte local_vers = 0;
163: long uuid;
164: long myipaddr;
165:
166: synchronized (getClass()) {
167: uuid = System.currentTimeMillis() * 1024 + count;
168: count++;
169: }
170:
171: // compute gtrid
172: // compute JOnAS gtrid
173: String s = Long.toHexString(local_vers)
174: + Long.toHexString(uuid) + "_"
175: + Long.toHexString(ipAddr) + "_" + serverName;
176:
177: if (s.length() > Xid.MAXBQUALSIZE) {
178: s = s.substring(0, Xid.MAXBQUALSIZE);
179: }
180:
181: gtrid = s.getBytes();
182: gtrid_length = gtrid.length;
183:
184: // XXX bqual is equal to gtrid in this constructor
185: bqual = s.getBytes();
186: bqual_length = bqual.length;
187:
188: if (TraceTm.jotm.isDebugEnabled()) {
189: TraceTm.jotm.debug("Xid (uuid= " + Long.toHexString(uuid)
190: + ")");
191: }
192: }
193:
194: /**
195: * Build an Xid from an otid_t CORBA
196: */
197: public XidImpl(int fid, int bqualsz, byte[] tid) {
198: if (TraceTm.jotm.isDebugEnabled()) {
199: TraceTm.jotm.debug("constructor from otid_t");
200: }
201:
202: // FormatId
203: formatId = fid;
204:
205: // gtrid
206: int gtridsz = tid.length - bqualsz;
207: gtrid = new byte[gtridsz];
208: System.arraycopy(tid, bqualsz, gtrid, 0, gtridsz);
209:
210: // bqual
211: bqual = new byte[bqualsz];
212: System.arraycopy(tid, 0, bqual, 0, bqualsz);
213:
214: // gtrid_length
215: gtrid_length = gtridsz;
216:
217: // bqual_length
218: bqual_length = bqualsz;
219: }
220:
221: /**
222: * build Xid with all its components
223: * (for performance on java serialization)
224: */
225: public XidImpl(int formatId, byte[] gtrid, byte[] bqual) {
226:
227: this .formatId = formatId;
228: this .gtrid = gtrid;
229: this .bqual = bqual;
230: this .gtrid_length = gtrid.length;
231: this .bqual_length = bqual.length;
232: }
233:
234: /**
235: * build a new Xid with a null BQual
236: */
237: public XidImpl() {
238: formatId = JOTM_FORMAT_ID;
239:
240: gtrid = makeGtrid();
241: gtrid_length = gtrid.length;
242: bqual = new byte[0];
243: bqual_length = bqual.length;
244: }
245:
246: /**
247: * build a new Xid from an existing Xid, preserving the gtrid,
248: * and using the 'index' as part of the unique but recognizable BQual.
249: * The important thing is that this method must return the same result
250: * on successive calls given the same input.
251: */
252: public XidImpl(Xid oldXid, int index) {
253:
254: if (TraceTm.jotm.isDebugEnabled()) {
255: TraceTm.jotm.debug("old XID= " + oldXid);
256: TraceTm.jotm.debug("index= " + index);
257: }
258:
259: formatId = oldXid.getFormatId();
260:
261: gtrid = oldXid.getGlobalTransactionId();
262: makeGtridBase();
263: gtrid_length = gtrid.length;
264:
265: bqual = new byte[MAXBQUALSIZE];
266: ByteBuffer bb = ByteBuffer.wrap(bqual);
267: bb.put(gtrid_base);
268: bb.putLong(0L); // (time stamp not used on bqual)
269: bb.putLong(index + 0L); // and this makes the bqual unique
270: bqual_length = bqual.length;
271: }
272:
273: /**
274: * Construct an Xid from a byteBuffer. This is necessary for use
275: * during recovery when the Xid has been converted to a String so
276: * that it can be written to a file. The Xid must be reconstructed
277: * from the byte array resulting from toString(true). Note that the
278: * byte array includes ':' characters as separators between
279: * components.
280: *
281: * NOTE: Current position of input ByteBuffer is employed!!
282: *
283: */
284:
285: public XidImpl(ByteBuffer XidByteBuffer) {
286: byte tempByte;
287:
288: tempByte = XidByteBuffer.get();
289:
290: while (tempByte != ':') {
291: formatId = (formatId * 16)
292: + ((int) tempByte - ((int) tempByte > 96 ? 87 : 48));
293: tempByte = XidByteBuffer.get();
294: }
295:
296: tempByte = XidByteBuffer.get();
297:
298: while (tempByte != ':') {
299: gtrid_length = (gtrid_length * 16)
300: + ((int) tempByte - ((int) tempByte > 96 ? 87 : 48));
301: tempByte = XidByteBuffer.get();
302: }
303: tempByte = XidByteBuffer.get();
304:
305: while (tempByte != ':') {
306: bqual_length = (bqual_length * 16)
307: + ((int) tempByte - ((int) tempByte > 96 ? 87 : 48));
308: tempByte = XidByteBuffer.get();
309: }
310:
311: gtrid = new byte[gtrid_length];
312: bqual = new byte[bqual_length];
313:
314: int tempInt;
315:
316: for (int i = 0; i <= (gtrid_length - 1); i++) {
317: byte tempByteUpper = XidByteBuffer.get();
318: byte tempByteLower = XidByteBuffer.get();
319: gtrid[i] = (byte) ((16 * ((int) tempByteUpper - ((int) tempByteUpper > 96 ? 87
320: : 48))) + ((int) tempByteLower - ((int) tempByteLower > 96 ? 87
321: : 48)));
322: }
323:
324: if (XidByteBuffer.get() != ':') {
325: if (TraceTm.recovery.isDebugEnabled()) {
326: TraceTm.recovery
327: .debug(" XXXX XidByteArray alignment is bad! XXX ");
328: }
329: }
330:
331: for (int i = 0; i <= (bqual_length - 1); i++) {
332: byte tempByteUpper = XidByteBuffer.get();
333: byte tempByteLower = XidByteBuffer.get();
334: bqual[i] = (byte) ((16 * ((int) tempByteUpper - ((int) tempByteUpper > 96 ? 87
335: : 48))) + ((int) tempByteLower - ((int) tempByteLower > 96 ? 87
336: : 48)));
337: }
338:
339: if (TraceTm.recovery.isDebugEnabled()) {
340: TraceTm.recovery.debug("Rebuilt Xid: "
341: + this .toString(true));
342: }
343: }
344:
345: /**
346: * Construct an Xid from a byte array. This is necessary for use
347: * during recovery when the Xid has been converted to a byte array so
348: * that it can be written to the Howl log. The Xid must be reconstructed
349: * from the byte array resulting from toString(true). Note that the
350: * byte array includes ':' characters as separators between components.
351: *
352: */
353:
354: public XidImpl(byte[] XidByteArray) {
355: byte tempByte;
356: int tempIndex = 0;
357:
358: tempByte = XidByteArray[tempIndex];
359:
360: while (tempByte != ':') {
361: formatId = (formatId * 16)
362: + ((int) tempByte - ((int) tempByte > 96 ? 87 : 48));
363: tempIndex++;
364: tempByte = XidByteArray[tempIndex];
365: }
366:
367: tempIndex++;
368: tempByte = XidByteArray[tempIndex];
369:
370: while (tempByte != ':') {
371: gtrid_length = (gtrid_length * 16)
372: + ((int) tempByte - ((int) tempByte > 96 ? 87 : 48));
373: tempIndex++;
374: tempByte = XidByteArray[tempIndex];
375: }
376:
377: tempIndex++;
378: tempByte = XidByteArray[tempIndex];
379:
380: while (tempByte != ':') {
381: bqual_length = (bqual_length * 16)
382: + ((int) tempByte - ((int) tempByte > 96 ? 87 : 48));
383: tempIndex++;
384: tempByte = XidByteArray[tempIndex];
385: }
386:
387: gtrid = new byte[gtrid_length];
388: bqual = new byte[bqual_length];
389:
390: int tempInt;
391:
392: for (int i = 0; i <= (gtrid_length - 1); i++) {
393: tempIndex++;
394: byte tempByteUpper = XidByteArray[tempIndex];
395: tempIndex++;
396: byte tempByteLower = XidByteArray[tempIndex];
397: gtrid[i] = (byte) ((16 * ((int) tempByteUpper - ((int) tempByteUpper > 96 ? 87
398: : 48))) + ((int) tempByteLower - ((int) tempByteLower > 96 ? 87
399: : 48)));
400: }
401:
402: tempIndex++;
403: tempByte = XidByteArray[tempIndex];
404:
405: if (tempByte != ':') {
406: if (TraceTm.recovery.isDebugEnabled()) {
407: TraceTm.recovery
408: .debug(" XXXX XidByteArray alignment is bad! XXX ");
409: }
410: }
411:
412: for (int i = 0; i <= (bqual_length - 1); i++) {
413: tempIndex++;
414: byte tempByteUpper = XidByteArray[tempIndex];
415: tempIndex++;
416: byte tempByteLower = XidByteArray[tempIndex];
417: bqual[i] = (byte) ((16 * ((int) tempByteUpper - ((int) tempByteUpper > 96 ? 87
418: : 48))) + ((int) tempByteLower - ((int) tempByteLower > 96 ? 87
419: : 48)));
420: }
421:
422: if (TraceTm.recovery.isDebugEnabled()) {
423: TraceTm.recovery.debug("Rebuilt Xid: "
424: + this .toString(true));
425: }
426: }
427:
428: /**
429: * The xid was passed from an external EIS (inflow transaction).
430: * Need to store the formatId, gtrid.length, bqual.length, gtrid,
431: * and bqual from the passed xid.
432: */
433:
434: public XidImpl(javax.transaction.xa.Xid passedXid) {
435: if (TraceTm.jotm.isDebugEnabled()) {
436: TraceTm.jotm.debug("passed XID= " + passedXid);
437: }
438:
439: formatId = passedXid.getFormatId();
440: gtrid = passedXid.getGlobalTransactionId();
441: gtrid_length = gtrid.length;
442: bqual = passedXid.getBranchQualifier();
443: bqual_length = bqual.length;
444: }
445:
446: // -------------------------------------------------------------------
447: // Xid implementation
448: // -------------------------------------------------------------------
449:
450: /**
451: * Provide static interface to recover uuid0 & uuid1 after journal
452: * replay.
453: */
454: public static void setUuids(long passedUuid0, long passedUuid1) {
455: uuid0 = passedUuid0;
456: uuid1 = passedUuid1;
457: uuidsRecovered = true;
458:
459: if (TraceTm.recovery.isDebugEnabled()) {
460: TraceTm.recovery.debug("uuids recovered; uuid0:" + uuid0
461: + " uuid1:" + uuid1);
462: }
463: }
464:
465: /**
466: * Get the format id for that Xid
467: */
468: public int getFormatId() {
469: return formatId;
470: }
471:
472: /**
473: * Get the Global Id for that Xid
474: */
475: public byte[] getGlobalTransactionId() {
476: return gtrid;
477: }
478:
479: /**
480: * Get the Branch Qualifier for that Xid
481: */
482: public byte[] getBranchQualifier() {
483: return bqual;
484: }
485:
486: // -------------------------------------------------------------------
487: // other methods
488: // -------------------------------------------------------------------
489:
490: /**
491: * Hex Dump of byte
492: */
493: static final void byteToHex(byte inbyte, StringBuffer str_buff) {
494:
495: int myByte = 0xFF & inbyte;
496:
497: str_buff.append(HexDigits[myByte]);
498: return;
499: }
500:
501: /**
502: * String form
503: * default toString() compresses Xid's
504: */
505: public String toString() {
506: return this .toString(false);
507: }
508:
509: public String toString(boolean Full) {
510:
511: byte[] gtrid_local = null;
512: byte[] bqual_local = null;
513:
514: if (Full && (fullString.length() != 0)) {
515: return fullString;
516: } else if (!Full && (shortString.length() != 0)) {
517: return shortString;
518: }
519:
520: // Buffers need two hex characters per byte
521: StringBuffer str_buff_gtrid = new StringBuffer(MAXGTRIDSIZE * 2);
522: StringBuffer str_buff_bqual = new StringBuffer(MAXBQUALSIZE * 2);
523:
524: gtrid_local = new byte[MAXGTRIDSIZE];
525: ByteBuffer aa = ByteBuffer.wrap(gtrid_local);
526:
527: System.arraycopy(gtrid, 0, gtrid_local, 0, gtrid_length);
528:
529: for (int i = 0; i < gtrid_length; i++) {
530: byteToHex(aa.get(), str_buff_gtrid);
531: }
532:
533: bqual_local = new byte[MAXBQUALSIZE];
534: ByteBuffer bb = ByteBuffer.wrap(bqual_local);
535:
536: if (bqual != null) {
537: System.arraycopy(bqual, 0, bqual_local, 0, bqual_length);
538:
539: for (int i = 0; i < bqual_length; i++) {
540: byteToHex(bb.get(), str_buff_bqual);
541: }
542: }
543:
544: if ((gtrid_length > 30) && !Full) { // be prepared to reduce output string
545: int strlen = str_buff_gtrid.length();
546: str_buff_gtrid.replace((strlen / 6), (strlen / 6) + 2,
547: "...");
548: str_buff_gtrid.delete((strlen / 6) + 3, strlen - 5);
549: }
550:
551: if ((bqual_length > 30) && !Full) { // be prepared to reduce output string
552: int strlen = str_buff_bqual.length();
553: str_buff_bqual.replace((strlen / 6), (strlen / 6) + 2,
554: "...");
555: str_buff_bqual.delete((strlen / 6) + 3, strlen - 5);
556: }
557:
558: if (Full) {
559: fullString = Long.toHexString(formatId) + ":"
560: + Long.toHexString(gtrid_length) + ":"
561: + Long.toHexString(bqual_length) + ":"
562: + str_buff_gtrid.toString() + ":"
563: + str_buff_bqual.toString();
564: return fullString;
565: }
566:
567: shortString = Long.toHexString(formatId) + ":"
568: + Long.toHexString(gtrid_length) + ":"
569: + Long.toHexString(bqual_length) + ":"
570: + str_buff_gtrid.toString() + ":"
571: + str_buff_bqual.toString();
572: return shortString;
573: }
574:
575: /*
576: * make a unique but recognizable gtrid.
577: *
578: * format:
579: * 1. internal version identifier - 1 byte
580: * 2. uuid - 16 bytes
581: * 3. host name - 16 bytes
582: * 4. server name - 15 bytes
583: * 5. timestamp - 8 bytes
584: * 6. [reserved for use by bqual - 8 bytes]
585: *
586: * Items 1 thru 4 are generated by makeGtridBase and comprise the recognizable
587: * portion of a gtrid or bqual. Together, these serve to make Xids generated on
588: * this system unique from those generated on other systems.
589: * Item 5 is generated by this routine and serves to make gtrids unique.
590: * Item 6 serves to distinguish different bquals belonging
591: * to the same Xid, and is generated elsewhere.
592: *
593: * Items 1 thru 4 are used to determine if we (JOTM) generated this gtrid/bqual.
594: */
595:
596: private byte[] makeGtrid() {
597: makeGtridBase();
598: long uniqueTimeStamp;
599:
600: synchronized (getClass()) {
601: uniqueTimeStamp = System.currentTimeMillis() * 1024 + count;
602: count++;
603: }
604:
605: ByteBuffer bb = ByteBuffer.allocate(gtrid_base.length + 8);
606: bb.put(gtrid_base);
607: bb.putLong(uniqueTimeStamp);
608: return bb.array();
609: }
610:
611: private void makeGtridBase() {
612: // acquire the configured uuid, host and server name.
613: // fabricate a uuid if one does not yet exist.
614: // and append a unique timestamp.
615:
616: synchronized (getClass()) {
617: if (rand == null) {
618: rand = new SecureRandom();
619:
620: if (uuidsRecovered == false) { // first time or no journal
621: //uuid0 = Long.parseLong(System.getProperty("jotm.uuid.part1"),16);
622: //uuid1 = Long.parseLong(System.getProperty("jotm.uuid.part2"),16);
623: uuid0 = rand.nextLong();
624: uuid1 = rand.nextLong();
625: XACommittingTx LogId = null;
626:
627: // We build the Inique ID Record in makeGtridBase
628: // Store the Unique ID Record using HOWL so it can manage for us.
629: // It will never have a DONE record written.
630: //
631: // The Unique ID record consists of two fields:
632: // 1. uuid0
633: // 2. uuid1
634: //
635: // The XA Unique ID record format:
636: // Unique ID record type1 (byte[3]) - 'RU1'
637: // Unique ID record stored uuido (long) - 8 bytes
638: // Unique ID record stored uuid1 (long) - 8 bytes
639: //
640:
641: byte[] UniqueID = new byte[3 + 8 + 8];
642: byte[][] UniqueIDRecord = new byte[1][3 + 8 + 8];
643:
644: String rt1 = "RU1";
645:
646: ByteBuffer rr1 = ByteBuffer.wrap(UniqueID);
647: rr1.put(rt1.getBytes());
648: rr1.putLong(uuid0);
649: rr1.putLong(uuid1);
650:
651: UniqueIDRecord[0] = UniqueID;
652:
653: if (Current.getDefaultRecovery()) {
654: try {
655: LogId = TransactionRecoveryImpl
656: .getTransactionRecovery()
657: .howlCommitLog(UniqueIDRecord);
658: } catch (Exception e) {
659: // If we cannot write the Log, we cannot perform recovery
660: String howlerror = "Cannot howlCommitLog:"
661: + e + " --" + e.getMessage();
662: TraceTm.recovery
663: .error("Got LogException from howlCommitLog writing UniqueIDRecord: "
664: + howlerror);
665:
666: // XXX throw new TransactionRolledbackException();
667: }
668: if (TraceTm.recovery.isDebugEnabled()) {
669: TraceTm.recovery
670: .debug("Wrote UniqueIDRecord; at:"
671: + LogId.getLogKey()
672: + " uuid0:" + uuid0
673: + " uuid1:" + uuid1);
674: }
675: }
676: }
677:
678: host = "";
679: server = "";
680: // make host & server names fixed length, as defined above
681: host = (host + " ").substring(0, 15);
682: server = (server + " ").substring(0, 14);
683: gtrid_base = new byte[1 + 8 + 8 + 16 + 15];
684: ByteBuffer bb = ByteBuffer.wrap(gtrid_base);
685: bb.put(internalVersId);
686: bb.putLong(uuid0);
687: bb.putLong(uuid1);
688: bb.put(host.getBytes());
689: bb.put(server.getBytes());
690: }
691: }
692: }
693:
694: /*
695: * Check if the specified gtrid or bqual is one which was generated
696: * by this version of JOTM.
697: *
698: * @return true or false
699: */
700:
701: public boolean IsThisOneOfOurs(byte[] gtrid_or_bqual) {
702: if (rand == null) {
703: makeGtrid(); /* init gtrid_base if not yet done */
704: }
705:
706: boolean ret = false;
707:
708: if (gtrid_or_bqual != null
709: && gtrid_or_bqual.length >= gtrid_base.length) {
710: byte[] gbase;
711:
712: if (gtrid_or_bqual.length == gtrid_base.length) {
713: gbase = gtrid_base;
714: } else {
715: gbase = new byte[gtrid_base.length];
716: System.arraycopy(gtrid_base, 0, gbase, 0,
717: gtrid_base.length);
718: }
719:
720: byte[] gtrid_local = null;
721: byte[] gtrid_bqual_local = null;
722:
723: // Buffers need two hex characters per byte
724: StringBuffer str_buff_gtrid_bqual = new StringBuffer(
725: gtrid_base.length * 2);
726: StringBuffer str_buff_gbase = new StringBuffer(
727: gtrid_base.length * 2);
728:
729: gtrid_local = new byte[gtrid_base.length];
730: ByteBuffer aa = ByteBuffer.wrap(gtrid_local);
731:
732: System.arraycopy(gtrid_base, 0, gtrid_local, 0,
733: gtrid_base.length);
734:
735: for (int i = 0; i < gtrid_base.length; i++) {
736: byteToHex(aa.get(), str_buff_gbase);
737: }
738:
739: gtrid_bqual_local = new byte[gtrid_base.length];
740: ByteBuffer bb = ByteBuffer.wrap(gtrid_local);
741:
742: System.arraycopy(gtrid_or_bqual, 0, gtrid_bqual_local, 0,
743: gtrid_base.length);
744:
745: for (int i = 0; i < gtrid_base.length; i++) {
746: byteToHex(bb.get(), str_buff_gtrid_bqual);
747: }
748:
749: if (TraceTm.jotm.isDebugEnabled()) {
750: TraceTm.jotm.debug("gtrid_or_bqual= "
751: + str_buff_gtrid_bqual);
752: TraceTm.jotm.debug("gbase= " + str_buff_gbase);
753: }
754:
755: if (str_buff_gtrid_bqual.toString().equals(
756: str_buff_gbase.toString())) {
757: ret = true;
758: }
759: }
760: return ret;
761: }
762:
763: // -------------------------------------------------------------------
764: // equals and hashCode
765: // -------------------------------------------------------------------
766:
767: /**
768: * return true if objects are identical
769: */
770: public boolean equals(Object obj2) {
771:
772: XidImpl xid2 = (XidImpl) obj2;
773:
774: if (formatId == xid2.getFormatId()
775: && java.util.Arrays.equals(bqual, xid2
776: .getBranchQualifier())
777: && java.util.Arrays.equals(gtrid, xid2
778: .getGlobalTransactionId())) {
779: return true;
780: } else {
781: return false;
782: }
783: }
784:
785: /**
786: * return a hashcode value for this object
787: */
788: public int hashCode() {
789:
790: int hc = 0;
791:
792: if (hashcodevalid == false) {
793:
794: for (int i = 0; i < gtrid.length; i++) {
795: hc = hc * 37 + gtrid[i];
796: }
797:
798: for (int i = 0; i < bqual.length; i++) {
799: hc = hc * 37 + bqual[i];
800: }
801:
802: myhashcode = hc;
803: hashcodevalid = true;
804: }
805: return myhashcode;
806: }
807: }
|