public void compressConglomerate(TransactionManager xact_manager, Transaction rawtran) throws StandardException { B2IController b2ic = new B2IController(); try { int open_mode = TransactionController.OPENMODE_FORUPDATE; // Do the actual open of the container in the super class. b2ic.init( xact_manager, // current transaction xact_manager.getRawStoreXact(), // current raw store xact false, // Not holdable open_mode, TransactionController.MODE_TABLE, xact_manager .getRawStoreXact() .newLockingPolicy( LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true), true, this, new B2IUndo(), (B2IStaticCompiledInfo) null, (DynamicCompiledOpenConglomInfo) null); b2ic.getContainer().compressContainer(); } finally { b2ic.close(); } return; }
protected void queueDeletePostCommitWork(RowPosition pos) throws StandardException { TransactionManager xact_mgr = open_conglom.getXactMgr(); xact_mgr.addPostCommitWork( new HeapPostCommit( xact_mgr.getAccessManager(), (Heap) open_conglom.getConglomerate(), pos.current_page.getPageNumber())); }
/** * Lock the base table. * * <p>Assumes that segment of the base container is the same as the segment of the btree segment. * * <p>RESOLVE - we really want to get the lock without opening the container. raw store will be * providing this. * * @param xact_manager Transaction to associate the lock with. * @exception StandardException Standard exception policy. */ public final ConglomerateController lockTable( TransactionManager xact_manager, int open_mode, int lock_level, int isolation_level) throws StandardException { open_mode |= TransactionController.OPENMODE_FOR_LOCK_ONLY; // open the base conglomerate - just to get the table lock. ConglomerateController cc = xact_manager.openConglomerate( this.baseConglomerateId, false, open_mode, lock_level, isolation_level); return (cc); }
/** * Bulk Load a B-tree secondary index. * * @see Conglomerate#load * @exception StandardException Standard Derby Error policy. raise * SQLState.STORE_CONGLOMERATE_DUPLICATE_KEY_EXCEPTION if a duplicate key is detected in the * load. */ public long load( TransactionManager xact_manager, boolean createConglom, RowLocationRetRowSource rowSource) throws StandardException { long num_rows_loaded = 0; B2IController b2ic = new B2IController(); try { int open_mode = TransactionController.OPENMODE_FORUPDATE; if (createConglom) { open_mode |= (ContainerHandle.MODE_UNLOGGED | ContainerHandle.MODE_CREATE_UNLOGGED); } // Do the actual open of the container in the super class. b2ic.init( xact_manager, // current transaction xact_manager.getRawStoreXact(), // current raw store xact false, // Not holdable open_mode, TransactionController.MODE_TABLE, xact_manager .getRawStoreXact() .newLockingPolicy( LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true), true, this, new B2IUndo(), (B2IStaticCompiledInfo) null, (DynamicCompiledOpenConglomInfo) null); num_rows_loaded = b2ic.load(xact_manager, createConglom, rowSource); } finally { b2ic.close(); } return (num_rows_loaded); }
/** * Drop this b-tree secondary index. * * @see Conglomerate#drop * @see BTree#drop * @exception StandardException Standard exception policy. */ public void drop(TransactionManager xact_manager) throws StandardException { // HACK to get around problem where index is dropped after the base // table. ConglomerateController base_cc = null; /* Get X table lock to make sure no thread is accessing index */ base_cc = lockTable( xact_manager, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_TABLE, TransactionController.ISOLATION_REPEATABLE_READ); xact_manager.getRawStoreXact().dropContainer(id); if (base_cc != null) base_cc.close(); }
/** * Initialize the scan for use. * * <p>Any changes to this method may have to be reflected in close as well. * * <p>The btree init opens the container (super.init), and stores away the state of the * qualifiers. The actual searching for the first position is delayed until the first next() call. * * @exception StandardException Standard exception policy. */ public void init( TransactionManager xact_manager, Transaction rawtran, int open_mode, int lock_level, LockingPolicy locking_policy, int isolation_level, boolean open_for_locking, FormatableBitSet scanColumnList, B2I conglomerate, B2IUndo undo) throws StandardException { // open and lock the base table. int base_open_mode = open_mode | TransactionController.OPENMODE_FOR_LOCK_ONLY; // open the base conglomerate - just to get lock base_cc_for_locking = xact_manager.openConglomerate( conglomerate.baseConglomerateId, false, base_open_mode, lock_level, isolation_level); BTreeLockingPolicy b2i_locking_policy = conglomerate.getBtreeLockingPolicy( rawtran, lock_level, open_mode, isolation_level, base_cc_for_locking, this); super.init( xact_manager, rawtran, false, open_mode, lock_level, b2i_locking_policy, scanColumnList, (DataValueDescriptor[]) null, // no start position supported ScanController.NA, // no start position supported (Qualifier[][]) null, // no qualifier supported (DataValueDescriptor[]) null, // no stop position supported ScanController.NA, // no stop position supported conglomerate, undo, (StaticCompiledOpenConglomInfo) null, (DynamicCompiledOpenConglomInfo) null); }
/** Initialize the scan, returning false if there was some error. */ public boolean init(TransactionManager tran) throws StandardException { if (SanityManager.DEBUG) { // We really expect to have at least one // merge run. SanityManager.ASSERT(mergeRuns != null); SanityManager.ASSERT(mergeRuns.size() > 0); // This sort scan also expects that the // caller has ensured that the sort buffer // capacity will hold a row from all the // merge runs. SanityManager.ASSERT(sortBuffer.capacity() >= mergeRuns.size()); } // Clear the sort buffer. sortBuffer.reset(); // Create an array to hold a scan controller // for each merge run. openScans = new StreamContainerHandle[mergeRuns.size()]; if (openScans == null) return false; // Open a scan on each merge run. int scanindex = 0; Enumeration e = mergeRuns.elements(); while (e.hasMoreElements()) { // get the container id long id = ((Long) e.nextElement()).longValue(); Transaction rawTran = tran.getRawStoreXact(); // get raw transaction int segmentId = StreamContainerHandle.TEMPORARY_SEGMENT; openScans[scanindex++] = rawTran.openStreamContainer(segmentId, id, hold); } // Load the initial rows. for (scanindex = 0; scanindex < openScans.length; scanindex++) mergeARow(scanindex); // Success! return true; }
protected long load( TransactionManager xact_manager, Heap heap, boolean createConglom, RowLocationRetRowSource rowSource) throws StandardException { long num_rows_loaded = 0; if (SanityManager.DEBUG) { SanityManager.ASSERT( open_conglom == null, "load expects container handle to be closed on entry."); } // The individual rows that are inserted are not logged. To use a // logged interface, use insert. RESOLVE: do we want to allow client // to use the load interface even for logged insert? int mode = (ContainerHandle.MODE_FORUPDATE | ContainerHandle.MODE_UNLOGGED); // If the container is being created in the same operation, don't log // page allocation. if (createConglom) mode |= ContainerHandle.MODE_CREATE_UNLOGGED; OpenConglomerate open_conglom = new OpenHeap(); if (open_conglom.init( (ContainerHandle) null, heap, heap.format_ids, heap.collation_ids, xact_manager, xact_manager.getRawStoreXact(), false, mode, TransactionController.MODE_TABLE, xact_manager .getRawStoreXact() .newLockingPolicy( LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true), (DynamicCompiledOpenConglomInfo) null) == null) { throw StandardException.newException( SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(heap.getId().getContainerId())); } this.init(open_conglom); // For bulk loading, we always use only brand new page because the row // insertion itself is not logged. We cannot pollute pages with // pre-existing data with unlogged rows because nobody is going to wipe // out these rows if the transaction rolls back. We are counting on // the allocation page rollback to obliterate these rows if the // transaction fails, or, in the CREAT_UNLOGGED case, the whole // container to be removed. Page page = open_conglom.getContainer().addPage(); boolean callbackWithRowLocation = rowSource.needsRowLocation(); RecordHandle rh; HeapRowLocation rowlocation; if (callbackWithRowLocation) rowlocation = new HeapRowLocation(); else rowlocation = null; FormatableBitSet validColumns = rowSource.getValidColumns(); try { // get the next row and its valid columns from the rowSource DataValueDescriptor[] row; while ((row = rowSource.getNextRowFromRowSource()) != null) { num_rows_loaded++; if (SanityManager.DEBUG) { // Make sure valid columns are in the list. The RowUtil // call is too expensive to make in a released system for // every insert. int invalidColumn = RowUtil.columnOutOfRange(row, validColumns, heap.format_ids.length); if (invalidColumn >= 0) { throw (StandardException.newException( SQLState.HEAP_TEMPLATE_MISMATCH, new Long(invalidColumn), new Long(heap.format_ids.length))); } } // Insert it onto this page as long as it can fit more rows. if ((rh = page.insert( row, validColumns, Page.INSERT_DEFAULT, AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD)) == null) { // Insert faied, row did not fit. Get a new page. page.unlatch(); page = null; page = open_conglom.getContainer().addPage(); // RESOLVE (mikem) - no long rows yet so the following code // will get an exception from the raw store for a row that // does not fit on a page. // // Multi-thread considerations aside, the raw store will // guarantee that any size row will fit on an empty page. rh = page.insert( row, validColumns, Page.INSERT_OVERFLOW, AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD); } // Else, the row fit. If we are expected to call back with the // row location, do so. All the while keep the page latched // and go for the next row. if (callbackWithRowLocation) { rowlocation.setFrom(rh); rowSource.rowLocation(rowlocation); } } page.unlatch(); page = null; // Done with the container, now we need to flush it to disk since // it is unlogged. if (!heap.isTemporary()) open_conglom.getContainer().flushContainer(); } finally { // If an error happened here, don't bother flushing the // container since the changes should be rolled back anyhow. close(); } return (num_rows_loaded); }
/** * Create an empty secondary index b-tree, using the generic b-tree to do the generic part of the * creation process. * * <p>This routine opens the newly created container, adds a single page, and makes this page the * root by inserting a LeafControlRow onto this page at slot 0 and marking in that control row * that the page is a root page. * * <p>The following properties are specific to the b-tree secondary index: * * <UL> * <LI>"baseConglomerateId" (integer). The conglomerate id of the base conglomerate is never * actually accessed by the b-tree secondary index implementation, it only serves as a * namespace for row locks. This property is required. * <LI>"rowLocationColumn" (integer). The zero-based index into the row which the b-tree * secondary index will assume holds a @see RowLocation of the base row in the base * conglomerate. This value will be used for acquiring locks. In this implementation * RowLocationColumn must be the last key column. This property is required. * </UL> * * A secondary index i (a, b) on table t (a, b, c) would have rows which looked like (a, b, * row_location). baseConglomerateId is set to the conglomerate id of t. rowLocationColumns is set * to 2. allowsDuplicates would be set to false, @see BTree#create. To create a unique secondary * index set uniquenessColumns to 2, this means that the btree code will compare the key values * but not the row id when determing uniqueness. To create a nonunique secondary index set * uniquenessColumns to 3, this would mean that the uniqueness test would include the row location * and since all row locations will be unique all rows inserted into the index will be * differentiated (at least) by row location. * * @see BTree#create * @exception StandardException Standard exception policy. */ public void create( TransactionManager xact_manager, int segmentId, long input_conglomid, DataValueDescriptor[] template, ColumnOrdering[] columnOrder, int[] collationIds, Properties properties, int temporaryFlag) throws StandardException { String property_value = null; Transaction rawtran = xact_manager.getRawStoreXact(); if (properties == null) { throw (StandardException.newException( SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID)); } // Get baseConglomerateId // property_value = properties.getProperty(PROPERTY_BASECONGLOMID); if (property_value == null) { throw (StandardException.newException( SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID)); } if (SanityManager.DEBUG) { if (property_value == null) SanityManager.THROWASSERT(PROPERTY_BASECONGLOMID + "property not passed to B2I.create()"); } baseConglomerateId = Long.parseLong(property_value); // Get rowLocationColumn // property_value = properties.getProperty(PROPERTY_ROWLOCCOLUMN); if (SanityManager.DEBUG) { if (property_value == null) SanityManager.THROWASSERT(PROPERTY_ROWLOCCOLUMN + "property not passed to B2I.create()"); } if (property_value == null) { throw (StandardException.newException( SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID)); } rowLocationColumn = Integer.parseInt(property_value); // Currently the row location column must be the last column (makes) // comparing the columns in the index easier. if (SanityManager.DEBUG) { SanityManager.ASSERT( rowLocationColumn == template.length - 1, "rowLocationColumn is not the last column in the index"); SanityManager.ASSERT(template[rowLocationColumn] instanceof RowLocation); // There must be at least one key column if (rowLocationColumn < 1) SanityManager.THROWASSERT( "rowLocationColumn (" + rowLocationColumn + ") expected to be >= 1"); } /* convert the sorting order information into a boolean array map. * If the sorting order for the columns is not provided, we * assign the default as Ascending Order. * array length is equal to template length, because column order * length changes whether it is unique or is non unique. store assumes * template length arrays. So, we make template length array and make * the last column as ascending instead of having lot of execeptions * code. */ ascDescInfo = new boolean[template.length]; for (int i = 0; i < ascDescInfo.length; i++) { if (columnOrder != null && i < columnOrder.length) ascDescInfo[i] = columnOrder[i].getIsAscending(); else ascDescInfo[i] = true; // default values - ascending order } // get collation ids from input collation ids, store it in the // conglom state. collation_ids = ConglomerateUtil.createCollationIds(template.length, collationIds); hasCollatedTypes = hasCollatedColumns(collation_ids); // Do the generic part of creating the b-tree. super.create( rawtran, segmentId, input_conglomid, template, properties, getTypeFormatId(), temporaryFlag); // open the base conglomerate - to get the lock ConglomerateController base_cc = xact_manager.openConglomerate( baseConglomerateId, false, TransactionController.OPENMODE_FOR_LOCK_ONLY, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE); OpenBTree open_btree = new OpenBTree(); BTreeLockingPolicy b2i_locking_policy = new B2ITableLocking3( rawtran, TransactionController.MODE_TABLE, rawtran.newLockingPolicy( LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true), base_cc, open_btree); // The following call will "open" the new btree. Create is // an interesting case. What we really want is read only table lock // on the base conglomerate and update locks on the index. For now // just get the update lock on the base table, this is done by the // lockTable() call made by base class. open_btree.init( (TransactionManager) xact_manager, // current user xact (TransactionManager) xact_manager, // current xact (ContainerHandle) null, // have init open the container. rawtran, false, (ContainerHandle.MODE_FORUPDATE), TransactionController.MODE_TABLE, b2i_locking_policy, // get table level lock. this, (LogicalUndo) null, // no logical undo necessary, as // initEmptyBtree() // work will be done single user and // rows will not move. (DynamicCompiledOpenConglomInfo) null); // Open the newly created container, and insert the first control row. LeafControlRow.initEmptyBtree(open_btree); open_btree.close(); base_cc.close(); }