0001: /*
0002:
0003: Derby - Class org.apache.derby.impl.store.access.RAMTransaction
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to you under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derby.impl.store.access;
0023:
0024: import java.util.ArrayList;
0025: import java.util.Enumeration;
0026: import java.util.Hashtable;
0027: import java.util.Properties;
0028: import java.util.Vector;
0029:
0030: import org.apache.derby.iapi.reference.SQLState;
0031: import org.apache.derby.iapi.util.ReuseFactory;
0032:
0033: import org.apache.derby.iapi.services.context.ContextManager;
0034:
0035: import org.apache.derby.iapi.services.io.Storable;
0036:
0037: import org.apache.derby.iapi.services.daemon.Serviceable;
0038: import org.apache.derby.iapi.services.monitor.Monitor;
0039: import org.apache.derby.iapi.services.sanity.SanityManager;
0040: import org.apache.derby.iapi.error.StandardException;
0041: import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;
0042: import org.apache.derby.iapi.store.access.conglomerate.ConglomerateFactory;
0043: import org.apache.derby.iapi.store.access.conglomerate.ScanManager;
0044: import org.apache.derby.iapi.store.access.conglomerate.MethodFactory;
0045: import org.apache.derby.iapi.store.access.conglomerate.ScanControllerRowSource;
0046: import org.apache.derby.iapi.store.access.conglomerate.Sort;
0047: import org.apache.derby.iapi.store.access.conglomerate.SortFactory;
0048: import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
0049: import org.apache.derby.iapi.store.access.AccessFactory;
0050: import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
0051: import org.apache.derby.iapi.store.access.ColumnOrdering;
0052: import org.apache.derby.iapi.store.access.ConglomerateController;
0053: import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
0054: import org.apache.derby.iapi.store.access.FileResource;
0055: import org.apache.derby.iapi.store.access.GroupFetchScanController;
0056: import org.apache.derby.iapi.store.access.Qualifier;
0057: import org.apache.derby.iapi.store.access.RowLocationRetRowSource;
0058: import org.apache.derby.iapi.store.access.RowSource;
0059: import org.apache.derby.iapi.store.access.ScanController;
0060: import org.apache.derby.iapi.store.access.SortController;
0061: import org.apache.derby.iapi.store.access.SortCostController;
0062: import org.apache.derby.iapi.store.access.SortObserver;
0063: import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
0064: import org.apache.derby.iapi.store.access.StoreCostController;
0065: import org.apache.derby.iapi.store.access.TransactionController;
0066:
0067: import org.apache.derby.iapi.store.access.XATransactionController;
0068:
0069: import org.apache.derby.iapi.store.raw.ContainerHandle;
0070: import org.apache.derby.iapi.store.raw.LockingPolicy;
0071:
0072: import org.apache.derby.iapi.store.raw.Loggable;
0073: import org.apache.derby.iapi.store.raw.Page;
0074: import org.apache.derby.iapi.store.raw.Transaction;
0075:
0076: import org.apache.derby.iapi.types.DataValueDescriptor;
0077:
0078: import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil;
0079:
0080: import org.apache.derby.iapi.store.access.DatabaseInstant;
0081:
0082: import org.apache.derby.iapi.store.access.BackingStoreHashtable;
0083: import org.apache.derby.iapi.services.io.FormatableBitSet;
0084:
0085: import java.io.Serializable;
0086:
0087: // debugging
0088: import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
0089: import org.apache.derby.iapi.services.stream.InfoStreams;
0090:
0091: public class RAMTransaction implements XATransactionController,
0092: TransactionManager {
0093:
0094: /**
0095: The corresponding raw store transaction.
0096: **/
0097: protected Transaction rawtran;
0098:
0099: /**
0100: The access manager this transaction is under.
0101: **/
0102: protected RAMAccessManager accessmanager;
0103:
0104: /**
0105: The context this transaction is being managed by.
0106: **/
0107: protected RAMTransactionContext context;
0108:
0109: /**
0110: The parent transaction if this is a nested user transaction.
0111: **/
0112: protected RAMTransaction parent_tran;
0113:
0114: // XXX (nat) management of the controllers is still embryonic.
0115: // XXX (nat) would be nice if sort controllers were like conglom controllers
0116: private Vector scanControllers;
0117: private Vector conglomerateControllers;
0118: private Vector sorts;
0119: private Vector sortControllers;
0120:
0121: /** List of sort identifiers (represented as <code>Integer</code> objects)
0122: * which can be reused. Since sort identifiers are used as array indexes,
0123: * we need to reuse them to avoid leaking memory (DERBY-912). */
0124: private ArrayList freeSortIds;
0125:
0126: /**
0127: Where to look for temporary conglomerates.
0128: **/
0129: protected Hashtable tempCongloms = null;
0130:
0131: /**
0132: Next id to use for a temporary conglomerate.
0133: **/
0134: private long nextTempConglomId = -1;
0135:
0136: /**
0137: * Set by alter table to indicate that the conglomerate cache needs to
0138: * be invalidated if a transaction aborting error is encountered, cleared
0139: * after cleanup.
0140: */
0141: private boolean alterTableCallMade = false;
0142:
0143: /**
0144: * The lock level of the transaction.
0145: * <p>
0146: * Cannot lock a level lower than the getSystemLockLevel(). So if
0147: * getSystemLockLevel() is table level locking, setting the transaction
0148: * locking level to record has no effect.
0149: **/
0150: private int transaction_lock_level;
0151:
0152: /**************************************************************************
0153: * Constructors for This class:
0154: **************************************************************************
0155: */
0156:
0157: private final void init(RAMAccessManager myaccessmanager,
0158: Transaction theRawTran, RAMTransaction parent_tran) {
0159: this .rawtran = theRawTran;
0160: this .parent_tran = parent_tran;
0161: accessmanager = myaccessmanager;
0162: scanControllers = new Vector();
0163: conglomerateControllers = new Vector();
0164:
0165: sorts = null; // allocated on demand.
0166: freeSortIds = null; // allocated on demand.
0167: sortControllers = null; // allocated on demand
0168:
0169: if (parent_tran != null) {
0170: // allow nested transactions to see temporary conglomerates which
0171: // were created in the parent transaction. This is necessary for
0172: // language which compiling plans in nested transactions against
0173: // user temporaries created in parent transactions.
0174:
0175: tempCongloms = parent_tran.tempCongloms;
0176: } else {
0177: tempCongloms = null; // allocated on demand
0178: }
0179: }
0180:
0181: protected RAMTransaction(RAMAccessManager myaccessmanager,
0182: Transaction theRawTran, RAMTransaction parent_transaction)
0183: throws StandardException {
0184: init(myaccessmanager, theRawTran, parent_transaction);
0185: }
0186:
0187: RAMTransaction(RAMAccessManager myaccessmanager, RAMTransaction tc,
0188: int format_id, byte[] global_id, byte[] branch_id)
0189: throws StandardException {
0190: init(myaccessmanager, tc.getRawStoreXact(), null);
0191:
0192: if (SanityManager.DEBUG)
0193: SanityManager.ASSERT(tc.getRawStoreXact().isIdle());
0194:
0195: this .context = tc.context;
0196:
0197: // switch the transaction pointer in the context to point to this xact
0198: this .context.setTransaction(this );
0199:
0200: this .rawtran.createXATransactionFromLocalTransaction(format_id,
0201: global_id, branch_id);
0202:
0203: // invalidate old tc, so caller does not use it. Can't just call
0204: // destroy as that screws up the contexts which we want to just leave
0205: // alone.
0206: tc.rawtran = null;
0207: }
0208:
0209: RAMTransaction() {
0210: }
0211:
0212: /**************************************************************************
0213: * Private/Protected methods of This class:
0214: **************************************************************************
0215: */
0216:
0217: // XXX (nat) currently closes all controllers.
0218: protected void closeControllers(boolean closeHeldControllers)
0219: throws StandardException {
0220: Enumeration e;
0221:
0222: if (!scanControllers.isEmpty()) {
0223: // loop from end to beginning, removing scans which are not held.
0224: for (int i = scanControllers.size() - 1; i >= 0; i--) {
0225: ScanManager sc = (ScanManager) scanControllers
0226: .elementAt(i);
0227:
0228: if (sc.closeForEndTransaction(closeHeldControllers)) {
0229: // TODO - now counting on scan's removing themselves by
0230: // calling the closeMe() method.
0231: /* scanControllers.removeElementAt(i); */
0232: }
0233: }
0234:
0235: if (closeHeldControllers) {
0236: if (SanityManager.DEBUG) {
0237: SanityManager.ASSERT(scanControllers.isEmpty());
0238: }
0239: // just to make sure everything has been closed and removed.
0240: scanControllers.removeAllElements();
0241: }
0242: }
0243:
0244: if (!conglomerateControllers.isEmpty()) {
0245: // loop from end to beginning, removing scans which are not held.
0246: for (int i = conglomerateControllers.size() - 1; i >= 0; i--) {
0247: ConglomerateController cc = (ConglomerateController) conglomerateControllers
0248: .elementAt(i);
0249:
0250: if (cc.closeForEndTransaction(closeHeldControllers)) {
0251: // TODO - now counting on cc's removing themselves by
0252: // calling the closeMe() method.
0253: /* conglomerateControllers.removeElementAt(i); */
0254: }
0255: }
0256:
0257: if (closeHeldControllers) {
0258: if (SanityManager.DEBUG) {
0259: SanityManager.ASSERT(scanControllers.isEmpty());
0260: }
0261: // just to make sure everything has been closed and removed.
0262: conglomerateControllers.removeAllElements();
0263: }
0264: }
0265:
0266: if ((sortControllers != null) && !sortControllers.isEmpty()) {
0267: if (closeHeldControllers) {
0268: e = sortControllers.elements();
0269: while (e.hasMoreElements()) {
0270: SortController sc = (SortController) e
0271: .nextElement();
0272: sc.close();
0273: }
0274: sortControllers.removeAllElements();
0275: }
0276: }
0277:
0278: if ((sorts != null) && (!sorts.isEmpty())) {
0279: if (closeHeldControllers) {
0280: e = sorts.elements();
0281: while (e.hasMoreElements()) {
0282: Sort sort = (Sort) e.nextElement();
0283: if (sort != null)
0284: sort.drop(this );
0285: }
0286: sorts.removeAllElements();
0287: freeSortIds.clear();
0288: }
0289: }
0290: }
0291:
0292: /**
0293: * Determine correct locking policy for a conglomerate open.
0294: * <p>
0295: * Determine from the following table whether to table or record lock
0296: * the conglomerate we are opening.
0297: * <p>
0298: *
0299: *
0300: * System level override
0301: * -------------------------------
0302: * user requests table locking record locking
0303: * ------------- ------------- --------------
0304: * TransactionController.MODE_TABLE TABLE TABLE
0305: * TransactionController.MODE_RECORD TABLE RECORD
0306: **/
0307: private LockingPolicy determine_locking_policy(
0308: int requested_lock_level, int isolation_level) {
0309: LockingPolicy ret_locking_policy;
0310:
0311: if ((accessmanager.getSystemLockLevel() == TransactionController.MODE_TABLE)
0312: || (requested_lock_level == TransactionController.MODE_TABLE)) {
0313: ret_locking_policy = accessmanager.table_level_policy[isolation_level];
0314: } else {
0315: ret_locking_policy = accessmanager.record_level_policy[isolation_level];
0316:
0317: }
0318: return (ret_locking_policy);
0319: }
0320:
0321: private int determine_lock_level(int requested_lock_level) {
0322: int ret_lock_level;
0323:
0324: if ((accessmanager.getSystemLockLevel() == TransactionController.MODE_TABLE)
0325: || (requested_lock_level == TransactionController.MODE_TABLE)) {
0326: ret_lock_level = TransactionController.MODE_TABLE;
0327: } else {
0328: ret_lock_level = TransactionController.MODE_RECORD;
0329:
0330: }
0331: return (ret_lock_level);
0332: }
0333:
0334: private Conglomerate findExistingConglomerate(long conglomId)
0335: throws StandardException {
0336: Conglomerate conglom = null;
0337:
0338: if (conglomId < 0) {
0339: if (tempCongloms != null)
0340: conglom = (Conglomerate) tempCongloms.get(new Long(
0341: conglomId));
0342: } else {
0343: conglom = accessmanager.conglomCacheFind(this , conglomId);
0344: }
0345:
0346: if (conglom == null) {
0347: throw StandardException.newException(
0348: SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST,
0349: new Long(conglomId));
0350: } else {
0351: return (conglom);
0352: }
0353: }
0354:
0355: private Conglomerate findConglomerate(long conglomId)
0356: throws StandardException {
0357: Conglomerate conglom = null;
0358:
0359: if (conglomId >= 0) {
0360: conglom = accessmanager.conglomCacheFind(this , conglomId);
0361: } else {
0362: if (tempCongloms != null)
0363: conglom = (Conglomerate) tempCongloms.get(new Long(
0364: conglomId));
0365: }
0366:
0367: return (conglom);
0368: }
0369:
0370: void setContext(RAMTransactionContext rtc) {
0371: context = rtc;
0372: }
0373:
0374: /**
0375: Get cache statistics for the specified cache
0376: */
0377: public long[] getCacheStats(String cacheName) {
0378: return getRawStoreXact().getCacheStats(cacheName);
0379: }
0380:
0381: private ConglomerateController openConglomerate(
0382: Conglomerate conglom, boolean hold, int open_mode,
0383: int lock_level, int isolation_level,
0384: StaticCompiledOpenConglomInfo static_info,
0385: DynamicCompiledOpenConglomInfo dynamic_info)
0386: throws StandardException {
0387: if (SanityManager.DEBUG) {
0388: if ((open_mode & ~(ContainerHandle.MODE_UNLOGGED
0389: | ContainerHandle.MODE_CREATE_UNLOGGED
0390: | ContainerHandle.MODE_FORUPDATE
0391: | ContainerHandle.MODE_READONLY
0392: | ContainerHandle.MODE_TRUNCATE_ON_COMMIT
0393: | ContainerHandle.MODE_DROP_ON_COMMIT
0394: | ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY
0395: | ContainerHandle.MODE_LOCK_NOWAIT
0396: | ContainerHandle.MODE_TRUNCATE_ON_ROLLBACK
0397: | ContainerHandle.MODE_FLUSH_ON_COMMIT
0398: | ContainerHandle.MODE_NO_ACTIONS_ON_COMMIT
0399: | ContainerHandle.MODE_TEMP_IS_KEPT
0400: | ContainerHandle.MODE_USE_UPDATE_LOCKS
0401: | ContainerHandle.MODE_SECONDARY_LOCKED | ContainerHandle.MODE_BASEROW_INSERT_LOCKED)) != 0) {
0402: SanityManager
0403: .THROWASSERT("Bad open mode to openConglomerate:"
0404: + Integer.toHexString(open_mode));
0405: }
0406:
0407: SanityManager.ASSERT(conglom != null);
0408:
0409: if (lock_level != MODE_RECORD && lock_level != MODE_TABLE) {
0410: SanityManager
0411: .THROWASSERT("Bad lock level to openConglomerate:"
0412: + lock_level);
0413: }
0414: }
0415:
0416: // Get a conglomerate controller.
0417: ConglomerateController cc = conglom.open(this , rawtran, hold,
0418: open_mode, determine_lock_level(lock_level),
0419: determine_locking_policy(lock_level, isolation_level),
0420: static_info, dynamic_info);
0421:
0422: // Keep track of it so we can release on close.
0423: conglomerateControllers.addElement(cc);
0424:
0425: return cc;
0426: }
0427:
0428: private ScanController openScan(Conglomerate conglom, boolean hold,
0429: int open_mode, int lock_level, int isolation_level,
0430: FormatableBitSet scanColumnList,
0431: DataValueDescriptor[] startKeyValue,
0432: int startSearchOperator, Qualifier qualifier[][],
0433: DataValueDescriptor[] stopKeyValue, int stopSearchOperator,
0434: StaticCompiledOpenConglomInfo static_info,
0435: DynamicCompiledOpenConglomInfo dynamic_info)
0436: throws StandardException {
0437: if (SanityManager.DEBUG) {
0438: if ((open_mode & ~(TransactionController.OPENMODE_FORUPDATE
0439: | TransactionController.OPENMODE_USE_UPDATE_LOCKS
0440: | TransactionController.OPENMODE_FOR_LOCK_ONLY
0441: | TransactionController.OPENMODE_LOCK_NOWAIT | TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0) {
0442: SanityManager.THROWASSERT("Bad open mode to openScan:"
0443: + Integer.toHexString(open_mode));
0444: }
0445:
0446: if (!((lock_level == MODE_RECORD | lock_level == MODE_TABLE))) {
0447: SanityManager.THROWASSERT("Bad lock level to openScan:"
0448: + lock_level);
0449: }
0450: }
0451:
0452: // Get a scan controller.
0453: ScanManager sm = conglom.openScan(this , rawtran, hold,
0454: open_mode, determine_lock_level(lock_level),
0455: determine_locking_policy(lock_level, isolation_level),
0456: isolation_level, scanColumnList, startKeyValue,
0457: startSearchOperator, qualifier, stopKeyValue,
0458: stopSearchOperator, static_info, dynamic_info);
0459:
0460: // Keep track of it so we can release on close.
0461: scanControllers.addElement(sm);
0462:
0463: return (sm);
0464: }
0465:
0466: /**
0467: Reset the cache statistics for the specified cache
0468: */
0469: public void resetCacheStats(String cacheName) {
0470: getRawStoreXact().resetCacheStats(cacheName);
0471: }
0472:
0473: /**
0474: * Invalidate the conglomerate cache, if necessary. If an alter table
0475: * call has been made then invalidate the cache.
0476: *
0477: * @exception StandardException Standard exception policy.
0478: **/
0479: protected void invalidateConglomerateCache()
0480: throws StandardException {
0481: if (alterTableCallMade) {
0482: accessmanager.conglomCacheInvalidate();
0483: alterTableCallMade = false;
0484: }
0485: }
0486:
0487: /**************************************************************************
0488: * Public Methods of TransactionController interface:
0489: **************************************************************************
0490: */
0491:
0492: /**
0493: Add a column to a conglomerate. The conglomerate must not be open in
0494: the current transaction. This also means that there must not be any
0495: active scans on it.
0496:
0497: The column can only be added at the spot just after the current set of
0498: columns.
0499:
0500: The template_column must be nullable.
0501:
0502: After this call has been made, all fetches of this column from rows that
0503: existed in the table prior to this call will return "null".
0504:
0505: @param conglomId The identifier of the conglomerate to drop.
0506: @param column_id The column number to add this column at.
0507: @param template_column An instance of the column to be added to table.
0508:
0509: @exception StandardException Only some types of conglomerates can support
0510: adding a column, for instance "heap" conglomerates support adding a
0511: column while "btree" conglomerates do not. If the column can not be
0512: added an exception will be thrown.
0513: **/
0514: public void addColumnToConglomerate(long conglomId, int column_id,
0515: Storable template_column) throws StandardException {
0516: boolean is_temporary = (conglomId < 0);
0517:
0518: Conglomerate conglom = findConglomerate(conglomId);
0519: if (conglom == null) {
0520: throw StandardException.newException(
0521: SQLState.AM_NO_SUCH_CONGLOMERATE_DROP, new Long(
0522: conglomId));
0523: }
0524:
0525: // Get exclusive lock on the table being altered.
0526: ConglomerateController cc = conglom
0527: .open(
0528: this ,
0529: rawtran,
0530: false,
0531: OPENMODE_FORUPDATE,
0532: MODE_TABLE,
0533: accessmanager.table_level_policy[TransactionController.ISOLATION_SERIALIZABLE],
0534: (StaticCompiledOpenConglomInfo) null,
0535: (DynamicCompiledOpenConglomInfo) null);
0536:
0537: conglom.addColumn(this , column_id, template_column);
0538:
0539: // remove the old entry in the Conglomerate directory, and add the
0540: // new one.
0541: if (is_temporary) {
0542: // remove old entry in the Conglomerate directory, and add new one
0543: if (tempCongloms != null)
0544: tempCongloms.remove(new Long(conglomId));
0545: tempCongloms.put(new Long(conglomId), conglom);
0546: } else {
0547: alterTableCallMade = true;
0548:
0549: // have access manager update the conglom to this new one.
0550: accessmanager.conglomCacheUpdateEntry(conglomId, conglom);
0551: }
0552:
0553: cc.close();
0554:
0555: return;
0556: }
0557:
0558: /**
0559: * Return static information about the conglomerate to be included in a
0560: * a compiled plan.
0561: * <p>
0562: * The static info would be valid until any ddl was executed on the
0563: * conglomid, and would be up to the caller to throw away when that
0564: * happened. This ties in with what language already does for other
0565: * invalidation of static info. The type of info in this would be
0566: * containerid and array of format id's from which templates can be created.
0567: * The info in this object is read only and can be shared among as many
0568: * threads as necessary.
0569: * <p>
0570: *
0571: * @return The static compiled information.
0572: *
0573: * @param conglomId The identifier of the conglomerate to open.
0574: *
0575: * @exception StandardException Standard exception policy.
0576: **/
0577: public StaticCompiledOpenConglomInfo getStaticCompiledConglomInfo(
0578: long conglomId) throws StandardException {
0579: return (findExistingConglomerate(conglomId)
0580: .getStaticCompiledConglomInfo(this , conglomId));
0581: }
0582:
0583: /**
0584: * Return dynamic information about the conglomerate to be dynamically
0585: * reused in repeated execution of a statement.
0586: * <p>
0587: * The dynamic info is a set of variables to be used in a given
0588: * ScanController or ConglomerateController. It can only be used in one
0589: * controller at a time. It is up to the caller to insure the correct
0590: * thread access to this info. The type of info in this is a scratch
0591: * template for btree traversal, other scratch variables for qualifier
0592: * evaluation, ...
0593: * <p>
0594: *
0595: * @return The dynamic information.
0596: *
0597: * @param conglomId The identifier of the conglomerate to open.
0598: *
0599: * @exception StandardException Standard exception policy.
0600: **/
0601: public DynamicCompiledOpenConglomInfo getDynamicCompiledConglomInfo(
0602: long conglomId) throws StandardException {
0603: return (findExistingConglomerate(conglomId)
0604: .getDynamicCompiledConglomInfo(conglomId));
0605: }
0606:
0607: private final int countCreatedSorts() {
0608: int ret_val = 0;
0609: if (sorts != null) {
0610: for (int i = 0; i < sorts.size(); i++) {
0611: if (sorts.elementAt(i) != null)
0612: ret_val++;
0613: }
0614: }
0615:
0616: return (ret_val);
0617: }
0618:
0619: /**
0620: * Report on the number of open conglomerates in the transaction.
0621: * <p>
0622: * There are 4 types of open "conglomerates" that can be tracked, those
0623: * opened by each of the following: openConglomerate(), openScan(),
0624: * openSort(), and openSortScan(). This routine can be used to either
0625: * report on the number of all opens, or may be used to track one
0626: * particular type of open.
0627: *
0628: * This routine is expected to be used for debugging only. An
0629: * implementation may only track this info under SanityManager.DEBUG mode.
0630: * If the implementation does not track the info it will return -1 (so
0631: * code using this call to verify that no congloms are open should check
0632: * for return <= 0 rather than == 0).
0633: *
0634: * The return value depends on the "which_to_count" parameter as follows:
0635: * OPEN_CONGLOMERATE - return # of openConglomerate() calls not close()'d.
0636: * OPEN_SCAN - return # of openScan() calls not close()'d.
0637: * OPEN_CREATED_SORTS - return # of sorts created (createSort()) in
0638: * current xact. There is currently no way to get
0639: * rid of these sorts before end of transaction.
0640: * OPEN_SORT - return # of openSort() calls not close()'d.
0641: * OPEN_TOTAL - return total # of all above calls not close()'d.
0642: * - note an implementation may return -1 if it does not track the
0643: * above information.
0644: *
0645: * @return The nunber of open's of a type indicated by "which_to_count"
0646: * parameter.
0647: *
0648: * @param which_to_count Which kind of open to report on.
0649: *
0650: * @exception StandardException Standard exception policy.
0651: **/
0652: public int countOpens(int which_to_count) throws StandardException {
0653: int ret_val = -1;
0654:
0655: switch (which_to_count) {
0656: case OPEN_CONGLOMERATE:
0657: ret_val = conglomerateControllers.size();
0658: break;
0659: case OPEN_SCAN:
0660: ret_val = scanControllers.size();
0661: break;
0662: case OPEN_CREATED_SORTS:
0663: ret_val = countCreatedSorts();
0664: break;
0665: case OPEN_SORT:
0666: ret_val = ((sortControllers != null) ? sortControllers
0667: .size() : 0);
0668: break;
0669: case OPEN_TOTAL:
0670: ret_val = conglomerateControllers.size()
0671: + scanControllers.size()
0672: + ((sortControllers != null) ? sortControllers
0673: .size() : 0) + countCreatedSorts();
0674: break;
0675: }
0676:
0677: return (ret_val);
0678: }
0679:
0680: /**
0681: * Create a new conglomerate.
0682: * <p>
0683: * @see TransactionController#createConglomerate
0684: *
0685: * @exception StandardException Standard exception policy.
0686: **/
0687: public long createConglomerate(String implementation,
0688: DataValueDescriptor[] template,
0689: ColumnOrdering[] columnOrder, Properties properties,
0690: int temporaryFlag) throws StandardException {
0691: // Find the appropriate factory for the desired implementation.
0692: MethodFactory mfactory;
0693: mfactory = accessmanager
0694: .findMethodFactoryByImpl(implementation);
0695: if (mfactory == null
0696: || !(mfactory instanceof ConglomerateFactory)) {
0697: throw StandardException.newException(
0698: SQLState.AM_NO_SUCH_CONGLOMERATE_TYPE,
0699: implementation);
0700: }
0701: ConglomerateFactory cfactory = (ConglomerateFactory) mfactory;
0702:
0703: // Create the conglomerate
0704: // RESOLVE (mikem) - eventually segmentid's will be passed into here
0705: // in the properties. For now just use 0.]
0706: int segment;
0707: long conglomid;
0708: if ((temporaryFlag & TransactionController.IS_TEMPORARY) == TransactionController.IS_TEMPORARY) {
0709: segment = ContainerHandle.TEMPORARY_SEGMENT;
0710: conglomid = ContainerHandle.DEFAULT_ASSIGN_ID;
0711: } else {
0712: segment = 0; // RESOLVE - only using segment 0
0713: conglomid = accessmanager.getNextConglomId(cfactory
0714: .getConglomerateFactoryId());
0715: }
0716:
0717: // call the factory to actually create the conglomerate.
0718: Conglomerate conglom = cfactory.createConglomerate(this ,
0719: segment, conglomid, template, columnOrder, properties,
0720: temporaryFlag);
0721:
0722: long conglomId;
0723: if ((temporaryFlag & TransactionController.IS_TEMPORARY) == TransactionController.IS_TEMPORARY) {
0724: conglomId = nextTempConglomId--;
0725: if (tempCongloms == null)
0726: tempCongloms = new Hashtable();
0727: tempCongloms.put(new Long(conglomId), conglom);
0728: } else {
0729: conglomId = conglom.getContainerid();
0730:
0731: accessmanager.conglomCacheAddEntry(conglomId, conglom);
0732: }
0733:
0734: return conglomId;
0735: }
0736:
0737: /**
0738: Create a conglomerate and populate it with rows from rowSource.
0739:
0740: @see TransactionController#createAndLoadConglomerate
0741: @exception StandardException Standard Cloudscape Error Policy
0742: */
0743: public long createAndLoadConglomerate(String implementation,
0744: DataValueDescriptor[] template,
0745: ColumnOrdering[] columnOrder, Properties properties,
0746: int temporaryFlag, RowLocationRetRowSource rowSource,
0747: long[] rowCount) throws StandardException {
0748: return (recreateAndLoadConglomerate(implementation, true,
0749: template, columnOrder, properties, temporaryFlag,
0750: 0 /* unused if recreate_ifempty is true */, rowSource,
0751: rowCount));
0752: }
0753:
0754: /**
0755: recreate a conglomerate and populate it with rows from rowSource.
0756:
0757: @see TransactionController#createAndLoadConglomerate
0758: @exception StandardException Standard Cloudscape Error Policy
0759: */
0760: public long recreateAndLoadConglomerate(String implementation,
0761: boolean recreate_ifempty, DataValueDescriptor[] template,
0762: ColumnOrdering[] columnOrder, Properties properties,
0763: int temporaryFlag, long orig_conglomId,
0764: RowLocationRetRowSource rowSource, long[] rowCount)
0765: throws StandardException
0766:
0767: {
0768: // RESOLVE: this create the conglom LOGGED, this is slower than
0769: // necessary although still correct.
0770: long conglomId = createConglomerate(implementation, template,
0771: columnOrder, properties, temporaryFlag);
0772:
0773: long rows_loaded = loadConglomerate(conglomId, true, // conglom is being created
0774: rowSource);
0775:
0776: if (rowCount != null)
0777: rowCount[0] = rows_loaded;
0778:
0779: if (!recreate_ifempty && (rows_loaded == 0)) {
0780: dropConglomerate(conglomId);
0781:
0782: conglomId = orig_conglomId;
0783: }
0784:
0785: return conglomId;
0786: }
0787:
0788: /**
0789: * Return a string with debug information about opened congloms/scans/sorts.
0790: * <p>
0791: * Return a string with debugging information about current opened
0792: * congloms/scans/sorts which have not been close()'d.
0793: * Calls to this routine are only valid under code which is conditional
0794: * on SanityManager.DEBUG.
0795: * <p>
0796: *
0797: * @return String with debugging information.
0798: *
0799: * @exception StandardException Standard exception policy.
0800: **/
0801: public String debugOpened() throws StandardException {
0802: String str = null;
0803:
0804: if (SanityManager.DEBUG) {
0805: Enumeration e;
0806:
0807: str = new String();
0808:
0809: e = scanControllers.elements();
0810: while (e.hasMoreElements()) {
0811: ScanController sc = (ScanController) e.nextElement();
0812: str += "open scan controller: " + sc + "\n";
0813: }
0814:
0815: e = conglomerateControllers.elements();
0816: while (e.hasMoreElements()) {
0817: ConglomerateController cc = (ConglomerateController) e
0818: .nextElement();
0819: str += "open conglomerate controller: " + cc + "\n";
0820: }
0821:
0822: if (sortControllers != null) {
0823: e = sortControllers.elements();
0824: while (e.hasMoreElements()) {
0825: SortController sc = (SortController) e
0826: .nextElement();
0827: str += "open sort controller: " + sc + "\n";
0828: }
0829: }
0830:
0831: if (sorts != null) {
0832: for (int i = 0; i < sorts.size(); i++) {
0833: Sort sort = (Sort) sorts.elementAt(i);
0834:
0835: if (sort != null) {
0836: str += "sorts created by createSort() in current xact:"
0837: + sort + "\n";
0838: }
0839: }
0840: }
0841:
0842: if (tempCongloms != null) {
0843: e = tempCongloms.keys();
0844: while (e.hasMoreElements()) {
0845: Long conglomId = (Long) e.nextElement();
0846: Conglomerate c = (Conglomerate) tempCongloms
0847: .get(conglomId);
0848: str += "temp conglomerate id = " + conglomId + ": "
0849: + c;
0850: }
0851: }
0852:
0853: }
0854:
0855: return (str);
0856: }
0857:
0858: public boolean conglomerateExists(long conglomId)
0859: throws StandardException {
0860: Conglomerate conglom = findConglomerate(conglomId);
0861: if (conglom == null)
0862: return false;
0863: return true;
0864: }
0865:
0866: public void dropConglomerate(long conglomId)
0867: throws StandardException {
0868: Conglomerate conglom = findExistingConglomerate(conglomId);
0869:
0870: conglom.drop(this );
0871:
0872: if (conglomId < 0) {
0873: if (tempCongloms != null)
0874: tempCongloms.remove(new Long(conglomId));
0875: } else {
0876: accessmanager.conglomCacheRemoveEntry(conglomId);
0877: }
0878: }
0879:
0880: /**
0881: * Retrieve the maximum value row in an ordered conglomerate.
0882: * <p>
0883: * Returns true and fetches the rightmost row of an ordered conglomerate
0884: * into "fetchRow" if there is at least one row in the conglomerate. If
0885: * there are no rows in the conglomerate it returns false.
0886: * <p>
0887: * Non-ordered conglomerates will not implement this interface, calls
0888: * will generate a StandardException.
0889: * <p>
0890: * RESOLVE - this interface is temporary, long term equivalent (and more)
0891: * functionality will be provided by the openBackwardScan() interface.
0892: *
0893: * @param conglomId The identifier of the conglomerate
0894: * to open the scan for.
0895: *
0896: * @param open_mode Specifiy flags to control opening of table.
0897: * OPENMODE_FORUPDATE - if set open the table for
0898: * update otherwise open table shared.
0899: * @param lock_level One of (MODE_TABLE, MODE_RECORD, or MODE_NONE).
0900: *
0901: * @param isolation_level The isolation level to lock the conglomerate at.
0902: * One of (ISOLATION_READ_COMMITTED or
0903: * ISOLATION_SERIALIZABLE).
0904: *
0905: * @param scanColumnList A description of which columns to return from
0906: * every fetch in the scan. template,
0907: * and scanColumnList work together
0908: * to describe the row to be returned by the scan -
0909: * see RowUtil for description of how these three
0910: * parameters work together to describe a "row".
0911: *
0912: * @param fetchRow The row to retrieve the maximum value into.
0913: *
0914: * @return boolean indicating if a row was found and retrieved or not.
0915: *
0916: * @exception StandardException Standard exception policy.
0917: **/
0918: public boolean fetchMaxOnBtree(long conglomId, int open_mode,
0919: int lock_level, int isolation_level,
0920: FormatableBitSet scanColumnList,
0921: DataValueDescriptor[] fetchRow) throws StandardException {
0922: // Find the conglomerate.
0923: Conglomerate conglom = findExistingConglomerate(conglomId);
0924:
0925: // Get a scan controller.
0926: return (conglom.fetchMaxOnBTree(this , rawtran, conglomId,
0927: open_mode, lock_level, determine_locking_policy(
0928: lock_level, isolation_level), isolation_level,
0929: scanColumnList, fetchRow));
0930: }
0931:
0932: /**
0933: * A superset of properties that "users" can specify.
0934: * <p>
0935: * A superset of properties that "users" (ie. from sql) can specify. Store
0936: * may implement other properties which should not be specified by users.
0937: * Layers above access may implement properties which are not known at
0938: * all to Access.
0939: * <p>
0940: * This list is a superset, as some properties may not be implemented by
0941: * certain types of conglomerates. For instant an in-memory store may not
0942: * implement a pageSize property. Or some conglomerates may not support
0943: * pre-allocation.
0944: * <p>
0945: * This interface is meant to be used by the SQL parser to do validation
0946: * of properties passsed to the create table statement, and also by the
0947: * various user interfaces which present table information back to the
0948: * user.
0949: * <p>
0950: * Currently this routine returns the following list:
0951: * derby.storage.initialPages
0952: * derby.storage.minimumRecordSize
0953: * derby.storage.pageReservedSpace
0954: * derby.storage.pageSize
0955: *
0956: * @return The superset of properties that "users" can specify.
0957: *
0958: **/
0959: public Properties getUserCreateConglomPropList() {
0960: Properties ret_properties = ConglomerateUtil
0961: .createUserRawStorePropertySet((Properties) null);
0962:
0963: return (ret_properties);
0964: }
0965:
0966: /**
0967: * Reveals whether the transaction has ever read or written data.
0968: *
0969: * @return true If the transaction has never read or written data.
0970: *
0971: **/
0972: public boolean isIdle() {
0973: return rawtran.isIdle();
0974: }
0975:
0976: /**
0977: * Reveals whether the transaction is a global or local transaction.
0978: *
0979: * @return true If the transaction was either started by
0980: * AccessFactory.startXATransaction() or was morphed to a global
0981: * transaction by calling
0982: * AccessFactory.createXATransactionFromLocalTransaction().
0983: *
0984: * @see AccessFactory#startXATransaction
0985: * @see TransactionController#createXATransactionFromLocalTransaction
0986: *
0987: **/
0988: public boolean isGlobal() {
0989: return (rawtran.getGlobalId() != null);
0990: }
0991:
0992: /**
0993: * Reveals whether the transaction is currently pristine.
0994: *
0995: * @return true If the transaction is Pristine.
0996: *
0997: * @see TransactionController#isPristine
0998: **/
0999: public boolean isPristine() {
1000: return rawtran.isPristine();
1001: }
1002:
1003: /**
1004: * Convert a local transaction to a global transaction.
1005: * <p>
1006: * Get a transaction controller with which to manipulate data within
1007: * the access manager. Tbis controller allows one to manipulate a
1008: * global XA conforming transaction.
1009: * <p>
1010: * Must only be called a previous local transaction was created and exists
1011: * in the context. Can only be called if the current transaction is in
1012: * the idle state. Upon return from this call the old tc will be unusable,
1013: * and all references to it should be dropped (it will have been implicitly
1014: * destroy()'d by this call.
1015: * <p>
1016: * The (format_id, global_id, branch_id) triplet is meant to come exactly
1017: * from a javax.transaction.xa.Xid. We don't use Xid so that the system
1018: * can be delivered on a non-1.2 vm system and not require the javax classes
1019: * in the path.
1020: *
1021: * @param format_id the format id part of the Xid - ie. Xid.getFormatId().
1022: * @param global_id the global transaction identifier part of XID - ie.
1023: * Xid.getGlobalTransactionId().
1024: * @param branch_id The branch qualifier of the Xid - ie.
1025: * Xid.getBranchQaulifier()
1026: *
1027: * @exception StandardException Standard exception policy.
1028: * @see TransactionController
1029: **/
1030: public/* XATransactionController */Object createXATransactionFromLocalTransaction(
1031: int format_id, byte[] global_id, byte[] branch_id)
1032: throws StandardException {
1033:
1034: getRawStoreXact().createXATransactionFromLocalTransaction(
1035: format_id, global_id, branch_id);
1036:
1037: return this ;
1038: }
1039:
1040: /**
1041: Bulk load into the conglomerate. Rows being loaded into the
1042: conglomerate are not logged.
1043:
1044: @param conglomId The conglomerate Id.
1045:
1046: @param createConglom If true, the conglomerate is being created in the
1047: same operation as the loadConglomerate. The enables further
1048: optimization as recovery does not require page allocation to be
1049: logged.
1050:
1051: @param rowSource Where the rows come from.
1052:
1053: @return true The number of rows loaded.
1054:
1055: @exception StandardException Standard Cloudscape Error Policy
1056: */
1057: public long loadConglomerate(long conglomId, boolean createConglom,
1058: RowLocationRetRowSource rowSource) throws StandardException {
1059: // Find the conglomerate.
1060: Conglomerate conglom = findExistingConglomerate(conglomId);
1061:
1062: // Load up the conglomerate with rows from the rowSource.
1063: // Don't need to keep track of the conglomerate controller because load
1064: // automatically closes it when it finished.
1065: return (conglom.load(this , createConglom, rowSource));
1066: }
1067:
1068: /**
1069: Use this for incremental load in the future.
1070:
1071: @param conglomId the conglomerate Id
1072: @param rowSource where the rows to be loaded comes from
1073:
1074: @exception StandardException Standard Cloudscape Error Policy
1075: */
1076: public void loadConglomerate(long conglomId,
1077: RowLocationRetRowSource rowSource) throws StandardException {
1078: loadConglomerate(conglomId, false, // conglomerate is not being created
1079: rowSource);
1080: }
1081:
1082: /**
1083: * Log an operation and then action it in the context of this transaction.
1084: * <p>
1085: * This simply passes the operation to the RawStore which logs and does it.
1086: * <p>
1087: *
1088: * @param operation the operation that is to be applied
1089: *
1090: * @exception StandardException Standard exception policy.
1091: **/
1092: public void logAndDo(Loggable operation) throws StandardException {
1093: rawtran.logAndDo(operation);
1094: }
1095:
1096: public ConglomerateController openCompiledConglomerate(
1097: boolean hold, int open_mode, int lock_level,
1098: int isolation_level,
1099: StaticCompiledOpenConglomInfo static_info,
1100: DynamicCompiledOpenConglomInfo dynamic_info)
1101: throws StandardException {
1102: if (SanityManager.DEBUG) {
1103: SanityManager.ASSERT(static_info != null);
1104: SanityManager.ASSERT(dynamic_info != null);
1105: }
1106:
1107: // in the current implementation, only Conglomerate's are passed around
1108: // as StaticCompiledOpenConglomInfo.
1109:
1110: return (openConglomerate((Conglomerate) static_info
1111: .getConglom(), hold, open_mode, lock_level,
1112: isolation_level, static_info, dynamic_info));
1113: }
1114:
1115: public ConglomerateController openConglomerate(long conglomId,
1116: boolean hold, int open_mode, int lock_level,
1117: int isolation_level) throws StandardException {
1118: return (openConglomerate(findExistingConglomerate(conglomId),
1119: hold, open_mode, lock_level, isolation_level,
1120: (StaticCompiledOpenConglomInfo) null,
1121: (DynamicCompiledOpenConglomInfo) null));
1122: }
1123:
1124: public long findConglomid(long container_id)
1125: throws StandardException {
1126: return (container_id);
1127: }
1128:
1129: public long findContainerid(long conglom_id)
1130: throws StandardException {
1131: return (conglom_id);
1132: }
1133:
1134: /**
1135: * Create a BackingStoreHashtable which contains all rows that qualify for
1136: * the described scan.
1137: **/
1138: public BackingStoreHashtable createBackingStoreHashtableFromScan(
1139: long conglomId, int open_mode, int lock_level,
1140: int isolation_level, FormatableBitSet scanColumnList,
1141: DataValueDescriptor[] startKeyValue,
1142: int startSearchOperator, Qualifier qualifier[][],
1143: DataValueDescriptor[] stopKeyValue, int stopSearchOperator,
1144: long max_rowcnt, int[] key_column_numbers,
1145: boolean remove_duplicates, long estimated_rowcnt,
1146: long max_inmemory_rowcnt, int initialCapacity,
1147: float loadFactor, boolean collect_runtimestats,
1148: boolean skipNullKeyColumns) throws StandardException {
1149: return (new BackingStoreHashTableFromScan(this , conglomId,
1150: open_mode, lock_level, isolation_level, scanColumnList,
1151: startKeyValue, startSearchOperator, qualifier,
1152: stopKeyValue, stopSearchOperator, max_rowcnt,
1153: key_column_numbers, remove_duplicates,
1154: estimated_rowcnt, max_inmemory_rowcnt, initialCapacity,
1155: loadFactor, collect_runtimestats, skipNullKeyColumns));
1156: }
1157:
1158: public GroupFetchScanController openGroupFetchScan(long conglomId,
1159: boolean hold, int open_mode, int lock_level,
1160: int isolation_level, FormatableBitSet scanColumnList,
1161: DataValueDescriptor[] startKeyValue,
1162: int startSearchOperator, Qualifier qualifier[][],
1163: DataValueDescriptor[] stopKeyValue, int stopSearchOperator)
1164: throws StandardException {
1165: if (SanityManager.DEBUG) {
1166: if ((open_mode & ~(TransactionController.OPENMODE_FORUPDATE
1167: | TransactionController.OPENMODE_FOR_LOCK_ONLY | TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0)
1168: SanityManager.THROWASSERT("Bad open mode to openScan:"
1169: + Integer.toHexString(open_mode));
1170:
1171: if (!(lock_level == MODE_RECORD | lock_level == MODE_TABLE))
1172: SanityManager.THROWASSERT("Bad lock level to openScan:"
1173: + lock_level);
1174: }
1175:
1176: // Find the conglomerate.
1177: Conglomerate conglom = findExistingConglomerate(conglomId);
1178:
1179: // Get a scan controller.
1180: ScanManager sm = conglom.openScan(this , rawtran, hold,
1181: open_mode, determine_lock_level(lock_level),
1182: determine_locking_policy(lock_level, isolation_level),
1183: isolation_level, scanColumnList, startKeyValue,
1184: startSearchOperator, qualifier, stopKeyValue,
1185: stopSearchOperator,
1186: (StaticCompiledOpenConglomInfo) null,
1187: (DynamicCompiledOpenConglomInfo) null);
1188:
1189: // Keep track of it so we can release on close.
1190: scanControllers.addElement(sm);
1191:
1192: return (sm);
1193: }
1194:
1195: /**
1196: * Purge all committed deleted rows from the conglomerate.
1197: * <p>
1198: * This call will purge committed deleted rows from the conglomerate,
1199: * that space will be available for future inserts into the conglomerate.
1200: * <p>
1201: *
1202: * @param conglomId Id of the conglomerate to purge.
1203: *
1204: * @exception StandardException Standard exception policy.
1205: **/
1206: public void purgeConglomerate(long conglomId)
1207: throws StandardException {
1208: findExistingConglomerate(conglomId).purgeConglomerate(this ,
1209: rawtran);
1210:
1211: return;
1212: }
1213:
1214: /**
1215: * Return free space from the conglomerate back to the OS.
1216: * <p>
1217: * Returns free space from the conglomerate back to the OS. Currently
1218: * only the sequential free pages at the "end" of the conglomerate can
1219: * be returned to the OS.
1220: * <p>
1221: *
1222: * @param conglomId Id of the conglomerate to purge.
1223: *
1224: * @exception StandardException Standard exception policy.
1225: **/
1226: public void compressConglomerate(long conglomId)
1227: throws StandardException {
1228: findExistingConglomerate(conglomId).compressConglomerate(this ,
1229: rawtran);
1230:
1231: return;
1232: }
1233:
1234: /**
1235: * Compress table in place.
1236: * <p>
1237: * Returns a GroupFetchScanController which can be used to move rows
1238: * around in a table, creating a block of free pages at the end of the
1239: * table. The process will move rows from the end of the table toward
1240: * the beginning. The GroupFetchScanController will return the
1241: * old row location, the new row location, and the actual data of any
1242: * row moved. Note that this scan only returns moved rows, not an
1243: * entire set of rows, the scan is designed specifically to be
1244: * used by either explicit user call of the SYSCS_ONLINE_COMPRESS_TABLE()
1245: * procedure, or internal background calls to compress the table.
1246: *
1247: * The old and new row locations are returned so that the caller can
1248: * update any indexes necessary.
1249: *
1250: * This scan always returns all collumns of the row.
1251: *
1252: * All inputs work exactly as in openScan(). The return is
1253: * a GroupFetchScanController, which only allows fetches of groups
1254: * of rows from the conglomerate.
1255: * <p>
1256: *
1257: * @return The GroupFetchScanController to be used to fetch the rows.
1258: *
1259: * @param conglomId see openScan()
1260: * @param hold see openScan()
1261: * @param open_mode see openScan()
1262: * @param lock_level see openScan()
1263: * @param isolation_level see openScan()
1264: *
1265: * @exception StandardException Standard exception policy.
1266: *
1267: * @see ScanController
1268: * @see GroupFetchScanController
1269: **/
1270: public GroupFetchScanController defragmentConglomerate(
1271: long conglomId, boolean online, boolean hold,
1272: int open_mode, int lock_level, int isolation_level)
1273: throws StandardException {
1274: if (SanityManager.DEBUG) {
1275: if ((open_mode & ~(TransactionController.OPENMODE_FORUPDATE
1276: | TransactionController.OPENMODE_FOR_LOCK_ONLY | TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0)
1277: SanityManager.THROWASSERT("Bad open mode to openScan:"
1278: + Integer.toHexString(open_mode));
1279:
1280: if (!(lock_level == MODE_RECORD | lock_level == MODE_TABLE))
1281: SanityManager.THROWASSERT("Bad lock level to openScan:"
1282: + lock_level);
1283: }
1284:
1285: // Find the conglomerate.
1286: Conglomerate conglom = findExistingConglomerate(conglomId);
1287:
1288: // Get a scan controller.
1289: ScanManager sm = conglom.defragmentConglomerate(this , rawtran,
1290: hold, open_mode, determine_lock_level(lock_level),
1291: determine_locking_policy(lock_level, isolation_level),
1292: isolation_level);
1293:
1294: // Keep track of it so we can release on close.
1295: scanControllers.addElement(sm);
1296:
1297: return (sm);
1298: }
1299:
1300: public ScanController openScan(long conglomId, boolean hold,
1301: int open_mode, int lock_level, int isolation_level,
1302: FormatableBitSet scanColumnList,
1303: DataValueDescriptor[] startKeyValue,
1304: int startSearchOperator, Qualifier qualifier[][],
1305: DataValueDescriptor[] stopKeyValue, int stopSearchOperator)
1306: throws StandardException {
1307: return (openScan(findExistingConglomerate(conglomId), hold,
1308: open_mode, lock_level, isolation_level, scanColumnList,
1309: startKeyValue, startSearchOperator, qualifier,
1310: stopKeyValue, stopSearchOperator,
1311: (StaticCompiledOpenConglomInfo) null,
1312: (DynamicCompiledOpenConglomInfo) null));
1313: }
1314:
1315: public ScanController openCompiledScan(boolean hold, int open_mode,
1316: int lock_level, int isolation_level,
1317: FormatableBitSet scanColumnList,
1318: DataValueDescriptor[] startKeyValue,
1319: int startSearchOperator, Qualifier qualifier[][],
1320: DataValueDescriptor[] stopKeyValue, int stopSearchOperator,
1321: StaticCompiledOpenConglomInfo static_info,
1322: DynamicCompiledOpenConglomInfo dynamic_info)
1323: throws StandardException {
1324: // in the current implementation, only Conglomerate's are passed around
1325: // as StaticCompiledOpenConglomInfo.
1326:
1327: if (SanityManager.DEBUG) {
1328: SanityManager.ASSERT(static_info != null);
1329: SanityManager.ASSERT(dynamic_info != null);
1330: SanityManager
1331: .ASSERT(static_info instanceof StaticCompiledOpenConglomInfo);
1332: SanityManager
1333: .ASSERT(dynamic_info instanceof DynamicCompiledOpenConglomInfo);
1334: }
1335:
1336: return (openScan(((Conglomerate) static_info.getConglom()),
1337: hold, open_mode, lock_level, isolation_level,
1338: scanColumnList, startKeyValue, startSearchOperator,
1339: qualifier, stopKeyValue, stopSearchOperator,
1340: static_info, dynamic_info));
1341: }
1342:
1343: /**
1344: * Return an open StoreCostController for the given conglomid.
1345: * <p>
1346: * Return an open StoreCostController which can be used to ask about
1347: * the estimated row counts and costs of ScanController and
1348: * ConglomerateController operations, on the given conglomerate.
1349: * <p>
1350: *
1351: * @return The open StoreCostController.
1352: *
1353: * @param conglomId The identifier of the conglomerate to open.
1354: *
1355: * @exception StandardException Standard exception policy.
1356: *
1357: * @see StoreCostController
1358: **/
1359: public StoreCostController openStoreCost(long conglomId)
1360: throws StandardException {
1361: // Find the conglomerate.
1362: Conglomerate conglom = findExistingConglomerate(conglomId);
1363:
1364: // Get a scan controller.
1365: StoreCostController scc = conglom.openStoreCost(this , rawtran);
1366:
1367: return (scc);
1368: }
1369:
1370: /**
1371: @see TransactionController#createSort
1372: @exception StandardException Standard error policy.
1373: **/
1374: public long createSort(Properties implParameters,
1375: DataValueDescriptor[] template,
1376: ColumnOrdering columnOrdering[], SortObserver sortObserver,
1377: boolean alreadyInOrder, long estimatedRows,
1378: int estimatedRowSize) throws StandardException {
1379: // Get the implementation type from the parameters.
1380: // XXX (nat) need to figure out how to select sort implementation.
1381: String implementation = null;
1382: if (implParameters != null)
1383: implementation = implParameters
1384: .getProperty(AccessFactoryGlobals.IMPL_TYPE);
1385:
1386: if (implementation == null)
1387: implementation = AccessFactoryGlobals.SORT_EXTERNAL;
1388:
1389: // Find the appropriate factory for the desired implementation.
1390: MethodFactory mfactory;
1391: mfactory = accessmanager
1392: .findMethodFactoryByImpl(implementation);
1393: if (mfactory == null || !(mfactory instanceof SortFactory)) {
1394: throw (StandardException.newException(
1395: SQLState.AM_NO_FACTORY_FOR_IMPLEMENTATION,
1396: implementation));
1397: }
1398: SortFactory sfactory = (SortFactory) mfactory;
1399:
1400: // Decide what segment the sort should use.
1401: int segment = 0; // XXX (nat) sorts always in segment 0
1402:
1403: // Create the sort.
1404: Sort sort = sfactory.createSort(this , segment, implParameters,
1405: template, columnOrdering, sortObserver, alreadyInOrder,
1406: estimatedRows, estimatedRowSize);
1407:
1408: // Add the sort to the sorts vector
1409: if (sorts == null) {
1410: sorts = new Vector();
1411: freeSortIds = new ArrayList();
1412: }
1413:
1414: int sortid;
1415: if (freeSortIds.isEmpty()) {
1416: // no free identifiers, add sort at the end
1417: sortid = sorts.size();
1418: sorts.addElement(sort);
1419: } else {
1420: // reuse a sort identifier
1421: sortid = ((Integer) freeSortIds
1422: .remove(freeSortIds.size() - 1)).intValue();
1423: sorts.setElementAt(sort, sortid);
1424: }
1425:
1426: return sortid;
1427: }
1428:
1429: /**
1430: Drop a sort.
1431: <p>
1432: Drop a sort created by a call to createSort() within the current
1433: transaction (sorts are automatically "dropped" at the end of a
1434: transaction. This call should only be made after all openSortScan()'s
1435: and openSort()'s have been closed.
1436: <p>
1437:
1438: @param sortid The identifier of the sort to drop, as returned from
1439: createSort.
1440: @exception StandardException From a lower-level exception.
1441: **/
1442: public void dropSort(long sortid) throws StandardException {
1443: // should call close on the sort.
1444: Sort sort = (Sort) sorts.elementAt((int) sortid);
1445:
1446: if (sort != null) {
1447: sort.drop(this );
1448: sorts.setElementAt(null, (int) sortid);
1449: freeSortIds.add(ReuseFactory.getInteger((int) sortid));
1450: }
1451: }
1452:
1453: /**
1454: @see TransactionController#getProperty
1455: @exception StandardException Standard exception policy.
1456: **/
1457: public Serializable getProperty(String key)
1458: throws StandardException {
1459: return (accessmanager.getTransactionalProperties().getProperty(
1460: this , key));
1461: }
1462:
1463: /**
1464: @see TransactionController#getPropertyDefault
1465: @exception StandardException Standard exception policy.
1466: **/
1467: public Serializable getPropertyDefault(String key)
1468: throws StandardException {
1469: return (accessmanager.getTransactionalProperties()
1470: .getPropertyDefault(this , key));
1471: }
1472:
1473: /**
1474: @see TransactionController#setProperty
1475: @exception StandardException Standard exception policy.
1476: **/
1477: public void setProperty(String key, Serializable value,
1478: boolean dbOnlyProperty) throws StandardException {
1479: accessmanager.getTransactionalProperties().setProperty(this ,
1480: key, value, dbOnlyProperty);
1481: }
1482:
1483: /**
1484: @see TransactionController#setProperty
1485: @exception StandardException Standard exception policy.
1486: **/
1487: public void setPropertyDefault(String key, Serializable value)
1488: throws StandardException {
1489: accessmanager.getTransactionalProperties().setPropertyDefault(
1490: this , key, value);
1491: }
1492:
1493: /**
1494: @see TransactionController#propertyDefaultIsVisible
1495: @exception StandardException Standard exception policy.
1496: **/
1497: public boolean propertyDefaultIsVisible(String key)
1498: throws StandardException {
1499: return accessmanager.getTransactionalProperties()
1500: .propertyDefaultIsVisible(this , key);
1501: }
1502:
1503: /**
1504: @see TransactionController#getProperties
1505: @exception StandardException Standard exception policy.
1506: **/
1507: public Properties getProperties() throws StandardException {
1508: return accessmanager.getTransactionalProperties()
1509: .getProperties(this );
1510: }
1511:
1512: /**
1513: @see TransactionController#openSort
1514: @exception StandardException Standard error policy.
1515: **/
1516: public SortController openSort(long id) throws StandardException {
1517: Sort sort;
1518:
1519: // Find the sort in the sorts list, throw an error
1520: // if it doesn't exist.
1521: if (sorts == null || id >= sorts.size()
1522: || (sort = ((Sort) sorts.elementAt((int) id))) == null) {
1523: throw StandardException.newException(
1524: SQLState.AM_NO_SUCH_SORT, new Long(id));
1525: }
1526:
1527: // Open it.
1528: SortController sc = sort.open(this );
1529:
1530: // Keep track of it so we can release on close.
1531: if (sortControllers == null)
1532: sortControllers = new Vector();
1533: sortControllers.addElement(sc);
1534:
1535: return sc;
1536: }
1537:
1538: /**
1539: * Return an open SortCostController.
1540: * <p>
1541: * Return an open SortCostController which can be used to ask about
1542: * the estimated costs of SortController() operations.
1543: * <p>
1544: *
1545: * @return The open StoreCostController.
1546: *
1547: * @exception StandardException Standard exception policy.
1548: *
1549: * @see StoreCostController
1550: **/
1551: public SortCostController openSortCostController(
1552: Properties implParameters) throws StandardException {
1553: // Get the implementation type from the parameters.
1554: // RESOLVE (mikem) need to figure out how to select sort implementation.
1555: String implementation = null;
1556:
1557: if (implementation == null)
1558: implementation = AccessFactoryGlobals.SORT_EXTERNAL;
1559:
1560: // Find the appropriate factory for the desired implementation.
1561: MethodFactory mfactory;
1562: mfactory = accessmanager
1563: .findMethodFactoryByImpl(implementation);
1564: if (mfactory == null || !(mfactory instanceof SortFactory)) {
1565: throw (StandardException.newException(
1566: SQLState.AM_NO_FACTORY_FOR_IMPLEMENTATION,
1567: implementation));
1568: }
1569: SortFactory sfactory = (SortFactory) mfactory;
1570:
1571: // open sort cost controller
1572: return (sfactory.openSortCostController());
1573: }
1574:
1575: /**
1576: @see TransactionController#openSortScan
1577: @exception StandardException Standard error policy.
1578: **/
1579: public ScanController openSortScan(long id, boolean hold)
1580: throws StandardException {
1581: Sort sort;
1582:
1583: // Find the sort in the sorts list, throw an error
1584: // if it doesn't exist.
1585: if (sorts == null || id >= sorts.size()
1586: || (sort = ((Sort) sorts.elementAt((int) id))) == null) {
1587: throw StandardException.newException(
1588: SQLState.AM_NO_SUCH_SORT, new Long(id));
1589: }
1590:
1591: // Open a scan on it.
1592: ScanController sc = sort.openSortScan(this , hold);
1593:
1594: // Keep track of it so we can release on close.
1595: scanControllers.addElement(sc);
1596:
1597: return sc;
1598: }
1599:
1600: /**
1601: @see TransactionController#openSortRowSource
1602: @exception StandardException Standard error policy.
1603: **/
1604: public RowLocationRetRowSource openSortRowSource(long id)
1605: throws StandardException {
1606: Sort sort;
1607:
1608: // Find the sort in the sorts list, throw an error
1609: // if it doesn't exist.
1610: if (sorts == null || id >= sorts.size()
1611: || (sort = ((Sort) sorts.elementAt((int) id))) == null) {
1612: throw StandardException.newException(
1613: SQLState.AM_NO_SUCH_SORT, new Long(id));
1614: }
1615:
1616: // Open a scan row source on it.
1617: ScanControllerRowSource sc = sort.openSortRowSource(this );
1618:
1619: // Keep track of it so we can release on close.
1620: scanControllers.addElement(sc);
1621:
1622: return sc;
1623: }
1624:
1625: public void commit() throws StandardException {
1626: this
1627: .closeControllers(false /* don't close held controllers */);
1628:
1629: rawtran.commit();
1630:
1631: alterTableCallMade = false;
1632:
1633: return;
1634: }
1635:
1636: public DatabaseInstant commitNoSync(int commitflag)
1637: throws StandardException {
1638: this
1639: .closeControllers(false /* don't close held controllers */);
1640: return rawtran.commitNoSync(commitflag);
1641: }
1642:
1643: public void abort() throws StandardException {
1644:
1645: if (alterTableCallMade) {
1646: accessmanager.conglomCacheInvalidate();
1647: alterTableCallMade = false;
1648: }
1649: this .closeControllers(true /* close all controllers */);
1650: rawtran.abort();
1651:
1652: if (parent_tran != null)
1653: parent_tran.abort();
1654: }
1655:
1656: /**
1657: * Get the context manager that the transaction was created with.
1658: * <p>
1659: *
1660: * @return The context manager that the transaction was created with.
1661: * **/
1662: public ContextManager getContextManager() {
1663: return (context.getContextManager());
1664: }
1665:
1666: public int setSavePoint(String name, Object kindOfSavepoint)
1667: throws StandardException {
1668: return rawtran.setSavePoint(name, kindOfSavepoint);
1669: }
1670:
1671: public int releaseSavePoint(String name, Object kindOfSavepoint)
1672: throws StandardException {
1673: return rawtran.releaseSavePoint(name, kindOfSavepoint);
1674: }
1675:
1676: public int rollbackToSavePoint(String name,
1677: boolean close_controllers, Object kindOfSavepoint)
1678: throws StandardException {
1679: if (close_controllers)
1680: this .closeControllers(true /* close all controllers */);
1681: return rawtran.rollbackToSavePoint(name, kindOfSavepoint);
1682: }
1683:
1684: public void destroy() {
1685: try {
1686: this .closeControllers(true /* close all controllers */);
1687:
1688: // If there's a transaction, abort it.
1689: if (rawtran != null) {
1690: rawtran.destroy();
1691: rawtran = null;
1692: }
1693:
1694: // If there's a context, pop it.
1695: if (context != null)
1696: context.popMe();
1697: context = null;
1698:
1699: accessmanager = null;
1700: tempCongloms = null;
1701: } catch (StandardException e) {
1702: // XXX (nat) really need to figure out what to do
1703: // if there's an exception while aborting.
1704: rawtran = null;
1705: context = null;
1706: accessmanager = null;
1707: tempCongloms = null;
1708: }
1709: }
1710:
1711: public boolean anyoneBlocked() {
1712: return rawtran.anyoneBlocked();
1713: }
1714:
1715: /**************************************************************************
1716: * Public Methods implementing the XATransactionController interface.
1717: **************************************************************************
1718: */
1719:
1720: /**
1721: * This method is called to commit the current XA global transaction.
1722: * <p>
1723: * RESOLVE - how do we map to the "right" XAExceptions.
1724: * <p>
1725: *
1726: * @param onePhase If true, the resource manager should use a one-phase
1727: * commit protocol to commit the work done on behalf of
1728: * current xid.
1729: *
1730: * @exception StandardException Standard exception policy.
1731: **/
1732: public void xa_commit(boolean onePhase) throws StandardException {
1733: rawtran.xa_commit(onePhase);
1734: }
1735:
1736: /**
1737: * This method is called to ask the resource manager to prepare for
1738: * a transaction commit of the transaction specified in xid.
1739: * <p>
1740: *
1741: * @return A value indicating the resource manager's vote on the
1742: * the outcome of the transaction. The possible values
1743: * are: XA_RDONLY or XA_OK. If the resource manager wants
1744: * to roll back the transaction, it should do so by
1745: * throwing an appropriate XAException in the prepare
1746: * method.
1747: *
1748: * @exception StandardException Standard exception policy.
1749: **/
1750: public int xa_prepare() throws StandardException {
1751: return (rawtran.xa_prepare());
1752: }
1753:
1754: /**
1755: * rollback the current global transaction.
1756: * <p>
1757: * The given transaction is roll'ed back and it's history is not
1758: * maintained in the transaction table or long term log.
1759: * <p>
1760: *
1761: * @exception StandardException Standard exception policy.
1762: **/
1763: public void xa_rollback() throws StandardException {
1764: rawtran.xa_rollback();
1765: }
1766:
1767: /**************************************************************************
1768: * Public Methods of TransactionManager interface:
1769: **************************************************************************
1770: */
1771:
1772: /**
1773: * Add to the list of post commit work.
1774: * <p>
1775: * Add to the list of post commit work that may be processed after this
1776: * transaction commits. If this transaction aborts, then the post commit
1777: * work list will be thrown away. No post commit work will be taken out
1778: * on a rollback to save point.
1779: * <p>
1780: * This routine simply delegates the work to the Rawstore transaction.
1781: *
1782: * @param work The post commit work to do.
1783: *
1784: **/
1785: public void addPostCommitWork(Serviceable work) {
1786: rawtran.addPostCommitWork(work);
1787:
1788: return;
1789: }
1790:
1791: /**
1792: * The ConglomerateController.close() method has been called on
1793: * "conglom_control".
1794: * <p>
1795: * Take whatever cleanup action is appropriate to a closed
1796: * conglomerateController. It is likely this routine will remove
1797: * references to the ConglomerateController object that it was maintaining
1798: * for cleanup purposes.
1799: *
1800: **/
1801: public void closeMe(ConglomerateController conglom_control) {
1802: conglomerateControllers.removeElement(conglom_control);
1803: }
1804:
1805: /**
1806: * The SortController.close() method has been called on "sort_control".
1807: * <p>
1808: * Take whatever cleanup action is appropriate to a closed
1809: * sortController. It is likely this routine will remove
1810: * references to the SortController object that it was maintaining
1811: * for cleanup purposes.
1812: **/
1813: public void closeMe(SortController sort_control) {
1814: sortControllers.removeElement(sort_control);
1815: }
1816:
1817: /**
1818: * The ScanManager.close() method has been called on "scan".
1819: * <p>
1820: * Take whatever cleanup action is appropriate to a closed scan. It is
1821: * likely this routine will remove references to the scan object that it
1822: * was maintaining for cleanup purposes.
1823: *
1824: **/
1825: public void closeMe(ScanManager scan) {
1826: scanControllers.removeElement(scan);
1827: }
1828:
1829: /**
1830: * Get reference to access factory which started this transaction.
1831: * <p>
1832: *
1833: * @return The AccessFactory which started this transaction.
1834: *
1835: **/
1836: public AccessFactory getAccessManager() {
1837: return (accessmanager);
1838: }
1839:
1840: /**
1841: * Get an Internal transaction.
1842: * <p>
1843: * Start an internal transaction. An internal transaction is a completely
1844: * separate transaction from the current user transaction. All work done
1845: * in the internal transaction must be physical (ie. it can be undone
1846: * physically by the rawstore at the page level, rather than logically
1847: * undone like btree insert/delete operations). The rawstore guarantee's
1848: * that in the case of a system failure all open Internal transactions are
1849: * first undone in reverse order, and then other transactions are undone
1850: * in reverse order.
1851: * <p>
1852: * Internal transactions are meant to implement operations which, if
1853: * interupted before completion will cause logical operations like tree
1854: * searches to fail. This special undo order insures that the state of
1855: * the tree is restored to a consistent state before any logical undo
1856: * operation which may need to search the tree is performed.
1857: * <p>
1858: *
1859: * @return The new internal transaction.
1860: *
1861: * @exception StandardException Standard exception policy.
1862: **/
1863: public TransactionManager getInternalTransaction()
1864: throws StandardException {
1865: // Get the context manager.
1866: ContextManager cm = getContextManager();
1867:
1868: // Allocate a new transaction no matter what.
1869:
1870: // Create a transaction, make a context for it, and push the context.
1871: // Note this puts the raw store transaction context
1872: // above the access context, which is required for
1873: // error handling assumptions to be correct.
1874:
1875: Transaction rawtran = accessmanager.getRawStore()
1876: .startInternalTransaction(cm);
1877: RAMTransaction rt = new RAMTransaction(accessmanager, rawtran,
1878: null);
1879: RAMTransactionContext rtc = new RAMTransactionContext(cm,
1880: AccessFactoryGlobals.RAMXACT_INTERNAL_CONTEXT_ID, rt,
1881: true /*abortAll */);
1882:
1883: rawtran.setDefaultLockingPolicy(accessmanager
1884: .getDefaultLockingPolicy());
1885:
1886: return (rt);
1887: }
1888:
1889: /**
1890: * Get an nested user transaction.
1891: * <p>
1892: * A nested user can be used exactly as any other TransactionController,
1893: * except as follows. For this discussion let the parent transaction
1894: * be the transaction used to make the getNestedUserTransaction(), and
1895: * let the child transaction be the transaction returned by the
1896: * getNestedUserTransaction() call.
1897: * <p>
1898: * The nesting is limited to one level deep. An exception will be thrown
1899: * if a subsequent getNestedUserTransaction() is called on the child
1900: * transaction.
1901: * <p>
1902: * The locks in the child transaction will be compatible with the locks
1903: * of the parent transaction.
1904: * <p>
1905: * A commit in the child transaction will release locks associated with
1906: * the child transaction only, work can continue in the parent transaction
1907: * at this point.
1908: * <p>
1909: * Any abort of the child transaction will result in an abort of both
1910: * the child transaction and parent transaction.
1911: * <p>
1912: * A TransactionController.destroy() call should be made on the child
1913: * transaction once all child work is done, and the caller wishes to
1914: * continue work in the parent transaction.
1915: * <p>
1916: * Nested internal transactions are meant to be used to implement
1917: * system work necessary to commit as part of implementing a user's
1918: * request, but where holding the lock for the duration of the user
1919: * transaction is not acceptable. 2 examples of this are system catalog
1920: * read locks accumulated while compiling a plan, and auto-increment.
1921: * <p>
1922: *
1923: * @return The new nested user transaction.
1924: *
1925: * @exception StandardException Standard exception policy.
1926: **/
1927: public TransactionController startNestedUserTransaction(
1928: boolean readOnly) throws StandardException {
1929: // Get the context manager.
1930: ContextManager cm = getContextManager();
1931:
1932: // Allocate a new transaction no matter what.
1933:
1934: // Create a transaction, make a context for it, and push the context.
1935: // Note this puts the raw store transaction context
1936: // above the access context, which is required for
1937: // error handling assumptions to be correct.
1938: //
1939: // Note that the compatibility space for the nested transaction
1940: // is "this", thus the new transaction shares the compatibility space
1941: // of the current transaction.
1942:
1943: Transaction child_rawtran = ((readOnly) ? accessmanager
1944: .getRawStore()
1945: .startNestedReadOnlyUserTransaction(
1946: this .getLockObject(), cm,
1947: AccessFactoryGlobals.NESTED_READONLY_USER_TRANS)
1948: : accessmanager
1949: .getRawStore()
1950: .startNestedUpdateUserTransaction(
1951: cm,
1952: AccessFactoryGlobals.NESTED_UPDATE_USER_TRANS));
1953:
1954: RAMTransaction rt = new RAMTransaction(accessmanager,
1955: child_rawtran, this );
1956:
1957: RAMTransactionContext rtc = new RAMTransactionContext(cm,
1958: AccessFactoryGlobals.RAMXACT_CHILD_CONTEXT_ID, rt, true /*abortAll */);
1959:
1960: child_rawtran.setDefaultLockingPolicy(accessmanager
1961: .getDefaultLockingPolicy());
1962:
1963: /*
1964: System.out.println("returning nested xact: " + rt +
1965: "child_rawtran = " + child_rawtran);
1966: */
1967:
1968: return (rt);
1969: }
1970:
1971: /**
1972: * Get the Transaction from the Transaction manager.
1973: * <p>
1974: * Access methods often need direct access to the "Transaction" - ie. the
1975: * raw store transaction, so give access to it.
1976: *
1977: * @return The raw store transaction.
1978: *
1979: **/
1980: public Transaction getRawStoreXact() {
1981: return (rawtran);
1982: }
1983:
1984: /**
1985: * Do work necessary to maintain the current position in all the scans.
1986: * <p>
1987: * The latched page in the conglomerate "congomid" is changing, do
1988: * whatever is necessary to maintain the current position of all the
1989: * scans open in this transaction.
1990: * <p>
1991: * For some conglomerates this may be a no-op.
1992: * <p>
1993: *
1994: * @param conglom Conglomerate being changed.
1995: * @param page Page in the conglomerate being changed.
1996: *
1997: * @exception StandardException Standard exception policy.
1998: **/
1999: public void saveScanPositions(Conglomerate conglom, Page page)
2000: throws StandardException {
2001: Enumeration e = scanControllers.elements();
2002: while (e.hasMoreElements()) {
2003: Object o = e.nextElement();
2004:
2005: if (SanityManager.DEBUG) {
2006: // The following debugging code is here because the following
2007: // (ScanManager) cast is occasionally causing a
2008: // java.lang.ClassCastException.
2009:
2010: if (!(o instanceof ScanManager)) {
2011: HeaderPrintWriter istream = Monitor.getStream();
2012:
2013: if (o == null)
2014: istream.println("next element was null\n");
2015: else
2016: istream
2017: .println("non ScanManager on list: "
2018: + o);
2019:
2020: istream.println("Current list of open scans: "
2021: + debugOpened());
2022: }
2023: }
2024: ScanManager sm = (ScanManager) o;
2025: sm.savePosition(conglom, page);
2026: }
2027: }
2028:
2029: public FileResource getFileHandler() {
2030: return rawtran.getFileHandler();
2031: }
2032:
2033: /**
2034: Return an object that when used as the compatability space *and*
2035: group for a lock request, guarantees that the lock will be removed
2036: on a commit or an abort.
2037: */
2038: public Object getLockObject() {
2039: return rawtran.getCompatibilitySpace();
2040: }
2041:
2042: /**
2043: * Get string id of the transaction.
2044: * <p>
2045: * This transaction "name" will be the same id which is returned in
2046: * the TransactionInfo information, used by the lock and transaction
2047: * vti's to identify transactions.
2048: * <p>
2049: * Although implementation specific, the transaction id is usually a number
2050: * which is bumped every time a commit or abort is issued.
2051: * <p>
2052: * For now return the toString() method, which does what we want. Later
2053: * if that is not good enough we can add public raw tran interfaces to
2054: * get exactly what we want.
2055: *
2056: * @return The a string which identifies the transaction.
2057: **/
2058: public String getTransactionIdString() {
2059: return (rawtran.toString());
2060: }
2061:
2062: /**
2063: * Get string id of the transaction that would be when the Transaction
2064: * is IN active state.
2065: **/
2066: public String getActiveStateTxIdString() {
2067: return (rawtran.getActiveStateTxIdString());
2068: }
2069:
2070: public String toString() {
2071: String str = null;
2072:
2073: if (SanityManager.DEBUG) {
2074: str = "rawtran = " + rawtran;
2075: }
2076: return (str);
2077: }
2078: }
|