KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > store > access > RAMTransaction


1 /*
2
3    Derby - Class org.apache.derby.impl.store.access.RAMTransaction
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.store.access;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.Enumeration JavaDoc;
26 import java.util.Hashtable JavaDoc;
27 import java.util.Properties JavaDoc;
28 import java.util.Vector JavaDoc;
29
30 import org.apache.derby.iapi.reference.SQLState;
31 import org.apache.derby.iapi.util.ReuseFactory;
32
33 import org.apache.derby.iapi.services.context.ContextManager;
34
35 import org.apache.derby.iapi.services.io.Storable;
36
37 import org.apache.derby.iapi.services.daemon.Serviceable;
38 import org.apache.derby.iapi.services.monitor.Monitor;
39 import org.apache.derby.iapi.services.sanity.SanityManager;
40 import org.apache.derby.iapi.error.StandardException;
41 import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;
42 import org.apache.derby.iapi.store.access.conglomerate.ConglomerateFactory;
43 import org.apache.derby.iapi.store.access.conglomerate.ScanManager;
44 import org.apache.derby.iapi.store.access.conglomerate.MethodFactory;
45 import org.apache.derby.iapi.store.access.conglomerate.ScanControllerRowSource;
46 import org.apache.derby.iapi.store.access.conglomerate.Sort;
47 import org.apache.derby.iapi.store.access.conglomerate.SortFactory;
48 import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
49 import org.apache.derby.iapi.store.access.AccessFactory;
50 import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
51 import org.apache.derby.iapi.store.access.ColumnOrdering;
52 import org.apache.derby.iapi.store.access.ConglomerateController;
53 import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
54 import org.apache.derby.iapi.store.access.FileResource;
55 import org.apache.derby.iapi.store.access.GroupFetchScanController;
56 import org.apache.derby.iapi.store.access.Qualifier;
57 import org.apache.derby.iapi.store.access.RowLocationRetRowSource;
58 import org.apache.derby.iapi.store.access.RowSource;
59 import org.apache.derby.iapi.store.access.ScanController;
60 import org.apache.derby.iapi.store.access.SortController;
61 import org.apache.derby.iapi.store.access.SortCostController;
62 import org.apache.derby.iapi.store.access.SortObserver;
63 import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
64 import org.apache.derby.iapi.store.access.StoreCostController;
65 import org.apache.derby.iapi.store.access.TransactionController;
66
67 import org.apache.derby.iapi.store.access.XATransactionController;
68
69
70 import org.apache.derby.iapi.store.raw.ContainerHandle;
71 import org.apache.derby.iapi.store.raw.LockingPolicy;
72
73
74 import org.apache.derby.iapi.store.raw.Loggable;
75 import org.apache.derby.iapi.store.raw.Page;
76 import org.apache.derby.iapi.store.raw.Transaction;
77
78 import org.apache.derby.iapi.types.DataValueDescriptor;
79
80 import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil;
81
82 import org.apache.derby.iapi.store.access.DatabaseInstant;
83
84 import org.apache.derby.iapi.store.access.BackingStoreHashtable;
85 import org.apache.derby.iapi.services.io.FormatableBitSet;
86
87 import java.io.Serializable JavaDoc;
88
89
90 // debugging
91
import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
92 import org.apache.derby.iapi.services.stream.InfoStreams;
93
94 public class RAMTransaction
95     implements XATransactionController, TransactionManager
96 {
97
98     /**
99     The corresponding raw store transaction.
100     **/

101     protected Transaction rawtran;
102
103     /**
104     The access manager this transaction is under.
105     **/

106     protected RAMAccessManager accessmanager;
107
108     /**
109     The context this transaction is being managed by.
110     **/

111     protected RAMTransactionContext context;
112
113     /**
114     The parent transaction if this is a nested user transaction.
115     **/

116     protected RAMTransaction parent_tran;
117
118     // XXX (nat) management of the controllers is still embryonic.
119
// XXX (nat) would be nice if sort controllers were like conglom controllers
120
private Vector JavaDoc scanControllers;
121     private Vector JavaDoc conglomerateControllers;
122     private Vector JavaDoc sorts;
123     private Vector JavaDoc sortControllers;
124
125     /** List of sort identifiers (represented as <code>Integer</code> objects)
126      * which can be reused. Since sort identifiers are used as array indexes,
127      * we need to reuse them to avoid leaking memory (DERBY-912). */

128     private ArrayList JavaDoc freeSortIds;
129
130     /**
131     Where to look for temporary conglomerates.
132     **/

133     protected Hashtable JavaDoc tempCongloms = null;
134
135     /**
136     Next id to use for a temporary conglomerate.
137     **/

138     private long nextTempConglomId = -1;
139
140     /**
141      * Set by alter table to indicate that the conglomerate cache needs to
142      * be invalidated if a transaction aborting error is encountered, cleared
143      * after cleanup.
144      */

145     private boolean alterTableCallMade = false;
146
147     /**
148      * The lock level of the transaction.
149      * <p>
150      * Cannot lock a level lower than the getSystemLockLevel(). So if
151      * getSystemLockLevel() is table level locking, setting the transaction
152      * locking level to record has no effect.
153      **/

154     private int transaction_lock_level;
155
156     /**************************************************************************
157      * Constructors for This class:
158      **************************************************************************
159      */

160
161     private final void init(
162     RAMAccessManager myaccessmanager,
163     Transaction theRawTran,
164     RAMTransaction parent_tran)
165     {
166         this.rawtran = theRawTran;
167         this.parent_tran = parent_tran;
168         accessmanager = myaccessmanager;
169         scanControllers = new Vector JavaDoc();
170         conglomerateControllers = new Vector JavaDoc();
171
172         sorts = null; // allocated on demand.
173
freeSortIds = null; // allocated on demand.
174
sortControllers = null; // allocated on demand
175

176         if (parent_tran != null)
177         {
178             // allow nested transactions to see temporary conglomerates which
179
// were created in the parent transaction. This is necessary for
180
// language which compiling plans in nested transactions against
181
// user temporaries created in parent transactions.
182

183             tempCongloms = parent_tran.tempCongloms;
184         }
185         else
186         {
187             tempCongloms = null; // allocated on demand
188
}
189     }
190
191     protected RAMTransaction(
192     RAMAccessManager myaccessmanager,
193     Transaction theRawTran,
194     RAMTransaction parent_transaction)
195         throws StandardException
196     {
197         init(myaccessmanager, theRawTran, parent_transaction);
198     }
199
200     RAMTransaction(
201     RAMAccessManager myaccessmanager,
202     RAMTransaction tc,
203     int format_id,
204     byte[] global_id,
205     byte[] branch_id)
206         throws StandardException
207     {
208         init(myaccessmanager, tc.getRawStoreXact(), null);
209
210         if (SanityManager.DEBUG)
211             SanityManager.ASSERT(tc.getRawStoreXact().isIdle());
212
213         this.context = tc.context;
214
215         // switch the transaction pointer in the context to point to this xact
216
this.context.setTransaction(this);
217
218         this.rawtran.createXATransactionFromLocalTransaction(
219             format_id, global_id, branch_id);
220
221         // invalidate old tc, so caller does not use it. Can't just call
222
// destroy as that screws up the contexts which we want to just leave
223
// alone.
224
tc.rawtran = null;
225     }
226
227
228     RAMTransaction()
229     {
230     }
231
232
233     /**************************************************************************
234      * Private/Protected methods of This class:
235      **************************************************************************
236      */

237
238
239     // XXX (nat) currently closes all controllers.
240
protected void closeControllers(boolean closeHeldControllers)
241         throws StandardException
242     {
243         Enumeration JavaDoc e;
244
245         if (!scanControllers.isEmpty())
246         {
247             // loop from end to beginning, removing scans which are not held.
248
for (int i = scanControllers.size() - 1; i >= 0; i--)
249             {
250                 ScanManager sc = (ScanManager) scanControllers.elementAt(i);
251
252                 if (sc.closeForEndTransaction(closeHeldControllers))
253                 {
254                     // TODO - now counting on scan's removing themselves by
255
// calling the closeMe() method.
256
/* scanControllers.removeElementAt(i); */
257                 }
258             }
259
260             if (closeHeldControllers)
261             {
262                 if (SanityManager.DEBUG)
263                 {
264                     SanityManager.ASSERT(scanControllers.isEmpty());
265                 }
266                 // just to make sure everything has been closed and removed.
267
scanControllers.removeAllElements();
268             }
269         }
270
271         if (!conglomerateControllers.isEmpty())
272         {
273             // loop from end to beginning, removing scans which are not held.
274
for (int i = conglomerateControllers.size() - 1; i >= 0; i--)
275             {
276                 ConglomerateController cc =
277                     (ConglomerateController)
278                         conglomerateControllers.elementAt(i);
279
280                 if (cc.closeForEndTransaction(closeHeldControllers))
281                 {
282                     // TODO - now counting on cc's removing themselves by
283
// calling the closeMe() method.
284
/* conglomerateControllers.removeElementAt(i); */
285                 }
286             }
287
288             if (closeHeldControllers)
289             {
290                 if (SanityManager.DEBUG)
291                 {
292                     SanityManager.ASSERT(scanControllers.isEmpty());
293                 }
294                 // just to make sure everything has been closed and removed.
295
conglomerateControllers.removeAllElements();
296             }
297         }
298
299         if ((sortControllers != null) && !sortControllers.isEmpty())
300         {
301             if (closeHeldControllers)
302             {
303                 e = sortControllers.elements();
304                 while (e.hasMoreElements())
305                 {
306                     SortController sc = (SortController) e.nextElement();
307                     sc.close();
308                 }
309                 sortControllers.removeAllElements();
310             }
311         }
312
313         if ((sorts != null) && (!sorts.isEmpty()))
314         {
315             if (closeHeldControllers)
316             {
317                 e = sorts.elements();
318                 while (e.hasMoreElements())
319                 {
320                     Sort sort = (Sort) e.nextElement();
321                     if (sort != null)
322                         sort.drop(this);
323                 }
324                 sorts.removeAllElements();
325                 freeSortIds.clear();
326             }
327         }
328     }
329
330
331     /**
332      * Determine correct locking policy for a conglomerate open.
333      * <p>
334      * Determine from the following table whether to table or record lock
335      * the conglomerate we are opening.
336      * <p>
337      *
338      *
339      * System level override
340      * -------------------------------
341      * user requests table locking record locking
342      * ------------- ------------- --------------
343      * TransactionController.MODE_TABLE TABLE TABLE
344      * TransactionController.MODE_RECORD TABLE RECORD
345      **/

346     private LockingPolicy determine_locking_policy(
347     int requested_lock_level,
348     int isolation_level)
349     {
350         LockingPolicy ret_locking_policy;
351
352         if ((accessmanager.getSystemLockLevel() ==
353                 TransactionController.MODE_TABLE) ||
354             (requested_lock_level == TransactionController.MODE_TABLE))
355         {
356             ret_locking_policy =
357                 accessmanager.table_level_policy[isolation_level];
358         }
359         else
360         {
361             ret_locking_policy =
362                 accessmanager.record_level_policy[isolation_level];
363             
364         }
365         return(ret_locking_policy);
366     }
367
368     private int determine_lock_level(
369     int requested_lock_level)
370     {
371         int ret_lock_level;
372
373         if ((accessmanager.getSystemLockLevel() ==
374                 TransactionController.MODE_TABLE) ||
375             (requested_lock_level == TransactionController.MODE_TABLE))
376         {
377             ret_lock_level = TransactionController.MODE_TABLE;
378         }
379         else
380         {
381             ret_lock_level = TransactionController.MODE_RECORD;
382             
383         }
384         return(ret_lock_level);
385     }
386
387     private Conglomerate findExistingConglomerate(long conglomId)
388         throws StandardException
389     {
390         Conglomerate conglom = null;
391
392         if (conglomId < 0)
393         {
394             if (tempCongloms != null)
395                 conglom = (Conglomerate) tempCongloms.get(new Long JavaDoc(conglomId));
396         }
397         else
398         {
399             conglom = accessmanager.conglomCacheFind(this, conglomId);
400         }
401
402         if (conglom == null)
403         {
404             throw StandardException.newException(
405                 SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST,
406                 new Long JavaDoc(conglomId));
407         }
408         else
409         {
410             return(conglom);
411         }
412     }
413
414     private Conglomerate findConglomerate(long conglomId)
415         throws StandardException
416     {
417         Conglomerate conglom = null;
418
419         if (conglomId >= 0)
420         {
421             conglom = accessmanager.conglomCacheFind(this, conglomId);
422         }
423         else
424         {
425             if (tempCongloms != null)
426                 conglom = (Conglomerate) tempCongloms.get(new Long JavaDoc(conglomId));
427         }
428
429         return(conglom);
430     }
431
432     void setContext(RAMTransactionContext rtc)
433     {
434         context = rtc;
435     }
436
437     /**
438         Get cache statistics for the specified cache
439     */

440     public long[] getCacheStats(String JavaDoc cacheName) {
441         return getRawStoreXact().getCacheStats(cacheName);
442     }
443
444     private ConglomerateController openConglomerate(
445     Conglomerate conglom,
446     boolean hold,
447     int open_mode,
448     int lock_level,
449     int isolation_level,
450     StaticCompiledOpenConglomInfo static_info,
451     DynamicCompiledOpenConglomInfo dynamic_info)
452         throws StandardException
453     {
454         if (SanityManager.DEBUG)
455         {
456             if ((open_mode &
457                     ~(ContainerHandle.MODE_UNLOGGED |
458                       ContainerHandle.MODE_CREATE_UNLOGGED |
459                       ContainerHandle.MODE_FORUPDATE |
460                       ContainerHandle.MODE_READONLY |
461                       ContainerHandle.MODE_TRUNCATE_ON_COMMIT |
462                       ContainerHandle.MODE_DROP_ON_COMMIT |
463                       ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY |
464                       ContainerHandle.MODE_LOCK_NOWAIT |
465                       ContainerHandle.MODE_TRUNCATE_ON_ROLLBACK |
466                       ContainerHandle.MODE_FLUSH_ON_COMMIT |
467                       ContainerHandle.MODE_NO_ACTIONS_ON_COMMIT |
468                       ContainerHandle.MODE_TEMP_IS_KEPT |
469                       ContainerHandle.MODE_USE_UPDATE_LOCKS |
470                       ContainerHandle.MODE_SECONDARY_LOCKED |
471                       ContainerHandle.MODE_BASEROW_INSERT_LOCKED)) != 0)
472             {
473                 SanityManager.THROWASSERT(
474                     "Bad open mode to openConglomerate:" +
475                         Integer.toHexString(open_mode));
476             }
477
478             SanityManager.ASSERT(conglom != null);
479             
480             if (lock_level != MODE_RECORD && lock_level != MODE_TABLE)
481             {
482                 SanityManager.THROWASSERT(
483                     "Bad lock level to openConglomerate:" + lock_level);
484             }
485         }
486
487         // Get a conglomerate controller.
488
ConglomerateController cc =
489             conglom.open(
490                 this, rawtran, hold, open_mode,
491                 determine_lock_level(lock_level),
492                 determine_locking_policy(lock_level, isolation_level),
493                 static_info,
494                 dynamic_info);
495
496         // Keep track of it so we can release on close.
497
conglomerateControllers.addElement(cc);
498
499         return cc;
500     }
501
502     private ScanController openScan(
503     Conglomerate conglom,
504     boolean hold,
505     int open_mode,
506     int lock_level,
507     int isolation_level,
508     FormatableBitSet scanColumnList,
509     DataValueDescriptor[] startKeyValue,
510     int startSearchOperator,
511     Qualifier qualifier[][],
512     DataValueDescriptor[] stopKeyValue,
513     int stopSearchOperator,
514     StaticCompiledOpenConglomInfo static_info,
515     DynamicCompiledOpenConglomInfo dynamic_info)
516         throws StandardException
517     {
518         if (SanityManager.DEBUG)
519         {
520             if ((open_mode &
521                  ~(TransactionController.OPENMODE_FORUPDATE |
522                    TransactionController.OPENMODE_USE_UPDATE_LOCKS |
523                    TransactionController.OPENMODE_FOR_LOCK_ONLY |
524                    TransactionController.OPENMODE_LOCK_NOWAIT |
525                    TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0)
526             {
527                 SanityManager.THROWASSERT(
528                     "Bad open mode to openScan:" +
529                     Integer.toHexString(open_mode));
530             }
531
532             if (!((lock_level == MODE_RECORD | lock_level == MODE_TABLE)))
533             {
534                 SanityManager.THROWASSERT(
535                     "Bad lock level to openScan:" + lock_level);
536             }
537         }
538
539         // Get a scan controller.
540
ScanManager sm =
541             conglom.openScan(
542                 this, rawtran, hold, open_mode,
543                 determine_lock_level(lock_level),
544                 determine_locking_policy(lock_level, isolation_level),
545                 isolation_level,
546                 scanColumnList,
547                 startKeyValue, startSearchOperator,
548                 qualifier,
549                 stopKeyValue, stopSearchOperator,
550                 static_info,
551                 dynamic_info);
552
553         // Keep track of it so we can release on close.
554
scanControllers.addElement(sm);
555
556         return(sm);
557     }
558
559
560
561     /**
562         Reset the cache statistics for the specified cache
563     */

564     public void resetCacheStats(String JavaDoc cacheName) {
565         getRawStoreXact().resetCacheStats(cacheName);
566     }
567
568     /**
569      * Invalidate the conglomerate cache, if necessary. If an alter table
570      * call has been made then invalidate the cache.
571      *
572      * @exception StandardException Standard exception policy.
573      **/

574     protected void invalidateConglomerateCache()
575         throws StandardException
576     {
577         if (alterTableCallMade)
578         {
579             accessmanager.conglomCacheInvalidate();
580             alterTableCallMade = false;
581         }
582     }
583
584
585     /**************************************************************************
586      * Public Methods of TransactionController interface:
587      **************************************************************************
588      */

589
590     /**
591     Add a column to a conglomerate. The conglomerate must not be open in
592     the current transaction. This also means that there must not be any
593     active scans on it.
594
595     The column can only be added at the spot just after the current set of
596     columns.
597
598     The template_column must be nullable.
599
600     After this call has been made, all fetches of this column from rows that
601     existed in the table prior to this call will return "null".
602
603     @param conglomId The identifier of the conglomerate to drop.
604     @param column_id The column number to add this column at.
605     @param template_column An instance of the column to be added to table.
606
607     @exception StandardException Only some types of conglomerates can support
608         adding a column, for instance "heap" conglomerates support adding a
609         column while "btree" conglomerates do not. If the column can not be
610         added an exception will be thrown.
611     **/

612     public void addColumnToConglomerate(
613     long conglomId,
614     int column_id,
615     Storable template_column)
616         throws StandardException
617     {
618         boolean is_temporary = (conglomId < 0);
619
620         Conglomerate conglom = findConglomerate(conglomId);
621         if (conglom == null)
622         {
623             throw StandardException.newException(
624                 SQLState.AM_NO_SUCH_CONGLOMERATE_DROP, new Long JavaDoc(conglomId));
625         }
626
627         // Get exclusive lock on the table being altered.
628
ConglomerateController cc =
629             conglom.open(
630                 this, rawtran, false, OPENMODE_FORUPDATE,
631                 MODE_TABLE,
632                 accessmanager.table_level_policy[
633                     TransactionController.ISOLATION_SERIALIZABLE],
634                 (StaticCompiledOpenConglomInfo) null,
635                 (DynamicCompiledOpenConglomInfo) null);
636
637         conglom.addColumn(this, column_id, template_column);
638
639         // remove the old entry in the Conglomerate directory, and add the
640
// new one.
641
if (is_temporary)
642         {
643             // remove old entry in the Conglomerate directory, and add new one
644
if (tempCongloms != null)
645                 tempCongloms.remove(new Long JavaDoc(conglomId));
646             tempCongloms.put(new Long JavaDoc(conglomId), conglom);
647         }
648         else
649         {
650             alterTableCallMade = true;
651
652             // have access manager update the conglom to this new one.
653
accessmanager.conglomCacheUpdateEntry(conglomId, conglom);
654         }
655
656         cc.close();
657
658         return;
659     }
660
661     /**
662      * Return static information about the conglomerate to be included in a
663      * a compiled plan.
664      * <p>
665      * The static info would be valid until any ddl was executed on the
666      * conglomid, and would be up to the caller to throw away when that
667      * happened. This ties in with what language already does for other
668      * invalidation of static info. The type of info in this would be
669      * containerid and array of format id's from which templates can be created.
670      * The info in this object is read only and can be shared among as many
671      * threads as necessary.
672      * <p>
673      *
674      * @return The static compiled information.
675      *
676      * @param conglomId The identifier of the conglomerate to open.
677      *
678      * @exception StandardException Standard exception policy.
679      **/

680     public StaticCompiledOpenConglomInfo getStaticCompiledConglomInfo(
681     long conglomId)
682         throws StandardException
683     {
684         return(
685             findExistingConglomerate(
686                 conglomId).getStaticCompiledConglomInfo(this, conglomId));
687     }
688
689     /**
690      * Return dynamic information about the conglomerate to be dynamically
691      * reused in repeated execution of a statement.
692      * <p>
693      * The dynamic info is a set of variables to be used in a given
694      * ScanController or ConglomerateController. It can only be used in one
695      * controller at a time. It is up to the caller to insure the correct
696      * thread access to this info. The type of info in this is a scratch
697      * template for btree traversal, other scratch variables for qualifier
698      * evaluation, ...
699      * <p>
700      *
701      * @return The dynamic information.
702      *
703      * @param conglomId The identifier of the conglomerate to open.
704      *
705      * @exception StandardException Standard exception policy.
706      **/

707     public DynamicCompiledOpenConglomInfo getDynamicCompiledConglomInfo(
708     long conglomId)
709         throws StandardException
710     {
711         return(
712             findExistingConglomerate(
713                 conglomId).getDynamicCompiledConglomInfo(conglomId));
714     }
715
716
717     private final int countCreatedSorts()
718     {
719         int ret_val = 0;
720         if (sorts != null)
721         {
722             for (int i = 0; i < sorts.size(); i++)
723             {
724                 if (sorts.elementAt(i) != null)
725                     ret_val++;
726             }
727         }
728
729         return(ret_val);
730     }
731
732     /**
733      * Report on the number of open conglomerates in the transaction.
734      * <p>
735      * There are 4 types of open "conglomerates" that can be tracked, those
736      * opened by each of the following: openConglomerate(), openScan(),
737      * openSort(), and openSortScan(). This routine can be used to either
738      * report on the number of all opens, or may be used to track one
739      * particular type of open.
740      *
741      * This routine is expected to be used for debugging only. An
742      * implementation may only track this info under SanityManager.DEBUG mode.
743      * If the implementation does not track the info it will return -1 (so
744      * code using this call to verify that no congloms are open should check
745      * for return <= 0 rather than == 0).
746      *
747      * The return value depends on the "which_to_count" parameter as follows:
748      * OPEN_CONGLOMERATE - return # of openConglomerate() calls not close()'d.
749      * OPEN_SCAN - return # of openScan() calls not close()'d.
750      * OPEN_CREATED_SORTS - return # of sorts created (createSort()) in
751      * current xact. There is currently no way to get
752      * rid of these sorts before end of transaction.
753      * OPEN_SORT - return # of openSort() calls not close()'d.
754      * OPEN_TOTAL - return total # of all above calls not close()'d.
755      * - note an implementation may return -1 if it does not track the
756      * above information.
757      *
758      * @return The nunber of open's of a type indicated by "which_to_count"
759      * parameter.
760      *
761      * @param which_to_count Which kind of open to report on.
762      *
763      * @exception StandardException Standard exception policy.
764      **/

765     public int countOpens(int which_to_count)
766         throws StandardException
767     {
768         int ret_val = -1;
769
770         switch (which_to_count)
771         {
772             case OPEN_CONGLOMERATE:
773                 ret_val = conglomerateControllers.size();
774                 break;
775             case OPEN_SCAN:
776                 ret_val = scanControllers.size();
777                 break;
778             case OPEN_CREATED_SORTS:
779                 ret_val = countCreatedSorts();
780                 break;
781             case OPEN_SORT:
782                 ret_val =
783                     ((sortControllers != null) ? sortControllers.size() : 0);
784                 break;
785             case OPEN_TOTAL:
786                 ret_val =
787                     conglomerateControllers.size() + scanControllers.size() +
788                     ((sortControllers != null) ? sortControllers.size() : 0) +
789                     countCreatedSorts();
790                 break;
791         }
792
793         return(ret_val);
794     }
795
796     /**
797      * Create a new conglomerate.
798      * <p>
799      * @see TransactionController#createConglomerate
800      *
801      * @exception StandardException Standard exception policy.
802      **/

803     public long createConglomerate(
804     String JavaDoc implementation,
805     DataValueDescriptor[] template,
806     ColumnOrdering[] columnOrder,
807     Properties JavaDoc properties,
808     int temporaryFlag)
809         throws StandardException
810     {
811         // Find the appropriate factory for the desired implementation.
812
MethodFactory mfactory;
813         mfactory = accessmanager.findMethodFactoryByImpl(implementation);
814         if (mfactory == null || !(mfactory instanceof ConglomerateFactory))
815         {
816             throw StandardException.newException(
817                     SQLState.AM_NO_SUCH_CONGLOMERATE_TYPE, implementation);
818         }
819         ConglomerateFactory cfactory = (ConglomerateFactory) mfactory;
820
821         // Create the conglomerate
822
// RESOLVE (mikem) - eventually segmentid's will be passed into here
823
// in the properties. For now just use 0.]
824
int segment;
825         long conglomid;
826         if ((temporaryFlag & TransactionController.IS_TEMPORARY)
827                 == TransactionController.IS_TEMPORARY)
828         {
829             segment = ContainerHandle.TEMPORARY_SEGMENT;
830             conglomid = ContainerHandle.DEFAULT_ASSIGN_ID;
831         }
832         else
833         {
834             segment = 0; // RESOLVE - only using segment 0
835
conglomid =
836                 accessmanager.getNextConglomId(
837                     cfactory.getConglomerateFactoryId());
838         }
839
840         // call the factory to actually create the conglomerate.
841
Conglomerate conglom =
842             cfactory.createConglomerate(
843                 this, segment, conglomid, template,
844                 columnOrder, properties, temporaryFlag);
845
846         long conglomId;
847         if ((temporaryFlag & TransactionController.IS_TEMPORARY)
848                 == TransactionController.IS_TEMPORARY)
849         {
850             conglomId = nextTempConglomId--;
851             if (tempCongloms == null)
852                 tempCongloms = new Hashtable JavaDoc();
853             tempCongloms.put(new Long JavaDoc(conglomId), conglom);
854         }
855         else
856         {
857             conglomId = conglom.getContainerid();
858
859             accessmanager.conglomCacheAddEntry(conglomId, conglom);
860         }
861
862         return conglomId;
863     }
864
865     /**
866         Create a conglomerate and populate it with rows from rowSource.
867
868         @see TransactionController#createAndLoadConglomerate
869         @exception StandardException Standard Cloudscape Error Policy
870     */

871     public long createAndLoadConglomerate(
872     String JavaDoc implementation,
873     DataValueDescriptor[] template,
874     ColumnOrdering[] columnOrder,
875     Properties JavaDoc properties,
876     int temporaryFlag,
877     RowLocationRetRowSource rowSource,
878     long[] rowCount)
879         throws StandardException
880     {
881         return(
882             recreateAndLoadConglomerate(
883                 implementation,
884                 true,
885                 template,
886                 columnOrder,
887                 properties,
888                 temporaryFlag,
889                 0 /* unused if recreate_ifempty is true */,
890                 rowSource,
891                 rowCount));
892     }
893
894     /**
895         recreate a conglomerate and populate it with rows from rowSource.
896
897         @see TransactionController#createAndLoadConglomerate
898         @exception StandardException Standard Cloudscape Error Policy
899     */

900     public long recreateAndLoadConglomerate(
901     String JavaDoc implementation,
902     boolean recreate_ifempty,
903     DataValueDescriptor[] template,
904     ColumnOrdering[] columnOrder,
905     Properties JavaDoc properties,
906     int temporaryFlag,
907     long orig_conglomId,
908     RowLocationRetRowSource rowSource,
909     long[] rowCount)
910         throws StandardException
911
912     {
913         // RESOLVE: this create the conglom LOGGED, this is slower than
914
// necessary although still correct.
915
long conglomId =
916             createConglomerate(
917                 implementation, template, columnOrder, properties, temporaryFlag);
918
919         long rows_loaded =
920             loadConglomerate(
921                 conglomId,
922                 true, // conglom is being created
923
rowSource);
924
925         if (rowCount != null)
926             rowCount[0] = rows_loaded;
927
928         if (!recreate_ifempty && (rows_loaded == 0))
929         {
930             dropConglomerate(conglomId);
931
932             conglomId = orig_conglomId;
933         }
934
935         return conglomId;
936     }
937
938     /**
939      * Return a string with debug information about opened congloms/scans/sorts.
940      * <p>
941      * Return a string with debugging information about current opened
942      * congloms/scans/sorts which have not been close()'d.
943      * Calls to this routine are only valid under code which is conditional
944      * on SanityManager.DEBUG.
945      * <p>
946      *
947      * @return String with debugging information.
948      *
949      * @exception StandardException Standard exception policy.
950      **/

951     public String JavaDoc debugOpened() throws StandardException
952     {
953         String JavaDoc str = null;
954
955         if (SanityManager.DEBUG)
956         {
957             Enumeration JavaDoc e;
958
959             str = new String JavaDoc();
960
961             e = scanControllers.elements();
962             while (e.hasMoreElements())
963             {
964                 ScanController sc = (ScanController) e.nextElement();
965                 str += "open scan controller: " + sc + "\n";
966             }
967
968             e = conglomerateControllers.elements();
969             while (e.hasMoreElements())
970             {
971                 ConglomerateController cc =
972                     (ConglomerateController) e.nextElement();
973                 str += "open conglomerate controller: " + cc + "\n";
974             }
975
976             if (sortControllers != null)
977             {
978                 e = sortControllers.elements();
979                 while (e.hasMoreElements())
980                 {
981                     SortController sc = (SortController) e.nextElement();
982                     str += "open sort controller: " + sc + "\n";
983                 }
984             }
985
986             if (sorts != null)
987             {
988                 for (int i = 0; i < sorts.size(); i++)
989                 {
990                     Sort sort = (Sort) sorts.elementAt(i);
991
992                     if (sort != null)
993                     {
994                         str +=
995                             "sorts created by createSort() in current xact:" +
996                             sort + "\n";
997                     }
998                 }
999             }
1000
1001            if (tempCongloms != null)
1002            {
1003                e = tempCongloms.keys();
1004                while (e.hasMoreElements())
1005                {
1006                    Long JavaDoc conglomId = (Long JavaDoc) e.nextElement();
1007                    Conglomerate c = (Conglomerate) tempCongloms.get(conglomId);
1008                    str += "temp conglomerate id = " + conglomId + ": " + c;
1009                }
1010            }
1011
1012        }
1013
1014        return(str);
1015    }
1016
1017    public boolean conglomerateExists(long conglomId)
1018        throws StandardException
1019    {
1020        Conglomerate conglom = findConglomerate(conglomId);
1021        if (conglom == null)
1022            return false;
1023        return true;
1024    }
1025
1026    public void dropConglomerate(long conglomId)
1027        throws StandardException
1028    {
1029        Conglomerate conglom = findExistingConglomerate(conglomId);
1030
1031        conglom.drop(this);
1032
1033        if (conglomId < 0)
1034        {
1035            if (tempCongloms != null)
1036                tempCongloms.remove(new Long JavaDoc(conglomId));
1037        }
1038        else
1039        {
1040            accessmanager.conglomCacheRemoveEntry(conglomId);
1041        }
1042    }
1043
1044    /**
1045     * Retrieve the maximum value row in an ordered conglomerate.
1046     * <p>
1047     * Returns true and fetches the rightmost row of an ordered conglomerate
1048     * into "fetchRow" if there is at least one row in the conglomerate. If
1049     * there are no rows in the conglomerate it returns false.
1050     * <p>
1051     * Non-ordered conglomerates will not implement this interface, calls
1052     * will generate a StandardException.
1053     * <p>
1054     * RESOLVE - this interface is temporary, long term equivalent (and more)
1055     * functionality will be provided by the openBackwardScan() interface.
1056     *
1057     * @param conglomId The identifier of the conglomerate
1058     * to open the scan for.
1059     *
1060     * @param open_mode Specifiy flags to control opening of table.
1061     * OPENMODE_FORUPDATE - if set open the table for
1062     * update otherwise open table shared.
1063     * @param lock_level One of (MODE_TABLE, MODE_RECORD, or MODE_NONE).
1064     *
1065     * @param isolation_level The isolation level to lock the conglomerate at.
1066     * One of (ISOLATION_READ_COMMITTED or
1067     * ISOLATION_SERIALIZABLE).
1068     *
1069     * @param scanColumnList A description of which columns to return from
1070     * every fetch in the scan. template,
1071     * and scanColumnList work together
1072     * to describe the row to be returned by the scan -
1073     * see RowUtil for description of how these three
1074     * parameters work together to describe a "row".
1075     *
1076     * @param fetchRow The row to retrieve the maximum value into.
1077     *
1078     * @return boolean indicating if a row was found and retrieved or not.
1079     *
1080     * @exception StandardException Standard exception policy.
1081     **/

1082    public boolean fetchMaxOnBtree(
1083    long conglomId,
1084    int open_mode,
1085    int lock_level,
1086    int isolation_level,
1087    FormatableBitSet scanColumnList,
1088    DataValueDescriptor[] fetchRow)
1089        throws StandardException
1090    {
1091        // Find the conglomerate.
1092
Conglomerate conglom = findExistingConglomerate(conglomId);
1093
1094        // Get a scan controller.
1095
return(
1096            conglom.fetchMaxOnBTree(
1097                this,
1098                rawtran,
1099                conglomId,
1100                open_mode,
1101                lock_level,
1102                determine_locking_policy(lock_level, isolation_level),
1103                isolation_level,
1104                scanColumnList,
1105                fetchRow));
1106    }
1107
1108
1109    /**
1110     * A superset of properties that "users" can specify.
1111     * <p>
1112     * A superset of properties that "users" (ie. from sql) can specify. Store
1113     * may implement other properties which should not be specified by users.
1114     * Layers above access may implement properties which are not known at
1115     * all to Access.
1116     * <p>
1117     * This list is a superset, as some properties may not be implemented by
1118     * certain types of conglomerates. For instant an in-memory store may not
1119     * implement a pageSize property. Or some conglomerates may not support
1120     * pre-allocation.
1121     * <p>
1122     * This interface is meant to be used by the SQL parser to do validation
1123     * of properties passsed to the create table statement, and also by the
1124     * various user interfaces which present table information back to the
1125     * user.
1126     * <p>
1127     * Currently this routine returns the following list:
1128     * derby.storage.initialPages
1129     * derby.storage.minimumRecordSize
1130     * derby.storage.pageReservedSpace
1131     * derby.storage.pageSize
1132     *
1133     * @return The superset of properties that "users" can specify.
1134     *
1135     **/

1136    public Properties JavaDoc getUserCreateConglomPropList()
1137    {
1138        Properties JavaDoc ret_properties =
1139            ConglomerateUtil.createUserRawStorePropertySet((Properties JavaDoc) null);
1140
1141        return(ret_properties);
1142    }
1143
1144    /**
1145     * Reveals whether the transaction has ever read or written data.
1146     *
1147     * @return true If the transaction has never read or written data.
1148     *
1149     **/

1150    public boolean isIdle()
1151    {
1152        return rawtran.isIdle();
1153    }
1154
1155    /**
1156     * Reveals whether the transaction is a global or local transaction.
1157     *
1158     * @return true If the transaction was either started by
1159     * AccessFactory.startXATransaction() or was morphed to a global
1160     * transaction by calling
1161     * AccessFactory.createXATransactionFromLocalTransaction().
1162     *
1163     * @see AccessFactory#startXATransaction
1164     * @see TransactionController#createXATransactionFromLocalTransaction
1165     *
1166     **/

1167    public boolean isGlobal()
1168    {
1169        return(rawtran.getGlobalId() != null);
1170    }
1171
1172    /**
1173     * Reveals whether the transaction is currently pristine.
1174     *
1175     * @return true If the transaction is Pristine.
1176     *
1177     * @see TransactionController#isPristine
1178     **/

1179    public boolean isPristine()
1180    {
1181        return rawtran.isPristine();
1182    }
1183
1184    /**
1185     * Convert a local transaction to a global transaction.
1186     * <p>
1187     * Get a transaction controller with which to manipulate data within
1188     * the access manager. Tbis controller allows one to manipulate a
1189     * global XA conforming transaction.
1190     * <p>
1191     * Must only be called a previous local transaction was created and exists
1192     * in the context. Can only be called if the current transaction is in
1193     * the idle state. Upon return from this call the old tc will be unusable,
1194     * and all references to it should be dropped (it will have been implicitly
1195     * destroy()'d by this call.
1196     * <p>
1197     * The (format_id, global_id, branch_id) triplet is meant to come exactly
1198     * from a javax.transaction.xa.Xid. We don't use Xid so that the system
1199     * can be delivered on a non-1.2 vm system and not require the javax classes
1200     * in the path.
1201     *
1202     * @param format_id the format id part of the Xid - ie. Xid.getFormatId().
1203     * @param global_id the global transaction identifier part of XID - ie.
1204     * Xid.getGlobalTransactionId().
1205     * @param branch_id The branch qualifier of the Xid - ie.
1206     * Xid.getBranchQaulifier()
1207     *
1208     * @exception StandardException Standard exception policy.
1209     * @see TransactionController
1210     **/

1211    public /* XATransactionController */ Object JavaDoc
1212    createXATransactionFromLocalTransaction(
1213    int format_id,
1214    byte[] global_id,
1215    byte[] branch_id)
1216        throws StandardException
1217    {
1218
1219        getRawStoreXact().createXATransactionFromLocalTransaction(
1220            format_id, global_id, branch_id);
1221
1222        return this;
1223    }
1224
1225    /**
1226        Bulk load into the conglomerate. Rows being loaded into the
1227        conglomerate are not logged.
1228
1229        @param conglomId The conglomerate Id.
1230
1231        @param createConglom If true, the conglomerate is being created in the
1232        same operation as the loadConglomerate. The enables further
1233        optimization as recovery does not require page allocation to be
1234        logged.
1235
1236        @param rowSource Where the rows come from.
1237
1238        @return true The number of rows loaded.
1239
1240        @exception StandardException Standard Cloudscape Error Policy
1241     */

1242    public long loadConglomerate(
1243    long conglomId,
1244    boolean createConglom,
1245    RowLocationRetRowSource rowSource)
1246        throws StandardException
1247    {
1248        // Find the conglomerate.
1249
Conglomerate conglom = findExistingConglomerate(conglomId);
1250
1251        // Load up the conglomerate with rows from the rowSource.
1252
// Don't need to keep track of the conglomerate controller because load
1253
// automatically closes it when it finished.
1254
return(conglom.load(this, createConglom, rowSource));
1255    }
1256
1257    /**
1258        Use this for incremental load in the future.
1259
1260        @param conglomId the conglomerate Id
1261        @param rowSource where the rows to be loaded comes from
1262
1263        @exception StandardException Standard Cloudscape Error Policy
1264     */

1265    public void loadConglomerate(
1266    long conglomId,
1267    RowLocationRetRowSource rowSource)
1268        throws StandardException
1269    {
1270        loadConglomerate(
1271                conglomId,
1272                false, // conglomerate is not being created
1273
rowSource);
1274    }
1275
1276    /**
1277     * Log an operation and then action it in the context of this transaction.
1278     * <p>
1279     * This simply passes the operation to the RawStore which logs and does it.
1280     * <p>
1281     *
1282     * @param operation the operation that is to be applied
1283     *
1284     * @exception StandardException Standard exception policy.
1285     **/

1286    public void logAndDo(Loggable operation)
1287        throws StandardException
1288    {
1289        rawtran.logAndDo(operation);
1290    }
1291
1292    public ConglomerateController openCompiledConglomerate(
1293    boolean hold,
1294    int open_mode,
1295    int lock_level,
1296    int isolation_level,
1297    StaticCompiledOpenConglomInfo static_info,
1298    DynamicCompiledOpenConglomInfo dynamic_info)
1299        throws StandardException
1300    {
1301        if (SanityManager.DEBUG)
1302        {
1303            SanityManager.ASSERT(static_info != null);
1304            SanityManager.ASSERT(dynamic_info != null);
1305        }
1306        
1307        // in the current implementation, only Conglomerate's are passed around
1308
// as StaticCompiledOpenConglomInfo.
1309

1310        return(
1311            openConglomerate(
1312                (Conglomerate) static_info.getConglom(),
1313                hold, open_mode, lock_level, isolation_level,
1314                static_info, dynamic_info));
1315    }
1316
1317    public ConglomerateController openConglomerate(
1318    long conglomId,
1319    boolean hold,
1320    int open_mode,
1321    int lock_level,
1322    int isolation_level)
1323        throws StandardException
1324    {
1325        return(
1326            openConglomerate(
1327                findExistingConglomerate(conglomId),
1328                hold, open_mode, lock_level, isolation_level,
1329                (StaticCompiledOpenConglomInfo) null,
1330                (DynamicCompiledOpenConglomInfo) null));
1331    }
1332
1333    public long findConglomid(long container_id)
1334        throws StandardException
1335    {
1336        return(container_id);
1337    }
1338
1339    public long findContainerid(long conglom_id)
1340        throws StandardException
1341    {
1342        return(conglom_id);
1343    }
1344
1345    /**
1346     * Create a BackingStoreHashtable which contains all rows that qualify for
1347     * the described scan.
1348     **/

1349    public BackingStoreHashtable createBackingStoreHashtableFromScan(
1350    long conglomId,
1351    int open_mode,
1352    int lock_level,
1353    int isolation_level,
1354    FormatableBitSet scanColumnList,
1355    DataValueDescriptor[] startKeyValue,
1356    int startSearchOperator,
1357    Qualifier qualifier[][],
1358    DataValueDescriptor[] stopKeyValue,
1359    int stopSearchOperator,
1360    long max_rowcnt,
1361    int[] key_column_numbers,
1362    boolean remove_duplicates,
1363    long estimated_rowcnt,
1364    long max_inmemory_rowcnt,
1365    int initialCapacity,
1366    float loadFactor,
1367    boolean collect_runtimestats,
1368    boolean skipNullKeyColumns)
1369        throws StandardException
1370    {
1371        return (
1372            new BackingStoreHashTableFromScan(
1373                this,
1374                conglomId,
1375                open_mode,
1376                lock_level,
1377                isolation_level,
1378                scanColumnList,
1379                startKeyValue,
1380                startSearchOperator,
1381                qualifier,
1382                stopKeyValue,
1383                stopSearchOperator,
1384                max_rowcnt,
1385                key_column_numbers,
1386                remove_duplicates,
1387                estimated_rowcnt,
1388                max_inmemory_rowcnt,
1389                initialCapacity,
1390                loadFactor,
1391                collect_runtimestats,
1392                skipNullKeyColumns));
1393    }
1394
1395
1396    public GroupFetchScanController openGroupFetchScan(
1397    long conglomId,
1398    boolean hold,
1399    int open_mode,
1400    int lock_level,
1401    int isolation_level,
1402    FormatableBitSet scanColumnList,
1403    DataValueDescriptor[] startKeyValue,
1404    int startSearchOperator,
1405    Qualifier qualifier[][],
1406    DataValueDescriptor[] stopKeyValue,
1407    int stopSearchOperator)
1408        throws StandardException
1409    {
1410        if (SanityManager.DEBUG)
1411        {
1412            if ((open_mode &
1413                ~(TransactionController.OPENMODE_FORUPDATE |
1414                  TransactionController.OPENMODE_FOR_LOCK_ONLY |
1415                  TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0)
1416                SanityManager.THROWASSERT(
1417                    "Bad open mode to openScan:" +
1418                    Integer.toHexString(open_mode));
1419
1420            if (!(lock_level == MODE_RECORD |
1421                 lock_level == MODE_TABLE))
1422                SanityManager.THROWASSERT(
1423                "Bad lock level to openScan:" + lock_level);
1424        }
1425
1426        // Find the conglomerate.
1427
Conglomerate conglom = findExistingConglomerate(conglomId);
1428
1429        // Get a scan controller.
1430
ScanManager sm =
1431            conglom.openScan(
1432                this, rawtran, hold, open_mode,
1433                determine_lock_level(lock_level),
1434                determine_locking_policy(lock_level, isolation_level),
1435                isolation_level,
1436                scanColumnList,
1437                startKeyValue, startSearchOperator,
1438                qualifier,
1439                stopKeyValue, stopSearchOperator,
1440                (StaticCompiledOpenConglomInfo) null,
1441                (DynamicCompiledOpenConglomInfo) null);
1442
1443        // Keep track of it so we can release on close.
1444
scanControllers.addElement(sm);
1445
1446        return(sm);
1447    }
1448
1449
1450
1451    /**
1452     * Purge all committed deleted rows from the conglomerate.
1453     * <p>
1454     * This call will purge committed deleted rows from the conglomerate,
1455     * that space will be available for future inserts into the conglomerate.
1456     * <p>
1457     *
1458     * @param conglomId Id of the conglomerate to purge.
1459     *
1460     * @exception StandardException Standard exception policy.
1461     **/

1462    public void purgeConglomerate(
1463    long conglomId)
1464        throws StandardException
1465    {
1466        findExistingConglomerate(conglomId).purgeConglomerate(
1467            this,
1468            rawtran);
1469
1470        return;
1471    }
1472
1473    /**
1474     * Return free space from the conglomerate back to the OS.
1475     * <p>
1476     * Returns free space from the conglomerate back to the OS. Currently
1477     * only the sequential free pages at the "end" of the conglomerate can
1478     * be returned to the OS.
1479     * <p>
1480     *
1481     * @param conglomId Id of the conglomerate to purge.
1482     *
1483     * @exception StandardException Standard exception policy.
1484     **/

1485    public void compressConglomerate(
1486    long conglomId)
1487        throws StandardException
1488    {
1489        findExistingConglomerate(conglomId).compressConglomerate(
1490            this,
1491            rawtran);
1492
1493        return;
1494    }
1495
1496    /**
1497     * Compress table in place.
1498     * <p>
1499     * Returns a GroupFetchScanController which can be used to move rows
1500     * around in a table, creating a block of free pages at the end of the
1501     * table. The process will move rows from the end of the table toward
1502     * the beginning. The GroupFetchScanController will return the
1503     * old row location, the new row location, and the actual data of any
1504     * row moved. Note that this scan only returns moved rows, not an
1505     * entire set of rows, the scan is designed specifically to be
1506     * used by either explicit user call of the SYSCS_ONLINE_COMPRESS_TABLE()
1507     * procedure, or internal background calls to compress the table.
1508     *
1509     * The old and new row locations are returned so that the caller can
1510     * update any indexes necessary.
1511     *
1512     * This scan always returns all collumns of the row.
1513     *
1514     * All inputs work exactly as in openScan(). The return is
1515     * a GroupFetchScanController, which only allows fetches of groups
1516     * of rows from the conglomerate.
1517     * <p>
1518     *
1519     * @return The GroupFetchScanController to be used to fetch the rows.
1520     *
1521     * @param conglomId see openScan()
1522     * @param hold see openScan()
1523     * @param open_mode see openScan()
1524     * @param lock_level see openScan()
1525     * @param isolation_level see openScan()
1526     *
1527     * @exception StandardException Standard exception policy.
1528     *
1529     * @see ScanController
1530     * @see GroupFetchScanController
1531     **/

1532    public GroupFetchScanController defragmentConglomerate(
1533    long conglomId,
1534    boolean online,
1535    boolean hold,
1536    int open_mode,
1537    int lock_level,
1538    int isolation_level)
1539        throws StandardException
1540    {
1541        if (SanityManager.DEBUG)
1542        {
1543            if ((open_mode &
1544                ~(TransactionController.OPENMODE_FORUPDATE |
1545                  TransactionController.OPENMODE_FOR_LOCK_ONLY |
1546                  TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0)
1547                SanityManager.THROWASSERT(
1548                    "Bad open mode to openScan:" +
1549                    Integer.toHexString(open_mode));
1550
1551            if (!(lock_level == MODE_RECORD |
1552                 lock_level == MODE_TABLE))
1553                SanityManager.THROWASSERT(
1554                "Bad lock level to openScan:" + lock_level);
1555        }
1556
1557        // Find the conglomerate.
1558
Conglomerate conglom = findExistingConglomerate(conglomId);
1559
1560        // Get a scan controller.
1561
ScanManager sm =
1562            conglom.defragmentConglomerate(
1563                this,
1564                rawtran,
1565                hold,
1566                open_mode,
1567                determine_lock_level(lock_level),
1568                determine_locking_policy(lock_level, isolation_level),
1569                isolation_level);
1570
1571        // Keep track of it so we can release on close.
1572
scanControllers.addElement(sm);
1573
1574        return(sm);
1575    }
1576
1577
1578    public ScanController openScan(
1579    long conglomId,
1580    boolean hold,
1581    int open_mode,
1582    int lock_level,
1583    int isolation_level,
1584    FormatableBitSet scanColumnList,
1585    DataValueDescriptor[] startKeyValue,
1586    int startSearchOperator,
1587    Qualifier qualifier[][],
1588    DataValueDescriptor[] stopKeyValue,
1589    int stopSearchOperator)
1590        throws StandardException
1591    {
1592        return(
1593            openScan(
1594                findExistingConglomerate(conglomId),
1595                hold,
1596                open_mode,
1597                lock_level,
1598                isolation_level,
1599                scanColumnList,
1600                startKeyValue,
1601                startSearchOperator,
1602                qualifier,
1603                stopKeyValue,
1604                stopSearchOperator,
1605                (StaticCompiledOpenConglomInfo) null,
1606                (DynamicCompiledOpenConglomInfo) null));
1607    }
1608
1609    public ScanController openCompiledScan(
1610    boolean hold,
1611    int open_mode,
1612    int lock_level,
1613    int isolation_level,
1614    FormatableBitSet scanColumnList,
1615    DataValueDescriptor[] startKeyValue,
1616    int startSearchOperator,
1617    Qualifier qualifier[][],
1618    DataValueDescriptor[] stopKeyValue,
1619    int stopSearchOperator,
1620    StaticCompiledOpenConglomInfo static_info,
1621    DynamicCompiledOpenConglomInfo dynamic_info)
1622        throws StandardException
1623    {
1624        // in the current implementation, only Conglomerate's are passed around
1625
// as StaticCompiledOpenConglomInfo.
1626

1627        if (SanityManager.DEBUG)
1628        {
1629            SanityManager.ASSERT(static_info != null);
1630            SanityManager.ASSERT(dynamic_info != null);
1631            SanityManager.ASSERT(
1632                static_info instanceof StaticCompiledOpenConglomInfo);
1633            SanityManager.ASSERT(
1634                dynamic_info instanceof DynamicCompiledOpenConglomInfo);
1635        }
1636
1637        return(
1638            openScan(
1639                ((Conglomerate) static_info.getConglom()),
1640                hold,
1641                open_mode,
1642                lock_level,
1643                isolation_level,
1644                scanColumnList,
1645                startKeyValue,
1646                startSearchOperator,
1647                qualifier,
1648                stopKeyValue,
1649                stopSearchOperator,
1650                static_info,
1651                dynamic_info));
1652    }
1653
1654
1655    /**
1656     * Return an open StoreCostController for the given conglomid.
1657     * <p>
1658     * Return an open StoreCostController which can be used to ask about
1659     * the estimated row counts and costs of ScanController and
1660     * ConglomerateController operations, on the given conglomerate.
1661     * <p>
1662     *
1663     * @return The open StoreCostController.
1664     *
1665     * @param conglomId The identifier of the conglomerate to open.
1666     *
1667     * @exception StandardException Standard exception policy.
1668     *
1669     * @see StoreCostController
1670     **/

1671    public StoreCostController openStoreCost(
1672    long conglomId)
1673        throws StandardException
1674    {
1675        // Find the conglomerate.
1676
Conglomerate conglom = findExistingConglomerate(conglomId);
1677
1678        // Get a scan controller.
1679
StoreCostController scc = conglom.openStoreCost(this, rawtran);
1680
1681        return(scc);
1682    }
1683
1684    /**
1685    @see TransactionController#createSort
1686    @exception StandardException Standard error policy.
1687    **/

1688    public long createSort(
1689    Properties JavaDoc implParameters,
1690    DataValueDescriptor[] template,
1691    ColumnOrdering columnOrdering[],
1692    SortObserver sortObserver,
1693    boolean alreadyInOrder,
1694    long estimatedRows,
1695    int estimatedRowSize)
1696        throws StandardException
1697    {
1698        // Get the implementation type from the parameters.
1699
// XXX (nat) need to figure out how to select sort implementation.
1700
String JavaDoc implementation = null;
1701        if (implParameters != null)
1702            implementation =
1703                implParameters.getProperty(AccessFactoryGlobals.IMPL_TYPE);
1704
1705        if (implementation == null)
1706            implementation = AccessFactoryGlobals.SORT_EXTERNAL;
1707
1708        // Find the appropriate factory for the desired implementation.
1709
MethodFactory mfactory;
1710        mfactory = accessmanager.findMethodFactoryByImpl(implementation);
1711        if (mfactory == null || !(mfactory instanceof SortFactory))
1712        {
1713            throw(
1714              StandardException.newException(
1715                  SQLState.AM_NO_FACTORY_FOR_IMPLEMENTATION, implementation));
1716        }
1717        SortFactory sfactory = (SortFactory) mfactory;
1718
1719        // Decide what segment the sort should use.
1720
int segment = 0; // XXX (nat) sorts always in segment 0
1721

1722        // Create the sort.
1723
Sort sort = sfactory.createSort(this, segment,
1724                        implParameters, template, columnOrdering,
1725                        sortObserver, alreadyInOrder, estimatedRows,
1726                        estimatedRowSize);
1727
1728        // Add the sort to the sorts vector
1729
if (sorts == null) {
1730            sorts = new Vector JavaDoc();
1731            freeSortIds = new ArrayList JavaDoc();
1732        }
1733
1734        int sortid;
1735        if (freeSortIds.isEmpty()) {
1736            // no free identifiers, add sort at the end
1737
sortid = sorts.size();
1738            sorts.addElement(sort);
1739        } else {
1740            // reuse a sort identifier
1741
sortid = ((Integer JavaDoc) freeSortIds.remove(freeSortIds.size() - 1))
1742                .intValue();
1743            sorts.setElementAt(sort, sortid);
1744        }
1745
1746        return sortid;
1747    }
1748
1749    /**
1750    Drop a sort.
1751    <p>
1752    Drop a sort created by a call to createSort() within the current
1753    transaction (sorts are automatically "dropped" at the end of a
1754    transaction. This call should only be made after all openSortScan()'s
1755    and openSort()'s have been closed.
1756    <p>
1757
1758    @param sortid The identifier of the sort to drop, as returned from
1759                  createSort.
1760    @exception StandardException From a lower-level exception.
1761    **/

1762    public void dropSort(long sortid)
1763        throws StandardException
1764    {
1765        // should call close on the sort.
1766
Sort sort = (Sort) sorts.elementAt((int) sortid);
1767
1768        if (sort != null)
1769        {
1770            sort.drop(this);
1771            sorts.setElementAt(null, (int) sortid);
1772            freeSortIds.add(ReuseFactory.getInteger((int) sortid));
1773        }
1774    }
1775
1776    /**
1777    @see TransactionController#getProperty
1778    @exception StandardException Standard exception policy.
1779    **/

1780    public Serializable JavaDoc getProperty(
1781    String JavaDoc key)
1782        throws StandardException
1783    {
1784        return
1785            (accessmanager.getTransactionalProperties().getProperty(this, key));
1786    }
1787
1788        /**
1789    @see TransactionController#getPropertyDefault
1790    @exception StandardException Standard exception policy.
1791    **/

1792    public Serializable JavaDoc getPropertyDefault(
1793    String JavaDoc key)
1794        throws StandardException
1795    {
1796        return
1797            (accessmanager.getTransactionalProperties().getPropertyDefault(this, key));
1798    }
1799
1800    /**
1801    @see TransactionController#setProperty
1802    @exception StandardException Standard exception policy.
1803    **/

1804    public void setProperty(
1805    String JavaDoc key,
1806    Serializable JavaDoc value,
1807    boolean dbOnlyProperty)
1808        throws StandardException
1809    {
1810        accessmanager.getTransactionalProperties().setProperty(
1811            this, key, value, dbOnlyProperty);
1812    }
1813
1814    /**
1815    @see TransactionController#setProperty
1816    @exception StandardException Standard exception policy.
1817    **/

1818    public void setPropertyDefault(
1819    String JavaDoc key,
1820    Serializable JavaDoc value)
1821        throws StandardException
1822    {
1823        accessmanager.getTransactionalProperties().setPropertyDefault(
1824            this, key, value);
1825    }
1826
1827    /**
1828    @see TransactionController#propertyDefaultIsVisible
1829    @exception StandardException Standard exception policy.
1830    **/

1831    public boolean propertyDefaultIsVisible(String JavaDoc key) throws StandardException
1832    {
1833        return accessmanager.getTransactionalProperties().propertyDefaultIsVisible(this,key);
1834    }
1835
1836    /**
1837    @see TransactionController#getProperties
1838    @exception StandardException Standard exception policy.
1839    **/

1840    public Properties JavaDoc getProperties()
1841        throws StandardException
1842    {
1843        return accessmanager.getTransactionalProperties().getProperties(this);
1844    }
1845
1846    /**
1847    @see TransactionController#openSort
1848    @exception StandardException Standard error policy.
1849    **/

1850    public SortController openSort(long id)
1851        throws StandardException
1852    {
1853        Sort sort;
1854
1855        // Find the sort in the sorts list, throw an error
1856
// if it doesn't exist.
1857
if (sorts == null || id >= sorts.size()
1858            || (sort = ((Sort) sorts.elementAt((int) id))) == null)
1859        {
1860            throw StandardException.newException(
1861                    SQLState.AM_NO_SUCH_SORT, new Long JavaDoc(id));
1862        }
1863
1864        // Open it.
1865
SortController sc = sort.open(this);
1866
1867        // Keep track of it so we can release on close.
1868
if (sortControllers == null)
1869            sortControllers = new Vector JavaDoc();
1870        sortControllers.addElement(sc);
1871
1872        return sc;
1873    }
1874
1875    /**
1876     * Return an open SortCostController.
1877     * <p>
1878     * Return an open SortCostController which can be used to ask about
1879     * the estimated costs of SortController() operations.
1880     * <p>
1881     *
1882     * @return The open StoreCostController.
1883     *
1884     * @exception StandardException Standard exception policy.
1885     *
1886     * @see StoreCostController
1887     **/

1888    public SortCostController openSortCostController(
1889    Properties JavaDoc implParameters)
1890        throws StandardException
1891    {
1892        // Get the implementation type from the parameters.
1893
// RESOLVE (mikem) need to figure out how to select sort implementation.
1894
String JavaDoc implementation = null;
1895
1896        if (implementation == null)
1897            implementation = AccessFactoryGlobals.SORT_EXTERNAL;
1898
1899        // Find the appropriate factory for the desired implementation.
1900
MethodFactory mfactory;
1901        mfactory = accessmanager.findMethodFactoryByImpl(implementation);
1902        if (mfactory == null || !(mfactory instanceof SortFactory))
1903        {
1904            throw(
1905              StandardException.newException(
1906                  SQLState.AM_NO_FACTORY_FOR_IMPLEMENTATION, implementation));
1907        }
1908        SortFactory sfactory = (SortFactory) mfactory;
1909
1910        // open sort cost controller
1911
return(sfactory.openSortCostController());
1912    }
1913
1914    /**
1915    @see TransactionController#openSortScan
1916    @exception StandardException Standard error policy.
1917    **/

1918    public ScanController openSortScan(
1919    long id,
1920    boolean hold)
1921        throws StandardException
1922    {
1923        Sort sort;
1924
1925        // Find the sort in the sorts list, throw an error
1926
// if it doesn't exist.
1927
if (sorts == null || id >= sorts.size()
1928            || (sort = ((Sort) sorts.elementAt((int) id))) == null)
1929        {
1930            throw StandardException.newException(
1931                    SQLState.AM_NO_SUCH_SORT, new Long JavaDoc(id));
1932        }
1933
1934        // Open a scan on it.
1935
ScanController sc = sort.openSortScan(this, hold);
1936
1937        // Keep track of it so we can release on close.
1938
scanControllers.addElement(sc);
1939
1940        return sc;
1941    }
1942
1943    /**
1944    @see TransactionController#openSortRowSource
1945    @exception StandardException Standard error policy.
1946    **/

1947    public RowLocationRetRowSource openSortRowSource(long id)
1948         throws StandardException
1949    {
1950        Sort sort;
1951
1952        // Find the sort in the sorts list, throw an error
1953
// if it doesn't exist.
1954
if (sorts == null || id >= sorts.size()
1955            || (sort = ((Sort) sorts.elementAt((int) id))) == null)
1956        {
1957            throw StandardException.newException(
1958                    SQLState.AM_NO_SUCH_SORT, new Long JavaDoc(id));
1959        }
1960
1961        // Open a scan row source on it.
1962
ScanControllerRowSource sc = sort.openSortRowSource(this);
1963
1964        // Keep track of it so we can release on close.
1965
scanControllers.addElement(sc);
1966
1967        return sc;
1968    }
1969
1970
1971    public void commit()
1972        throws StandardException
1973    {
1974        this.closeControllers(false /* don't close held controllers */ );
1975
1976        rawtran.commit();
1977
1978        alterTableCallMade = false;
1979
1980        return;
1981    }
1982
1983    public DatabaseInstant commitNoSync(int commitflag)
1984        throws StandardException
1985    {
1986        this.closeControllers(false /* don't close held controllers */ );
1987        return rawtran.commitNoSync(commitflag);
1988    }
1989
1990    public void abort()
1991        throws StandardException
1992    {
1993    
1994        if (alterTableCallMade)
1995        {
1996            accessmanager.conglomCacheInvalidate();
1997            alterTableCallMade = false;
1998        }
1999        this.closeControllers(true /* close all controllers */ );
2000        rawtran.abort();
2001
2002        if (parent_tran != null)
2003            parent_tran.abort();
2004    }
2005
2006    /**
2007     * Get the context manager that the transaction was created with.
2008     * <p>
2009     *
2010     * @return The context manager that the transaction was created with.
2011     * **/

2012    public ContextManager getContextManager()
2013    {
2014        return(context.getContextManager());
2015    }
2016
2017    public int setSavePoint(String JavaDoc name, Object JavaDoc kindOfSavepoint)
2018        throws StandardException
2019    {
2020        return rawtran.setSavePoint(name, kindOfSavepoint);
2021    }
2022
2023    public int releaseSavePoint(String JavaDoc name, Object JavaDoc kindOfSavepoint)
2024        throws StandardException
2025    {
2026        return rawtran.releaseSavePoint(name, kindOfSavepoint);
2027    }
2028
2029    public int rollbackToSavePoint(String JavaDoc name, boolean close_controllers, Object JavaDoc kindOfSavepoint)
2030        throws StandardException
2031    {
2032        if (close_controllers)
2033            this.closeControllers(true /* close all controllers */ );
2034        return rawtran.rollbackToSavePoint(name, kindOfSavepoint);
2035    }
2036
2037    public void destroy()
2038    {
2039        try
2040        {
2041            this.closeControllers(true /* close all controllers */);
2042            
2043            // If there's a transaction, abort it.
2044
if (rawtran != null) {
2045                rawtran.destroy();
2046                rawtran = null;
2047            }
2048            
2049
2050            // If there's a context, pop it.
2051
if (context != null)
2052                context.popMe();
2053            context = null;
2054
2055            accessmanager = null;
2056            tempCongloms = null;
2057        }
2058        catch (StandardException e)
2059        {
2060            // XXX (nat) really need to figure out what to do
2061
// if there's an exception while aborting.
2062
rawtran = null;
2063            context = null;
2064            accessmanager = null;
2065            tempCongloms = null;
2066        }
2067    }
2068
2069    public boolean anyoneBlocked()
2070    {
2071        return rawtran.anyoneBlocked();
2072    }
2073
2074    /**************************************************************************
2075     * Public Methods implementing the XATransactionController interface.
2076     **************************************************************************
2077     */

2078
2079    /**
2080     * This method is called to commit the current XA global transaction.
2081     * <p>
2082     * RESOLVE - how do we map to the "right" XAExceptions.
2083     * <p>
2084     *
2085     * @param onePhase If true, the resource manager should use a one-phase
2086     * commit protocol to commit the work done on behalf of
2087     * current xid.
2088     *
2089     * @exception StandardException Standard exception policy.
2090     **/

2091    public void xa_commit(
2092    boolean onePhase)
2093        throws StandardException
2094    {
2095        rawtran.xa_commit(onePhase);
2096    }
2097
2098    /**
2099     * This method is called to ask the resource manager to prepare for
2100     * a transaction commit of the transaction specified in xid.
2101     * <p>
2102     *
2103     * @return A value indicating the resource manager's vote on the
2104     * the outcome of the transaction. The possible values
2105     * are: XA_RDONLY or XA_OK. If the resource manager wants
2106     * to roll back the transaction, it should do so by
2107     * throwing an appropriate XAException in the prepare
2108     * method.
2109     *
2110     * @exception StandardException Standard exception policy.
2111     **/

2112    public int xa_prepare()
2113        throws StandardException
2114    {
2115        return(rawtran.xa_prepare());
2116    }
2117
2118    /**
2119     * rollback the current global transaction.
2120     * <p>
2121     * The given transaction is roll'ed back and it's history is not
2122     * maintained in the transaction table or long term log.
2123     * <p>
2124     *
2125     * @exception StandardException Standard exception policy.
2126     **/

2127    public void xa_rollback()
2128        throws StandardException
2129    {
2130        rawtran.xa_rollback();
2131    }
2132
2133    /**************************************************************************
2134     * Public Methods of TransactionManager interface:
2135     **************************************************************************
2136     */

2137
2138    /**
2139     * Add to the list of post commit work.
2140     * <p>
2141     * Add to the list of post commit work that may be processed after this
2142     * transaction commits. If this transaction aborts, then the post commit
2143     * work list will be thrown away. No post commit work will be taken out
2144     * on a rollback to save point.
2145     * <p>
2146     * This routine simply delegates the work to the Rawstore transaction.
2147     *
2148     * @param work The post commit work to do.
2149     *
2150     **/

2151    public void addPostCommitWork(Serviceable work)
2152    {
2153        rawtran.addPostCommitWork(work);
2154
2155        return;
2156    }
2157
2158    /**
2159     * The ConglomerateController.close() method has been called on
2160     * "conglom_control".
2161     * <p>
2162     * Take whatever cleanup action is appropriate to a closed
2163     * conglomerateController. It is likely this routine will remove
2164     * references to the ConglomerateController object that it was maintaining
2165     * for cleanup purposes.
2166     *
2167     **/

2168    public void closeMe(ConglomerateController conglom_control)
2169    {
2170        conglomerateControllers.removeElement(conglom_control);
2171    }
2172
2173    /**
2174     * The SortController.close() method has been called on "sort_control".
2175     * <p>
2176     * Take whatever cleanup action is appropriate to a closed
2177     * sortController. It is likely this routine will remove
2178     * references to the SortController object that it was maintaining
2179     * for cleanup purposes.
2180     **/

2181    public void closeMe(SortController sort_control)
2182    {
2183        sortControllers.removeElement(sort_control);
2184    }
2185
2186    /**
2187     * The ScanManager.close() method has been called on "scan".
2188     * <p>
2189     * Take whatever cleanup action is appropriate to a closed scan. It is
2190     * likely this routine will remove references to the scan object that it
2191     * was maintaining for cleanup purposes.
2192     *
2193     **/

2194    public void closeMe(ScanManager scan)
2195    {
2196        scanControllers.removeElement(scan);
2197    }
2198
2199    /**
2200     * Get reference to access factory which started this transaction.
2201     * <p>
2202     *
2203     * @return The AccessFactory which started this transaction.
2204     *
2205     **/

2206    public AccessFactory getAccessManager()
2207    {
2208        return(accessmanager);
2209    }
2210
2211    /**
2212     * Get an Internal transaction.
2213     * <p>
2214     * Start an internal transaction. An internal transaction is a completely
2215     * separate transaction from the current user transaction. All work done
2216     * in the internal transaction must be physical (ie. it can be undone
2217     * physically by the rawstore at the page level, rather than logically
2218     * undone like btree insert/delete operations). The rawstore guarantee's
2219     * that in the case of a system failure all open Internal transactions are
2220     * first undone in reverse order, and then other transactions are undone
2221     * in reverse order.
2222     * <p>
2223     * Internal transactions are meant to implement operations which, if
2224     * interupted before completion will cause logical operations like tree
2225     * searches to fail. This special undo order insures that the state of
2226     * the tree is restored to a consistent state before any logical undo
2227     * operation which may need to search the tree is performed.
2228     * <p>
2229     *
2230     * @return The new internal transaction.
2231     *
2232     * @exception StandardException Standard exception policy.
2233     **/

2234    public TransactionManager getInternalTransaction()
2235        throws StandardException
2236    {
2237        // Get the context manager.
2238
ContextManager cm = getContextManager();
2239
2240        // Allocate a new transaction no matter what.
2241

2242        // Create a transaction, make a context for it, and push the context.
2243
// Note this puts the raw store transaction context
2244
// above the access context, which is required for
2245
// error handling assumptions to be correct.
2246

2247        Transaction rawtran =
2248            accessmanager.getRawStore().startInternalTransaction(cm);
2249        RAMTransaction rt = new RAMTransaction(accessmanager, rawtran, null);
2250        RAMTransactionContext rtc =
2251            new RAMTransactionContext(
2252                cm, AccessFactoryGlobals.RAMXACT_INTERNAL_CONTEXT_ID,
2253                rt, true /*abortAll */);
2254
2255        rawtran.setDefaultLockingPolicy(
2256                accessmanager.getDefaultLockingPolicy());
2257
2258        return(rt);
2259    }
2260
2261    /**
2262     * Get an nested user transaction.
2263     * <p>
2264     * A nested user can be used exactly as any other TransactionController,
2265     * except as follows. For this discussion let the parent transaction
2266     * be the transaction used to make the getNestedUserTransaction(), and
2267     * let the child transaction be the transaction returned by the
2268     * getNestedUserTransaction() call.
2269     * <p>
2270     * The nesting is limited to one level deep. An exception will be thrown
2271     * if a subsequent getNestedUserTransaction() is called on the child
2272     * transaction.
2273     * <p>
2274     * The locks in the child transaction will be compatible with the locks
2275     * of the parent transaction.
2276     * <p>
2277     * A commit in the child transaction will release locks associated with
2278     * the child transaction only, work can continue in the parent transaction
2279     * at this point.
2280     * <p>
2281     * Any abort of the child transaction will result in an abort of both
2282     * the child transaction and parent transaction.
2283     * <p>
2284     * A TransactionController.destroy() call should be made on the child
2285     * transaction once all child work is done, and the caller wishes to
2286     * continue work in the parent transaction.
2287     * <p>
2288     * Nested internal transactions are meant to be used to implement
2289     * system work necessary to commit as part of implementing a user's
2290     * request, but where holding the lock for the duration of the user
2291     * transaction is not acceptable. 2 examples of this are system catalog
2292     * read locks accumulated while compiling a plan, and auto-increment.
2293     * <p>
2294     *
2295     * @return The new nested user transaction.
2296     *
2297     * @exception StandardException Standard exception policy.
2298     **/

2299    public TransactionController startNestedUserTransaction(boolean readOnly)
2300        throws StandardException
2301    {
2302        // Get the context manager.
2303
ContextManager cm = getContextManager();
2304
2305        // Allocate a new transaction no matter what.
2306

2307        // Create a transaction, make a context for it, and push the context.
2308
// Note this puts the raw store transaction context
2309
// above the access context, which is required for
2310
// error handling assumptions to be correct.
2311
//
2312
// Note that the compatibility space for the nested transaction
2313
// is "this", thus the new transaction shares the compatibility space
2314
// of the current transaction.
2315

2316
2317        Transaction child_rawtran =
2318            ((readOnly) ?
2319                accessmanager.getRawStore().startNestedReadOnlyUserTransaction(
2320                    this.getLockObject(), cm,
2321                    AccessFactoryGlobals.NESTED_READONLY_USER_TRANS) :
2322                accessmanager.getRawStore().startNestedUpdateUserTransaction(
2323                    cm, AccessFactoryGlobals.NESTED_UPDATE_USER_TRANS));
2324
2325        RAMTransaction rt =
2326            new RAMTransaction(accessmanager, child_rawtran, this);
2327
2328        RAMTransactionContext rtc =
2329            new RAMTransactionContext(
2330                cm,
2331                AccessFactoryGlobals.RAMXACT_CHILD_CONTEXT_ID,
2332                rt, true /*abortAll */);
2333
2334        child_rawtran.setDefaultLockingPolicy(
2335                accessmanager.getDefaultLockingPolicy());
2336
2337        /*
2338        System.out.println("returning nested xact: " + rt +
2339                "child_rawtran = " + child_rawtran);
2340                */

2341
2342        return(rt);
2343    }
2344
2345    /**
2346     * Get the Transaction from the Transaction manager.
2347     * <p>
2348     * Access methods often need direct access to the "Transaction" - ie. the
2349     * raw store transaction, so give access to it.
2350     *
2351     * @return The raw store transaction.
2352     *
2353     **/

2354    public Transaction getRawStoreXact()
2355    {
2356        return(rawtran);
2357    }
2358
2359
2360    /**
2361     * Do work necessary to maintain the current position in all the scans.
2362     * <p>
2363     * The latched page in the conglomerate "congomid" is changing, do
2364     * whatever is necessary to maintain the current position of all the
2365     * scans open in this transaction.
2366     * <p>
2367     * For some conglomerates this may be a no-op.
2368     * <p>
2369     *
2370     * @param conglom Conglomerate being changed.
2371     * @param page Page in the conglomerate being changed.
2372     *
2373     * @exception StandardException Standard exception policy.
2374     **/

2375    public void saveScanPositions(Conglomerate conglom, Page page)
2376        throws StandardException
2377    {
2378        Enumeration JavaDoc e = scanControllers.elements();
2379        while (e.hasMoreElements())
2380        {
2381            Object JavaDoc o = e.nextElement();
2382
2383            if (SanityManager.DEBUG)
2384            {
2385                // The following debugging code is here because the following
2386
// (ScanManager) cast is occasionally causing a
2387
// java.lang.ClassCastException.
2388

2389                if (!(o instanceof ScanManager))
2390                {
2391                    HeaderPrintWriter istream = Monitor.getStream();
2392                    
2393                    if (o == null)
2394                        istream.println("next element was null\n");
2395                    else
2396                        istream.println("non ScanManager on list: " + o);
2397
2398                    istream.println(
2399                        "Current list of open scans: " + debugOpened());
2400                }
2401            }
2402            ScanManager sm = (ScanManager) o;
2403            sm.savePosition(conglom, page);
2404        }
2405    }
2406
2407    public FileResource getFileHandler() {
2408        return rawtran.getFileHandler();
2409    }
2410
2411    /**
2412        Return an object that when used as the compatability space *and*
2413        group for a lock request, guarantees that the lock will be removed
2414        on a commit or an abort.
2415    */

2416    public Object JavaDoc getLockObject()
2417    {
2418        return rawtran.getCompatibilitySpace();
2419    }
2420
2421    /**
2422     * Get string id of the transaction.
2423     * <p>
2424     * This transaction "name" will be the same id which is returned in
2425     * the TransactionInfo information, used by the lock and transaction
2426     * vti's to identify transactions.
2427     * <p>
2428     * Although implementation specific, the transaction id is usually a number
2429     * which is bumped every time a commit or abort is issued.
2430     * <p>
2431     * For now return the toString() method, which does what we want. Later
2432     * if that is not good enough we can add public raw tran interfaces to
2433     * get exactly what we want.
2434     *
2435     * @return The a string which identifies the transaction.
2436     **/

2437    public String JavaDoc getTransactionIdString()
2438    {
2439        return(rawtran.toString());
2440    }
2441
2442
2443    /**
2444     * Get string id of the transaction that would be when the Transaction
2445     * is IN active state.
2446     **/

2447    public String JavaDoc getActiveStateTxIdString()
2448    {
2449        return(rawtran.getActiveStateTxIdString());
2450    }
2451
2452
2453    public String JavaDoc toString()
2454    {
2455        String JavaDoc str = null;
2456
2457        if (SanityManager.DEBUG)
2458        {
2459            str = "rawtran = " + rawtran;
2460        }
2461        return(str);
2462    }
2463}
2464
Popular Tags