Source Code Cross Referenced for TransactionTable.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » store » raw » xact » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.store.raw.xact 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:
003:           Derby - Class org.apache.derby.impl.store.raw.xact.TransactionTable
004:
005:           Licensed to the Apache Software Foundation (ASF) under one or more
006:           contributor license agreements.  See the NOTICE file distributed with
007:           this work for additional information regarding copyright ownership.
008:           The ASF licenses this file to you under the Apache License, Version 2.0
009:           (the "License"); you may not use this file except in compliance with
010:           the License.  You may obtain a copy of the License at
011:
012:              http://www.apache.org/licenses/LICENSE-2.0
013:
014:           Unless required by applicable law or agreed to in writing, software
015:           distributed under the License is distributed on an "AS IS" BASIS,
016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017:           See the License for the specific language governing permissions and
018:           limitations under the License.
019:
020:         */
021:
022:        package org.apache.derby.impl.store.raw.xact;
023:
024:        import org.apache.derby.iapi.services.context.ContextManager;
025:
026:        import org.apache.derby.iapi.services.sanity.SanityManager;
027:        import org.apache.derby.iapi.services.io.Formatable;
028:        import org.apache.derby.iapi.services.io.FormatIdUtil;
029:        import org.apache.derby.iapi.services.io.StoredFormatIds;
030:
031:        import org.apache.derby.iapi.store.access.TransactionInfo;
032:
033:        import org.apache.derby.iapi.store.raw.GlobalTransactionId;
034:
035:        import org.apache.derby.iapi.store.raw.log.LogInstant;
036:
037:        import org.apache.derby.iapi.store.raw.xact.RawTransaction;
038:        import org.apache.derby.iapi.store.raw.xact.TransactionId;
039:
040:        import org.apache.derby.iapi.error.StandardException;
041:
042:        import org.apache.derby.iapi.services.io.CompressedNumber;
043:
044:        import java.util.Hashtable;
045:        import java.util.Enumeration;
046:        import java.io.ObjectOutput;
047:        import java.io.ObjectInput;
048:        import java.io.IOException;
049:
050:        /**
051:         The transaction table is used by the transaction factory to keep track of
052:         all transactions that are in the system.
053:
054:         <BR> The transction table serves the following purposes: <OL> 
055:
056:         <LI> checkpoint - when a checkpoint log record is written out, it writes
057:         out also all transactions that have updated the database.  RESOLVE: this is
058:         actually not used right now - rather, the transaction table is
059:         reconstructed during the redo phase by traversing from the undo LWM.  It is
060:         a goal to use this transaction table (and traversing from the redoLWM)
061:         instead of rebuilding it to speed up recovery.
062:
063:         <LI> Quiesce State - when a  system enters the quiesce state, it needs to account
064:         for all transactions in the system, even those which are just started and
065:         are in their IDLE state.
066:
067:         <LI> TransactionTable VTI - we need to get a snapshot of all transactions
068:         in the system for diagnostic purposes.
069:         </OL>
070:
071:         In order to speed up the time it takes to look up a transaction from the
072:         transaction table, each transaction must have a unique transaction Id.
073:         This means newly coined transaction must also have a transaction Id.
074:
075:         <P>During recovery, there is only one real xact object doing all the
076:         recovery work, but there could be many outstanding transactions that are
077:         gleamed from the log.  Each of these "recovery transactions" have its on
078:         entry into the transaction table but they all share the same Xact object.
079:
080:         <P>Multithreading considerations:<BR>
081:         TransactionTable must be MT-safe it is called upon by many threads
082:         simultaneously (except during recovery)
083:
084:         <P><B> This class depends on Hashtable synchronization!! </B>
085:
086:         */
087:
088:        public class TransactionTable implements  Formatable {
089:            /*
090:             * Fields
091:             */
092:
093:            private Hashtable trans;
094:
095:            private TransactionId largestUpdateXactId;
096:
097:            /**
098:            	MT - not needed for constructor
099:             */
100:            public TransactionTable() {
101:                trans = new Hashtable(17);
102:            }
103:
104:            /*************************************************************
105:             * generic methods called by all clients of transaction table
106:             * Must be MT -safe
107:             ************************************************************/
108:            private TransactionTableEntry findTransactionEntry(TransactionId id) {
109:
110:                if (SanityManager.DEBUG)
111:                    SanityManager.ASSERT(id != null,
112:                            "findTransacionEntry with null id");
113:
114:                // Hashtable is synchronized
115:                return (TransactionTableEntry) trans.get(id);
116:            }
117:
118:            void add(Xact xact, boolean exclude) {
119:                TransactionId id = xact.getId();
120:
121:                synchronized (this ) {
122:                    TransactionTableEntry ent = findTransactionEntry(id);
123:
124:                    if (ent == null) {
125:                        ent = new TransactionTableEntry(xact, id, 0,
126:                                exclude ? TransactionTableEntry.EXCLUDE : 0);
127:
128:                        trans.put(id, ent);
129:
130:                        if (SanityManager.DEBUG) {
131:                            if (SanityManager.DEBUG_ON("TranTrace")) {
132:                                SanityManager.DEBUG("TranTrace",
133:                                        "adding transaction " + id);
134:                                SanityManager.showTrace(new Throwable(
135:                                        "TranTrace"));
136:                            }
137:                        }
138:                    }
139:
140:                    if (SanityManager.DEBUG) {
141:                        if (exclude != ent.needExclusion())
142:                            SanityManager
143:                                    .THROWASSERT("adding the same transaction with different exclusion: "
144:                                            + exclude
145:                                            + " "
146:                                            + ent.needExclusion());
147:                    }
148:                }
149:
150:                if (SanityManager.DEBUG) {
151:
152:                    if (SanityManager.DEBUG_ON("memoryLeakTrace")) {
153:
154:                        if (trans.size() > 50)
155:                            System.out
156:                                    .println("memoryLeakTrace:TransactionTable "
157:                                            + trans.size());
158:                    }
159:                }
160:            }
161:
162:            /*
163:            	remove the transaction Id an return false iff the transaction is found
164:            	in the table and it doesn't need exclusion during quiesce state
165:             */
166:            boolean remove(TransactionId id) {
167:                if (SanityManager.DEBUG)
168:                    SanityManager
169:                            .ASSERT(id != null,
170:                                    "cannot remove transaction from table with null id");
171:
172:                if (SanityManager.DEBUG) {
173:                    if (SanityManager.DEBUG_ON("TranTrace")) {
174:                        SanityManager.DEBUG("TranTrace",
175:                                "removing transaction " + id);
176:                        SanityManager.showTrace(new Throwable("TranTrace"));
177:                    }
178:                }
179:
180:                // Hashtable is synchronized
181:                TransactionTableEntry ent = (TransactionTableEntry) trans
182:                        .remove(id);
183:                return (ent == null || ent.needExclusion());
184:            }
185:
186:            /**
187:            	Change a transaction to update or add an update transaction to this table.
188:
189:            	@param tid the transaction id
190:            	@param tran the transaction to be added
191:            	@param transactionStatus the transaction status that is stored in the
192:            			BeginXact log record
193:             */
194:            public void addUpdateTransaction(TransactionId tid,
195:                    RawTransaction tran, int transactionStatus) {
196:
197:                // we need to synchronize on the transaction table because we have to
198:                // prevent this state change from happening when the transaction table
199:                // itself is written out to the checkpoint.  This is the only
200:                // protection the TransactionTableEntry has to prevent fields in myxact
201:                // from changing underneath it while it is being written out.
202:                synchronized (this ) {
203:                    TransactionTableEntry ent = findTransactionEntry(tid);
204:
205:                    if (ent != null) {
206:                        // this happens during run time, when a transaction that is
207:                        // already started changed status to an update transaction
208:
209:                        ent
210:                                .updateTransactionStatus((Xact) tran,
211:                                        transactionStatus,
212:                                        TransactionTableEntry.UPDATE);
213:                    } else {
214:                        // this happens during recovery, that's why we haven't seen
215:                        // this transaction before - it is added in the doMe of the 
216:                        // BeginXact log record.
217:                        //
218:                        // No matter what this transaction is, it won't need to be run
219:                        // in quiesce state because we are in recovery.
220:                        ent = new TransactionTableEntry((Xact) tran, tid,
221:                                transactionStatus, TransactionTableEntry.UPDATE
222:                                        | TransactionTableEntry.EXCLUDE
223:                                        | TransactionTableEntry.RECOVERY);
224:                        trans.put(tid, ent);
225:
226:                    }
227:
228:                    if (XactId.compare(ent.getXid(), largestUpdateXactId) > 0)
229:                        largestUpdateXactId = ent.getXid();
230:                }
231:            }
232:
233:            /**
234:                Change update transaction to non-update
235:
236:            	<P>MT - MT safe, since vector is MT-safe.
237:
238:            	@param id the transaction Id
239:             */
240:            void removeUpdateTransaction(TransactionId id) {
241:                // we need to synchronize on the transaction table because we have to
242:                // prevent this state change from happening when the transaction table
243:                // itself is written out to the checkpoint.  This is the only
244:                // protection the TransactionTableEntry has to prevent fields in myxact
245:                // from changing underneath it while it is being written out.
246:
247:                synchronized (this ) {
248:                    TransactionTableEntry ent = findTransactionEntry(id);
249:
250:                    if (SanityManager.DEBUG) {
251:                        SanityManager
252:                                .ASSERT(ent != null,
253:                                        "removing update transaction that is not there");
254:                    }
255:
256:                    ent.removeUpdateTransaction();
257:
258:                    // If we are committing a recovery transaction, remove it from the
259:                    // transaction table.  The xact object which is doing the work is
260:                    // not going to be closed even though the transaction is done.
261:                    if (ent.isRecovery())
262:                        remove(id);
263:                }
264:
265:                return;
266:            }
267:
268:            /**************************************************************************
269:             * Transaction table methods used by XA.
270:             **************************************************************************
271:             */
272:
273:            /**
274:             * Return the hash table to the XA layer.
275:             * <p>
276:             * The XA code will do linear read-only operations on the hash table,
277:             * write operations are only done in this module.  It is a little ugly
278:             * to export the hash table, but I wanted to move the XA specific code
279:             * into the XA module, so that we could configure out the XA code if
280:             * necessary.
281:             * <p>
282:             *
283:             * Must be MT -safe, depends on sync hash table, and must get 
284:             *     synchronized(hash_table) for linear searches.
285:             *
286:             * @return The ContextManager of the transaction being searched for.
287:             *
288:             **/
289:            public Hashtable getTableForXA() {
290:                return (trans);
291:            }
292:
293:            /**
294:                Change transaction to prepared.
295:
296:            	<P>MT - unsafe, caller is recovery, which is single threaded.
297:
298:            	@param id the transaction Id
299:             */
300:            void prepareTransaction(TransactionId id) {
301:                // we need to synchronize on the transaction table because we have to
302:                // prevent this state change from happening when the transaction table
303:                // itself is written out to the checkpoint.  This is the only
304:                // protection the TransactionTableEntry has to prevent fields in myxact
305:                // from changing underneath it while it is being written out.
306:
307:                TransactionTableEntry ent = findTransactionEntry(id);
308:
309:                if (SanityManager.DEBUG) {
310:                    SanityManager.ASSERT(ent != null,
311:                            "preparing transaction that is not there");
312:                }
313:
314:                ent.prepareTransaction();
315:
316:                return;
317:            }
318:
319:            /**
320:             * Find a transaction in the table by Global transaction id.
321:             * <p>
322:             * This routine use to be only called during offline recovery so performance
323:             * was not critical.  Since that time more calls have been made, including
324:             * one in startGlobalTransaction() so a linear search may no longer
325:             * be appropriate.  See DERBY-828.
326:             *
327:             * @return The ContextManager of the transaction being searched for.
328:             *
329:             * @param global_id The global transaction we are searching for.
330:             **/
331:            public ContextManager findTransactionContextByGlobalId(
332:                    GlobalXactId global_id) {
333:                ContextManager cm = null;
334:
335:                // Need to hold sync while linear searching the hash table.
336:                synchronized (trans) {
337:                    for (Enumeration e = trans.elements(); e.hasMoreElements();) {
338:                        TransactionTableEntry entry = (TransactionTableEntry) e
339:                                .nextElement();
340:
341:                        if (entry != null) {
342:                            GlobalTransactionId entry_gid = entry.getGid();
343:
344:                            if (entry_gid != null
345:                                    && entry_gid.equals(global_id)) {
346:                                cm = entry.getXact().getContextManager();
347:                                break;
348:                            }
349:                        }
350:                    }
351:                }
352:
353:                return (cm);
354:            }
355:
356:            /***********************************************************
357:             * called when system is being quiesced, must be MT - safe
358:             ***********************************************************/
359:            /**
360:            	Return true if there is no transaction actively updating the database.
361:            	New transaction may be started or old transaction committed
362:            	right afterward, the caller of this routine must have other ways to
363:            	stop transactions from starting or ending.
364:
365:            	<P>MT - safe
366:             */
367:            boolean hasActiveUpdateTransaction() {
368:                synchronized (this ) {
369:                    for (Enumeration e = trans.elements(); e.hasMoreElements();) {
370:                        TransactionTableEntry ent = (TransactionTableEntry) e
371:                                .nextElement();
372:                        if (ent != null && ent.isUpdate())
373:                            return true;
374:                    }
375:                }
376:                return false;
377:            }
378:
379:            /************************************************************
380:             * methods called only by checkpoint
381:             ***********************************************************/
382:            /*
383:             * Formatable methods
384:             */
385:
386:            /**
387:            	Return my format identifier.
388:             */
389:            public int getTypeFormatId() {
390:                return StoredFormatIds.RAW_STORE_TRANSACTION_TABLE;
391:            }
392:
393:            /**
394:              @exception IOException problem reading the transaction table
395:             */
396:            public void writeExternal(ObjectOutput out) throws IOException {
397:                //don't let the transactions status change while writing out(beetle:5533)
398:                //Note: syncing both on trans and this variable could be avoided if
399:                //all the routines in this class are sycned on "this" and does not
400:                //depend on hash table synchronization. But that will be overkill 
401:                //because this routine gets called only on checkpoints and others
402:                //are used more often.
403:
404:                synchronized (this ) {
405:                    // don't touch the transaction table when I am being written out
406:                    synchronized (trans) {
407:                        int count = 0;
408:                        int maxcount = trans.size();
409:
410:                        // first count up the number of active update transactions 
411:                        for (Enumeration e = trans.elements(); e
412:                                .hasMoreElements();) {
413:                            TransactionTableEntry ent = (TransactionTableEntry) e
414:                                    .nextElement();
415:                            if (ent != null && ent.isUpdate())
416:                                count++;
417:                        }
418:
419:                        CompressedNumber.writeInt(out, count);
420:
421:                        // now write them out
422:                        if (count > 0) {
423:                            for (Enumeration e = trans.elements(); e
424:                                    .hasMoreElements();) {
425:                                TransactionTableEntry ent = (TransactionTableEntry) e
426:                                        .nextElement();
427:                                if (ent != null && ent.isUpdate()) {
428:                                    // only writes out update transaction
429:                                    out.writeObject(ent);
430:                                }
431:                            }
432:                        }
433:                    }
434:                }
435:            }
436:
437:            /************************************************************
438:             * methods called only by recovery
439:             ************************************************************/
440:
441:            /**
442:              @exception IOException problem reading the transaction table
443:              @exception ClassNotFoundException problem reading the transaction table
444:             */
445:            public void readExternal(ObjectInput in) throws IOException,
446:                    ClassNotFoundException {
447:                // RESOLVE: this is only read in checkpoint record, but we have not
448:                // finish the work on using this transaction table to cut down on redo
449:                // so this transaction table is effectively and futilely thrown away!
450:
451:                int count = CompressedNumber.readInt(in);
452:                if (count == 0)
453:                    return;
454:
455:                for (int i = 0; i < count; i++) {
456:                    TransactionTableEntry ent = (TransactionTableEntry) in
457:                            .readObject();
458:
459:                    if (SanityManager.DEBUG)
460:                        SanityManager.ASSERT(ent.getXid() != null,
461:                                "read in transaction table entry with null id");
462:
463:                    trans.put(ent.getXid(), ent);
464:
465:                    if (ent.isUpdate()
466:                            && XactId
467:                                    .compare(ent.getXid(), largestUpdateXactId) > 0) {
468:                        largestUpdateXactId = ent.getXid();
469:                    }
470:                }
471:
472:            }
473:
474:            /**
475:            	Return the largest update transactionId I have seen so far.
476:
477:            	<P>MT - unsafe, caller is recovery, which is single threaded.
478:             */
479:            public TransactionId largestUpdateXactId() {
480:                return largestUpdateXactId;
481:            }
482:
483:            /**
484:            	Is there an active internal transaction in the transaction table.
485:
486:            	<P>MT - unsafe, caller is recovery, which is single threaded.
487:             */
488:            public boolean hasRollbackFirstTransaction() {
489:                for (Enumeration e = trans.elements(); e.hasMoreElements();) {
490:                    TransactionTableEntry ent = (TransactionTableEntry) e
491:                            .nextElement();
492:
493:                    if (ent != null
494:                            && ent.isRecovery()
495:                            && (ent.getTransactionStatus() & Xact.RECOVERY_ROLLBACK_FIRST) != 0) {
496:                        return true;
497:                    }
498:                }
499:                return false;
500:            }
501:
502:            /**
503:               Is there a prepared transaction that are recovered 
504:               durring the recovery in the transaction table.
505:
506:               <P>MT - unsafe, caller is recovery, which is single threaded.
507:             */
508:            public boolean hasPreparedRecoveredXact() {
509:                return hasPreparedXact(true);
510:            }
511:
512:            /**
513:               Is there a prepared transaction in the transaction table.
514:               <P>MT - unsafe, called during boot, which is single threaded.
515:             */
516:            public boolean hasPreparedXact() {
517:                return hasPreparedXact(false);
518:            }
519:
520:            /**
521:             * Is there a prepared transaction in the transaction table.
522:             * 
523:             * <P>MT - unsafe, caller is recovery/at boot, which is single threaded.
524:             *
525:             * @param recovered  <code> true </code> to search  for transaction 
526:             *                  that are in prepared during recovery.  
527:             *                  recovered tranaction. 
528:             *                  <code> false > to search for just prepared 
529:             *                  transactons. 
530:             * @return         <code> true if there is a prepared transaction and
531:             *                  recovered when <code> recovered </code> argument is 
532:             *                  <code> true </code>
533:             */
534:
535:            private boolean hasPreparedXact(boolean recovered) {
536:                for (Enumeration e = trans.elements(); e.hasMoreElements();) {
537:                    TransactionTableEntry ent = (TransactionTableEntry) e
538:                            .nextElement();
539:
540:                    if (ent != null
541:                            && (ent.getTransactionStatus() & Xact.END_PREPARED) != 0) {
542:                        if (recovered) {
543:                            if (ent.isRecovery())
544:                                return true;
545:                        } else {
546:                            return true;
547:                        }
548:                    }
549:                }
550:                return false;
551:            }
552:
553:            /**
554:            	Get the most recently added transaction that says it needs to be
555:            	rolled back first (an InternalXact) from the transaction table and make
556:            	the passed in transaction assume its identity. 
557:            	<B> Should only be used in recovery undo !! </B>
558:            	RESOLVE: (sku)I don't think even these internal transactions need to be
559:            	rolled back in the reverse order, because they are physical in nature.
560:            	But it won't hurt.
561:
562:            	<P>MT - unsafe, caller is recovery, which is single threaded.
563:             */
564:            public boolean getMostRecentRollbackFirstTransaction(
565:                    RawTransaction tran) {
566:
567:                if (trans.isEmpty()) {
568:                    // set tranaction to idle
569:                    return findAndAssumeTransaction((TransactionId) null, tran);
570:                }
571:
572:                TransactionId id = null;
573:                for (Enumeration e = trans.elements(); e.hasMoreElements();) {
574:                    TransactionTableEntry ent = (TransactionTableEntry) e
575:                            .nextElement();
576:
577:                    if (ent != null
578:                            && ent.isUpdate()
579:                            && ent.isRecovery()
580:                            && (ent.getTransactionStatus() & Xact.RECOVERY_ROLLBACK_FIRST) != 0) {
581:                        // try to locate the most recent one
582:                        if (id == null || XactId.compare(id, ent.getXid()) < 0)
583:                            id = ent.getXid();
584:                    }
585:                }
586:
587:                if (id == null) // set transaction to idle
588:                {
589:                    return findAndAssumeTransaction(id, tran);
590:                } else {
591:                    // there is a rollback first transaction
592:                    boolean found = findAndAssumeTransaction(id, tran);
593:
594:                    if (SanityManager.DEBUG) {
595:                        if (!found) {
596:                            SanityManager
597:                                    .THROWASSERT("cannot find transaction "
598:                                            + id + " in table");
599:                        }
600:                    }
601:
602:                    return true;
603:                }
604:            }
605:
606:            /**
607:            	Get the most recently non-prepared added transaction from the 
608:                transaction table and make the passed in transaction assume its 
609:                identity.  Prepared transactions will not be undone.
610:
611:            	RESOLVE: (sku) I don't think normal user transactions needs to be
612:            	rolled back in order, but it won't hurt.
613:
614:            	<B> Should only be used in recovery undo !! </B>
615:
616:            	<P>MT - unsafe, caller is recovery, which is single threaded.
617:             */
618:            public boolean getMostRecentTransactionForRollback(
619:                    RawTransaction tran) {
620:                TransactionId id = null;
621:
622:                if (!trans.isEmpty()) {
623:                    for (Enumeration e = trans.elements(); e.hasMoreElements();) {
624:                        TransactionTableEntry ent = (TransactionTableEntry) e
625:                                .nextElement();
626:
627:                        if (ent != null && ent.isUpdate() && ent.isRecovery()
628:                                && !ent.isPrepared()) {
629:                            // try to locate the most recent one
630:                            if (id == null
631:                                    || XactId.compare(id, ent.getXid()) < 0)
632:                                id = ent.getXid();
633:                        }
634:
635:                        if (SanityManager.DEBUG) {
636:                            if (ent != null
637:                                    && ent.isUpdate()
638:                                    && ent.isRecovery()
639:                                    && (ent.getTransactionStatus() & Xact.RECOVERY_ROLLBACK_FIRST) != 0) {
640:                                SanityManager
641:                                        .THROWASSERT("still rollback first xacts in the tran table!");
642:                            }
643:                        }
644:                    }
645:
646:                    if (SanityManager.DEBUG) {
647:                        // if all transactions are prepared then it is possible that
648:                        // no transaction will be found, in that case id will be null.
649:                        if (id != null) {
650:                            SanityManager
651:                                    .ASSERT(findTransactionEntry(id) != null);
652:                        } else {
653:                            // all transactions in the table must be prepared.
654:                            for (Enumeration e = trans.elements(); e
655:                                    .hasMoreElements();) {
656:                                TransactionTableEntry ent = (TransactionTableEntry) e
657:                                        .nextElement();
658:                                SanityManager.ASSERT(ent.isPrepared());
659:                            }
660:                        }
661:                    }
662:                }
663:
664:                return (findAndAssumeTransaction(id, tran));
665:            }
666:
667:            /**
668:            	Get the most recently added transaction that says it is prepared during
669:                recovery the transaction table and make the passed in transaction 
670:                assume its identity. This routine turns off the isRecovery() state
671:            	<B> Should only be used in recovery handle prepare after undo !! </B>
672:
673:            	<P>MT - unsafe, caller is recovery, which is single threaded.
674:             */
675:
676:            /**
677:             * Get the most recent recovered prepared transaction.
678:             * <p>
679:             * Get the most recently added transaction that says it is prepared during 
680:             * recovery the transaction table and make the passed in transaction 
681:             * assume its identity. 
682:             * <p>
683:             * This routine, unlike the redo and rollback getMostRecent*() routines
684:             * expects a brand new transaction to be passed in.  If a candidate 
685:             * transaction is found, then upon return the transaction table will 
686:             * be altered such that the old entry no longer exists, and a new entry
687:             * will exist pointing to the transaction passed in.  The new entry will
688:             * look the same as if the prepared transaction had been created during
689:             * runtime rather than recovery.
690:             *
691:             * <B> Should only be used in recovery handle prepare after undo !! </B>
692:             *
693:             * <P>MT - unsafe, caller is recovery, which is single threaded.
694:             *
695:             * @return true if a candidate transaction has been found.  false if no
696:             *         prepared/recovery transactions found in the table.
697:             *
698:             * @param tran   Newly allocated transaction to add to link to a entry.
699:             *
700:             **/
701:            public boolean getMostRecentPreparedRecoveredXact(
702:                    RawTransaction tran) {
703:                TransactionTableEntry found_ent = null;
704:
705:                if (!trans.isEmpty()) {
706:                    TransactionId id = null;
707:                    GlobalTransactionId gid = null;
708:                    TransactionTableEntry ent;
709:
710:                    for (Enumeration e = trans.elements(); e.hasMoreElements();) {
711:                        ent = (TransactionTableEntry) e.nextElement();
712:
713:                        if (ent != null && ent.isRecovery() && ent.isPrepared()) {
714:                            // try to locate the most recent one
715:                            if (id == null
716:                                    || XactId.compare(id, ent.getXid()) < 0) {
717:                                found_ent = ent;
718:                                id = ent.getXid();
719:                                gid = ent.getGid();
720:                            }
721:                        }
722:                    }
723:
724:                    if (SanityManager.DEBUG) {
725:                        if (found_ent == null) {
726:                            // if no entry's were found then the transaction table
727:                            // should have the passed in idle tran, and the rest should
728:                            // be non-recover, prepared global transactions.
729:                            for (Enumeration e = trans.elements(); e
730:                                    .hasMoreElements();) {
731:                                ent = (TransactionTableEntry) e.nextElement();
732:
733:                                if (XactId.compare(ent.getXid(), tran.getId()) != 0) {
734:                                    SanityManager.ASSERT(!ent.isRecovery()
735:                                            && ent.isPrepared());
736:                                    SanityManager.ASSERT(ent.getGid() != null);
737:                                }
738:                            }
739:                        }
740:                    }
741:
742:                    if (found_ent != null) {
743:                        // At this point there are 2 tt entries of interest:
744:                        //     new_ent - the read only transaction entry that was 
745:                        //               created when we allocated a new transaction.
746:                        //               We will just throw this one away after 
747:                        //               assuming the identity of the global xact.
748:                        //     found_ent
749:                        //             - the entry of the transaction that we are going
750:                        //               to take over.
751:                        TransactionTableEntry new_ent = (TransactionTableEntry) trans
752:                                .remove(tran.getId());
753:
754:                        // At this point only the found_ent should be in the table.
755:                        if (SanityManager.DEBUG) {
756:                            SanityManager
757:                                    .ASSERT(findTransactionEntry(id) == found_ent);
758:                        }
759:
760:                        ((Xact) tran).assumeGlobalXactIdentity(found_ent);
761:
762:                        // transform this recovery entry, into a runtime entry.
763:                        found_ent.unsetRecoveryStatus();
764:                    }
765:                }
766:
767:                return (found_ent != null);
768:            }
769:
770:            /**
771:            	Get the least recently added (oldest) transaction
772:            	@return the RawTransaction's first log instant
773:
774:            	<P>MT - safe, caller can be recovery or checkpoint
775:             */
776:            public LogInstant getFirstLogInstant() {
777:                // assume for now that it is acceptable to return null if a transaction
778:                // starts right in the middle of this call.
779:
780:                if (trans.isEmpty()) {
781:                    return null;
782:                } else {
783:                    LogInstant logInstant = null;
784:
785:                    // bug 5632: need to sychronize so that another thread does not 
786:                    // come in and disrupt the for loop, we got an exception on next,
787:                    // likely because hash table changed by another thread after
788:                    // hasMoreElements() called, but before nextElement().
789:
790:                    synchronized (trans) {
791:                        for (Enumeration e = trans.elements(); e
792:                                .hasMoreElements();) {
793:                            TransactionTableEntry ent = (TransactionTableEntry) e
794:                                    .nextElement();
795:
796:                            if (ent != null && ent.isUpdate()) {
797:                                if (logInstant == null
798:                                        || ent.getFirstLog().lessThan(
799:                                                logInstant)) {
800:                                    logInstant = ent.getFirstLog();
801:                                }
802:                            }
803:                        }
804:                    }
805:
806:                    return logInstant;
807:                }
808:            }
809:
810:            /**
811:            	Find a transaction using the transaction id, and make the passed in
812:            	transaction assume the identity and properties of that transaction.
813:
814:            	<P>MT - unsafe, caller is recovery, which is single threaded.
815:
816:            	@param id transaction Id
817:            	@param tran the transaction that was made to assume the transactionID
818:            	and all other relavent information stored in the transaction table
819:            	@return true if transaction can be found, false otherwise
820:             */
821:            boolean findAndAssumeTransaction(TransactionId id,
822:                    RawTransaction tran) {
823:                // the only caller for this method right now is recovery.  
824:                // No need to put in any concurrency control
825:                TransactionTableEntry ent = null;
826:
827:                if (id != null && !trans.isEmpty()) {
828:                    ent = findTransactionEntry(id);
829:
830:                    if (SanityManager.DEBUG) {
831:                        if (ent != null)
832:                            SanityManager
833:                                    .ASSERT(ent.isRecovery(),
834:                                            "assuming the id of a non-recovery transaction");
835:                    }
836:                }
837:
838:                // if no transaction entry found, set transaction to idle
839:                ((Xact) tran).assumeIdentity(ent);
840:
841:                return (ent != null);
842:
843:            }
844:
845:            /**********************************************************
846:             * Transaction table vti and diagnostics
847:             * MT - unsafe, caller is getting a snap shot which may be inconsistent 
848:             *********************************************************/
849:
850:            /**
851:            	Get a printable version of the transaction table
852:             */
853:            public TransactionInfo[] getTransactionInfo() {
854:                if (trans.isEmpty())
855:                    return null;
856:
857:                // while taking a snap shot, no adding or removing of transaction
858:                TransactionInfo[] tinfo;
859:
860:                if (SanityManager.DEBUG)
861:                    SanityManager.DEBUG("TranTrace", toString());
862:
863:                synchronized (this ) {
864:                    int ntran = trans.size();
865:                    tinfo = new TransactionTableEntry[ntran];
866:
867:                    LogInstant logInstant = null;
868:                    int i = 0;
869:
870:                    for (Enumeration e = trans.elements(); e.hasMoreElements();) {
871:                        TransactionTableEntry ent = (TransactionTableEntry) e
872:                                .nextElement();
873:
874:                        if (ent != null)
875:                            tinfo[i++] = (TransactionTableEntry) ent.clone();
876:
877:                        if (SanityManager.DEBUG)
878:                            SanityManager.ASSERT(ent != null,
879:                                    "transaction table has null entry");
880:                    }
881:                }
882:
883:                return tinfo;
884:            }
885:
886:            public String toString() {
887:                if (SanityManager.DEBUG) {
888:                    StringBuffer str = new StringBuffer(1000).append(
889:                            "\n**************************\n").append(
890:                            super .toString()).append(
891:                            "\nTransaction Table: size = ")
892:                            .append(trans.size()).append(
893:                                    " largestUpdateXactId = ").append(
894:                                    largestUpdateXactId).append("\n");
895:
896:                    boolean hasReadOnlyTransaction = false;
897:
898:                    for (Enumeration e = trans.elements(); e.hasMoreElements();) {
899:                        TransactionTableEntry ent = (TransactionTableEntry) e
900:                                .nextElement();
901:
902:                        if (ent != null && ent.isUpdate())
903:                            str.append(ent.toString());
904:
905:                        if (ent != null && !ent.isUpdate())
906:                            hasReadOnlyTransaction = true;
907:                    }
908:
909:                    if (hasReadOnlyTransaction) {
910:                        str.append("\n READ ONLY TRANSACTIONS \n");
911:
912:                        for (Enumeration e = trans.elements(); e
913:                                .hasMoreElements();) {
914:                            TransactionTableEntry ent = (TransactionTableEntry) e
915:                                    .nextElement();
916:
917:                            if (ent != null && !ent.isUpdate())
918:                                str.append(ent.toString());
919:                        }
920:                    }
921:                    str.append("---------------------------");
922:                    return str.toString();
923:                } else
924:                    return null;
925:            }
926:
927:        }
ww___w___._j_a__v___a2__s_.__c__o_m | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.