001: /*
002:
003: Derby - Class org.apache.derby.impl.store.access.btree.index.B2I
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.btree.index;
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: import org.apache.derby.iapi.error.StandardException;
036: import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;
037: import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
038: import org.apache.derby.iapi.store.access.conglomerate.ScanManager;
039: import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;
040: import org.apache.derby.iapi.store.access.ConglomerateController;
041: import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;
042: import org.apache.derby.iapi.store.access.Qualifier;
043: import org.apache.derby.iapi.types.RowLocation;
044: import org.apache.derby.iapi.store.access.RowLocationRetRowSource;
045: import org.apache.derby.iapi.store.access.ScanController;
046: import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
047: import org.apache.derby.iapi.store.access.StoreCostController;
048: import org.apache.derby.iapi.store.access.TransactionController;
049: import org.apache.derby.iapi.store.access.ColumnOrdering;
050:
051: import org.apache.derby.iapi.services.io.FormatIdUtil;
052: import org.apache.derby.iapi.services.io.StoredFormatIds;
053:
054: import org.apache.derby.iapi.store.raw.ContainerHandle;
055: import org.apache.derby.iapi.store.raw.LockingPolicy;
056: import org.apache.derby.iapi.store.raw.Page;
057: import org.apache.derby.iapi.store.raw.RecordHandle;
058: import org.apache.derby.iapi.store.raw.Transaction;
059:
060: import org.apache.derby.iapi.types.DataValueDescriptor;
061:
062: import org.apache.derby.impl.store.access.btree.BTree;
063: import org.apache.derby.impl.store.access.btree.BTreeLockingPolicy;
064: import org.apache.derby.impl.store.access.btree.LeafControlRow;
065: import org.apache.derby.impl.store.access.btree.ControlRow;
066: import org.apache.derby.impl.store.access.btree.OpenBTree;
067: import org.apache.derby.impl.store.access.btree.WaitError;
068:
069: import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil;
070: import org.apache.derby.iapi.services.io.FormatableBitSet;
071: import org.apache.derby.iapi.services.cache.ClassSize;
072:
073: /*
074: * @format_id ACCESS_B2I_V1_ID
075: *
076: * @purpose The tag that describes the on disk representation of the B2I
077: * conglomerate object. The B2I conglomerate object is stored in
078: * a field of a row in the Conglomerate directory.
079: *
080: * @upgrade This format was made obsolete in the kimono release.
081: *
082: * @disk_layout
083: * containerid(long)
084: * segmentid(int)
085: * number_of_key_fields(int)
086: * number_of_unique_columns(int)
087: * allow_duplicates(boolean)
088: * maintain_parent_links(boolean)
089: * format_of_this_conlgomerate(byte[])
090: * array_of_format_ids(byte[][])
091: * baseConglomerateId(long)
092: * rowLocationColumn(int)
093: */
094:
095: /*
096: * @format_id ACCESS_B2I_V2_ID
097: *
098: * @purpose The tag that describes the on disk representation of the B2I
099: * conglomerate object. The B2I 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_key_fields(int)
117: * number_of_unique_columns(int)
118: * allow_duplicates(boolean)
119: * maintain_parent_links(boolean)
120: * array_of_format_ids(byte[][])
121: * baseConglomerateId(long)
122: * rowLocationColumn(int)
123: */
124:
125: /**
126: * Implements an instance of a B-Tree secondary index conglomerate.
127: * A B2I object has two roles.
128: * <ol>
129: * <li>
130: * The B2I object is stored on disk, and holds the store specific
131: * information needed to access/describe the conglomerate. This
132: * includes information such as the format ids of the columns,
133: * the conglomerate id of the base table, the location of
134: * row location column.
135: * </li>
136: * <li>
137: * Access to all the interfaces start by making a call off the
138: * Conglomerate interface. So for instance to get a scan on the
139: * conglomerate method {@link #openScan openScan} should be called.
140: * </li>
141: * </ol>
142: */
143: public class B2I extends BTree {
144: public static final String PROPERTY_BASECONGLOMID = "baseConglomerateId";
145: public static final String PROPERTY_ROWLOCCOLUMN = "rowLocationColumn";
146:
147: public static final int FORMAT_NUMBER = StoredFormatIds.ACCESS_B2I_V3_ID;
148:
149: /*
150: ** Fields of B2I.
151: */
152:
153: /**
154: The id of the conglomerate which contains the base table.
155: Row locations inserted into this secondary index are assumed
156: to refer to that conglomerate. Used to obtain table/row locks on the
157: base table rows which the index rows point at.
158: **/
159: protected long baseConglomerateId;
160:
161: /**
162: The column id (zero-based integer index) of the column which holds the row
163: location to the base conglomerate.
164: The default value of RowLocationColumn is the last key column.
165: Used to obtain table/row locks on the base table rows with the index rows
166: point at.
167: Currently, RowLocationColumn must be the last key column.
168: **/
169: protected int rowLocationColumn;
170:
171: private static final int BASE_MEMORY_USAGE = ClassSize
172: .estimateBaseFromCatalog(B2I.class);
173:
174: public int estimateMemoryUsage() {
175: return BASE_MEMORY_USAGE;
176: }
177:
178: /**************************************************************************
179: * Constructors for This class:
180: **************************************************************************
181: */
182:
183: /**************************************************************************
184: * Protected locking implmentations of abtract BTree routines:
185: * getBtreeLockingPolicy
186: * lockTable
187: **************************************************************************
188: */
189:
190: /**
191: * Create a new btree locking policy from scratch.
192: *
193: * @exception StandardException Standard exception policy.
194: **/
195: protected BTreeLockingPolicy getBtreeLockingPolicy(
196: Transaction rawtran, int lock_level, int mode,
197: int isolation_level, ConglomerateController base_cc,
198: OpenBTree open_btree) throws StandardException {
199: BTreeLockingPolicy ret_locking_policy = null;
200:
201: if (SanityManager.DEBUG) {
202: SanityManager
203: .ASSERT(
204: (isolation_level == TransactionController.ISOLATION_SERIALIZABLE)
205: || (isolation_level == TransactionController.ISOLATION_REPEATABLE_READ)
206: || (isolation_level == TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK)
207: || (isolation_level == TransactionController.ISOLATION_READ_COMMITTED)
208: || (isolation_level == TransactionController.ISOLATION_READ_UNCOMMITTED),
209: "bad isolation_level = " + isolation_level);
210: }
211:
212: if (lock_level == TransactionController.MODE_TABLE) {
213: ret_locking_policy = new B2ITableLocking3(rawtran,
214: lock_level, rawtran.newLockingPolicy(
215: LockingPolicy.MODE_CONTAINER,
216: isolation_level, true), base_cc, open_btree);
217: } else if (lock_level == TransactionController.MODE_RECORD) {
218: if (isolation_level == TransactionController.ISOLATION_SERIALIZABLE) {
219: ret_locking_policy = new B2IRowLocking3(rawtran,
220: lock_level, rawtran.newLockingPolicy(
221: LockingPolicy.MODE_RECORD,
222: isolation_level, true), base_cc,
223: open_btree);
224: } else if ((isolation_level == TransactionController.ISOLATION_REPEATABLE_READ)) {
225: ret_locking_policy = new B2IRowLockingRR(rawtran,
226: lock_level, rawtran.newLockingPolicy(
227: LockingPolicy.MODE_RECORD,
228: isolation_level, true), base_cc,
229: open_btree);
230: } else if ((isolation_level == TransactionController.ISOLATION_READ_COMMITTED)
231: || (isolation_level == TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK)) {
232: ret_locking_policy = new B2IRowLocking2(rawtran,
233: lock_level, rawtran.newLockingPolicy(
234: LockingPolicy.MODE_RECORD,
235: isolation_level, true), base_cc,
236: open_btree);
237: } else if (isolation_level == TransactionController.ISOLATION_READ_UNCOMMITTED) {
238: ret_locking_policy = new B2IRowLocking1(rawtran,
239: lock_level, rawtran.newLockingPolicy(
240: LockingPolicy.MODE_RECORD,
241: isolation_level, true), base_cc,
242: open_btree);
243: }
244: }
245:
246: if (SanityManager.DEBUG) {
247: SanityManager.ASSERT(ret_locking_policy != null,
248: "ret_locking_policy == null");
249: }
250:
251: return (ret_locking_policy);
252: }
253:
254: /**
255: * Lock the base table.
256: * <p>
257: * Assumes that segment of the base container is the same as the segment
258: * of the btree segment.
259: * <p>
260: * RESOLVE - we really want to get the lock without opening the container.
261: * raw store will be providing this.
262: *
263: * @param xact_manager Transaction to associate the lock with.
264: *
265: * @exception StandardException Standard exception policy.
266: **/
267: public final ConglomerateController lockTable(
268: TransactionManager xact_manager, int open_mode,
269: int lock_level, int isolation_level)
270: throws StandardException {
271: open_mode |= TransactionController.OPENMODE_FOR_LOCK_ONLY;
272:
273: // open the base conglomerate - just to get the table lock.
274: ConglomerateController cc = xact_manager.openConglomerate(
275: this .baseConglomerateId, false, open_mode, lock_level,
276: isolation_level);
277:
278: return (cc);
279: }
280:
281: /**************************************************************************
282: * Private methods of B2I, arranged alphabetically.
283: **************************************************************************
284: */
285:
286: private void traverseRight() {
287: // RESOLVE - Do I have to do this???????????????
288:
289: if (SanityManager.DEBUG)
290: SanityManager.THROWASSERT("not implemented.");
291: }
292:
293: /*
294: ** Methods of B2I.
295: */
296:
297: /**
298: Create an empty secondary index b-tree, using the generic b-tree to do the
299: generic part of the creation process.
300:
301: This routine opens the newly created container, adds a single page, and
302: makes this page the root by inserting a LeafControlRow onto this page
303: at slot 0 and marking in that control row that the page is a root page.
304:
305: The following properties are specific to the b-tree secondary index:
306: <UL>
307: <LI> "baseConglomerateId" (integer). The conglomerate id of the base
308: conglomerate is never actually accessed by the b-tree secondary
309: index implementation, it only serves as a namespace for row locks.
310: This property is required.
311: <LI> "rowLocationColumn" (integer). The zero-based index into the row which
312: the b-tree secondary index will assume holds a @see RowLocation of
313: the base row in the base conglomerate. This value will be used
314: for acquiring locks. In this implementation RowLocationColumn must be
315: the last key column.
316: This property is required.
317: </UL>
318:
319: A secondary index i (a, b) on table t (a, b, c) would have rows
320: which looked like (a, b, row_location). baseConglomerateId is set to the
321: conglomerate id of t. rowLocationColumns is set to 2. allowsDuplicates
322: would be set to false, @see BTree#create. To create a unique
323: secondary index set uniquenessColumns to 2, this means that the btree
324: code will compare the key values but not the row id when determing
325: uniqueness. To create a nonunique secondary index set uniquenessColumns
326: to 3, this would mean that the uniqueness test would include the row
327: location and since all row locations will be unique all rows inserted
328: into the index will be differentiated (at least) by row location.
329:
330: @see BTree#create
331:
332: @exception StandardException Standard exception policy.
333: **/
334: public void create(TransactionManager xact_manager, int segmentId,
335: long input_conglomid, DataValueDescriptor[] template,
336: ColumnOrdering[] columnOrder, Properties properties,
337: int temporaryFlag) throws StandardException {
338: String property_value = null;
339: Transaction rawtran = xact_manager.getRawStoreXact();
340:
341: if (properties == null) {
342: throw (StandardException.newException(
343: SQLState.BTREE_PROPERTY_NOT_FOUND,
344: PROPERTY_BASECONGLOMID));
345: }
346:
347: // Get baseConglomerateId //
348: property_value = properties.getProperty(PROPERTY_BASECONGLOMID);
349: if (property_value == null) {
350: throw (StandardException.newException(
351: SQLState.BTREE_PROPERTY_NOT_FOUND,
352: PROPERTY_BASECONGLOMID));
353: }
354:
355: if (SanityManager.DEBUG) {
356: if (property_value == null)
357: SanityManager.THROWASSERT(PROPERTY_BASECONGLOMID
358: + "property not passed to B2I.create()");
359: }
360:
361: baseConglomerateId = Long.parseLong(property_value);
362:
363: // Get rowLocationColumn //
364: property_value = properties.getProperty(PROPERTY_ROWLOCCOLUMN);
365:
366: if (SanityManager.DEBUG) {
367: if (property_value == null)
368: SanityManager.THROWASSERT(PROPERTY_ROWLOCCOLUMN
369: + "property not passed to B2I.create()");
370: }
371:
372: if (property_value == null) {
373: throw (StandardException.newException(
374: SQLState.BTREE_PROPERTY_NOT_FOUND,
375: PROPERTY_BASECONGLOMID));
376: }
377:
378: rowLocationColumn = Integer.parseInt(property_value);
379:
380: // Currently the row location column must be the last column (makes)
381: // comparing the columns in the index easier.
382: if (SanityManager.DEBUG) {
383: SanityManager
384: .ASSERT(rowLocationColumn == template.length - 1,
385: "rowLocationColumn is not the last column in the index");
386: SanityManager
387: .ASSERT(template[rowLocationColumn] instanceof RowLocation);
388:
389: // There must be at least one key column
390: if (rowLocationColumn < 1)
391: SanityManager.THROWASSERT("rowLocationColumn ("
392: + rowLocationColumn + ") expected to be >= 1");
393: }
394:
395: /* covert the sorting order information into a boolean array map.
396: * If the sorting order for the columns is not provided, we
397: * assign the default as Ascending Order.
398: * array length is equla to template length , because column order
399: * length changes wther it is unique is non unique. store assumes
400: * template length arrays. So , we make template length array and make
401: * the last column as ascending instead of having lot of execeptions code.
402: */
403:
404: ascDescInfo = new boolean[template.length];
405: for (int i = 0; i < ascDescInfo.length; i++) {
406: if (columnOrder != null && i < columnOrder.length)
407: ascDescInfo[i] = columnOrder[i].getIsAscending();
408: else
409: ascDescInfo[i] = true; // default values - ascending order
410: }
411:
412: // Do the generic part of creating the b-tree.
413: super .create(rawtran, segmentId, input_conglomid, template,
414: properties, getTypeFormatId(), temporaryFlag);
415:
416: // open the base conglomerate - to get the lock
417: ConglomerateController base_cc = xact_manager.openConglomerate(
418: baseConglomerateId, false,
419: TransactionController.OPENMODE_FOR_LOCK_ONLY,
420: TransactionController.MODE_TABLE,
421: TransactionController.ISOLATION_SERIALIZABLE);
422:
423: OpenBTree open_btree = new OpenBTree();
424:
425: BTreeLockingPolicy b2i_locking_policy = new B2ITableLocking3(
426: rawtran, TransactionController.MODE_TABLE,
427: rawtran.newLockingPolicy(LockingPolicy.MODE_CONTAINER,
428: TransactionController.ISOLATION_SERIALIZABLE,
429: true), base_cc, open_btree);
430:
431: // The following call will "open" the new btree. Create is
432: // an interesting case. What we really want is read only table lock
433: // on the base conglomerate and update locks on the index. For now
434: // just get the update lock on the base table, this is done by the
435: // lockTable() call made by base class.
436:
437: open_btree.init(
438: (TransactionManager) xact_manager, // current user xact
439: (TransactionManager) xact_manager, // current xact
440: (ContainerHandle) null, // have init open the container.
441: rawtran, false, (ContainerHandle.MODE_FORUPDATE),
442: TransactionController.MODE_TABLE, b2i_locking_policy, // get table level lock.
443: this , (LogicalUndo) null, // no logical undo necessary, as
444: // initEmptyBtree()
445: // work will be done single user and
446: // rows will not move.
447: (DynamicCompiledOpenConglomInfo) null);
448:
449: // Open the newly created container, and insert the first control row.
450: LeafControlRow.initEmptyBtree(open_btree);
451:
452: open_btree.close();
453:
454: base_cc.close();
455: }
456:
457: /*
458: ** Methods of Conglomerate
459: */
460:
461: /**
462: * Retrieve the maximum value row in an ordered conglomerate.
463: * <p>
464: * Returns true and fetches the rightmost row of an ordered conglomerate
465: * into "fetchRow" if there is at least one row in the conglomerate. If
466: * there are no rows in the conglomerate it returns false.
467: * <p>
468: * Non-ordered conglomerates will not implement this interface, calls
469: * will generate a StandardException.
470: * <p>
471: * RESOLVE - this interface is temporary, long term equivalent (and more)
472: * functionality will be provided by the openBackwardScan() interface.
473: *
474: * @param xact_manager The TransactionController under which this
475: * operation takes place.
476: *
477: * @param conglomId The identifier of the conglomerate
478: * to open the scan for.
479: *
480: * @param open_mode Specifiy flags to control opening of table.
481: * OPENMODE_FORUPDATE - if set open the table for
482: * update otherwise open table shared.
483: * @param lock_level One of (MODE_TABLE, MODE_RECORD, or MODE_NONE).
484: *
485: * @param isolation_level The isolation level to lock the conglomerate at.
486: * One of (ISOLATION_READ_COMMITTED or ISOLATION_SERIALIZABLE).
487: *
488: * @param scanColumnList A description of which columns to return from
489: * every fetch in the scan. template,
490: * and scanColumnList work together
491: * to describe the row to be returned by the scan -
492: * see RowUtil for description of how these three
493: * parameters work together to describe a "row".
494: *
495: * @param fetchRow The row to retrieve the maximum value into.
496: *
497: * @return boolean indicating if a row was found and retrieved or not.
498: *
499: * @exception StandardException Standard exception policy.
500: **/
501: public boolean fetchMaxOnBTree(TransactionManager xact_manager,
502: Transaction rawtran, long conglomId, int open_mode,
503: int lock_level, LockingPolicy locking_policy,
504: int isolation_level, FormatableBitSet scanColumnList,
505: DataValueDescriptor[] fetchRow) throws StandardException {
506: boolean row_exists;
507:
508: // row level locking implementation.
509:
510: // RESOLVE (revisit implementation after all the Xena rowlocking
511: // changes have been made). Can probably come up with single
512: // path implementation.
513:
514: // Create a new b-tree secondary index scan.
515: B2IMaxScan b2is = new B2IMaxScan();
516:
517: // Initialize it.
518: b2is.init(xact_manager, rawtran, open_mode, lock_level,
519: locking_policy, isolation_level,
520: true /* get locks on base table as part of open */,
521: scanColumnList, this , new B2IUndo());
522:
523: row_exists = b2is.fetchMax(fetchRow);
524:
525: b2is.close();
526:
527: return (row_exists);
528: }
529:
530: /**
531: Bulk Load a B-tree secondary index.
532:
533: @see Conglomerate#load
534: @exception StandardException Standard Cloudscape Error policy.
535: raise SQLState.STORE_CONGLOMERATE_DUPLICATE_KEY_EXCEPTION if a duplicate
536: key is detected in the load.
537: **/
538:
539: public long load(TransactionManager xact_manager,
540: boolean createConglom, RowLocationRetRowSource rowSource)
541: throws StandardException {
542: long num_rows_loaded = 0;
543: B2IController b2ic = new B2IController();
544:
545: try {
546: int open_mode = TransactionController.OPENMODE_FORUPDATE;
547:
548: if (createConglom) {
549: open_mode |= (ContainerHandle.MODE_UNLOGGED | ContainerHandle.MODE_CREATE_UNLOGGED);
550: }
551:
552: // Do the actual open of the container in the super class.
553: b2ic
554: .init(
555: xact_manager, // current transaction
556: xact_manager.getRawStoreXact(), // current raw store xact
557: false, // Not holdable
558: open_mode,
559: TransactionController.MODE_TABLE,
560: xact_manager
561: .getRawStoreXact()
562: .newLockingPolicy(
563: LockingPolicy.MODE_CONTAINER,
564: TransactionController.ISOLATION_SERIALIZABLE,
565: true), true, this ,
566: new B2IUndo(),
567: (B2IStaticCompiledInfo) null,
568: (DynamicCompiledOpenConglomInfo) null);
569:
570: num_rows_loaded = b2ic.load(xact_manager, createConglom,
571: rowSource);
572:
573: } finally {
574: b2ic.close();
575: }
576:
577: return (num_rows_loaded);
578: }
579:
580: /**
581: Open a b-tree controller.
582: @see Conglomerate#open
583:
584: @exception StandardException Standard exception policy.
585: **/
586: public ConglomerateController open(TransactionManager xact_manager,
587: Transaction rawtran, boolean hold, int open_mode,
588: int lock_level, LockingPolicy locking_policy,
589: StaticCompiledOpenConglomInfo static_info,
590: DynamicCompiledOpenConglomInfo dynamic_info)
591: throws StandardException {
592: // Create a new b-tree secondary index controller.
593: B2IController b2ic = new B2IController();
594:
595: // Do the actual open of the container in the super class.
596: b2ic.init(
597: xact_manager, // current transaction
598: rawtran, // current raw store transaction
599: hold, // holdability
600: open_mode, lock_level, locking_policy, true, this ,
601: new B2IUndo(), (B2IStaticCompiledInfo) static_info,
602: dynamic_info);
603:
604: // Return it to the caller.
605: return b2ic;
606: }
607:
608: /**
609: Open a b-tree secondary index scan controller.
610: @see Conglomerate#openScan
611: @see BTree#openScan
612:
613: @exception StandardException Standard exception policy.
614: **/
615: public ScanManager openScan(TransactionManager xact_manager,
616: Transaction rawtran, boolean hold, int open_mode,
617: int lock_level, LockingPolicy locking_policy,
618: int isolation_level, FormatableBitSet scanColumnList,
619: DataValueDescriptor[] startKeyValue,
620: int startSearchOperator, Qualifier qualifier[][],
621: DataValueDescriptor[] stopKeyValue, int stopSearchOperator,
622: StaticCompiledOpenConglomInfo static_info,
623: DynamicCompiledOpenConglomInfo dynamic_info)
624: throws StandardException {
625: // Create a new b-tree secondary index scan.
626: B2IForwardScan b2is = new B2IForwardScan();
627:
628: // Initialize it.
629: b2is.init(xact_manager, rawtran, hold, open_mode, lock_level,
630: locking_policy, isolation_level,
631: true /* get locks on base table as part of open */,
632: scanColumnList, startKeyValue, startSearchOperator,
633: qualifier, stopKeyValue, stopSearchOperator, this ,
634: new B2IUndo(), (B2IStaticCompiledInfo) static_info,
635: dynamic_info);
636:
637: // Return it to the caller.
638: return b2is;
639: }
640:
641: /**
642: * Open a b-tree compress scan.
643: * <p>
644: * B2I does not support a compress scan.
645: * <p>
646: * @see Conglomerate#defragmentConglomerate
647: *
648: * @exception StandardException Standard exception policy.
649: **/
650: public ScanManager defragmentConglomerate(
651: TransactionManager xact_manager, Transaction rawtran,
652: boolean hold, int open_mode, int lock_level,
653: LockingPolicy locking_policy, int isolation_level)
654: throws StandardException {
655: throw StandardException
656: .newException(SQLState.BTREE_UNIMPLEMENTED_FEATURE);
657: }
658:
659: public void purgeConglomerate(TransactionManager xact_manager,
660: Transaction rawtran) throws StandardException {
661: // currently on work to do in btree's for purge rows, purging
662: // happens best when split is about to happen.
663: return;
664: }
665:
666: public void compressConglomerate(TransactionManager xact_manager,
667: Transaction rawtran) throws StandardException {
668: B2IController b2ic = new B2IController();
669:
670: try {
671: int open_mode = TransactionController.OPENMODE_FORUPDATE;
672:
673: // Do the actual open of the container in the super class.
674: b2ic
675: .init(
676: xact_manager, // current transaction
677: xact_manager.getRawStoreXact(), // current raw store xact
678: false, // Not holdable
679: open_mode,
680: TransactionController.MODE_TABLE,
681: xact_manager
682: .getRawStoreXact()
683: .newLockingPolicy(
684: LockingPolicy.MODE_CONTAINER,
685: TransactionController.ISOLATION_SERIALIZABLE,
686: true), true, this ,
687: new B2IUndo(),
688: (B2IStaticCompiledInfo) null,
689: (DynamicCompiledOpenConglomInfo) null);
690:
691: b2ic.getContainer().compressContainer();
692:
693: } finally {
694: b2ic.close();
695: }
696:
697: return;
698: }
699:
700: /**
701: * Return an open StoreCostController for the conglomerate.
702: * <p>
703: * Return an open StoreCostController which can be used to ask about
704: * the estimated row counts and costs of ScanController and
705: * ConglomerateController operations, on the given conglomerate.
706: * <p>
707: * @param xact_manager The TransactionController under which this
708: * operation takes place.
709: * @param rawtran raw transaction context in which scan is managed.
710: *
711: * @return The open StoreCostController.
712: *
713: * @exception StandardException Standard exception policy.
714: *
715: * @see StoreCostController
716: **/
717: public StoreCostController openStoreCost(
718: TransactionManager xact_manager, Transaction rawtran)
719: throws StandardException {
720: B2ICostController b2icost = new B2ICostController();
721:
722: b2icost.init(xact_manager, this , rawtran);
723:
724: return (b2icost);
725: }
726:
727: /**
728: Drop this b-tree secondary index.
729: @see Conglomerate#drop
730: @see BTree#drop
731:
732: @exception StandardException Standard exception policy.
733: **/
734: public void drop(TransactionManager xact_manager)
735: throws StandardException {
736: // HACK to get around problem where index is dropped after the base
737: // table.
738: ConglomerateController base_cc = null;
739:
740: /* Get X table lock to make sure no thread is accessing index */
741: base_cc = lockTable(xact_manager,
742: TransactionController.OPENMODE_FORUPDATE,
743: TransactionController.MODE_TABLE,
744: TransactionController.ISOLATION_REPEATABLE_READ);
745:
746: xact_manager.getRawStoreXact().dropContainer(id);
747:
748: if (base_cc != null)
749: base_cc.close();
750: }
751:
752: /**
753: * Return static information about the conglomerate to be included in a
754: * a compiled plan.
755: * <p>
756: * The static info would be valid until any ddl was executed on the
757: * conglomid, and would be up to the caller to throw away when that
758: * happened. This ties in with what language already does for other
759: * invalidation of static info. The type of info in this would be
760: * containerid and array of format id's from which templates can be created.
761: * The info in this object is read only and can be shared among as many
762: * threads as necessary.
763: * <p>
764: *
765: * @return The static compiled information.
766: *
767: * @param conglomId The identifier of the conglomerate to open.
768: *
769: * @exception StandardException Standard exception policy.
770: **/
771: public StaticCompiledOpenConglomInfo getStaticCompiledConglomInfo(
772: TransactionController xact_manager, long conglomId)
773: throws StandardException {
774: return (new B2IStaticCompiledInfo(xact_manager, this ));
775: }
776:
777: /*
778: ** Methods of Storable (via Conglomerate via BTree).
779: ** This class is responsible for re/storing its
780: ** own state and calling its superclass to store its'.
781: */
782:
783: /*
784: * Storable interface, implies Externalizable, TypedFormat
785: */
786:
787: /**
788: Return my format identifier.
789:
790: @see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId
791: */
792: public int getTypeFormatId() {
793: return StoredFormatIds.ACCESS_B2I_V3_ID;
794: }
795:
796: /**
797: Store the stored representation of the column value in the stream.
798: It might be easier to simply store the properties - which would certainly
799: make upgrading easier.*/
800: public void writeExternal_v36(ObjectOutput out) throws IOException {
801: super .writeExternal(out);
802: out.writeLong(baseConglomerateId);
803: out.writeInt(rowLocationColumn);
804: }
805:
806: /**
807: Restore the in-memory representation from the stream.
808:
809: @exception ClassNotFoundException Thrown if the stored representation is
810: serialized and a class named in the stream could not be found.
811:
812: @see java.io.Externalizable#readExternal
813: */
814: public void readExternal_v36(ObjectInput in) throws IOException,
815: ClassNotFoundException {
816: super .readExternal(in);
817:
818: // XXX (nat) need to improve error handling
819: baseConglomerateId = in.readLong();
820: rowLocationColumn = in.readInt();
821: //set the default (Ascending) sort order
822: ascDescInfo = new boolean[nKeyFields];
823: for (int i = 0; i < ascDescInfo.length; i++)
824: ascDescInfo[i] = true;
825: }
826:
827: /**
828: Store the stored representation of the column value in the stream.
829: It might be easier to simply store the properties - which would certainly
830: make upgrading easier.
831:
832: */
833: public void writeExternal(ObjectOutput out) throws IOException {
834: super .writeExternal(out);
835: out.writeLong(baseConglomerateId);
836: out.writeInt(rowLocationColumn);
837:
838: // if the conglomerate type is not not the version2
839: // sorting information is stored from version V3(release 3.7)
840: if (conglom_format_id != StoredFormatIds.ACCESS_B2I_V2_ID) {
841: //write the coulmsn sort information as bits
842: FormatableBitSet ascDescBits = new FormatableBitSet(
843: ascDescInfo.length);
844: for (int i = 0; i < ascDescInfo.length; i++) {
845: if (ascDescInfo[i])
846: ascDescBits.set(i);
847: }
848: ascDescBits.writeExternal(out);
849: }
850:
851: }
852:
853: /**
854: Restore the in-memory representation from the stream.
855:
856: @exception ClassNotFoundException Thrown if the stored representation is
857: serialized and a class named in the stream could not be found.
858:
859: @see java.io.Externalizable#readExternal
860: */
861: private final void localReadExternal(ObjectInput in)
862: throws IOException, ClassNotFoundException {
863: super .readExternal(in);
864:
865: // XXX (nat) need to improve error handling
866: baseConglomerateId = in.readLong();
867: rowLocationColumn = in.readInt();
868:
869: // if the conglomerate type is not the version2
870: // sorting info is avaialable from version v3(release 3.7)
871: if (conglom_format_id != StoredFormatIds.ACCESS_B2I_V2_ID) {
872: // read the column sort order info
873: FormatableBitSet ascDescBits = new FormatableBitSet();
874: ascDescBits.readExternal(in);
875: ascDescInfo = new boolean[ascDescBits.getLength()];
876: for (int i = 0; i < ascDescBits.getLength(); i++)
877: ascDescInfo[i] = ascDescBits.isSet(i);
878: } else {
879: //set the default (Ascending) sort order
880: ascDescInfo = new boolean[nKeyFields];
881: for (int i = 0; i < ascDescInfo.length; i++)
882: ascDescInfo[i] = true;
883:
884: }
885:
886: }
887:
888: public void readExternal(ObjectInput in) throws IOException,
889: ClassNotFoundException {
890: localReadExternal(in);
891: }
892:
893: public void readExternalFromArray(ArrayInputStream in)
894: throws IOException, ClassNotFoundException {
895: localReadExternal(in);
896: }
897: }
|