001: /*
002:
003: Derby - Class org.apache.derby.impl.store.access.heap.Heap
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.heap;
023:
024: import java.io.ObjectOutput;
025: import java.io.ObjectInput;
026: import java.io.IOException;
027: import java.util.Properties;
028:
029: import org.apache.derby.iapi.reference.SQLState;
030:
031: import org.apache.derby.iapi.services.io.ArrayInputStream;
032: import org.apache.derby.iapi.services.io.FormatableBitSet;
033:
034: import org.apache.derby.iapi.services.sanity.SanityManager;
035:
036: import org.apache.derby.iapi.services.io.Formatable;
037: import org.apache.derby.iapi.services.io.FormatIdUtil;
038: import org.apache.derby.iapi.services.io.Storable;
039: import org.apache.derby.iapi.services.io.StoredFormatIds;
040:
041: import org.apache.derby.iapi.error.StandardException;
042:
043: import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;
044: import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
045: import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
046: import org.apache.derby.iapi.store.access.conglomerate.ScanManager;
047: import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
048:
049: import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
050: import org.apache.derby.iapi.store.access.ConglomerateController;
051: import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
052: import org.apache.derby.iapi.store.access.Qualifier;
053: import org.apache.derby.iapi.store.access.RowLocationRetRowSource;
054: import org.apache.derby.iapi.store.access.RowUtil;
055: import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
056: import org.apache.derby.iapi.store.access.StoreCostController;
057: import org.apache.derby.iapi.store.access.TransactionController;
058:
059: import org.apache.derby.iapi.store.raw.ContainerKey;
060: import org.apache.derby.iapi.store.raw.ContainerHandle;
061: import org.apache.derby.iapi.store.raw.LockingPolicy;
062: import org.apache.derby.iapi.store.raw.Transaction;
063: import org.apache.derby.iapi.store.raw.Page;
064: import org.apache.derby.iapi.store.raw.RawStoreFactory;
065: import org.apache.derby.iapi.store.raw.RecordHandle;
066:
067: import org.apache.derby.iapi.types.DataValueDescriptor;
068:
069: import org.apache.derby.iapi.services.cache.ClassSize;
070:
071: import org.apache.derby.iapi.types.DataType;
072:
073: import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil;
074: import org.apache.derby.impl.store.access.conglomerate.GenericConglomerate;
075: import org.apache.derby.impl.store.access.conglomerate.OpenConglomerate;
076: import org.apache.derby.impl.store.access.conglomerate.OpenConglomerateScratchSpace;
077:
078: import java.sql.ResultSet;
079: import java.sql.SQLException;
080:
081: /**
082: * @format_id ACCESS_HEAP_V1_ID
083: *
084: * @purpose The tag that describes the on disk representation of the Heap
085: * conglomerate object. The Heap conglomerate object is stored in
086: * a field of a row in the Conglomerate directory.
087: *
088: * @upgrade This format was made obsolete in the kimono release.
089: *
090: * @disk_layout
091: * containerid(long)
092: * segmentid(int)
093: **/
094:
095: /**
096: * @format_id ACCESS_HEAP_V2_ID
097: *
098: * @purpose The tag that describes the on disk representation of the Heap
099: * conglomerate object. The Heap conglomerate object is stored in
100: * a field of a row in the Conglomerate directory.
101: *
102: * @upgrade The format id of this object is currently always read from disk
103: * as a separate column in the conglomerate directory. To read
104: * A conglomerate object from disk and upgrade it to the current
105: * version do the following:
106: *
107: * format_id = get format id from a separate column
108: * Upgradable conglom_obj = instantiate empty obj(format_id)
109: * read in conglom_obj from disk
110: * conglom = conglom_obj.upgradeToCurrent();
111: *
112: * @disk_layout
113: * format_of_this_conlgomerate(byte[])
114: * containerid(long)
115: * segmentid(int)
116: * number_of_columns(int)
117: * array_of_format_ids(byte[][])
118: **/
119:
120: /**
121:
122: A heap object corresponds to an instance of a heap conglomerate. It caches
123: information which makes it fast to open heap controllers from it.
124:
125: **/
126:
127: public final class Heap extends GenericConglomerate implements
128: Conglomerate, StaticCompiledOpenConglomInfo {
129:
130: /*
131: ** Fields of Heap.
132: */
133:
134: protected ContainerKey id;
135:
136: /**
137: * The format id's of each of the columns in the heap table.
138: **/
139: int[] format_ids;
140:
141: private static final int BASE_MEMORY_USAGE = ClassSize
142: .estimateBaseFromCatalog(Heap.class);
143: private static final int CONTAINER_KEY_MEMORY_USAGE = ClassSize
144: .estimateBaseFromCatalog(ContainerKey.class);
145:
146: public int estimateMemoryUsage() {
147: int sz = BASE_MEMORY_USAGE;
148:
149: if (null != id)
150: sz += CONTAINER_KEY_MEMORY_USAGE;
151: if (null != format_ids)
152: sz += format_ids.length * ClassSize.getIntSize();
153: return sz;
154: } // end of estimateMemoryUsage
155:
156: /*
157: ** Methods of Heap.
158: */
159:
160: /* Constructors for This class: */
161:
162: /**
163: * Zero arg constructor for Monitor to create empty object.
164: **/
165: public Heap() {
166: }
167:
168: /* Private/Protected methods of This class: */
169:
170: /**
171: * Create a heap conglomerate.
172: * <p>
173: * Create a heap conglomerate. This method is called from the heap factory
174: * to create a new instance of a heap.
175: * <p>
176: *
177: * @exception StandardException Standard exception policy.
178: **/
179: protected void create(Transaction rawtran, int segmentId,
180: long input_containerid, DataValueDescriptor[] template,
181: Properties properties, int tmpFlag)
182: throws StandardException {
183: // Create a container for the heap table with
184: // default minimumRecordSize to be at least
185: // MINIMUM_RECORD_SIZE_DEFAULT (12),
186: // to guarantee there is enough room for updates
187: // of the row.
188: // Here we only take care of the case that
189: // that the properties are set with the create
190: // statement. For the case when properties are
191: // not set with the create statement, it is taken
192: // care of in fileContainer.java: createInfoFromProp().
193: if (properties != null) {
194: String value = properties
195: .getProperty(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER);
196:
197: int minimumRecordSize = (value == null) ? RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT
198: : Integer.parseInt(value);
199:
200: if (minimumRecordSize < RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT) {
201: properties
202: .put(
203: RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER,
204: Integer
205: .toString(RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT));
206: }
207: }
208:
209: // Create a container for the heap with default page size.
210: long containerid = rawtran.addContainer(segmentId,
211: input_containerid, ContainerHandle.MODE_DEFAULT,
212: properties, tmpFlag);
213:
214: // Make sure the container was actually created.
215: if (containerid < 0) {
216: throw StandardException
217: .newException(SQLState.HEAP_CANT_CREATE_CONTAINER);
218: }
219:
220: // Keep track of what segment the container's in.
221: id = new ContainerKey(segmentId, containerid);
222:
223: // Heap requires a template representing every column in the table.
224: if ((template == null) || (template.length == 0)) {
225: throw StandardException
226: .newException(SQLState.HEAP_COULD_NOT_CREATE_CONGLOMERATE);
227: }
228:
229: // get format id's from each column in template and store it in the
230: // conglomerate state.
231: this .format_ids = ConglomerateUtil.createFormatIds(template);
232:
233: // need to open the container and insert the row. Since we are
234: // creating it no need to bother with locking since no one can get
235: // to it until after we have created it and returned it's id.
236: ContainerHandle container = null;
237: Page page = null;
238:
239: try {
240: container = rawtran
241: .openContainer(
242: id,
243: (LockingPolicy) null,
244: ContainerHandle.MODE_FORUPDATE
245: | (isTemporary() ? ContainerHandle.MODE_TEMP_IS_KEPT
246: : 0));
247:
248: // row in slot 0 of heap page 1 which is just a single column with
249: // the heap entry.
250: DataValueDescriptor[] control_row = new DataValueDescriptor[1];
251: control_row[0] = this ;
252:
253: page = container.getPage(ContainerHandle.FIRST_PAGE_NUMBER);
254:
255: page.insertAtSlot(Page.FIRST_SLOT_NUMBER, control_row,
256: (FormatableBitSet) null, (LogicalUndo) null,
257: Page.INSERT_OVERFLOW,
258: AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);
259: page.unlatch();
260: page = null;
261:
262: // Don't include the control row in the estimated row count.
263: container.setEstimatedRowCount(0, /* unused flag */0);
264: } finally {
265: if (container != null)
266: container.close();
267: if (page != null)
268: page.unlatch();
269: }
270: }
271:
272: /**
273: * Create a heap conglomerate during the boot process.
274: * <p>
275: * Manufacture a Heap Conglomerate out of "thin" air, to boot strap
276: * the system. Create an in-memory Heap Conglomerate with the input
277: * parameters, The caller will use this to open the conglomerate
278: * conglomerate and read the "real" values from disk. Conglom-conglom
279: * is always on segment 0.
280: *
281: *
282: * @param containerid The container id of the conglomerate.
283: * @param template Object array describing the columns of the heap.
284: **/
285: public void boot_create(long containerid,
286: DataValueDescriptor[] template) {
287: id = new ContainerKey(0, containerid);
288: this .format_ids = ConglomerateUtil.createFormatIds(template);
289: }
290:
291: /*
292: ** Methods of Conglomerate
293: */
294:
295: /**
296: * Add a column to the heap conglomerate.
297: * <p>
298: * This routine update's the in-memory object version of the Heap
299: * Conglomerate to have one more column of the type described by the
300: * input template column.
301: *
302: * @param column_id The column number to add this column at.
303: * @param template_column An instance of the column to be added to table.
304: *
305: * @exception StandardException Standard exception policy.
306: **/
307: public void addColumn(TransactionManager xact_manager,
308: int column_id, Storable template_column)
309: throws StandardException {
310: // need to open the container and update the row containing the
311: // serialized format of the heap.
312: ContainerHandle container = null;
313: Page page = null;
314: Transaction rawtran = xact_manager.getRawStoreXact();
315:
316: try {
317: container = rawtran
318: .openContainer(
319: id,
320: rawtran
321: .newLockingPolicy(
322: LockingPolicy.MODE_CONTAINER,
323: TransactionController.ISOLATION_SERIALIZABLE,
324: true),
325: ContainerHandle.MODE_FORUPDATE
326: | (isTemporary() ? ContainerHandle.MODE_TEMP_IS_KEPT
327: : 0));
328:
329: if (column_id != format_ids.length) {
330: if (SanityManager.DEBUG)
331: SanityManager.THROWASSERT("column_id = "
332: + column_id + "format_ids.length = "
333: + format_ids.length + "format_ids = "
334: + format_ids);
335:
336: throw (StandardException.newException(
337: SQLState.HEAP_TEMPLATE_MISMATCH, new Long(
338: column_id), new Long(
339: this .format_ids.length)));
340: }
341:
342: // create a new array, and copy old values to it.
343: int[] old_format_ids = format_ids;
344: format_ids = new int[old_format_ids.length + 1];
345: System.arraycopy(old_format_ids, 0, format_ids, 0,
346: old_format_ids.length);
347:
348: // add the new column
349: format_ids[old_format_ids.length] = template_column
350: .getTypeFormatId();
351:
352: // row in slot 0 of heap page 1 which is just a single column with
353: // the heap entry.
354: DataValueDescriptor[] control_row = new DataValueDescriptor[1];
355: control_row[0] = this ;
356:
357: page = container.getPage(ContainerHandle.FIRST_PAGE_NUMBER);
358:
359: page.updateAtSlot(Page.FIRST_SLOT_NUMBER, control_row,
360: (FormatableBitSet) null);
361:
362: page.unlatch();
363: page = null;
364: } finally {
365: if (container != null)
366: container.close();
367: if (page != null)
368: page.unlatch();
369: }
370:
371: return;
372: }
373:
374: /**
375: Drop this heap.
376: @see Conglomerate#drop
377:
378: @exception StandardException Standard exception policy.
379: **/
380: public void drop(TransactionManager xact_manager)
381: throws StandardException {
382: xact_manager.getRawStoreXact().dropContainer(id);
383: }
384:
385: /**
386: * Retrieve the maximum value row in an ordered conglomerate.
387: * <p>
388: * Returns true and fetches the rightmost row of an ordered conglomerate
389: * into "fetchRow" if there is at least one row in the conglomerate. If
390: * there are no rows in the conglomerate it returns false.
391: * <p>
392: * Non-ordered conglomerates will not implement this interface, calls
393: * will generate a StandardException.
394: * <p>
395: * RESOLVE - this interface is temporary, long term equivalent (and more)
396: * functionality will be provided by the openBackwardScan() interface.
397: *
398: * @param conglomId The identifier of the conglomerate
399: * to open the scan for.
400: *
401: * @param open_mode Specifiy flags to control opening of table.
402: * OPENMODE_FORUPDATE - if set open the table for
403: * update otherwise open table shared.
404: * @param lock_level One of (MODE_TABLE, MODE_RECORD, or MODE_NONE).
405: *
406: * @param isolation_level The isolation level to lock the conglomerate at.
407: * One of (ISOLATION_READ_COMMITTED or
408: * ISOLATION_SERIALIZABLE).
409: *
410: * @param scanColumnList A description of which columns to return from
411: * every fetch in the scan. template,
412: * and scanColumnList work together
413: * to describe the row to be returned by the scan -
414: * see RowUtil for description of how these three
415: * parameters work together to describe a "row".
416: *
417: * @param fetchRow The row to retrieve the maximum value into.
418: *
419: * @return boolean indicating if a row was found and retrieved or not.
420: *
421: * @exception StandardException Standard exception policy.
422: **/
423: public boolean fetchMaxOnBTree(TransactionManager xact_manager,
424: Transaction rawtran, long conglomId, int open_mode,
425: int lock_level, LockingPolicy locking_policy,
426: int isolation_level, FormatableBitSet scanColumnList,
427: DataValueDescriptor[] fetchRow) throws StandardException {
428: // no support for max on a heap table.
429: throw (StandardException
430: .newException(SQLState.HEAP_UNIMPLEMENTED_FEATURE));
431: }
432:
433: /**
434: * Get the id of the container of the conglomerate.
435: * <p>
436: * Will have to change when a conglomerate could have more than one
437: * container. The ContainerKey is a combination of the container id
438: * and segment id.
439: *
440: * @return The ContainerKey.
441: **/
442: public final ContainerKey getId() {
443: return (id);
444: }
445:
446: public final long getContainerid() {
447: return (id.getContainerId());
448: }
449:
450: /**
451: * Return dynamic information about the conglomerate to be dynamically
452: * reused in repeated execution of a statement.
453: * <p>
454: * The dynamic info is a set of variables to be used in a given
455: * ScanController or ConglomerateController. It can only be used in one
456: * controller at a time. It is up to the caller to insure the correct
457: * thread access to this info. The type of info in this is a scratch
458: * template for btree traversal, other scratch variables for qualifier
459: * evaluation, ...
460: * <p>
461: *
462: * @return The dynamic information.
463: *
464: * @param conglomId The identifier of the conglomerate to open.
465: *
466: * @exception StandardException Standard exception policy.
467: **/
468: public DynamicCompiledOpenConglomInfo getDynamicCompiledConglomInfo(
469: long conglomId) throws StandardException {
470: return (new OpenConglomerateScratchSpace(format_ids));
471: }
472:
473: /**
474: * Return static information about the conglomerate to be included in a
475: * a compiled plan.
476: * <p>
477: * The static info would be valid until any ddl was executed on the
478: * conglomid, and would be up to the caller to throw away when that
479: * happened. This ties in with what language already does for other
480: * invalidation of static info. The type of info in this would be
481: * containerid and array of format id's from which templates can be created.
482: * The info in this object is read only and can be shared among as many
483: * threads as necessary.
484: * <p>
485: *
486: * @return The static compiled information.
487: *
488: * @param conglomId The identifier of the conglomerate to open.
489: *
490: * @exception StandardException Standard exception policy.
491: **/
492: public StaticCompiledOpenConglomInfo getStaticCompiledConglomInfo(
493: TransactionController tc, long conglomId)
494: throws StandardException {
495: return (this );
496: }
497:
498: /**
499: * Is this conglomerate temporary?
500: * <p>
501: *
502: * @return whether conglomerate is temporary or not.
503: **/
504: public boolean isTemporary() {
505: return (id.getSegmentId() == ContainerHandle.TEMPORARY_SEGMENT);
506: }
507:
508: /**
509: * Bulk load into the conglomerate.
510: * <p>
511: *
512: * @see Conglomerate#load
513: *
514: * @exception StandardException Standard exception policy.
515: **/
516: public long load(TransactionManager xact_manager,
517: boolean createConglom, RowLocationRetRowSource rowSource)
518: throws StandardException {
519: long num_rows_loaded = 0;
520:
521: HeapController heapcontroller = new HeapController();
522:
523: try {
524: num_rows_loaded = heapcontroller.load(xact_manager, this ,
525: createConglom, rowSource);
526: } finally {
527: // Done with this heap controller.
528: heapcontroller.close();
529: }
530:
531: return (num_rows_loaded);
532: }
533:
534: /**
535: * Open a heap controller.
536: * <p>
537: *
538: * @see Conglomerate#open
539: *
540: * @exception StandardException Standard exception policy.
541: **/
542: public ConglomerateController open(TransactionManager xact_manager,
543: Transaction rawtran, boolean hold, int open_mode,
544: int lock_level, LockingPolicy locking_policy,
545: StaticCompiledOpenConglomInfo static_info,
546: DynamicCompiledOpenConglomInfo dynamic_info)
547: throws StandardException {
548: OpenConglomerate open_conglom = new OpenHeap();
549:
550: if (open_conglom.init((ContainerHandle) null, this ,
551: this .format_ids, xact_manager, rawtran, hold,
552: open_mode, lock_level, locking_policy, dynamic_info) == null) {
553: throw StandardException.newException(
554: SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(id
555: .getContainerId()).toString());
556: }
557:
558: HeapController heapcontroller = new HeapController();
559:
560: heapcontroller.init(open_conglom);
561:
562: return (heapcontroller);
563: }
564:
565: /**
566: * Open a heap scan controller.
567: * <p>
568: *
569: * @see Conglomerate#openScan
570: *
571: * @exception StandardException Standard exception policy.
572: **/
573: public ScanManager openScan(TransactionManager xact_manager,
574: Transaction rawtran, boolean hold, int open_mode,
575: int lock_level, LockingPolicy locking_policy,
576: int isolation_level, FormatableBitSet scanColumnList,
577: DataValueDescriptor[] startKeyValue,
578: int startSearchOperator, Qualifier qualifier[][],
579: DataValueDescriptor[] stopKeyValue, int stopSearchOperator,
580: StaticCompiledOpenConglomInfo static_info,
581: DynamicCompiledOpenConglomInfo dynamic_info)
582: throws StandardException {
583: // Heap scans do not suppport start and stop scan positions (these
584: // only make sense for ordered storage structures).
585: if (!RowUtil.isRowEmpty(startKeyValue)
586: || !RowUtil.isRowEmpty(stopKeyValue)) {
587: throw StandardException
588: .newException(SQLState.HEAP_UNIMPLEMENTED_FEATURE);
589: }
590:
591: OpenConglomerate open_conglom = new OpenHeap();
592:
593: if (open_conglom.init((ContainerHandle) null, this ,
594: this .format_ids, xact_manager, rawtran, hold,
595: open_mode, lock_level, locking_policy, dynamic_info) == null) {
596: throw StandardException.newException(
597: SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(id
598: .getContainerId()));
599: }
600:
601: HeapScan heapscan = new HeapScan();
602:
603: heapscan.init(open_conglom, scanColumnList, startKeyValue,
604: startSearchOperator, qualifier, stopKeyValue,
605: stopSearchOperator);
606:
607: return (heapscan);
608: }
609:
610: public void purgeConglomerate(TransactionManager xact_manager,
611: Transaction rawtran) throws StandardException {
612: OpenConglomerate open_for_ddl_lock = null;
613: HeapController heapcontroller = null;
614: TransactionManager nested_xact = null;
615:
616: try {
617: open_for_ddl_lock = new OpenHeap();
618:
619: // Open table in intended exclusive mode in the top level
620: // transaction, this will stop any ddl from happening until
621: // purge of whole table is finished.
622:
623: if (open_for_ddl_lock.init((ContainerHandle) null, this ,
624: this .format_ids, xact_manager, rawtran, false,
625: TransactionController.OPENMODE_FORUPDATE,
626: TransactionController.MODE_RECORD, null, null) == null) {
627: throw StandardException.newException(
628: SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(id
629: .getContainerId()));
630: }
631:
632: // perform all the "real" work in a non-readonly nested user
633: // transaction, so that as work is completed on each page resources
634: // can be released. Must be careful as all locks obtained in nested
635: // transaction will conflict with parent transaction - so this call
636: // must be made only if parent transaction can have no conflicting
637: // locks on the table, otherwise the purge will fail with a self
638: // deadlock.
639: nested_xact = (TransactionManager) xact_manager
640: .startNestedUserTransaction(false);
641:
642: // now open the table in a nested user transaction so that each
643: // page worth of work can be committed after it is done.
644:
645: OpenConglomerate open_conglom = new OpenHeap();
646:
647: if (open_conglom
648: .init(
649: (ContainerHandle) null,
650: this ,
651: this .format_ids,
652: nested_xact,
653: nested_xact.getRawStoreXact(),
654: true,
655: TransactionController.OPENMODE_FORUPDATE,
656: TransactionController.MODE_RECORD,
657: nested_xact
658: .getRawStoreXact()
659: .newLockingPolicy(
660: LockingPolicy.MODE_RECORD,
661: TransactionController.ISOLATION_REPEATABLE_READ,
662: true), null) == null) {
663: throw StandardException.newException(
664: SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(id
665: .getContainerId()).toString());
666: }
667:
668: heapcontroller = new HeapController();
669:
670: heapcontroller.init(open_conglom);
671:
672: Page page = open_conglom.getContainer().getFirstPage();
673:
674: boolean purgingDone = false;
675:
676: while (page != null) {
677: long pageno = page.getPageNumber();
678: purgingDone = heapcontroller
679: .purgeCommittedDeletes(page);
680:
681: if (purgingDone) {
682: page = null;
683:
684: // commit xact to free resouurces ASAP, commit will
685: // unlatch the page if it has not already been unlatched
686: // by a remove.
687: open_conglom.getXactMgr().commitNoSync(
688: TransactionController.RELEASE_LOCKS);
689:
690: // the commit closes the underlying container, so let
691: // the heapcontroller know this has happened. Usually
692: // the transaction takes care of this, but this controller
693: // is internal, so the transaction does not know about it.
694: heapcontroller.closeForEndTransaction(false);
695:
696: // the commit will close the underlying
697: open_conglom.reopen();
698: } else {
699: page.unlatch();
700: page = null;
701: }
702:
703: page = open_conglom.getContainer().getNextPage(pageno);
704: }
705: } finally {
706: if (open_for_ddl_lock != null)
707: open_for_ddl_lock.close();
708: if (heapcontroller != null)
709: heapcontroller.close();
710: if (nested_xact != null) {
711: nested_xact
712: .commitNoSync(TransactionController.RELEASE_LOCKS);
713: nested_xact.destroy();
714: }
715: }
716:
717: return;
718: }
719:
720: public void compressConglomerate(TransactionManager xact_manager,
721: Transaction rawtran) throws StandardException {
722: OpenConglomerate open_conglom = null;
723: HeapController heapcontroller = null;
724:
725: try {
726: open_conglom = new OpenHeap();
727:
728: // Open table in intended exclusive mode in the top level
729: // transaction, this will stop any ddl from happening until
730: // purge of whole table is finished.
731:
732: if (open_conglom
733: .init(
734: (ContainerHandle) null,
735: this ,
736: this .format_ids,
737: xact_manager,
738: rawtran,
739: false,
740: TransactionController.OPENMODE_FORUPDATE,
741: TransactionController.MODE_TABLE,
742: rawtran
743: .newLockingPolicy(
744: LockingPolicy.MODE_CONTAINER,
745: TransactionController.ISOLATION_REPEATABLE_READ,
746: true), null) == null) {
747: throw StandardException.newException(
748: SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(id
749: .getContainerId()));
750: }
751:
752: heapcontroller = new HeapController();
753:
754: heapcontroller.init(open_conglom);
755:
756: open_conglom.getContainer().compressContainer();
757: } finally {
758: if (open_conglom != null)
759: open_conglom.close();
760: }
761:
762: return;
763: }
764:
765: /**
766: * Open a heap compress scan.
767: * <p>
768: *
769: * @see Conglomerate#defragmentConglomerate
770: *
771: * @exception StandardException Standard exception policy.
772: **/
773: public ScanManager defragmentConglomerate(
774: TransactionManager xact_manager, Transaction rawtran,
775: boolean hold, int open_mode, int lock_level,
776: LockingPolicy locking_policy, int isolation_level)
777: throws StandardException {
778: OpenConglomerate open_conglom = new OpenHeap();
779:
780: if (open_conglom
781: .init(
782: (ContainerHandle) null,
783: this ,
784: this .format_ids,
785: xact_manager,
786: rawtran,
787: hold,
788: open_mode,
789: lock_level,
790: rawtran
791: .newLockingPolicy(
792: LockingPolicy.MODE_RECORD,
793: TransactionController.ISOLATION_REPEATABLE_READ,
794: true), null) == null) {
795: throw StandardException.newException(
796: SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(id
797: .getContainerId()));
798: }
799:
800: HeapCompressScan heap_compress_scan = new HeapCompressScan();
801:
802: heap_compress_scan.init(open_conglom, null, null, 0, null,
803: null, 0);
804:
805: return (heap_compress_scan);
806: }
807:
808: /**
809: * Return an open StoreCostController for the conglomerate.
810: * <p>
811: * Return an open StoreCostController which can be used to ask about
812: * the estimated row counts and costs of ScanController and
813: * ConglomerateController operations, on the given conglomerate.
814: * <p>
815: * @param xact_manager The TransactionController under which this
816: * operation takes place.
817: * @param rawtran raw transaction context in which scan is managed.
818: *
819: * @return The open StoreCostController.
820: *
821: * @exception StandardException Standard exception policy.
822: *
823: * @see StoreCostController
824: **/
825: public StoreCostController openStoreCost(
826: TransactionManager xact_manager, Transaction rawtran)
827: throws StandardException {
828: OpenHeap open_conglom = new OpenHeap();
829:
830: if (open_conglom.init((ContainerHandle) null, this ,
831: this .format_ids, xact_manager, rawtran, false,
832: ContainerHandle.MODE_READONLY,
833: TransactionController.MODE_TABLE, (LockingPolicy) null,
834: (DynamicCompiledOpenConglomInfo) null) == null) {
835: throw StandardException.newException(
836: SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(id
837: .getContainerId()));
838: }
839:
840: HeapCostController heapcost = new HeapCostController();
841:
842: heapcost.init(open_conglom);
843:
844: return (heapcost);
845: }
846:
847: /**
848: * Print this heap.
849: **/
850: public String toString() {
851: return (id == null) ? "null" : id.toString();
852: }
853:
854: /**************************************************************************
855: * Public Methods of StaticCompiledOpenConglomInfo Interface:
856: **************************************************************************
857: */
858:
859: /**
860: * return the "Conglomerate".
861: * <p>
862: * For heap just return "this", which both implements Conglomerate and
863: * StaticCompiledOpenConglomInfo.
864: * <p>
865: *
866: * @return this
867: **/
868: public DataValueDescriptor getConglom() {
869: return (this );
870: }
871:
872: /**************************************************************************
873: * Methods of Storable (via Conglomerate)
874: * Storable interface, implies Externalizable, TypedFormat
875: **************************************************************************
876: */
877:
878: /**
879: * Return my format identifier.
880: *
881: * @see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId
882: **/
883: public int getTypeFormatId() {
884: return StoredFormatIds.ACCESS_HEAP_V2_ID;
885: }
886:
887: /**
888: * Return whether the value is null or not.
889: *
890: * @see org.apache.derby.iapi.services.io.Storable#isNull
891: **/
892: public boolean isNull() {
893: return id == null;
894: }
895:
896: /**
897: * Restore the in-memory representation to the null value.
898: *
899: * @see org.apache.derby.iapi.services.io.Storable#restoreToNull
900: *
901: **/
902: public void restoreToNull() {
903: id = null;
904: }
905:
906: /**
907: * Store the stored representation of the column value in the stream.
908: *
909: **/
910: public void writeExternal(ObjectOutput out) throws IOException {
911:
912: // write the format id of this conglomerate
913: FormatIdUtil.writeFormatIdInteger(out, this .getTypeFormatId());
914:
915: out.writeInt((int) id.getSegmentId());
916: out.writeLong(id.getContainerId());
917:
918: // write number of columns in heap.
919: out.writeInt(format_ids.length);
920:
921: // write out array of format id's
922: ConglomerateUtil.writeFormatIdArray(format_ids, out);
923: }
924:
925: /**
926: * Restore the in-memory representation from the stream.
927: *
928: * @see java.io.Externalizable#readExternal
929: **/
930: public void readExternal(ObjectInput in) throws IOException {
931: // read the format id of this conglomerate.
932: FormatIdUtil.readFormatIdInteger(in);
933:
934: int segmentid = in.readInt();
935: long containerid = in.readLong();
936:
937: id = new ContainerKey(segmentid, containerid);
938:
939: // read the number of columns in the heap.
940: int num_columns = in.readInt();
941:
942: // read the array of format ids.
943: format_ids = ConglomerateUtil
944: .readFormatIdArray(num_columns, in);
945: }
946:
947: public void readExternalFromArray(ArrayInputStream in)
948: throws IOException {
949: // read the format id of this conglomerate.
950: FormatIdUtil.readFormatIdInteger(in);
951:
952: int segmentid = in.readInt();
953: long containerid = in.readLong();
954:
955: id = new ContainerKey(segmentid, containerid);
956:
957: // read the number of columns in the heap.
958: int num_columns = in.readInt();
959:
960: // read the array of format ids.
961: format_ids = ConglomerateUtil
962: .readFormatIdArray(num_columns, in);
963: }
964:
965: }
|