001: /*
002:
003: Derby - Class org.apache.derby.impl.store.access.conglomerate.OpenConglomerate
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.store.access.conglomerate;
023:
024: import org.apache.derby.iapi.reference.SQLState;
025:
026: import org.apache.derby.iapi.services.sanity.SanityManager;
027:
028: import org.apache.derby.iapi.error.StandardException;
029:
030: import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;
031: import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
032:
033: import org.apache.derby.iapi.store.access.ConglomPropertyQueryable;
034: import org.apache.derby.iapi.store.access.ConglomerateController;
035: import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
036: import org.apache.derby.iapi.store.access.Qualifier;
037: import org.apache.derby.iapi.store.access.RowUtil;
038: import org.apache.derby.iapi.store.access.SpaceInfo;
039: import org.apache.derby.iapi.store.access.TransactionController;
040:
041: import org.apache.derby.iapi.store.raw.ContainerHandle;
042: import org.apache.derby.iapi.store.raw.FetchDescriptor;
043: import org.apache.derby.iapi.store.raw.LockingPolicy;
044: import org.apache.derby.iapi.store.raw.Page;
045: import org.apache.derby.iapi.store.raw.RecordHandle;
046: import org.apache.derby.iapi.store.raw.Transaction;
047:
048: import org.apache.derby.iapi.types.DataValueDescriptor;
049:
050: import org.apache.derby.iapi.types.RowLocation;
051:
052: import java.util.Properties;
053:
054: /**
055:
056: A Generic class which implements the basic functionality needed to operate
057: on an "open" conglomerate. This class assumes the following general things
058: about the access method.
059: <p>
060: The access method is page based and contained in a single container maintained
061: by raw store.
062:
063: **/
064:
065: public abstract class OpenConglomerate {
066: /**************************************************************************
067: * Fields of the class
068: **************************************************************************
069: */
070:
071: /**
072: * The following group of fields are all basic input parameters which are
073: * provided by the calling code when doing any sort of operation requiring
074: * an open conglomerate (openScan(), open(), openCostController(), ...).
075: * These are just saved values from what was initially input.
076: **/
077: private Conglomerate init_conglomerate;
078: private TransactionManager init_xact_manager;
079: private Transaction init_rawtran;
080: private int init_openmode;
081: private int init_lock_level;
082: private DynamicCompiledOpenConglomInfo init_dynamic_info;
083: private boolean init_hold;
084: private LockingPolicy init_locking_policy;
085:
086: /**
087: * convenience boolean's for various mode's
088: **/
089: private boolean useUpdateLocks;
090: private boolean forUpdate;
091: private boolean getBaseTableLocks;
092:
093: /**
094: * scratch space used for stuff like templates, export rows, ...
095: **/
096: private OpenConglomerateScratchSpace runtime_mem;
097:
098: /*
099: * The open raw store container associated with this open conglomerate
100: **/
101: private ContainerHandle container;
102:
103: /**************************************************************************
104: * Constructors for This class:
105: **************************************************************************
106: */
107:
108: /**************************************************************************
109: * Private methods for This class:
110: **************************************************************************
111: */
112:
113: /**************************************************************************
114: * abstract methods of This class:
115: **************************************************************************
116: */
117:
118: /**
119: * Return an "empty" row location object of the correct type.
120: * <p>
121: *
122: * @return The empty Rowlocation.
123: *
124: * @exception StandardException Standard exception policy.
125: **/
126: protected abstract RowLocation newRowLocationTemplate()
127: throws StandardException;
128:
129: abstract public int[] getFormatIds();
130:
131: /**************************************************************************
132: * Public Methods implementing standard store row locking interfaces:
133: * latchPage(RowPosition)
134: * latchPageAndRepositionScan(RowPosition)
135: * lockPositionForRead(RowPosition, aux_pos, moveForwardIfRowDisappears)
136: * lockPositionForWrite(RowPosition, forInsert, wait)
137: * unlockPositionAfterRead(RowPosition)
138: **************************************************************************
139: */
140: /**
141: * Latch the page containing the current RowPosition, and reposition scan.
142: * <p>
143: * Upon return the scan will hold a latch on the page to continue the
144: * scan on. The scan will positioned on the record, just before the
145: * next record to return.
146: *
147: * Note that for both hold cursor and read uncommitted support this routine
148: * handles all cases of either the current position "dissappearing" (either
149: * the row and/or page). The row and/or page can disappear by deleted
150: * space being reclaimed post commit of that delete, and for some reason
151: * the code requesting the reposition does not have locks which prevented
152: * the space reclamation. Both hold cursor and read uncommitted scans are
153: * examples of ways the caller will not prevent space reclamation from
154: * claiming the position.
155: *
156: * This implementation also automatically updates the RowPosition to
157: * point at the slot containing the current RowPosition. This slot
158: * value is only valid while the latch is held.
159: *
160: * @return true if scan had to reposition because a row disappeared.
161: *
162: * @exception StandardException Standard exception policy.
163: **/
164: public boolean latchPageAndRepositionScan(RowPosition pos)
165: throws StandardException {
166: boolean scan_repositioned = false;
167:
168: // Get the page the record handle refers to.
169: pos.current_page = null;
170:
171: try {
172: if (pos.current_rh != null) {
173: pos.current_page = container.getPage(pos.current_rh
174: .getPageNumber());
175: }
176:
177: } catch (Throwable t) {
178: // Assume all errors are caused by the page "disappearing", will
179: // handle this by positioning on next page in code below.
180: // Note that in most cases if the page does not exist, getPage()
181: // will return null rather than throw an exception, so this path
182: // is hard to reach.
183:
184: // just continue on first record of the next page.
185: // This should only happen if the page on which the scan was
186: // positioned had all of it's row deleted and the page was
187: // purged.
188:
189: // This can happen in a cursor held across a commit, where the
190: // scan needs to be repositioned after the first "next()" in the
191: // subsequent reopen() of the held cursor.
192: }
193:
194: if (pos.current_page != null) {
195: try {
196: // reposition scan at the old position, now that latch is held.
197: pos.current_slot = pos.current_page
198: .getSlotNumber(pos.current_rh);
199: } catch (StandardException se) {
200: scan_repositioned = true;
201:
202: // The record that the scan was positioned on, no longer exists.
203: // The normal way this happens is if we were positioned on
204: // a deleted row, without holding a lock on it, and while
205: // the scan did not hold the latch on the page a post commit
206: // job purged the row as part of space reclamation. This can
207: // happen in all ISOLATION level scans below serializable.
208: pos.current_slot = pos.current_page
209: .getNextSlotNumber(pos.current_rh);
210:
211: if (pos.current_slot == -1) {
212: // in this case we there are no more rows on this page
213: // to visit, so position on the next page. In this case
214: // the row that the scan was positioned on was purged,
215: // and there exists no rows now which are greater than this
216: // record id.
217:
218: pos.current_page.unlatch();
219: pos.current_page = null;
220: } else {
221: // The way scans work, need to position on the row just
222: // before the one to return "next". The first thing the
223: // next loop will do is move the scan forward one row.
224: pos.current_slot--;
225: }
226: }
227: }
228:
229: if (pos.current_page == null) {
230: // position on the next page.
231: long current_pageno;
232:
233: if (pos.current_rh != null) {
234: current_pageno = pos.current_rh.getPageNumber();
235: } else if (pos.current_pageno != ContainerHandle.INVALID_PAGE_NUMBER) {
236: current_pageno = pos.current_pageno;
237: } else {
238: // no valid position, return a null page
239: return (false);
240: }
241:
242: pos.current_page = container.getNextPage(current_pageno);
243:
244: pos.current_slot = Page.FIRST_SLOT_NUMBER - 1;
245:
246: // now position is tracked by active page
247: pos.current_pageno = ContainerHandle.INVALID_PAGE_NUMBER;
248:
249: scan_repositioned = true;
250: }
251:
252: if (scan_repositioned) {
253: pos.current_rh = null;
254: }
255:
256: return (scan_repositioned);
257: }
258:
259: /**
260: * Latch the page containing the current RowPosition.
261: * <p>
262: * This implementation also automatically updates the RowPosition to
263: * point at the slot containing the current RowPosition. This slot
264: * value is only valid while the latch is held.
265: *
266: * @exception StandardException Standard exception policy.
267: **/
268: public boolean latchPage(RowPosition pos) throws StandardException {
269: pos.current_page = null;
270:
271: try {
272: pos.current_page = container.getPage(pos.current_rh
273: .getPageNumber());
274:
275: } catch (Throwable t) {
276: // Assume all errors are caused by the page "disappearing", will
277: // handle this by returning false indicating that row can't be
278: // found. This can easily happen when using read uncommitted
279: // isolation level.
280: }
281:
282: if (pos.current_page != null) {
283: try {
284: pos.current_slot = pos.current_page
285: .getSlotNumber(pos.current_rh);
286:
287: return (true);
288: } catch (Throwable t) {
289: // Assume all errors are caused by the row "disappearing",
290: // will handle this by returning false indicating that row
291: // can't be found. This can easily happen when using read
292: // uncommitted isolation level.
293:
294: pos.current_page.unlatch();
295: pos.current_page = null;
296: }
297: }
298:
299: return (false);
300: }
301:
302: /**
303: * Lock row at given row position for read.
304: * <p>
305: * This routine requests a row lock NOWAIT on the row located at the given
306: * RowPosition. If the lock is granted NOWAIT the
307: * routine will return true. If the lock cannot be granted NOWAIT, then
308: * the routine will release the latch on "page" and then it will request
309: * a WAIT lock on the row.
310: * <p>
311: * This implementation:
312: * Assumes latch held on current_page.
313: * If the current_rh field of RowPosition is non-null it is assumed that
314: * we want to lock that record handle and that we don't have a slot number.
315: * If the current_rh field of RowPosition is null, it is assumed the we
316: * want to lock the indicated current_slot. Upon return current_rh will
317: * point to the record handle associated with current_slot.
318: * <p>
319: * After waiting and getting the lock on the row, this routine will fix up
320: * RowPosition to point at the row locked. This means it will get the
321: * page latch again, and it will fix the current_slot to point at the
322: * waited for record handle - it may have moved while waiting on the lock.
323: *
324: * @param pos Position to lock.
325: * @param aux_pos If you have to give up latch to get lock, then also
326: * unlock this position if it is non-null.
327: * @param moveForwardIfRowDisappears
328: * If true, then this routine must handle the case where
329: * the row id we are waiting on disappears when the latch
330: * is released. If false an exception will be thrown if
331: * the row disappears.
332: * @param waitForLock
333: * if true wait for lock, if lock can't be granted NOWAIT,
334: * else if false, throw a lock timeout exception if the
335: * lock can't be granted without waiting.
336: *
337: * @return true if lock granted without releasing the latch, else return
338: * false.
339: *
340: * @exception StandardException Standard exception policy.
341: **/
342: public boolean lockPositionForRead(RowPosition pos,
343: RowPosition aux_pos, boolean moveForwardIfRowDisappears,
344: boolean waitForLock) throws StandardException {
345: if (pos.current_rh == null) {
346: if (SanityManager.DEBUG) {
347: SanityManager
348: .ASSERT(pos.current_page != null
349: && pos.current_slot != Page.INVALID_SLOT_NUMBER);
350:
351: }
352:
353: // work around for lockmanager problem with lock/latch releasing.
354: // Get RecordHandle to lock.
355: pos.current_rh = pos.current_page
356: .getRecordHandleAtSlot(pos.current_slot);
357:
358: if (SanityManager.DEBUG) {
359: // make sure current_rh and current_slot are in sync
360: if (pos.current_slot != pos.current_page
361: .getSlotNumber(pos.current_rh)) {
362: SanityManager.THROWASSERT("current_slot = "
363: + pos.current_slot
364: + "current_rh = "
365: + pos.current_rh
366: + "current_rh.slot = "
367: + pos.current_page
368: .getSlotNumber(pos.current_rh));
369: }
370: }
371: }
372:
373: if (SanityManager.DEBUG)
374: SanityManager.ASSERT(pos.current_rh != null);
375:
376: boolean lock_granted_with_latch_held = this .container
377: .getLockingPolicy().lockRecordForRead(init_rawtran,
378: container, pos.current_rh, false /* NOWAIT */,
379: forUpdate);
380:
381: if (!lock_granted_with_latch_held) {
382:
383: // Could not get the lock NOWAIT, release latch and wait for lock.
384: pos.current_page.unlatch();
385: pos.current_page = null;
386:
387: if (aux_pos != null) {
388: aux_pos.current_page.unlatch();
389: aux_pos.current_page = null;
390: }
391:
392: if (!waitForLock) {
393: // throw lock timeout error.
394: throw StandardException
395: .newException(SQLState.LOCK_TIMEOUT);
396: }
397:
398: this .container.getLockingPolicy().lockRecordForRead(
399: init_rawtran, container, pos.current_rh,
400: true /* WAIT */, forUpdate);
401:
402: if (moveForwardIfRowDisappears) {
403:
404: if (latchPageAndRepositionScan(pos)) {
405: if (pos.current_slot != -1) {
406: // If scan was repositioned to just before a valid row
407: // on the current page, then move forward and lock and
408: // return that row (slot != -1).
409: //
410: // Let the caller handle the "-1"
411: // case, which may be one of 3 cases - need to go to
412: // slot 1 on current page, need to go to next page,
413: // need to end scan as there is no "next" page. All
414: // 3 cases are handled by the generic scan loop in
415: // GenericScanController.fetchRows().
416:
417: pos.positionAtNextSlot();
418: lockPositionForRead(pos, aux_pos, true, true);
419:
420: }
421: }
422: } else {
423: latchPage(pos);
424: }
425: }
426:
427: return (lock_granted_with_latch_held);
428: }
429:
430: public boolean lockPositionForWrite(RowPosition pos,
431: boolean forInsert, boolean waitForLock)
432: throws StandardException {
433: if (pos.current_rh == null) {
434: if (SanityManager.DEBUG) {
435: SanityManager.ASSERT(pos.current_page != null);
436: SanityManager
437: .ASSERT(pos.current_slot != Page.INVALID_SLOT_NUMBER);
438:
439: }
440:
441: // work around for lockmanager problem with lock/latch releasing.
442: // Get RecordHandle to lock.
443: pos.current_rh = pos.current_page.fetchFromSlot(null,
444: pos.current_slot, RowUtil.EMPTY_ROW,
445: RowUtil.EMPTY_ROW_FETCH_DESCRIPTOR, true);
446:
447: if (SanityManager.DEBUG) {
448: // make sure current_rh and current_slot are in sync
449: if (pos.current_slot != pos.current_page
450: .getSlotNumber(pos.current_rh)) {
451: SanityManager.THROWASSERT("current_slot = "
452: + pos.current_slot
453: + "current_rh = "
454: + pos.current_rh
455: + "current_rh.slot = "
456: + pos.current_page
457: .getSlotNumber(pos.current_rh));
458: }
459: }
460: }
461:
462: if (SanityManager.DEBUG)
463: SanityManager.ASSERT(pos.current_rh != null);
464:
465: boolean lock_granted_with_latch_held = this .container
466: .getLockingPolicy().lockRecordForWrite(init_rawtran,
467: pos.current_rh, forInsert, false /* NOWAIT */);
468:
469: if (!lock_granted_with_latch_held) {
470: if (!waitForLock) {
471: // throw lock timeout error.
472: throw StandardException
473: .newException(SQLState.LOCK_TIMEOUT);
474: }
475:
476: // Could not get the lock NOWAIT, release latch and wait for lock.
477: pos.current_page.unlatch();
478: pos.current_page = null;
479:
480: if (!waitForLock) {
481: // throw lock timeout error.
482: throw StandardException
483: .newException(SQLState.LOCK_TIMEOUT);
484: }
485:
486: this .container.getLockingPolicy()
487: .lockRecordForWrite(init_rawtran, pos.current_rh,
488: forInsert, true /* WAIT */);
489:
490: latchPage(pos);
491: }
492:
493: return (lock_granted_with_latch_held);
494: }
495:
496: /**
497: * Unlock the record after a previous request to lock it.
498: * <p>
499: * Unlock the record after a previous call to lockRecordForRead(). It is
500: * expected that RowPosition contains information used to lock the record,
501: * Thus it is important if using a single RowPosition to track a scan to
502: * call unlock before you move the position forward to the next record.
503: * <p>
504: * Note that this routine assumes that the row was locked forUpdate if
505: * the OpenConglomerate is forUpdate, else it assumes the record was
506: * locked for read.
507: *
508: * @exception StandardException Standard exception policy.
509: **/
510: public void unlockPositionAfterRead(RowPosition pos)
511: throws StandardException {
512: if (!isClosed())
513: container.getLockingPolicy().unlockRecordAfterRead(
514: init_rawtran, container, pos.current_rh, forUpdate,
515: pos.current_rh_qualified);
516: }
517:
518: /**************************************************************************
519: * Public Methods implementing ConglomPropertyQueryable Interface:
520: **************************************************************************
521: */
522:
523: /**
524: * Request set of properties associated with a table.
525: * <p>
526: * Returns a property object containing all properties that the store
527: * knows about, which are stored persistently by the store. This set
528: * of properties may vary from implementation to implementation of the
529: * store.
530: * <p>
531: * This call is meant to be used only for internal query of the properties
532: * by jbms, for instance by language during bulk insert so that it can
533: * create a new conglomerate which exactly matches the properties that
534: * the original container was created with. This call should not be used
535: * by the user interface to present properties to users as it may contain
536: * properties that are meant to be internal to jbms. Some properties are
537: * meant only to be specified by jbms code and not by users on the command
538: * line.
539: * <p>
540: * Note that not all properties passed into createConglomerate() are stored
541: * persistently, and that set may vary by store implementation.
542: *
543: * @param prop Property list to add properties to. If null, routine will
544: * create a new Properties object, fill it in and return it.
545: *
546: * @exception StandardException Standard exception policy.
547: **/
548: public Properties getInternalTablePropertySet(Properties prop)
549: throws StandardException {
550: Properties ret_properties = ConglomerateUtil
551: .createRawStorePropertySet(prop);
552:
553: getTableProperties(ret_properties);
554:
555: return (ret_properties);
556: }
557:
558: /**
559: * Request the system properties associated with a table.
560: * <p>
561: * Request the value of properties that are associated with a table. The
562: * following properties can be requested:
563: * derby.storage.pageSize
564: * derby.storage.pageReservedSpace
565: * derby.storage.minimumRecordSize
566: * derby.storage.initialPages
567: * <p>
568: * To get the value of a particular property add it to the property list,
569: * and on return the value of the property will be set to it's current
570: * value. For example:
571: *
572: * get_prop(ConglomerateController cc)
573: * {
574: * Properties prop = new Properties();
575: * prop.put("derby.storage.pageSize", "");
576: * cc.getTableProperties(prop);
577: *
578: * System.out.println(
579: * "table's page size = " +
580: * prop.getProperty("derby.storage.pageSize");
581: * }
582: *
583: * @param prop Property list to fill in.
584: *
585: * @exception StandardException Standard exception policy.
586: **/
587: public void getTableProperties(Properties prop)
588: throws StandardException {
589: container.getContainerProperties(prop);
590:
591: return;
592: }
593:
594: /**************************************************************************
595: * Public Accessors of This class:
596: **************************************************************************
597: */
598: public final TransactionManager getXactMgr() {
599: return (init_xact_manager);
600: }
601:
602: public final Transaction getRawTran() {
603: return (init_rawtran);
604: }
605:
606: public final ContainerHandle getContainer() {
607: return (container);
608: }
609:
610: public final int getOpenMode() {
611: return (init_openmode);
612: }
613:
614: public final Conglomerate getConglomerate() {
615: return (init_conglomerate);
616: }
617:
618: public final boolean getHold() {
619: return (init_hold);
620: }
621:
622: public final boolean isForUpdate() {
623: return (forUpdate);
624: }
625:
626: public final boolean isClosed() {
627: return (container == null);
628: }
629:
630: public final boolean isUseUpdateLocks() {
631: return (useUpdateLocks);
632: }
633:
634: public final OpenConglomerateScratchSpace getRuntimeMem() {
635: return (runtime_mem);
636: }
637:
638: /**************************************************************************
639: * Public Methods implementing some ConglomerateController Interfaces:
640: **************************************************************************
641: */
642:
643: /**
644: * Check consistency of a conglomerate.
645: * <p>
646: * Checks the consistency of the data within a given conglomerate, does not
647: * check consistency external to the conglomerate (ie. does not check that
648: * base table row pointed at by a secondary index actually exists).
649: * <p>
650: * There is no checking in the default implementation, you must override
651: * to get conglomerate specific consistency checking.
652: *
653: * @exception StandardException Standard exception policy.
654: **/
655: public void checkConsistency() throws StandardException {
656: return;
657: }
658:
659: public void debugConglomerate() throws StandardException {
660: if (SanityManager.DEBUG) {
661: SanityManager.DEBUG_PRINT("p_heap",
662: "\nHEAP DUMP:containerId " + container.getId());
663:
664: // get a template.
665:
666: DataValueDescriptor[] row = runtime_mem
667: .get_row_for_export();
668:
669: // Print pages of the heap.
670: Page page = container.getFirstPage();
671:
672: while (page != null) {
673: SanityManager.DEBUG_PRINT("p_heap", ConglomerateUtil
674: .debugPage(page, 0, false, row));
675:
676: long pageid = page.getPageNumber();
677: page.unlatch();
678: page = container.getNextPage(pageid);
679: }
680: }
681:
682: return;
683: }
684:
685: /**
686: Get information about space used by the conglomerate.
687: **/
688: public SpaceInfo getSpaceInfo() throws StandardException {
689: return container.getSpaceInfo();
690: }
691:
692: protected boolean isKeyed() {
693: return false;
694: }
695:
696: /**
697: * is the open btree table locked?
698: **/
699: protected boolean isTableLocked() {
700: return (init_lock_level == TransactionController.MODE_TABLE);
701: }
702:
703: /**************************************************************************
704: * Public Methods of this class:
705: **************************************************************************
706: */
707:
708: /**
709: * Open the container.
710: * <p>
711: * Open the container, obtaining necessary locks. Most work is actually
712: * done by RawStore.openContainer().
713: *
714: * @exception StandardException Standard exception policy.
715: **/
716: public ContainerHandle init(ContainerHandle open_container,
717: Conglomerate conglomerate, int[] format_ids,
718: TransactionManager xact_manager, Transaction rawtran,
719: boolean hold, int openmode, int lock_level,
720: LockingPolicy locking_policy,
721: DynamicCompiledOpenConglomInfo dynamic_info)
722: throws StandardException {
723: // save state of all inputs.
724: init_conglomerate = conglomerate;
725: init_xact_manager = xact_manager;
726: init_rawtran = rawtran;
727: init_openmode = openmode;
728: init_lock_level = lock_level;
729: init_dynamic_info = dynamic_info;
730: init_hold = hold;
731: init_locking_policy = locking_policy;
732:
733: // either use passed in "compiled" runtime scratch space, or create
734: // new space.
735: this .runtime_mem = (dynamic_info != null ? ((OpenConglomerateScratchSpace) dynamic_info)
736: : new OpenConglomerateScratchSpace(format_ids));
737:
738: // Is this an open for update or read? This will
739: // be passed down to the raw store fetch methods, which allows
740: // it to do the appropriate locking.
741: this .forUpdate = ((openmode & ContainerHandle.MODE_FORUPDATE) != 0);
742:
743: // keep track of whether this open conglomerate should use update locks.
744: this .useUpdateLocks = ((openmode & ContainerHandle.MODE_USE_UPDATE_LOCKS) != 0);
745:
746: // If this flag is set, then the client has already locked the row
747: // by accessing it through the secondary index and has already locked
748: // the row, so the base conglomerate need not re-lock the row.
749: this .getBaseTableLocks = ((openmode & ContainerHandle.MODE_SECONDARY_LOCKED) == 0);
750:
751: // if the conglomerate is temporary, open with IS_KEPT set.
752: // RESOLVE(mikem): track 1825
753: // don't want to open temp cantainer with IS_KEPT always.
754: if (conglomerate.isTemporary()) {
755: init_openmode |= ContainerHandle.MODE_TEMP_IS_KEPT;
756: }
757:
758: if (!getBaseTableLocks)
759: init_locking_policy = null;
760:
761: // Open the container.
762: this .container = (open_container != null ? open_container
763: : rawtran.openContainer(conglomerate.getId(),
764: init_locking_policy, init_openmode));
765:
766: return (this .container);
767: }
768:
769: /**
770: * Open the container.
771: * <p>
772: * Open the container, obtaining necessary locks. Most work is actually
773: * done by RawStore.openContainer(). Will only reopen() if the container
774: * is not already open.
775: *
776: * @exception StandardException Standard exception policy.
777: **/
778: public ContainerHandle reopen() throws StandardException {
779: // reget transaction from context manager, in the case of XA
780: // transaction this may have changed.
781: //
782: /* TODO - XA transactions my change the current transaction on the
783: * context stack. Will want to something like:
784: *
785: * init_rawtran = context_manager.getcurrenttransaction()
786: */
787:
788: if (this .container == null) {
789: this .container = init_rawtran.openContainer(
790: init_conglomerate.getId(), init_locking_policy,
791: init_openmode);
792: }
793:
794: return (this .container);
795: }
796:
797: /**
798: * Close the container.
799: * <p>
800: * Handles being closed more than once.
801: *
802: * @exception StandardException Standard exception policy.
803: **/
804: public void close() throws StandardException {
805: if (container != null) {
806: container.close();
807: container = null;
808: }
809: }
810: }
|