EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.impl.store.raw.xact]

COVERAGE SUMMARY FOR SOURCE FILE [XactFactory.java]

nameclass, %method, %block, %line, %
XactFactory.java100% (1/1)97%  (37/38)90%  (807/900)89%  (161.7/181)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class XactFactory100% (1/1)97%  (37/38)90%  (807/900)89%  (161.7/181)
XactFactory (): void 100% (1/1)100% (11/11)100% (4/4)
add (Xact, boolean): void 100% (1/1)100% (6/6)100% (2/2)
addUpdateTransaction (TransactionId, RawTransaction, int): void 100% (1/1)93%  (13/14)97%  (2.9/3)
boot (boolean, Properties): void 100% (1/1)100% (175/175)100% (21/21)
canSupport (Properties): boolean 100% (1/1)100% (2/2)100% (1/1)
createFinished (): void 100% (1/1)65%  (11/17)67%  (4/6)
findTransaction (TransactionId, RawTransaction): boolean 100% (1/1)100% (6/6)100% (1/1)
findUserTransaction (RawStoreFactory, ContextManager, String): RawTransaction 100% (1/1)95%  (36/38)97%  (6.8/7)
firstUpdateInstant (): LogInstant 100% (1/1)100% (4/4)100% (1/1)
flushLogOnCommit (String): boolean 100% (1/1)100% (11/11)100% (1/1)
getLockFactory (): LockFactory 100% (1/1)100% (3/3)100% (1/1)
getLockingPolicy (int, int, boolean): LockingPolicy 100% (1/1)35%  (15/43)37%  (4.8/13)
getTransactionInfo (): TransactionInfo [] 100% (1/1)92%  (11/12)96%  (1.9/2)
getTransactionTable (): Formatable 100% (1/1)100% (3/3)100% (1/1)
getXAResourceManager (): Object 100% (1/1)100% (15/15)100% (3/3)
handlePreparedXacts (RawStoreFactory): void 100% (1/1)87%  (55/63)97%  (13.5/14)
inDatabaseCreation (): boolean 100% (1/1)100% (3/3)100% (1/1)
makeNewUUID (): UUID 0%   (0/1)0%   (0/4)0%   (0/1)
markCorrupt (StandardException): StandardException 100% (1/1)100% (7/7)100% (2/2)
noActiveUpdateTransaction (): boolean 100% (1/1)100% (8/8)100% (1/1)
prepareTransaction (TransactionId): void 100% (1/1)92%  (11/12)97%  (2.9/3)
pushTransactionContext (ContextManager, String, Xact, boolean, RawStoreFactor... 100% (1/1)100% (21/21)100% (5/5)
remove (TransactionId): boolean 100% (1/1)100% (5/5)100% (1/1)
removeUpdateTransaction (TransactionId): void 100% (1/1)92%  (11/12)97%  (2.9/3)
resetTranId (): void 100% (1/1)100% (18/18)100% (5/5)
rollbackAllTransactions (RawTransaction, RawStoreFactory): void 100% (1/1)94%  (80/85)98%  (19.5/20)
setNewTransactionId (TransactionId, Xact): void 100% (1/1)88%  (38/43)98%  (9.8/10)
setRawStoreFactory (RawStoreFactory): void 100% (1/1)97%  (28/29)99%  (6/6)
startCommonTransaction (RawStoreFactory, ContextManager, boolean, Object, Str... 100% (1/1)96%  (43/45)98%  (6.8/7)
startGlobalTransaction (RawStoreFactory, ContextManager, int, byte [], byte [... 100% (1/1)91%  (29/32)83%  (5/6)
startInternalTransaction (RawStoreFactory, ContextManager): RawTransaction 100% (1/1)97%  (30/31)98%  (4.9/5)
startNestedReadOnlyUserTransaction (RawStoreFactory, Object, ContextManager, ... 100% (1/1)100% (10/10)100% (1/1)
startNestedTopTransaction (RawStoreFactory, ContextManager): RawTransaction 100% (1/1)97%  (34/35)98%  (5.9/6)
startNestedUpdateUserTransaction (RawStoreFactory, ContextManager, String): R... 100% (1/1)100% (10/10)100% (1/1)
startTransaction (RawStoreFactory, ContextManager, String): RawTransaction 100% (1/1)100% (10/10)100% (1/1)
stop (): void 100% (1/1)100% (7/7)100% (3/3)
submitPostCommitWork (Serviceable): boolean 100% (1/1)83%  (10/12)67%  (2/3)
useTransactionTable (Formatable): void 100% (1/1)45%  (17/38)56%  (5/9)

1/*
2 
3   Derby - Class org.apache.derby.impl.store.raw.xact.XactFactory
4 
5   Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.impl.store.raw.xact;
22 
23import org.apache.derby.iapi.reference.Property;
24import org.apache.derby.iapi.reference.SQLState;
25 
26import org.apache.derby.iapi.services.context.ContextService;
27import org.apache.derby.iapi.services.context.ContextManager;
28import org.apache.derby.iapi.services.daemon.DaemonService;
29import org.apache.derby.iapi.services.daemon.Serviceable;
30import org.apache.derby.iapi.services.locks.LockFactory;
31import org.apache.derby.iapi.services.monitor.ModuleControl;
32import org.apache.derby.iapi.services.monitor.ModuleSupportable;
33import org.apache.derby.iapi.services.monitor.Monitor;
34import org.apache.derby.iapi.services.sanity.SanityManager;
35import org.apache.derby.iapi.services.io.Formatable;
36import org.apache.derby.iapi.services.io.FormatIdUtil;
37import org.apache.derby.iapi.services.uuid.UUIDFactory;
38import org.apache.derby.catalog.UUID;
39 
40import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
41import org.apache.derby.iapi.store.access.TransactionController;
42import org.apache.derby.iapi.store.access.TransactionInfo;
43 
44import org.apache.derby.iapi.store.access.AccessFactory;
45 
46import org.apache.derby.iapi.store.access.xa.XAResourceManager;
47 
48import org.apache.derby.iapi.store.raw.LockingPolicy;
49import org.apache.derby.iapi.store.raw.GlobalTransactionId;
50import org.apache.derby.iapi.store.raw.RawStoreFactory;
51import org.apache.derby.iapi.store.raw.Transaction;
52 
53import org.apache.derby.iapi.store.raw.data.DataFactory;
54 
55import org.apache.derby.iapi.store.raw.log.LogFactory;
56import org.apache.derby.iapi.store.raw.log.LogInstant;
57 
58import org.apache.derby.iapi.store.raw.xact.TransactionFactory;
59import org.apache.derby.iapi.store.raw.xact.RawTransaction;
60import org.apache.derby.iapi.store.raw.xact.TransactionId;
61 
62import org.apache.derby.iapi.error.StandardException;
63 
64import org.apache.derby.impl.store.raw.xact.XactXAResourceManager;
65 
66import java.util.Enumeration;
67import java.util.Properties;
68import java.util.Hashtable;
69 
70public class XactFactory implements TransactionFactory, ModuleControl, ModuleSupportable
71{
72        protected static final String USER_CONTEXT_ID        = "UserTransaction";
73        protected static final String NESTED_READONLY_USER_CONTEXT_ID = 
74        "NestedRawReadOnlyUserTransaction";
75        protected static final String NESTED_UPDATE_USER_CONTEXT_ID = 
76        "NestedRawUpdateUserTransaction";
77        protected static final String INTERNAL_CONTEXT_ID    = "InternalTransaction";
78        protected static final String NTT_CONTEXT_ID         = "NestedTransaction";
79 
80         /*
81        ** Fields
82        */
83 
84        protected DaemonService rawStoreDaemon;
85 
86        private   UUIDFactory           uuidFactory;
87        protected ContextService                contextFactory;
88        protected LockFactory           lockFactory;
89        protected LogFactory            logFactory;
90        protected DataFactory           dataFactory;
91        protected RawStoreFactory       rawStoreFactory;
92 
93        public TransactionTable ttab;
94        private long        tranId;
95        private LockingPolicy[][] lockingPolicies = new LockingPolicy[3][6];
96 
97        private boolean inCreateNoLog = false;        // creating database, no logging
98 
99        private   XAResourceManager xa_resource;
100 
101        private Object   backupSemaphore = new Object();
102        private long     backupBlockingOperations = 0;
103        private boolean  inBackup = false;
104 
105        /*
106        ** Constructor
107        */
108 
109        public XactFactory() {
110                super();
111        }
112 
113        /*
114        ** Methods of ModuleControl
115        */
116        public boolean canSupport(Properties startParams) {
117                return true;
118        }
119 
120        public void        boot(boolean create, Properties properties)
121                throws StandardException
122        {
123 
124                uuidFactory = Monitor.getMonitor().getUUIDFactory();
125                
126                contextFactory = ContextService.getFactory();
127 
128                lockFactory = 
129            (LockFactory) Monitor.bootServiceModule(false, this,
130                                org.apache.derby.iapi.reference.Module.LockFactory, properties);
131 
132                
133        // adding entries to locking policy table which means we support that
134        // level of concurrency.
135                lockingPolicies[LockingPolicy.MODE_NONE]
136                       [TransactionController.ISOLATION_NOLOCK] =
137                            new NoLocking();
138 
139                lockingPolicies[LockingPolicy.MODE_RECORD]
140                       [TransactionController.ISOLATION_NOLOCK] =
141                            new NoLocking();
142                lockingPolicies[LockingPolicy.MODE_RECORD]
143                       [TransactionController.ISOLATION_READ_UNCOMMITTED] =
144                            new RowLocking1(lockFactory);
145            lockingPolicies[LockingPolicy.MODE_RECORD]
146                       [TransactionController.ISOLATION_READ_COMMITTED] =
147                            new RowLocking2(lockFactory);
148            lockingPolicies[LockingPolicy.MODE_RECORD]
149                       [TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] =
150                            new RowLocking2nohold(lockFactory);
151            lockingPolicies[LockingPolicy.MODE_RECORD]
152                       [TransactionController.ISOLATION_REPEATABLE_READ] =
153                            new RowLockingRR(lockFactory);
154            lockingPolicies[LockingPolicy.MODE_RECORD]
155                       [TransactionController.ISOLATION_SERIALIZABLE] =
156                            new RowLocking3(lockFactory);
157 
158                lockingPolicies[LockingPolicy.MODE_CONTAINER]
159                       [TransactionController.ISOLATION_NOLOCK] =
160                            new NoLocking();
161 
162        // note that current implementation of read uncommitted still gets
163        // container and container intent locks to prevent concurrent ddl.  Thus
164        // the read uncommitted containerlocking implementation is the same as
165        // the read committed implementation.  Future customer requests may 
166        // force us to change this - we will then have to figure out how to
167        // handle a table being dropped while a read uncommitted scanner is
168        // reading it - currently we just block that from happening.
169                lockingPolicies[LockingPolicy.MODE_CONTAINER]
170                       [TransactionController.ISOLATION_READ_UNCOMMITTED] =
171                            new ContainerLocking2(lockFactory);
172            lockingPolicies[LockingPolicy.MODE_CONTAINER]
173                       [TransactionController.ISOLATION_READ_COMMITTED] =
174                            new ContainerLocking2(lockFactory);
175            lockingPolicies[LockingPolicy.MODE_CONTAINER]
176                       [TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] =
177                            new ContainerLocking2(lockFactory);
178            lockingPolicies[LockingPolicy.MODE_CONTAINER]
179                       [TransactionController.ISOLATION_REPEATABLE_READ] =
180                            new ContainerLocking3(lockFactory);
181            lockingPolicies[LockingPolicy.MODE_CONTAINER]
182                       [TransactionController.ISOLATION_SERIALIZABLE] =
183                            new ContainerLocking3(lockFactory);
184 
185 
186                if (create)
187                {
188                        ttab = new TransactionTable();
189 
190                        String noLog =
191                                properties.getProperty(Property.CREATE_WITH_NO_LOG);
192 
193                        inCreateNoLog = (noLog != null && Boolean.valueOf(noLog).booleanValue());
194 
195                }
196        }
197 
198        public void        stop() {
199 
200                if (rawStoreDaemon != null)
201                        rawStoreDaemon.stop();
202 
203        }
204 
205        /*
206        ** Methods of TransactionFactory
207        */
208 
209        /**
210                Get the LockFactory to use with this store.
211        */
212        public LockFactory getLockFactory() {
213                return lockFactory;
214        }
215 
216 
217        /**
218                Database creation finished
219                @exception StandardException standard cloudscape error policy
220        */
221        public void createFinished() throws StandardException
222        {
223                if (!inCreateNoLog) 
224        {
225            throw StandardException.newException(SQLState.XACT_CREATE_NO_LOG);
226        }
227 
228                // make sure there is no active update transaction
229                if (ttab.hasActiveUpdateTransaction())
230        {
231            throw StandardException.newException(SQLState.XACT_CREATE_NO_LOG);
232        }
233 
234                inCreateNoLog = false;
235        }
236 
237    /**
238     * Common work done to create local or global transactions.
239     *
240     * @param rsf    the raw store factory creating this xact.
241     * @param cm     the current context manager to associate the xact with.
242     * @param compatibilitySpace 
243     *               if null, use the transaction being created, else if 
244     *               non-null use this compatibilitySpace.
245     *
246         * @exception  StandardException  Standard exception policy.
247     **/
248        private RawTransaction startCommonTransaction(
249    RawStoreFactory rsf,
250    ContextManager  cm,
251    boolean         readOnly,
252    Object          compatibilitySpace,
253    String          xact_context_id,
254    String          transName,
255    boolean         excludeMe)
256        throws StandardException
257    {
258 
259                if (SanityManager.DEBUG)
260                {
261                        if (rawStoreFactory != null)
262                                SanityManager.ASSERT(
263                    rawStoreFactory == rsf, "raw store factory different");
264 
265                                SanityManager.ASSERT(
266                    cm == contextFactory.getCurrentContextManager());
267                }
268 
269                Xact xact = 
270            new Xact(this, logFactory, dataFactory, readOnly, compatibilitySpace);
271 
272        xact.setTransName(transName);
273                pushTransactionContext(cm, xact_context_id, xact,
274                                                           false /* abortAll */,
275                                                           rsf,
276                                                           excludeMe /* excludeMe during quiesce state */);
277                return xact;
278        }
279 
280        public RawTransaction startTransaction(
281    RawStoreFactory rsf,
282    ContextManager cm,
283    String transName)
284        throws StandardException
285    {
286        return(startCommonTransaction(
287                rsf, cm, false, null, USER_CONTEXT_ID, transName, true));
288        }
289 
290        public RawTransaction startNestedReadOnlyUserTransaction(
291    RawStoreFactory rsf,
292    Object          compatibilitySpace,
293    ContextManager  cm,
294    String          transName)
295        throws StandardException
296    {
297        return(startCommonTransaction(
298            rsf, cm, true, compatibilitySpace, 
299            NESTED_READONLY_USER_CONTEXT_ID, transName, false));
300        }
301 
302        public RawTransaction startNestedUpdateUserTransaction(
303    RawStoreFactory rsf,
304    ContextManager  cm,
305    String          transName)
306        throws StandardException
307    {
308        return(startCommonTransaction(
309            rsf, cm, false, null, 
310            NESTED_UPDATE_USER_CONTEXT_ID, transName, true));
311        }
312 
313        public RawTransaction startGlobalTransaction(
314    RawStoreFactory rsf,
315    ContextManager  cm,
316    int             format_id,
317    byte[]          global_id,
318    byte[]          branch_id)
319        throws StandardException
320    {
321        GlobalXactId gid = new GlobalXactId(format_id, global_id, branch_id);
322 
323        if (ttab.findTransactionContextByGlobalId(gid) != null)
324        {
325            throw StandardException.newException(SQLState.STORE_XA_XAER_DUPID);
326        }
327 
328        RawTransaction xact = 
329            startCommonTransaction(
330                rsf, cm, false, null, 
331                USER_CONTEXT_ID, AccessFactoryGlobals.USER_TRANS_NAME, true);
332 
333        xact.setTransactionId(gid, xact.getId());
334 
335        return(xact);
336        }
337 
338 
339 
340        public RawTransaction findUserTransaction(
341    RawStoreFactory rsf,
342    ContextManager  contextMgr,
343    String transName)
344                 throws StandardException
345        {
346                if (SanityManager.DEBUG)
347                {
348                        SanityManager.ASSERT(
349                contextMgr == contextFactory.getCurrentContextManager(),
350                "passed in context mgr not the same as current context mgr");
351 
352                        if (rawStoreFactory != null)
353                                SanityManager.ASSERT(
354                    rawStoreFactory == rsf, "raw store factory different");
355                }
356 
357                XactContext xc = (XactContext)contextMgr.getContext(USER_CONTEXT_ID);
358                if (xc == null)
359                        return startTransaction(rsf, contextMgr, transName);
360                else
361                        return xc.getTransaction();
362         }
363 
364 
365        public RawTransaction startNestedTopTransaction(RawStoreFactory rsf, ContextManager cm)
366        throws StandardException
367    {
368 
369                if (SanityManager.DEBUG)
370                {
371                        if (rawStoreFactory != null)
372                                SanityManager.ASSERT(
373                    rawStoreFactory == rsf, "raw store factory different");
374                }
375 
376                Xact xact = 
377            new Xact(this, logFactory, dataFactory, false, null);
378 
379                // hold latches etc. past commit in NTT
380                xact.setPostComplete();
381                pushTransactionContext(cm, NTT_CONTEXT_ID, xact, 
382                                                           true /* abortAll */,
383                                                           rsf, 
384                                                           true /* excludeMe during quiesce state*/);
385                return xact;
386        }
387 
388        public RawTransaction startInternalTransaction(RawStoreFactory rsf, ContextManager cm) 
389        throws StandardException 
390    {
391                if (SanityManager.DEBUG)
392                {
393                        if (rawStoreFactory != null)
394                                SanityManager.ASSERT(
395                    rawStoreFactory == rsf, "raw store factory different");
396                }
397 
398 
399                Xact xact = new InternalXact(this, logFactory, dataFactory);
400                pushTransactionContext(cm, INTERNAL_CONTEXT_ID, xact, 
401                                                           true /* abortAll*/,
402                                                           rsf,
403                                                           true /* excludeMe during quiesce state */);
404                return xact;
405        }
406 
407        /*
408         * the following TransactionFactory methods are to support recovery and
409         * should only be used by recovery!
410         */
411 
412        /**
413                Find the TransactionTableEntry with the given ID and make the passed in
414                transaction assume the identity and properties of that
415                TransactionTableEntry.
416                Used in recovery only.
417        */
418        public boolean findTransaction(TransactionId id,  RawTransaction tran)
419        {
420                return ttab.findAndAssumeTransaction(id, tran);
421        }
422 
423 
424        /**
425                Rollback all active transactions that has updated the raw store.
426                Use the recovery Transaction that is passed in to do all the work.
427                Used in recovery only.
428 
429                <P>
430                Transactions are rolled back in the following order:
431                <OL>
432                <LI>internal transactions in reversed beginXact chronological order,
433                <LI>all other transactions in reversed beginXact chronological order,
434                </NL>
435 
436                @param recoveryTransaction use this transaction to do all the user 
437                                   transaction work
438 
439                @exception StandardException any exception thrown during rollback
440        */
441        public void rollbackAllTransactions(
442    RawTransaction  recoveryTransaction,
443    RawStoreFactory rsf) 
444        throws StandardException
445        {
446                if (SanityManager.DEBUG)
447                {
448                        if (rawStoreFactory != null)
449                                SanityManager.ASSERT(
450                    rawStoreFactory == rsf, "raw store factory different");
451 
452                        SanityManager.ASSERT(
453                recoveryTransaction != null, "recovery transaction null");
454                }
455 
456                int irbcount = 0;
457 
458                // First undo internal transactions if there is any
459                if (ttab.hasRollbackFirstTransaction())
460                {
461                        RawTransaction internalTransaction = startInternalTransaction(rsf,
462                                recoveryTransaction.getContextManager());
463 
464                        // make this transaction be aware that it is being used by recovery
465                        internalTransaction.recoveryTransaction();
466 
467                        if (SanityManager.DEBUG)
468                                SanityManager.ASSERT(
469                    internalTransaction.handlesPostTerminationWork() == false,
470                    "internal recovery xact handles post termination work");
471 
472                        while(ttab.getMostRecentRollbackFirstTransaction(
473                                                internalTransaction))
474                        {
475                                irbcount++;
476                                internalTransaction.abort();
477                        }
478 
479                        internalTransaction.close();
480                }
481 
482                if (SanityManager.DEBUG)
483                {
484                        SanityManager.ASSERT(
485                ttab.hasRollbackFirstTransaction() == false,
486                "cant rollback user xacts with existing active internal xacts");
487                }
488 
489                int rbcount = 0;
490 
491                // recoveryTransacion assumes the identity of the most recent xact
492                while(ttab.getMostRecentTransactionForRollback(recoveryTransaction))
493                {
494                        if (SanityManager.DEBUG)
495            {
496                                SanityManager.ASSERT(
497                    recoveryTransaction.handlesPostTerminationWork() == false,
498                    "recovery transaction handles post termination work");
499            }
500 
501                        rbcount++;
502                        recoveryTransaction.abort();
503                }
504 
505                if (SanityManager.DEBUG)
506                {
507                        if (rbcount > 0 || irbcount > 0)
508                        {
509                                // RESOLVE: put this in the log trace
510                                //        System.out.println(
511                //            "Recovery rolled back " + irbcount + 
512                //            " internal transactions,"
513                                //                        + rbcount + " user transactions");
514                        }
515                }
516 
517        }
518 
519 
520        /**
521        Run through all prepared transactions known to this factory 
522        and restore their state such that they remain after recovery, and
523        can be found and handled by a XA transaction manager.  This includes
524        creating a context manager for each, pushing a xact context, and
525        reclaiming update locks on all data changed by the transaction.
526 
527        Expected to be called just after the redo and undo recovery loops, 
528        where the transaction table should be empty except for prepared
529        xacts.
530 
531                Used only in recovery.
532 
533                @exception StandardException Cloudscape Standard Error policy
534        */
535        public void handlePreparedXacts(
536    RawStoreFactory rsf)
537        throws StandardException
538        {
539                if (SanityManager.DEBUG)
540                {
541 
542                        if (rawStoreFactory != null)
543                                SanityManager.ASSERT(
544                    rawStoreFactory == rsf, "raw store factory different");
545                }
546 
547        int prepared_count = 0;
548 
549                if (ttab.hasPreparedRecoveredXact())
550                {
551            // if there any prepared xacts 
552 
553            // At this point recovery has used one context and one transaction
554            // to deal with all transactions.  Prepared transactions are to
555            // be left in the transaction table, but the must have real and
556            // separate CM's and transactions associated with them.
557 
558            // save old context.  Errors may go to funky contexts (the new
559            // context we created to bring the prepared transaction into the
560            // real world after recovery) after we switch contexts, but any 
561            // error we get at this point is going to shut down the db.
562 
563            while (true)
564            {
565                // allocate new context and associate new xact with it.
566                ContextManager cm      = contextFactory.newContextManager();
567                contextFactory.setCurrentContextManager(cm);
568 
569                                try {
570                RawTransaction rawtran = 
571                    startTransaction(
572                        rawStoreFactory, cm, 
573                        AccessFactoryGlobals.USER_TRANS_NAME);
574 
575                if (ttab.getMostRecentPreparedRecoveredXact(rawtran))
576                {
577                    // found a prepared xact.  The reprepare() call will 
578                    // accumulate locks, and change the transaction table entry
579                    // to not be "in-recovery" so that it won't show up again.
580                    rawtran.reprepare();
581 
582                    if (SanityManager.DEBUG)
583                        prepared_count++;
584                }
585                else
586                {
587                    // get rid of last transaction allocated.
588                    rawtran.destroy();
589                    break;
590                }
591                                }
592                                finally
593                                {
594                                         contextFactory.resetCurrentContextManager(cm);
595                                }
596            }
597 
598                }
599 
600                if (SanityManager.DEBUG)
601                {
602            // RESOLVE - need to only do this under a debug flag.
603            // SanityManager.DEBUG_PRINT("",
604            // "Recovery re-prepared " + prepared_count + " xa transactions.");
605                }
606        }
607 
608 
609        /**
610                Get the earliest log instant that is still active, ie, the first log
611                record logged by the earliest transaction that is still active.
612                <BR>
613                The logging system must guarentee that the transaction table is
614                populated in the order transactions are started.
615                Used in recovery only.
616        */
617 
618        public LogInstant firstUpdateInstant()
619        {
620                return ttab.getFirstLogInstant();
621        }
622 
623        /*
624        ** Methods of Corruptable
625        */
626 
627        /**
628                Really this is just a convience routine for callers that might not
629                have access to a log factory.
630        */
631        public StandardException markCorrupt(StandardException originalError) {
632                logFactory.markCorrupt(originalError);
633                return originalError;
634        }
635 
636        /*
637        **                Implementation specific methods.
638        */
639 
640        public void setNewTransactionId(TransactionId oldxid, Xact t)
641        {
642                XactId xid;
643                boolean excludeMe = true; // by default
644 
645                if (oldxid != null)
646                        excludeMe = remove(oldxid);
647 
648                synchronized(this)
649                {
650                        xid = new XactId(tranId++);
651                }
652 
653                t.setTransactionId(t.getGlobalId(), xid);
654 
655                // RESOLVE: How does a real global xact id get set?
656 
657                // If we got rid of the oldxid, that means this transaction object has
658                // merely committed and starting the next transaction with the same
659                // xact object.  In that case, the transaction context will remain the
660                // same and won't be pushed.  We need to add this transaction with the
661                // new id back into the transaction table.  If we did not get rid of
662                // the old oldxid, that means this is a brand new transaction being
663                // created.  The pushTransactionContext call will add it to the
664                // transaction table with the appropriate flags
665                if (oldxid != null)
666                        add(t, excludeMe);
667        }
668 
669        /*
670        **        Set the shortTranId, this is called by the log factory after recovery
671        */
672        public void resetTranId()
673        {
674                XactId xid = (XactId)ttab.largestUpdateXactId();
675                if (xid != null)
676                        tranId = xid.getId() + 1;
677                else
678                        tranId = 1;
679        }
680 
681 
682        /**
683                Create a new RawTransaction, a context for it and push the context
684                onto the current context manager.  Then add the transacion to the
685                transaction table.
686 
687                @param contextName the name of the transaction context
688                @param xact the Transaction object
689                @param abortAll if true, then any error will abort the whole
690                transaction.  Otherwise, let XactContext.cleanupOnError decide what to
691                do
692                @param rsf the raw store factory
693                @param excludeMe during systeme quiesce, i.e., this transaction should
694                not be allowed to be active during a quiesce state.
695 
696 
697                @exception StandardException Standard Cloudscape error policy
698 
699        */
700        protected void pushTransactionContext(ContextManager cm, String contextName, 
701                                                                                  Xact xact,
702                                                                                  boolean abortAll, 
703                                                                                  RawStoreFactory rsf,
704                                                                                  boolean excludeMe)
705                 throws StandardException 
706        {
707                if (cm.getContext(contextName) != null)        
708        {
709            throw StandardException.newException(
710                    SQLState.XACT_TRANSACTION_ACTIVE);
711        }
712                
713                XactContext xc = new XactContext(cm, contextName, xact, abortAll, rsf);
714 
715                // this transaction is now added to the transaction table.
716                // This will cause an idle transaction to take on an identity, which is
717                // unfortunate.  The reason why we have to add the transaction to the
718                // table right now is because the transaction table is used to bring
719                // system  to quisce state to  regulate who can go active during quiesce
720                // state, and if we add the transaction
721                // when it goes active, then there is a window where this transaction
722                // can sneak in.  The transaction table itself does not keep track of
723                // whether transactions can be started or not because quiesce related
724                // transactions can start after all other user
725                // transactions are excluded.  
726                // RESOLVE: need to put more thought on the overall requirement and
727                // design of the transaction table that satisfies the need of all the
728                // clients, namely: checkpoint, recovery, quiesce mode, transaction table.
729 
730                add(xact, excludeMe);
731 
732        }
733 
734        /**
735                Add a transaction to the list of transactions that has updated
736                the raw store.  
737                <P>
738                This is called underneath the BeginXact log operation's doMe method.
739                The logging system must guarentee that transactions are added in the
740                true order they are started, as defined by the order of beginXact log
741                record in the log.
742        */
743        protected void addUpdateTransaction(
744    TransactionId   id, 
745    RawTransaction  t, 
746    int             transactionStatus)
747        {
748                if (SanityManager.DEBUG)
749                        SanityManager.ASSERT(
750                id != null, "addding update transaction with null id");
751 
752                ttab.addUpdateTransaction(id, t, transactionStatus);
753        }
754 
755        /**
756                Remove a transaction from the list of transactions that has updated the
757                raw store.
758        */
759        protected void removeUpdateTransaction(TransactionId id)
760        {
761                if (SanityManager.DEBUG)
762                        SanityManager.ASSERT(
763                id != null, "remove update transaction with null id");
764 
765                ttab.removeUpdateTransaction(id);
766        } 
767 
768        /**
769        Change state of transaction to prepared.  Used by recovery to update
770        the transaction table entry to prepared state.
771        */
772        protected void prepareTransaction(TransactionId id)
773        {
774                if (SanityManager.DEBUG)
775                        SanityManager.ASSERT(
776                id != null, "prepare transaction with null id");
777 
778                ttab.prepareTransaction(id);
779        } 
780 
781        /**
782                Submit this post commit work to the post commit daemon
783        */
784        public boolean submitPostCommitWork(Serviceable work)
785        {
786                if (rawStoreDaemon != null)
787                        return rawStoreDaemon.enqueue(work, work.serviceASAP());
788                return false;
789        }
790 
791        public void setRawStoreFactory(RawStoreFactory rsf) throws StandardException 
792        {
793                if (SanityManager.DEBUG)
794                {
795                        SanityManager.ASSERT(rsf != null, "rawStoreFactory == null");
796                }
797 
798                rawStoreFactory = rsf;
799 
800                // no need to remember raw store factory, 
801                // just remember which daemon to use
802                rawStoreDaemon = rsf.getDaemon();
803 
804                // now its ok to look for the log and data factory
805                // log factory is booted by the data factory
806                logFactory = (LogFactory) Monitor.findServiceModule(this, rsf.getLogFactoryModule());
807 
808                // data factory is booted by the raw store implementation
809                dataFactory = (DataFactory) Monitor.findServiceModule(this, rsf.getDataFactoryModule());
810        }
811 
812        /**
813                Returns true if there is no in flight updating tranasaction.
814                Caller must be aware that if there is no other mechanism to stop
815                transactions from starting and ending, then this information is
816                outdated as soon as it is reported.
817 
818                Only call this function in special times - e.g, during recovery
819        */
820        public boolean noActiveUpdateTransaction()
821        {
822                return (ttab.hasActiveUpdateTransaction() == false);
823        }
824 
825        /*
826                remove the transaction Id an return false iff the transaction is found
827                in the table and it doesn't need exclusion from quiesce state
828         */
829        protected boolean remove(TransactionId xactId)
830        {
831                return ttab.remove(xactId);
832        }
833 
834        protected void add(Xact xact, boolean excludeMe)
835        {
836                ttab.add(xact, excludeMe);
837        }
838 
839 
840        /**
841                Make a new UUID for whomever that wants it
842        */
843        public UUID makeNewUUID()
844        {
845                return uuidFactory.createUUID();
846        }
847 
848        /**
849                Decide if a transaction of this contextId needs to flush the log when
850                it commits
851        */
852        public boolean flushLogOnCommit(String contextName)
853        {
854                //
855                // if this is a user transaction, flush the log
856                // if this is an internal or nested top transaction, do not
857                // flush, let it age out.
858                //
859                return (contextName == USER_CONTEXT_ID || 
860                                contextName.equals(USER_CONTEXT_ID));
861        }
862 
863 
864        /**
865                Get a locking policy for a transaction.
866        */
867        final LockingPolicy getLockingPolicy(
868    int     mode, 
869    int     isolation, 
870    boolean stricterOk)
871    {
872 
873                if (mode == LockingPolicy.MODE_NONE)
874                        isolation = TransactionController.ISOLATION_NOLOCK;
875 
876                LockingPolicy policy = lockingPolicies[mode][isolation];
877 
878                if ((policy != null) || (!stricterOk))
879                        return policy;
880 
881                for (mode++; mode <= LockingPolicy.MODE_CONTAINER; mode++) 
882        {
883                        for (int i = isolation; 
884                 i <= TransactionController.ISOLATION_SERIALIZABLE; 
885                 i++) 
886            {
887                                policy = lockingPolicies[mode][i];
888                                if (policy != null)
889                                        return policy;
890                        }
891                }
892 
893                return null;
894        }
895 
896        /*
897                Return the transaction table to be logged with the checkpoint operation
898         */
899        public Formatable getTransactionTable()
900        {
901                return ttab;
902        }
903 
904        /*
905                Use this transaction table, which is gotten from a checkpoint
906                operation.  Use ONLY during recovery.
907         */
908        public void useTransactionTable(Formatable transactionTable) 
909                 throws StandardException 
910        {
911                if (ttab != null && transactionTable != null)
912        {
913            throw StandardException.newException(
914                    SQLState.XACT_TRANSACTION_TABLE_IN_USE);
915        }
916 
917                if (ttab == null)
918                {
919                        if (transactionTable == null)
920                                ttab = new TransactionTable();
921                        else
922                        {
923                                if (SanityManager.DEBUG)
924                                {
925                                        if ((transactionTable instanceof TransactionTable) ==
926                                                false)
927                                        {
928                                                SanityManager.THROWASSERT(
929                                                        "using transaction table which is of class " + 
930                                                        transactionTable.getClass().getName());
931                                        }
932                                }
933                                ttab = (TransactionTable)transactionTable;
934                        }
935                }
936                // else transactionTable must be null, if we already have a transaction
937                // table, no need to do anything
938        }
939 
940        public TransactionInfo[] getTransactionInfo()
941        {
942                if (SanityManager.DEBUG)
943                        SanityManager.ASSERT(ttab != null, "transaction table is null");
944                return ttab.getTransactionInfo();
945        }
946 
947 
948        // @return false, if the Database creation finished
949        public boolean inDatabaseCreation()
950        {
951                return inCreateNoLog;
952        }
953        
954        /*
955         * Return the module providing XAresource interface to the transaction 
956     * table. 
957     *
958         * @exception StandardException Standard cloudscape exception policy.
959         */
960        public /* XAResourceManager */ Object getXAResourceManager()
961        throws StandardException
962    {
963        if (xa_resource == null)
964            xa_resource = new XactXAResourceManager(rawStoreFactory, ttab);
965 
966        return(xa_resource);
967    }
968 
969 
970    /**
971     * Block the online backup. Backup needs to be blocked while 
972     * executing any unlogged operations or any opearation that 
973     * prevents from  making a consistent backup.
974     * 
975     * @param wait if <tt>true</tt>, waits until the backup 
976     *             is blocked. 
977     * @return     <tt>true</tt> if backup is blocked.
978     *                           <tt>false</tt> otherwise.
979     * @exception StandardException if interrupted while waiting for a 
980     *           backup  to complete.
981     */
982        protected boolean blockBackup(boolean wait)
983        throws StandardException 
984        {
985                synchronized(backupSemaphore) {
986            // do not allow backup blocking operations, if online backup is
987            // is in progress.
988                        if (inBackup) 
989            {
990                if(wait) {
991                    while(inBackup) {
992                        try {
993                            backupSemaphore.wait();
994                        } catch (InterruptedException ie) {
995                            throw StandardException.interrupt(ie);
996                        }
997                    }
998                }else {
999                    return false;
1000                }
1001                        }
1002 
1003            // not in online backup, allow backup blocking operations
1004            backupBlockingOperations++;
1005            return true;
1006                }
1007        }
1008 
1009 
1010        /**
1011     * Unblock the backup, a backup blocking operation finished. 
1012         */
1013        protected void unblockBackup()
1014        {
1015                synchronized(backupSemaphore) {
1016                        if (SanityManager.DEBUG)
1017                                SanityManager.ASSERT(backupBlockingOperations > 0, 
1018                    "no backup blocking opeations in progress"); 
1019                        
1020                        backupBlockingOperations--;
1021 
1022                        if (inBackup) {
1023                                // wake up the online backupthread
1024                                backupSemaphore.notifyAll(); 
1025                        }
1026                }
1027        }
1028 
1029        /**
1030         * Checks if there are any backup blocking operations in progress and 
1031         * prevents new ones from starting until the backup is finished. 
1032         * If backup blocking operations are in progress and  <code> wait </code>
1033         * parameter value is <tt>true</tt>, then it will wait for the current 
1034         * backup blocking operations to finish. 
1035         * 
1036         * A Consistent backup can not be made if there are any backup 
1037         * blocking operations (like unlogged operations) are in progress
1038         *
1039         * @param wait if <tt>true</tt>, waits for the current backup blocking 
1040         *             operation in progress to finish.
1041         * @return     <tt>true</tt> if no backup blocking operations are in 
1042     *             progress
1043         *             <tt>false</tt> otherwise.
1044         * @exception StandardException if interrupted or a runtime exception occurs
1045         */
1046        public boolean blockBackupBlockingOperations(boolean wait) 
1047                throws StandardException 
1048        {
1049                synchronized(backupSemaphore) {
1050                        if (wait) {
1051                                // set the inBackup state to true first to stop new backup
1052                                // blocking operation from starting.
1053                                inBackup= true;
1054                                try        {
1055                                        // wait for backup blocking operation in progress to finish
1056                                        while(backupBlockingOperations > 0)
1057                                        {
1058                                                try        {
1059                                                        backupSemaphore.wait();
1060                                                }
1061                                                catch (InterruptedException ie) {
1062                                                        // make sure we are not stuck in the backup state 
1063                            // if we caught an interrupt exception and the 
1064                            // calling thread may not have a chance to clear 
1065                            // the in backup state.
1066 
1067                                                        inBackup = false;
1068                                                        backupSemaphore.notifyAll();
1069                                                        throw StandardException.interrupt(ie);
1070                                                }
1071                                        }
1072                                }
1073                                catch (RuntimeException rte) {
1074                                        // make sure we are not stuck in backup state if we
1075                                        // caught a run time exception and the calling thread may 
1076                    // not have a chance to clear the in backup state.
1077                                        inBackup= false;
1078                                        backupSemaphore.notifyAll();
1079                                        throw rte;                // rethrow run time exception
1080                                }
1081                        } else {
1082                                // check if any backup blocking operations that are in  progress
1083                                if (backupBlockingOperations == 0)
1084                                        inBackup = true;
1085                        }
1086            
1087                }
1088 
1089        if (SanityManager.DEBUG) {
1090            if (inBackup) {
1091                SanityManager.ASSERT(backupBlockingOperations == 0 ,
1092                                 "store is not in correct state for backup");
1093            }
1094        }
1095 
1096                return inBackup;
1097        }
1098 
1099 
1100        /**
1101         * Backup completed. Allow backup blocking operations. 
1102         */
1103        public void unblockBackupBlockingOperations()
1104        {
1105                synchronized(backupSemaphore) {
1106                        inBackup = false;
1107                        backupSemaphore.notifyAll();
1108                }
1109        }
1110        
1111}

[all classes][org.apache.derby.impl.store.raw.xact]
EMMA 2.0.5312 (C) Vladimir Roubtsov