KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > core > TransactionManager


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Core License version 1 published by ozone-db.org.
3
//
4
// The original code and portions created by SMB are
5
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
6
//
7
// $Id: TransactionManager.java,v 1.11.2.2 2003/12/21 16:01:23 per_nyfelt Exp $
8

9 package org.ozoneDB.core;
10
11 import org.ozoneDB.*;
12 import org.ozoneDB.DxLib.*;
13 import org.ozoneDB.core.DbRemote.*;
14 import org.ozoneDB.core.dr.DeadlockRecognition;
15 import org.ozoneDB.util.LogWriter;
16
17 import java.util.Random JavaDoc;
18
19
20 /**
21  * The transaction manager is the factory for transactions and locks.
22  *
23  *
24  * @author <a HREF="http://www.softwarebuero.de/">SMB</a>
25  * @author <a HREF="http://www.medium.net/">Medium.net</a>
26  * @version $Revision: 1.11.2.2 $Date: 2003/12/21 16:01:23 $
27  */

28 public final class TransactionManager extends ServerComponent {
29
30     /**
31      * All currently running transactions (taID -> ta).
32      */

33     protected DxMap taTable;
34
35     /**
36      * In local mode this maps threads to transactions.
37      */

38     protected DxMap threadTable;
39
40     /**
41      * Used to signal a deadlock and which Transaction should abort.
42      */

43     protected Transaction deadlockTA;
44
45     /**
46      * True if one thread runs exclusively.
47      */

48     protected Thread JavaDoc exclusiveThread;
49
50     protected long acquireCount;
51
52     public TransactionManager( Env _env ) {
53         super( _env );
54 // _env.getLogWriter().newEntry(this,"<init>(): _env="+_env+",env="+env+".",LogWriter.INFO);
55
taTable = new DxHashMap( 32 );
56         threadTable = new DxHashMap( 32 );
57     }
58
59
60     public void startup() throws Exception JavaDoc {
61         env.logWriter.newEntry( this, "startup...", LogWriter.INFO );
62     }
63
64
65     public void shutdown() throws Exception JavaDoc {
66         env.logWriter.newEntry( this, "shutdown...", LogWriter.INFO );
67
68         env.logWriter.newEntry( this, " there are " + taTable.count() + " pending transaction(s)", LogWriter.INFO );
69         if (!taTable.isEmpty()) {
70             env.logWriter.newEntry( this, " aborting pending transactions...", LogWriter.INFO );
71             DxIterator it = taTable.iterator();
72             while (it.next() != null) {
73                 ((Transaction)it.object()).stop();
74             }
75
76             env.logWriter.newEntry( this, " waiting for transactions to end...", LogWriter.INFO );
77             for (int sec = 10; !taTable.isEmpty(); sec--) {
78                 Thread.sleep( 1000 );
79             }
80         }
81
82         env.logWriter.newEntry( this, "acquire count total:" + acquireCount, LogWriter.INFO );
83     }
84
85
86     public void save() throws Exception JavaDoc {
87     }
88
89
90     /**
91      * Factory method to generate proper Lock objects. These Lock objects are
92      * used in the store backend but they have to be generated in the core to
93      * meet the requirements of the transaction implementation.
94      */

95     public Lock newLock() {
96         return new MROWLock();
97     }
98
99
100     public int taTableCount() {
101         return taTable.count();
102     }
103
104
105     public Transaction taForID( TransactionID taID ) {
106         return (Transaction)taTable.elementForKey( taID );
107     }
108
109
110     /**
111      * der aktuelle thread is auch die aktuelle transaktion (wenn der
112      * thread ueberhaupt eine transaktion ist)
113      */

114     public Transaction currentTA() {
115         Thread JavaDoc thread = Thread.currentThread();
116
117         // see startTransaction()
118
if (thread instanceof CommandThread) {
119             return ((CommandThread) thread).ta;
120         } else {
121             Transaction result = (Transaction) threadTable.elementForKey(thread);
122             return result;
123         }
124     }
125
126
127     public Transaction newTransaction( User owner ) throws TransactionException {
128         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
129             env.logWriter.newEntry( this, "newTransaction() *****************************", LogWriter.DEBUG3 );
130         }
131
132         if (currentTA() != null) {
133             throw new TransactionException( "Thread is already joined to a transaction.", TransactionException.STATE );
134         }
135
136         Transaction ta = env.storeManager.createTransaction(env, owner);
137         Thread JavaDoc thread = Thread.currentThread();
138
139         // in the server threads are CommandThreads and the corresponding
140
// transaction is a member of the CommandThread
141
if (thread instanceof CommandThread) {
142             CommandThread commandThread = (CommandThread)Thread.currentThread();
143             commandThread.setTransaction( ta );
144         }
145
146         if (env.logWriter.hasTarget( LogWriter.DEBUG2 )) {
147             env.logWriter.newEntry( this, "newTransaction(): ta="+ta+", thread="+thread+".", LogWriter.DEBUG2 );
148         }
149
150         synchronized (this) {
151             // if we are local, threads can be of any type; we add them to the
152
// threadTable to be able to found the corresponding transaction
153
threadTable.addForKey( ta, thread );
154
155             taTable.addForKey( ta, ta.taID() );
156             
157         }
158         return ta;
159     }
160
161
162     /**
163      * Delete the transaction that is associated with the current thread.
164      */

165     public void deleteTransaction() {
166         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
167             env.logWriter.newEntry( this, "deleteTransaction() --------------------------", LogWriter.DEBUG3 );
168         }
169
170         Transaction ta = currentTA();
171         if (ta == null) {
172             env.logWriter.newEntry( this, "deleteTransaction(): thread is not joined to a transaction.",
173                     LogWriter.WARN );
174         } else {
175             if (env.logWriter.hasTarget( LogWriter.DEBUG2 )) {
176                 env.logWriter.newEntry( this, "deleteTransaction() ta="+ta+".", LogWriter.DEBUG2 );
177             }
178             synchronized (this) {
179                 acquireCount += ta.acquireCount;
180                 if (false&&env.logWriter.hasTarget( LogWriter.DEBUG2 )) {
181                     env.logWriter.newEntry( this, " acquire count:" + ta.acquireCount, LogWriter.DEBUG2 );
182                     env.logWriter.newEntry( this, " total :" + acquireCount, LogWriter.DEBUG2 );
183                 }
184
185                 Thread JavaDoc thread = Thread.currentThread();
186                 if (thread instanceof CommandThread) {
187                     ((CommandThread)thread).setTransaction( null );
188                 }
189
190                 threadTable.removeForKey( thread );
191                 taTable.removeForKey( ta.taID() );
192
193                 env.getGarbageCollector().removeTransactionRequiredToComplete(ta);
194             }
195         }
196     }
197
198     /**
199         If we notify all transactions, they not-blocked-ones may wake up from sleeping.
200     */

201     protected boolean alsoNotifySomeSleepingTransactions = true;
202
203     /**
204      * Notify each thread that is associated with a currently blocked
205      * transaction by calling notifyAll() on the blocked transaction.
206      */

207     public void notifyWaitingTransactions() {
208         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
209             env.logWriter.newEntry( this, "notifyWaitingTransactions()", LogWriter.DEBUG3 );
210         }
211
212         DxArrayBag tas = new DxArrayBag( taTable.count() );
213
214         // search all blocked transactions in a synchronized block (to prevent
215
// others from chnaging the taTable) but call notifyAll() later in a
216
// non-synchronized block tp prevent us from deadlocks
217
synchronized (this) {
218             DxIterator it = taTable.iterator();
219             Transaction ta;
220             while ((ta = (Transaction)it.next()) != null) {
221                 if ((ta.blocker != null)) {
222                     tas.add( ta );
223                 }
224             }
225
226             if (alsoNotifySomeSleepingTransactions) {
227                 if (tas.isEmpty()) {
228                     it.reset();
229                     while ((ta = (Transaction)it.next()) != null) {
230                         if (ta.isSleeping()) { // A sleeping
231
tas.add(ta);
232                             break;
233                         }
234                     }
235                 }
236             }
237         }
238
239         DxIterator it = tas.iterator();
240         Transaction ta;
241         while ((ta = (Transaction)it.next()) != null) {
242             if (false&&env.logWriter.hasTarget( LogWriter.DEBUG )) {
243                 env.logWriter.newEntry( this, " notify: " + ta, LogWriter.DEBUG );
244             }
245             synchronized (ta) {
246                 ta.notifyAll();
247             }
248         }
249     }
250
251
252     /**
253      * Handle the specified command on behalf of the current thread/transaction.
254      * This method is called by the InvokeServer after it has handled
255      * InvokeServer specific command.
256      */

257     public void handleCommand(DbCommand command,DbInvokeClient client) {
258         handleCommand(command,client.getUser());
259     }
260
261     /**
262      * Handle the specified command on behalf of the current thread/transaction.
263      * This method is called by the InvokeServer after it has handled
264      * InvokeServer specific command.
265      */

266     public void handleCommand(DbCommand command,User user) {
267         if (env.logWriter.hasTarget( LogWriter.DEBUG )) {
268             env.logWriter.newEntry( this, "handleCommand(): " + command.toString(), LogWriter.DEBUG );
269         }
270
271         CurrentDatabase.register(env.getDatabase());
272         
273         try {
274             command.result = null;
275             try {
276                 // close this connection/thread/transaction
277
if (command instanceof DbCloseConn) {
278                     Transaction ta = currentTA();
279                     if (ta != null) {
280                         abortTransaction( ta, command );
281                         deleteTransaction();
282                     }
283                 } else if (!(command instanceof DbTransaction)) {
284     
285                     // perform all commands other then DbTransaction
286
Transaction ta = currentTA();
287                     if (ta == null) {
288                         completeTransaction( command, /*client*/ user );
289                     } else {
290                         // if something goes wrong while performing this command the client
291
// has to abort the transaction
292
performCommand( ta, command );
293                     }
294                 } else {
295                     // perform transaction demarcation command; test for error conditions
296
// and signal error via command.result to avoid exceptions that are
297
// converted to OzoneInternalException by the enclosing try/catch
298
switch (((DbTransaction)command).mode()) {
299                         case DbTransaction.MODE_BEGIN: {
300                             if (currentTA() != null) {
301                                 command.result = new TransactionException( "Thread is already joined to a transaction.",
302                                         TransactionException.STATE );
303                             } else {
304                                 Transaction ta = newTransaction(user /*client.getUser()*/);
305                                 command.result = ta.taID();
306                             }
307                         } break;
308                         case DbTransaction.MODE_PREPARE: {
309                             prepareTransaction( currentTA(), command );
310                         } break;
311                         case DbTransaction.MODE_COMMIT_TWOPHASE: {
312                             commitTransaction( currentTA(), command );
313                             deleteTransaction();
314                         } break;
315                         case DbTransaction.MODE_COMMIT_ONEPHASE: {
316                             Transaction ta = currentTA();
317                             if (prepareTransaction( ta, command )) {
318                                 commitTransaction( ta, command );
319                             }
320                             deleteTransaction();
321                         } break;
322                         case DbTransaction.MODE_ABORT: {
323                             abortTransaction( currentTA(), command );
324                             deleteTransaction();
325                         } break;
326                         case DbTransaction.MODE_CHECKPOINT: {
327                             command.result = new OzoneInternalException( "External CHECKPOINT is not implemented yet." );
328                         } break;
329                         case DbTransaction.MODE_STATUS: {
330                             command.result = new Integer JavaDoc( currentTA().status() );
331                         } break;
332                     }
333                 }
334             } catch (Throwable JavaDoc e) {
335                 // all exception that are not handled by the underlying methods
336
// are internal 'panic' errors
337
env.logWriter.newEntry( this, "handleCommand(): " + e, e, LogWriter.ERROR );
338                 command.result = new OzoneInternalException(e.toString(),e);
339                 deleteTransaction();
340             }
341         } finally {
342             CurrentDatabase.unregister();
343         }
344     }
345
346
347     /**
348      * Perform the specified command within a new transaction.
349      */

350     protected void completeTransaction( DbCommand command,User user /*DbInvokeClient client*/) throws Exception JavaDoc {
351         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
352             env.logWriter.newEntry( this, "completeTransaction(): " + command, LogWriter.DEBUG3 );
353         }
354         if (/*client.getUser()*/user == null) {
355             throw new TransactionException( "No owner set for current transaction." );
356         }
357
358         Transaction ta = newTransaction(/*client.getUser()*/ user);
359
360         // perform->prepare->commit/abort
361
boolean alright = false;
362
363         try {
364             if (alright = performCommand( ta, command )) {
365                 if (prepareTransaction( ta, command )) {
366                     commitTransaction( ta, command );
367                 }
368             }
369         } catch (Exception JavaDoc e) {
370             e.printStackTrace();
371             if (env.logWriter.hasTarget(LogWriter.WARN)) {
372                 env.logWriter.newEntry(this,"completeTransaction("+command+"): We've caught an exception (following) and that's why we'll abort now.",e,LogWriter.WARN);
373             }
374             throw e;
375         } catch (Error JavaDoc e) {
376             e.printStackTrace();
377             if (env.logWriter.hasTarget(LogWriter.WARN)) {
378                 env.logWriter.newEntry(this,"completeTransaction("+command+"): We've caught an error (following) and that's why we'll abort now.",e,LogWriter.WARN);
379             }
380             throw e;
381         } finally {
382             if (!alright) {
383                 abortTransaction(ta,command);
384             }
385         }
386         deleteTransaction();
387     }
388
389
390     /**
391      * Perform the specified command on behalf of the specified
392      * thread/transaction. If the transaction has performed only one command
393      * until now, this handles deadlocks by re-performing the command again
394      * until it throws an exception or completes sucessfully. Otherwise an
395      * exception is thrown
396      *
397      *
398      * @return True if the command did not throw an exception
399      * @throws Exception Any exception always signals an internal error.
400      */

401     protected boolean performCommand( Transaction ta, DbCommand command ) throws Exception JavaDoc {
402         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
403             env.logWriter.newEntry( this, "performCommand(): start: " + ta.toString() + ", " + command.toString(),LogWriter.DEBUG3);
404         }
405
406         boolean result = true;
407
408         try {
409             // result goes in command.result
410
result = ta.performCommand( command );
411
412         // other than TransactionError exceptions are catched by
413
// ta.performCommand()
414
} catch (TransactionError e) {
415             if (e.code() == TransactionError.DEADLOCK) {
416
417                 if (ta.commandCount > 1) {
418                     env.logWriter.newEntry( this, ta.toString() + " deadlocked; throwing exception...",
419                             LogWriter.WARN );
420                     command.result = new DeadlockException( "" );
421                     result = false;
422                 } else {
423                     Random JavaDoc rand = new Random JavaDoc();
424                     boolean deadlocked = true;
425                     while (deadlocked) {
426                         try {
427                             env.logWriter.newEntry( this, ta.toString() + " aborting... (DEADLOCK)", LogWriter.WARN );
428                             abortTransaction( ta, command );
429
430                             ta.setDeadlocked(false);
431
432                             long millis = (long)(rand.nextDouble() * ta.increaseDeadlockWaitTimeMaximum());
433                             env.logWriter.newEntry( this, ta.toString() + " sleeping " + millis + " milliseconds...",
434                                     LogWriter.WARN );
435                             ta.sleep(millis);
436
437                             env.logWriter.newEntry( this, ta.toString() + " re-run...", LogWriter.WARN );
438                             ta.reset();
439                             result = ta.performCommand( command );
440
441                             deadlocked = false;
442                         }
443                         catch (TransactionError ee) {
444                             if (ee.code() == TransactionError.DEADLOCK) {
445                             // still deadlocked
446
} else {
447                                 throw ee;
448                             }
449                         }
450                     }
451                 }
452             } else {
453                 // other than DEADLOCK TransactionErrors are internal errors
454
throw e;
455             }
456         } finally {
457             if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
458                 env.logWriter.newEntry( this, "performCommand(): end: " + ta.toString() + ", " + command.toString(),LogWriter.DEBUG3);
459             }
460         }
461         return result;
462     }
463
464
465     /**
466      * Prepare the specified transaction. Return true on success and false
467      * if something failed. In this case the transaction is rolled back. This
468      * method throws an exception only if an internal server error occured.
469      */

470     protected boolean prepareTransaction( Transaction ta, DbCommand command ) throws Exception JavaDoc {
471         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
472             env.logWriter.newEntry( this, "prepareTransaction()", LogWriter.DEBUG3 );
473         }
474
475         // if the commit was requested by the client, the following conditions
476
// are not internal error and so they must not throw an exception
477
if (ta == null) {
478             env.logWriter.newEntry( this, "prepareTransaction(): Thread is not joined to a transaction.",
479                     LogWriter.WARN );
480             command.result = new TransactionException( "Thread is not joined to a transaction.", TransactionException.STATE );
481             return false;
482         } else if (ta.status != Transaction.STATUS_STARTED) {
483             env.logWriter.newEntry( this,
484                     "prepareTransaction():" + ta.toString() + ": Transaction has inproper status.", LogWriter.WARN );
485             command.result = new TransactionException( "Transaction has inproper status.", TransactionException.STATE );
486             return false;
487         } else if (ta.rollbackOnly) {
488             env.logWriter.newEntry( this, "prepareTransaction():" + ta.toString() + ": rollback only.",
489                     LogWriter.WARN );
490             abortTransaction( ta, command );
491             command.result = new TransactionException( "Transaction is in rollback only status.", TransactionException.ROLLBACK );
492             return false;
493         } else {
494             try {
495                 // beginExclusion();
496
ta.prepareCommit();
497                 return true;
498             } catch (Throwable JavaDoc e) {
499                 env.logWriter.newEntry( this, "Prepare transaction failed: " + ta.toString() + "; aborting...", e,
500                         LogWriter.WARN );
501                 abortTransaction( ta, command );
502
503                 command.result = new TransactionException( e.toString(), TransactionException.ROLLBACK );
504                 return false;
505             } finally {
506             // endExclusion();
507
}
508         }
509     }
510
511
512     protected void commitTransaction( Transaction ta, DbCommand command ) throws Exception JavaDoc {
513         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
514             env.logWriter.newEntry( this, "commitTransaction()", LogWriter.DEBUG3 );
515         }
516
517         // if the commit was requested by the client, the following conditions
518
// are not internal error and so they must not throw an exception
519
if (ta == null) {
520             env.logWriter.newEntry( this, "commitTransaction(): Thread is not joined to a transaction.", LogWriter.WARN );
521             command.result = new TransactionException( "Thread is not joined to a transaction.", TransactionException.STATE );
522         } else if (ta.status != Transaction.STATUS_PREPARED) {
523             env.logWriter.newEntry( this, "commitTransaction(): " + ta.toString() + ": Transaction has inproper status.", LogWriter.WARN );
524             command.result = new TransactionException( "Transaction has inproper status.", TransactionException.STATE );
525         } else {
526             try {
527                 beginExclusion();
528                 ta.commit();
529             } catch (Throwable JavaDoc e) {
530                 env.logWriter.newEntry( this, "Commit transaction failed: " + ta.toString(), e, LogWriter.WARN );
531                 command.result = e;
532                 if (e instanceof Error JavaDoc) {
533                     throw (Error JavaDoc)e;
534                 } else {
535                     throw (Exception JavaDoc)e;
536                 }
537             } finally {
538                 endExclusion();
539                 notifyWaitingTransactions();
540             }
541         }
542     }
543
544
545     protected void abortTransaction( Transaction ta, DbCommand command ) throws Exception JavaDoc {
546         if (env.logWriter.hasTarget(LogWriter.DEBUG3)) {
547             env.logWriter.newEntry(this, "abortTransaction()",LogWriter.DEBUG3);
548         }
549
550         // if the commit was requested by the client, the following conditions
551
// are not internal error and so they must not throw an exception
552
if (ta == null) {
553             env.logWriter.newEntry( this, "abortTransaction(): Thread is not joined to a transaction.",
554                     LogWriter.WARN );
555             command.result = new TransactionException( "Thread is not joined to a transaction.", TransactionException.STATE );
556         } else if (ta.status >= Transaction.STATUS_COMMITING) {
557             env.logWriter.newEntry( this, "abortTransaction(): " + ta.toString() + ": Transaction has inproper status.",
558                     LogWriter.WARN );
559             command.result = new TransactionException( "Transaction has inproper status.", TransactionException.STATE );
560         } else {
561             try {
562                 beginExclusion();
563                 ta.abort( command );
564             } catch (Throwable JavaDoc e) {
565                 env.logWriter.newEntry( this, "Aborting transaction failed: " + ta.toString(), e, LogWriter.WARN );
566                 command.result = e;
567                 if (e instanceof Error JavaDoc) {
568                     throw (Error JavaDoc)e;
569                 } else {
570                     throw (Exception JavaDoc)e;
571                 }
572             } finally {
573                 endExclusion();
574                 notifyWaitingTransactions();
575             }
576         }
577     }
578
579
580     /**
581      * Blocks execution until there is no thread scheduled for exclusive
582      * execution or the exclusive thread is the current thread.
583      */

584     public void checkExclusion() {
585         // evaluate the current thread only if there actually is an
586
// exclusiveThread
587
if (exclusiveThread != null && exclusiveThread != Thread.currentThread()) {
588             synchronized (this) {
589                 while (exclusiveThread != null && exclusiveThread != Thread.currentThread()) {
590                     try {
591                         if (false) {
592                             env.logWriter.newEntry(this,"checkExclusion(): waiting... ("+currentTA()+")",LogWriter.DEBUG2);
593                         }
594                         wait();
595                         if (false) {
596                             env.logWriter.newEntry(this,"checkExclusion(): notified... ("+currentTA()+")",LogWriter.DEBUG2);
597                         }
598                     } catch (InterruptedException JavaDoc e) {
599                     }
600                 }
601             }
602         }
603     }
604
605
606     protected synchronized void beginExclusion() {
607         checkExclusion();
608
609         Thread JavaDoc currentThread = Thread.currentThread();
610         if (exclusiveThread != null && exclusiveThread != currentThread) {
611             throw new RuntimeException JavaDoc( "Another thread already runs exclusively." );
612         }
613
614         exclusiveThread = currentThread;
615
616         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
617             env.logWriter.newEntry( this, "beginExclusion(): ", LogWriter.DEBUG3 );
618         }
619     }
620
621
622     protected synchronized void endExclusion() {
623         if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
624             env.logWriter.newEntry( this, "endExclusion(): ", LogWriter.DEBUG3 );
625         }
626
627         Thread JavaDoc currentThread = Thread.currentThread();
628         if (exclusiveThread != currentThread) {
629             throw new RuntimeException JavaDoc( "Current thread does not run exclusively." );
630         }
631
632         exclusiveThread = null;
633         notifyAll();
634     }
635
636
637     /**
638      * This method checks for deadlocks between all current transaction.
639      */

640     public synchronized void checkDeadlocks() {
641         DeadlockRecognition dr = env.deadlockRecognition();
642
643         // count blocked transactions
644
int blockedCount = 0;
645         DxIterator it = taTable.iterator();
646         for (Transaction ta; (ta = (Transaction)it.next()) != null;) {
647             if (ta.isBlocked()) {
648                 blockedCount++;
649             }
650         }
651
652 // env.logWriter.newEntry( this,"*** checkDeadlocks: blockedCount=" + blockedCount + " exclusive=" + exclusiveThread,LogWriter.DEBUG3 );
653

654         // we need to check things only if there are at least 2 blocked ta's
655
if (blockedCount >= 2) {
656
657             try {
658                 // ensure that nothing changes while we check for deadlocks
659
beginExclusion();
660
661                 it = taTable.iterator();
662                 for (Transaction ta; (ta = (Transaction)it.next()) != null;) {
663                     Transaction candidate = (Transaction)dr.detectDeadlock( ta );
664                     if (candidate != null) {
665                         env.logWriter.newEntry( this, "*** *** DEADLOCK DETECTED: ta=" + ta, LogWriter.WARN );
666
667
668                         if (false) { // Why should we sleep here?
669
// Thread.sleep(5000);
670
} else {
671                             /*
672                                 We should just synchronized so that we commit the now-set "deadlocked" flags of
673                                 the deadlocked transactions into main memory where they can read them out.
674                             */

675                             /* Even that commit should happen sooner or later. */
676                             /*
677                             synchronized (candidate) {
678                             }
679                             Thread.sleep(1);
680                             */

681                         }
682
683                         // this will be checked by all transactions using
684
// isDeadlockTA() to determine if it has to abort
685
deadlockTA = candidate;
686                         // env.storeManager.containerForID (null, ta.blocker).notifyAllTAs (ta);
687
synchronized (deadlockTA) {
688                             deadlockTA.notifyAll();
689                         }
690
691                         // DR runs on a higher priority than normal transactions, so
692
// we have to stop after there is one deadlock detected to let
693
// the notification wakeup released transactions; if there are
694
// more deadlocks we will catch them next time
695
return;
696                     }
697                 }
698             } finally {
699                 endExclusion();
700             }
701         }
702     }
703
704
705     /**
706      * Check if the given transaction should abort because of
707      * a deadlock.
708      */

709     public synchronized boolean isDeadlockTA( Transaction ta ) {
710         if (ta == deadlockTA) {
711             deadlockTA = null;
712             return true;
713         }
714         return false;
715     }
716
717     /**
718         Starts the GarbageColection pre-phase. This is the time where all transactions have to complete (either commit or rollback)
719         until there are no transactions left which were created before this call.
720     */

721     public void startGarbageCollectionWaitForCurrentTransactionsToCompletePhase(GarbageCollector garbageCollector) {
722         synchronized (this) {
723             DxIterator i = taTable.elementSet().iterator();
724
725             while (i.next()!=null) {
726                 garbageCollector.addTransactionRequiredToComplete(i.object());
727             }
728             garbageCollector.checkForEndOfWaitForCurrentTransactionsToCompletePhase();
729         }
730     }
731 }
732
733 // :indentSize=4:tabSize=4:noTabs=true:
734
Popular Tags