Source Code Cross Referenced for TransactionManager.java in  » Database-DBMS » Ozone-1.1 » org » ozoneDB » core » 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 » Ozone 1.1 » org.ozoneDB.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // You can redistribute this software and/or modify it under the terms of
002:        // the Ozone Core License version 1 published by ozone-db.org.
003:        //
004:        // The original code and portions created by SMB are
005:        // Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
006:        //
007:        // $Id: TransactionManager.java,v 1.2 2002/06/08 00:49:38 mediumnet Exp $
008:
009:        package org.ozoneDB.core;
010:
011:        import java.io.IOException;
012:        import java.util.Random;
013:        import org.ozoneDB.*;
014:        import org.ozoneDB.DxLib.*;
015:        import org.ozoneDB.core.DbRemote.*;
016:        import org.ozoneDB.core.dr.*;
017:        import org.ozoneDB.util.*;
018:
019:        /**
020:         * The transaction manager is the factory for transactions and locks.
021:         * 
022:         * 
023:         * @author <a href="http://www.softwarebuero.de/">SMB</a>
024:         * @author <a href="http://www.medium.net/">Medium.net</a>
025:         * @version $Revision: 1.2 $Date: 2002/06/08 00:49:38 $
026:         */
027:        public final class TransactionManager extends ServerComponent {
028:
029:            /**
030:             * All currently running transactions. taID -> ta
031:             */
032:            protected DxMap taTable;
033:
034:            /**
035:             * In local mode this maps threads to transactions.
036:             */
037:            protected DxMap threadTable;
038:
039:            /**
040:             * Used to signal a deadlock and which Transaction should abort.
041:             */
042:            protected Transaction deadlockTA;
043:
044:            /**
045:             * True if one thread runs exclusively.
046:             */
047:            protected Thread exclusiveThread;
048:
049:            protected long acquireCount;
050:
051:            public TransactionManager(Env _env) {
052:                super (_env);
053:                taTable = new DxHashMap(32);
054:                threadTable = new DxHashMap(32);
055:            }
056:
057:            public void startup() throws Exception {
058:                env.logWriter.newEntry(this , "startup...", LogWriter.INFO);
059:            }
060:
061:            public void shutdown() throws Exception {
062:                env.logWriter.newEntry(this , "shutdown...", LogWriter.INFO);
063:
064:                env.logWriter.newEntry(this , "    there are " + taTable.count()
065:                        + " pending transaction(s)", LogWriter.INFO);
066:                if (!taTable.isEmpty()) {
067:                    env.logWriter.newEntry(this ,
068:                            "    aborting pending transactions...",
069:                            LogWriter.INFO);
070:                    DxIterator it = taTable.iterator();
071:                    while (it.next() != null) {
072:                        ((Transaction) it.object()).stop();
073:                    }
074:
075:                    env.logWriter.newEntry(this ,
076:                            "    waiting for transactions to end...",
077:                            LogWriter.INFO);
078:                    for (int sec = 10; !taTable.isEmpty(); sec--) {
079:                        Thread.sleep(1000);
080:                    }
081:                }
082:
083:                env.logWriter.newEntry(this , "acquire count total:"
084:                        + acquireCount, LogWriter.INFO);
085:            }
086:
087:            public void save() throws Exception {
088:            }
089:
090:            /**
091:             * Factory method to generate proper Lock objects. These Lock objects are
092:             * used in the store backend but they have to be generated in the core to
093:             * meet the requirements of the transaction implementation.
094:             */
095:            public Lock newLock() {
096:                return new MROWLock();
097:            }
098:
099:            public int taTableCount() {
100:                return taTable.count();
101:            }
102:
103:            public Transaction taForID(TransactionID taID) {
104:                return (Transaction) taTable.elementForKey(taID);
105:            }
106:
107:            /**
108:             * der aktuelle thread is auch die aktuelle transaktion (wenn der
109:             * thread ueberhaupt eine transaktion ist)
110:             */
111:            public Transaction currentTA() {
112:                Thread thread = Thread.currentThread();
113:
114:                // see startTransaction()
115:                if (thread instanceof  CommandThread) {
116:                    return ((CommandThread) thread).ta;
117:                } else {
118:                    Transaction result = (Transaction) threadTable
119:                            .elementForKey(thread);
120:                    return result;
121:                }
122:            }
123:
124:            public Transaction newTransaction(User owner) throws TransactionExc {
125:                if (false && env.logWriter.hasTarget(LogWriter.DEBUG2)) {
126:                    env.logWriter.newEntry(this ,
127:                            "newTransaction() *****************************",
128:                            LogWriter.DEBUG2);
129:                }
130:
131:                if (currentTA() != null) {
132:                    throw new TransactionExc(
133:                            "Thread is already joined to a transaction.",
134:                            TransactionExc.STATE);
135:                }
136:
137:                Transaction ta = new Transaction(env, owner);
138:                Thread thread = Thread.currentThread();
139:
140:                // in the server threads are CommandThreads and the corresponding
141:                // transaction is a member of the CommandThread
142:                if (thread instanceof  CommandThread) {
143:                    CommandThread commandThread = (CommandThread) Thread
144:                            .currentThread();
145:                    commandThread.setTransaction(ta);
146:                }
147:
148:                if (env.logWriter.hasTarget(LogWriter.DEBUG2)) {
149:                    env.logWriter.newEntry(this , "newTransaction(): ta=" + ta
150:                            + ", thread=" + thread + ".", LogWriter.DEBUG2);
151:                }
152:
153:                synchronized (this ) {
154:                    // if we are local, threads can be of any type; we add them to the
155:                    // threadTable to be able to found the corresponding transaction
156:                    threadTable.addForKey(ta, thread);
157:
158:                    taTable.addForKey(ta, ta.taID());
159:                }
160:                return ta;
161:            }
162:
163:            /**
164:             * Delete the transaction that is associated with the current thread.
165:             */
166:            public void deleteTransaction() {
167:                if (false && env.logWriter.hasTarget(LogWriter.DEBUG2)) {
168:                    env.logWriter.newEntry(this ,
169:                            "deleteTransaction() --------------------------",
170:                            LogWriter.DEBUG2);
171:                }
172:
173:                Transaction ta = currentTA();
174:                if (ta == null) {
175:                    env.logWriter
176:                            .newEntry(
177:                                    this ,
178:                                    "deleteTransaction(): thread is not joined to a transaction.",
179:                                    LogWriter.WARN);
180:                } else {
181:                    if (env.logWriter.hasTarget(LogWriter.DEBUG2)) {
182:                        env.logWriter.newEntry(this , "deleteTransaction() ta="
183:                                + ta + ".", LogWriter.DEBUG2);
184:                    }
185:                    synchronized (this ) {
186:                        acquireCount += ta.acquireCount;
187:                        if (false && env.logWriter.hasTarget(LogWriter.DEBUG2)) {
188:                            env.logWriter.newEntry(this , "    acquire count:"
189:                                    + ta.acquireCount, LogWriter.DEBUG2);
190:                            env.logWriter.newEntry(this , "    total        :"
191:                                    + acquireCount, LogWriter.DEBUG2);
192:                        }
193:
194:                        Thread thread = Thread.currentThread();
195:                        if (thread instanceof  CommandThread) {
196:                            ((CommandThread) thread).setTransaction(null);
197:                        }
198:
199:                        threadTable.removeForKey(thread);
200:                        taTable.removeForKey(ta.taID());
201:
202:                        env.getGarbageCollector()
203:                                .removeTransactionRequiredToComplete(ta);
204:                    }
205:                }
206:            }
207:
208:            /**
209:                If we notify all transactions, they not-blocked-ones may wake up from sleeping.
210:             */
211:            protected boolean alsoNotifySomeSleepingTransactions = true;
212:
213:            /**
214:             * Notify each thread that is associated with a currently blocked
215:             * transaction by calling notifyAll() on the blocked transaction.
216:             */
217:            public void notifyWaitingTransactions() {
218:                if (false && env.logWriter.hasTarget(LogWriter.DEBUG3)) {
219:                    env.logWriter.newEntry(this , "notifyWaitingTransactions()",
220:                            LogWriter.DEBUG3);
221:                }
222:
223:                DxArrayBag tas = new DxArrayBag(taTable.count());
224:
225:                // search all blocked transactions in a synchronized block (to prevent
226:                // others from chnaging the taTable) but call notifyAll() later in a
227:                // non-synchronized block tp prevent us from deadlocks
228:                synchronized (this ) {
229:                    DxIterator it = taTable.iterator();
230:                    Transaction ta;
231:                    while ((ta = (Transaction) it.next()) != null) {
232:                        if ((ta.blocker != null)) {
233:                            tas.add(ta);
234:                        }
235:                    }
236:
237:                    if (alsoNotifySomeSleepingTransactions) {
238:                        if (tas.isEmpty()) {
239:                            it.reset();
240:                            while ((ta = (Transaction) it.next()) != null) {
241:                                if (ta.isSleeping()) { // A sleeping
242:                                    tas.add(ta);
243:                                    break;
244:                                }
245:                            }
246:                        }
247:                    }
248:                }
249:
250:                DxIterator it = tas.iterator();
251:                Transaction ta;
252:                while ((ta = (Transaction) it.next()) != null) {
253:                    if (false && env.logWriter.hasTarget(LogWriter.DEBUG)) {
254:                        env.logWriter.newEntry(this , "    notify: " + ta,
255:                                LogWriter.DEBUG);
256:                    }
257:                    synchronized (ta) {
258:                        ta.notifyAll();
259:                    }
260:                }
261:            }
262:
263:            /**
264:             * Handle the specified command on behalf of the current thread/transaction.
265:             * This method is called by the InvokeServer after it has handled
266:             * InvokeServer specific command.
267:             */
268:            public void handleCommand(DbCommand command, DbInvokeClient client) {
269:                handleCommand(command, client.getUser());
270:            }
271:
272:            /**
273:             * Handle the specified command on behalf of the current thread/transaction.
274:             * This method is called by the InvokeServer after it has handled
275:             * InvokeServer specific command.
276:             */
277:            public void handleCommand(DbCommand command, User user) {
278:                if (env.logWriter.hasTarget(LogWriter.DEBUG)) {
279:                    env.logWriter.newEntry(this , "handleCommand(): "
280:                            + command.toString(), LogWriter.DEBUG);
281:                }
282:
283:                command.result = null;
284:                try {
285:                    // close this connection/thread/transaction
286:                    if (command instanceof  DbCloseConn) {
287:                        Transaction ta = currentTA();
288:                        if (ta != null) {
289:                            abortTransaction(ta, command);
290:                            deleteTransaction();
291:                        }
292:                    } else if (!(command instanceof  DbTransaction)) {
293:
294:                        // perform all commands other then DbTransaction
295:                        Transaction ta = currentTA();
296:                        if (ta == null) {
297:                            completeTransaction(command, /*client*/user);
298:                        } else {
299:                            // if something goes wrong while performing this command the client
300:                            // has to abort the transaction
301:                            performCommand(ta, command);
302:                        }
303:                    } else {
304:                        // perform transaction demarcation command; test for error conditions
305:                        // and signal error via command.result to avoid exceptions that are
306:                        // converted to OzoneInternalExc by the enclosing try/catch
307:                        switch (((DbTransaction) command).mode()) {
308:
309:                        case DbTransaction.MODE_BEGIN: {
310:                            if (currentTA() != null) {
311:                                command.result = new TransactionExc(
312:                                        "Thread is already joined to a transaction.",
313:                                        TransactionExc.STATE);
314:                            } else {
315:                                Transaction ta = newTransaction(user /*client.getUser()*/);
316:                                command.result = ta.taID();
317:                            }
318:                            break;
319:                        }
320:
321:                        case DbTransaction.MODE_PREPARE: {
322:                            prepareTransaction(currentTA(), command);
323:                            break;
324:                        }
325:
326:                        case DbTransaction.MODE_COMMIT_TWOPHASE: {
327:                            commitTransaction(currentTA(), command);
328:                            deleteTransaction();
329:                            break;
330:                        }
331:
332:                        case DbTransaction.MODE_COMMIT_ONEPHASE: {
333:                            Transaction ta = currentTA();
334:                            if (prepareTransaction(ta, command)) {
335:                                commitTransaction(ta, command);
336:                            }
337:                            deleteTransaction();
338:                            break;
339:                        }
340:
341:                        case DbTransaction.MODE_ABORT: {
342:                            abortTransaction(currentTA(), command);
343:                            deleteTransaction();
344:                            break;
345:                        }
346:
347:                        case DbTransaction.MODE_CHECKPOINT: {
348:                            command.result = new OzoneInternalExc(
349:                                    "External CHECKPOINT is not implemented yet.");
350:                            break;
351:                        }
352:                        case DbTransaction.MODE_STATUS: {
353:                            command.result = new Integer(currentTA().status());
354:                            break;
355:                        }
356:                        }
357:                    }
358:                } catch (Throwable e) {
359:                    // all exception that are not handled by the underlying methods
360:                    // are internal 'panic' errors
361:                    env.logWriter.newEntry(this , "handleCommand(): " + e, e,
362:                            LogWriter.ERROR);
363:                    command.result = new OzoneInternalExc(e.toString(), e);
364:                    deleteTransaction();
365:                }
366:            }
367:
368:            /**
369:             * Perform the specified command within a new transaction.
370:             */
371:            protected void completeTransaction(DbCommand command, User user /*DbInvokeClient client*/)
372:                    throws Exception {
373:                if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
374:                    env.logWriter.newEntry(this , "completeTransaction(): "
375:                            + command, LogWriter.DEBUG3);
376:                }
377:                if (/*client.getUser()*/user == null) {
378:                    throw new TransactionExc(
379:                            "No owner set for current transaction.");
380:                }
381:
382:                Transaction ta = newTransaction(/*client.getUser()*/user);
383:
384:                // perform->prepare->commit/abort
385:                boolean alright = false;
386:
387:                try {
388:                    if (alright = performCommand(ta, command)) {
389:                        if (prepareTransaction(ta, command)) {
390:                            commitTransaction(ta, command);
391:                        }
392:                    }
393:                } finally {
394:                    if (!alright) {
395:                        abortTransaction(ta, command);
396:                    }
397:                }
398:                deleteTransaction();
399:            }
400:
401:            /**
402:             * Perform the specified command on behalf of the specified
403:             * thread/transaction. If the transaction has performed only one command
404:             * until now, this handles deadlocks by re-performing the command again
405:             * until it throws an exception or completes sucessfully. Otherwise an
406:             * exception is thrown
407:             * 
408:             * 
409:             * @return True if the command did not throw an exception
410:             * @throws Exception Any exception always signals an internal error.
411:             */
412:            protected boolean performCommand(Transaction ta, DbCommand command)
413:                    throws Exception {
414:                if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
415:                    env.logWriter.newEntry(this , "performCommand(): start: "
416:                            + ta.toString() + ", " + command.toString(),
417:                            LogWriter.DEBUG3);
418:                }
419:
420:                boolean result = true;
421:
422:                try {
423:                    // result goes in command.result
424:                    result = ta.performCommand(command);
425:
426:                    // other than TransactionError exceptions are catched by
427:                    // ta.performCommand()
428:                } catch (TransactionError e) {
429:                    if (e.code() == TransactionError.DEADLOCK) {
430:
431:                        if (ta.commandCount > 1) {
432:                            env.logWriter.newEntry(this , ta.toString()
433:                                    + " deadlocked; throwing exception...",
434:                                    LogWriter.WARN);
435:                            command.result = new DeadlockExc("");
436:                            result = false;
437:                        } else {
438:                            Random rand = new Random();
439:                            boolean deadlocked = true;
440:                            while (deadlocked) {
441:                                try {
442:                                    env.logWriter.newEntry(this , ta.toString()
443:                                            + " aborting... (DEADLOCK)",
444:                                            LogWriter.WARN);
445:                                    abortTransaction(ta, command);
446:
447:                                    ta.setDeadlocked(false);
448:
449:                                    long millis = (long) (rand.nextDouble() * ta
450:                                            .increaseDeadlockWaitTimeMaximum());
451:                                    env.logWriter.newEntry(this , ta.toString()
452:                                            + " sleeping " + millis
453:                                            + " milliseconds...",
454:                                            LogWriter.WARN);
455:                                    ta.sleep(millis);
456:
457:                                    env.logWriter.newEntry(this , ta.toString()
458:                                            + " re-run...", LogWriter.WARN);
459:                                    ta.reset();
460:                                    result = ta.performCommand(command);
461:
462:                                    deadlocked = false;
463:                                } catch (TransactionError ee) {
464:                                    if (ee.code() == TransactionError.DEADLOCK) {
465:                                        // still deadlocked
466:                                    } else {
467:                                        throw ee;
468:                                    }
469:                                }
470:                            }
471:                        }
472:                    } else {
473:                        // other than DEADLOCK TransactionErrors are internal errors
474:                        throw e;
475:                    }
476:                } finally {
477:                    if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
478:                        env.logWriter.newEntry(this , "performCommand(): end: "
479:                                + ta.toString() + ", " + command.toString(),
480:                                LogWriter.DEBUG3);
481:                    }
482:                }
483:                return result;
484:            }
485:
486:            /**
487:             * Prepare the specified transaction. Return true on success and false
488:             * if something failed. In this case the transaction is rolled back. This
489:             * method throws an exception only if an internal server error occured.
490:             */
491:            protected boolean prepareTransaction(Transaction ta,
492:                    DbCommand command) throws Exception {
493:                if (false && env.logWriter.hasTarget(LogWriter.DEBUG3)) {
494:                    env.logWriter.newEntry(this , "prepareTransaction()",
495:                            LogWriter.DEBUG3);
496:                }
497:
498:                // if the commit was requested by the client, the following conditions
499:                // are not internal error and so they must not throw an exception
500:                if (ta == null) {
501:                    env.logWriter
502:                            .newEntry(
503:                                    this ,
504:                                    "prepareTransaction(): Thread is not joined to a transaction.",
505:                                    LogWriter.WARN);
506:                    command.result = new TransactionExc(
507:                            "Thread is not joined to a transaction.",
508:                            TransactionExc.STATE);
509:                    return false;
510:                } else if (ta.status != Transaction.STATUS_STARTED) {
511:                    env.logWriter.newEntry(this , "prepareTransaction():"
512:                            + ta.toString()
513:                            + ": Transaction has inproper status.",
514:                            LogWriter.WARN);
515:                    command.result = new TransactionExc(
516:                            "Transaction has inproper status.",
517:                            TransactionExc.STATE);
518:                    return false;
519:                } else if (ta.rollbackOnly) {
520:                    env.logWriter.newEntry(this , "prepareTransaction():"
521:                            + ta.toString() + ": rollback only.",
522:                            LogWriter.WARN);
523:                    abortTransaction(ta, command);
524:                    command.result = new TransactionExc(
525:                            "Transaction is in rollback only status.",
526:                            TransactionExc.ROLLBACK);
527:                    return false;
528:                } else {
529:                    try {
530:                        // beginExclusion();
531:                        ta.prepareCommit();
532:                        return true;
533:                    } catch (Throwable e) {
534:                        env.logWriter.newEntry(this ,
535:                                "Prepare transaction failed: " + ta.toString()
536:                                        + "; aborting...", e, LogWriter.WARN);
537:                        abortTransaction(ta, command);
538:
539:                        command.result = new TransactionExc(e.toString(),
540:                                TransactionExc.ROLLBACK);
541:                        return false;
542:                    } finally {
543:                        // endExclusion();
544:                    }
545:                }
546:            }
547:
548:            protected void commitTransaction(Transaction ta, DbCommand command)
549:                    throws Exception {
550:                if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
551:                    env.logWriter.newEntry(this , "commitTransaction()",
552:                            LogWriter.DEBUG3);
553:                }
554:
555:                // if the commit was requested by the client, the following conditions
556:                // are not internal error and so they must not throw an exception
557:                if (ta == null) {
558:                    env.logWriter
559:                            .newEntry(
560:                                    this ,
561:                                    "commitTransaction(): Thread is not joined to a transaction.",
562:                                    LogWriter.WARN);
563:                    command.result = new TransactionExc(
564:                            "Thread is not joined to a transaction.",
565:                            TransactionExc.STATE);
566:                } else if (ta.status != Transaction.STATUS_PREPARED) {
567:                    env.logWriter.newEntry(this , "commitTransaction(): "
568:                            + ta.toString()
569:                            + ": Transaction has inproper status.",
570:                            LogWriter.WARN);
571:                    command.result = new TransactionExc(
572:                            "Transaction has inproper status.",
573:                            TransactionExc.STATE);
574:                } else {
575:                    try {
576:                        beginExclusion();
577:                        ta.commit();
578:                    } catch (Throwable e) {
579:                        env.logWriter.newEntry(this ,
580:                                "Commit transaction failed: " + ta.toString(),
581:                                e, LogWriter.WARN);
582:                        command.result = e;
583:                        if (e instanceof  Error) {
584:                            throw (Error) e;
585:                        } else {
586:                            throw (Exception) e;
587:                        }
588:                    } finally {
589:                        endExclusion();
590:                        notifyWaitingTransactions();
591:                    }
592:                }
593:            }
594:
595:            protected void abortTransaction(Transaction ta, DbCommand command)
596:                    throws Exception {
597:                if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
598:                    env.logWriter.newEntry(this , "abortTransaction()",
599:                            LogWriter.DEBUG3);
600:                }
601:
602:                // if the commit was requested by the client, the following conditions
603:                // are not internal error and so they must not throw an exception
604:                if (ta == null) {
605:                    env.logWriter
606:                            .newEntry(
607:                                    this ,
608:                                    "abortTransaction(): Thread is not joined to a transaction.",
609:                                    LogWriter.WARN);
610:                    command.result = new TransactionExc(
611:                            "Thread is not joined to a transaction.",
612:                            TransactionExc.STATE);
613:                } else if (ta.status >= Transaction.STATUS_COMMITING) {
614:                    env.logWriter.newEntry(this , "abortTransaction(): "
615:                            + ta.toString()
616:                            + ": Transaction has inproper status.",
617:                            LogWriter.WARN);
618:                    command.result = new TransactionExc(
619:                            "Transaction has inproper status.",
620:                            TransactionExc.STATE);
621:                } else {
622:                    try {
623:                        beginExclusion();
624:                        ta.abort(command);
625:                    } catch (Throwable e) {
626:                        env.logWriter
627:                                .newEntry(this , "Aborting transaction failed: "
628:                                        + ta.toString(), e, LogWriter.WARN);
629:                        command.result = e;
630:                        if (e instanceof  Error) {
631:                            throw (Error) e;
632:                        } else {
633:                            throw (Exception) e;
634:                        }
635:                    } finally {
636:                        endExclusion();
637:                        notifyWaitingTransactions();
638:                    }
639:                }
640:            }
641:
642:            /**
643:             * Blocks execution until there is no thread scheduled for exclusive
644:             * execution or the exclusive thread is the current thread.
645:             */
646:            public void checkExclusion() {
647:                // evaluate the current thread only if there actually is an
648:                // exclusiveThread
649:                if (exclusiveThread != null
650:                        && exclusiveThread != Thread.currentThread()) {
651:                    synchronized (this ) {
652:                        while (exclusiveThread != null
653:                                && exclusiveThread != Thread.currentThread()) {
654:                            try {
655:                                env.logWriter.newEntry(this ,
656:                                        "checkExclusion(): waiting... ("
657:                                                + currentTA() + ")",
658:                                        LogWriter.DEBUG2);
659:                                wait();
660:                                env.logWriter.newEntry(this ,
661:                                        "checkExclusion(): notified... ("
662:                                                + currentTA() + ")",
663:                                        LogWriter.DEBUG2);
664:                            } catch (InterruptedException e) {
665:                            }
666:                        }
667:                    }
668:                }
669:            }
670:
671:            protected synchronized void beginExclusion() {
672:                checkExclusion();
673:
674:                Thread currentThread = Thread.currentThread();
675:                if (exclusiveThread != null && exclusiveThread != currentThread) {
676:                    throw new RuntimeException(
677:                            "Another thread already runs exclusively.");
678:                }
679:
680:                exclusiveThread = currentThread;
681:
682:                if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
683:                    //          env.logWriter.newEntry( this, "beginExclusion(): ", LogWriter.DEBUG3 );
684:                }
685:            }
686:
687:            protected synchronized void endExclusion() {
688:                if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
689:                    //          env.logWriter.newEntry( this, "endExclusion(): ", LogWriter.DEBUG3 );
690:                }
691:
692:                Thread currentThread = Thread.currentThread();
693:                if (exclusiveThread != currentThread) {
694:                    throw new RuntimeException(
695:                            "Current thread does not run exclusively.");
696:                }
697:
698:                exclusiveThread = null;
699:                notifyAll();
700:            }
701:
702:            /**
703:             * This method checks for deadlocks between all current transaction.
704:             */
705:            public synchronized void checkDeadlocks() throws Exception {
706:                DeadlockRecognition dr = env.deadlockRecognition();
707:
708:                // count blocked transactions
709:                int blockedCount = 0;
710:                DxIterator it = taTable.iterator();
711:                for (Transaction ta; (ta = (Transaction) it.next()) != null;) {
712:                    if (ta.isBlocked()) {
713:                        blockedCount++;
714:                    }
715:                }
716:
717:                //      env.logWriter.newEntry( this,"*** checkDeadlocks: blockedCount=" + blockedCount + " exclusive=" + exclusiveThread,LogWriter.DEBUG3 );
718:
719:                // we need to check things only if there are at least 2 blocked ta's
720:                if (blockedCount >= 2) {
721:
722:                    try {
723:                        // ensure that nothing changes while we check for deadlocks
724:                        beginExclusion();
725:
726:                        it = taTable.iterator();
727:                        for (Transaction ta; (ta = (Transaction) it.next()) != null;) {
728:                            Transaction candidate = (Transaction) dr
729:                                    .detectDeadlock(ta);
730:                            if (candidate != null) {
731:                                env.logWriter.newEntry(this ,
732:                                        "*** *** DEADLOCK DETECTED: ta=" + ta,
733:                                        LogWriter.WARN);
734:
735:                                if (false) { // Why should we sleep here?
736:                                    Thread.sleep(5000);
737:                                } else {
738:                                    /*
739:                                        We should just synchronized so that we commit the now-set "deadlocked" flags of
740:                                        the deadlocked transactions into main memory where they can read them out.
741:                                     */
742:                                    /* Even that commit should happen sooner or later. */
743:                                    /*
744:                                    synchronized (candidate) {
745:                                    }
746:                                    Thread.sleep(1);
747:                                     */
748:                                }
749:
750:                                // this will be checked by all transactions using
751:                                // isDeadlockTA() to determine if it has to abort
752:                                deadlockTA = candidate;
753:                                // env.storeManager.containerForID (null, ta.blocker).notifyAllTAs (ta);
754:                                synchronized (deadlockTA) {
755:                                    deadlockTA.notifyAll();
756:                                }
757:
758:                                // DR runs on a higher priority than normal transactions, so
759:                                // we have to stop after there is one deadlock detected to let
760:                                // the notification wakeup released transactions; if there are
761:                                // more deadlocks we will catch them next time
762:                                return;
763:                            }
764:                        }
765:                    } finally {
766:                        endExclusion();
767:                    }
768:                }
769:            }
770:
771:            /**
772:             * Check if the given transaction should abort because of
773:             * a deadlock.
774:             */
775:            public synchronized boolean isDeadlockTA(Transaction ta) {
776:                if (ta == deadlockTA) {
777:                    deadlockTA = null;
778:                    return true;
779:                }
780:                return false;
781:            }
782:
783:            /**
784:            	Starts the GarbageColection pre-phase. This is the time where all transactions have to complete (either commit or rollback)
785:            	until there are no transactions left which were created before this call.
786:             */
787:            public void startGarbageCollectionWaitForCurrentTransactionsToCompletePhase(
788:                    GarbageCollector garbageCollector) {
789:                synchronized (this ) {
790:                    DxIterator i = taTable.elementSet().iterator();
791:
792:                    while (i.next() != null) {
793:                        garbageCollector.addTransactionRequiredToComplete(i
794:                                .object());
795:                    }
796:                    garbageCollector
797:                            .checkForEndOfWaitForCurrentTransactionsToCompletePhase();
798:                }
799:            }
800:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.