use of org.apache.derby.iapi.store.access.TransactionController in project derby by apache.
the class AlterTableConstantAction method defragmentRows.
/**
* Defragment rows in the given table.
* <p>
* Scans the rows at the end of a table and moves them to free spots
* towards the beginning of the table. In the same transaction all
* associated indexes are updated to reflect the new location of the
* base table row.
* <p>
* After a defragment pass, if was possible, there will be a set of
* empty pages at the end of the table which can be returned to the
* operating system by calling truncateEnd(). The allocation bit
* maps will be set so that new inserts will tend to go to empty and
* half filled pages starting from the front of the conglomerate.
*
* @param tc transaction controller to use to do updates.
*/
private void defragmentRows(TransactionController tc) throws StandardException {
GroupFetchScanController base_group_fetch_cc = null;
int num_indexes = 0;
int[][] index_col_map = null;
ScanController[] index_scan = null;
ConglomerateController[] index_cc = null;
DataValueDescriptor[][] index_row = null;
TransactionController nested_tc = null;
try {
nested_tc = tc.startNestedUserTransaction(false, true);
switch(td.getTableType()) {
/* Skip views and vti tables */
case TableDescriptor.VIEW_TYPE:
case TableDescriptor.VTI_TYPE:
return;
// DERBY-719,DERBY-720
default:
break;
}
/* Get a row template for the base table */
ExecRow br = lcc.getLanguageConnectionFactory().getExecutionFactory().getValueRow(td.getNumberOfColumns());
/* Fill the row with nulls of the correct type */
for (ColumnDescriptor cd : td.getColumnDescriptorList()) {
br.setColumn(cd.getPosition(), cd.getType().getNull());
}
DataValueDescriptor[][] row_array = new DataValueDescriptor[100][];
row_array[0] = br.getRowArray();
RowLocation[] old_row_location_array = new RowLocation[100];
RowLocation[] new_row_location_array = new RowLocation[100];
// Create the following 3 arrays which will be used to update
// each index as the scan moves rows about the heap as part of
// the compress:
// index_col_map - map location of index cols in the base row,
// ie. index_col_map[0] is column offset of 1st
// key column in base row. All offsets are 0
// based.
// index_scan - open ScanController used to delete old index row
// index_cc - open ConglomerateController used to insert new
// row
ConglomerateDescriptor[] conglom_descriptors = td.getConglomerateDescriptors();
// conglom_descriptors has an entry for the conglomerate and each
// one of it's indexes.
num_indexes = conglom_descriptors.length - 1;
// if indexes exist, set up data structures to update them
if (num_indexes > 0) {
// allocate arrays
index_col_map = new int[num_indexes][];
index_scan = new ScanController[num_indexes];
index_cc = new ConglomerateController[num_indexes];
index_row = new DataValueDescriptor[num_indexes][];
setup_indexes(nested_tc, td, index_col_map, index_scan, index_cc, index_row);
}
/* Open the heap for reading */
base_group_fetch_cc = nested_tc.defragmentConglomerate(td.getHeapConglomerateId(), false, true, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE);
int num_rows_fetched;
while ((num_rows_fetched = base_group_fetch_cc.fetchNextGroup(row_array, old_row_location_array, new_row_location_array)) != 0) {
if (num_indexes > 0) {
for (int row = 0; row < num_rows_fetched; row++) {
for (int index = 0; index < num_indexes; index++) {
fixIndex(row_array[row], index_row[index], old_row_location_array[row], new_row_location_array[row], index_cc[index], index_scan[index], index_col_map[index]);
}
}
}
}
// TODO - It would be better if commits happened more frequently
// in the nested transaction, but to do that there has to be more
// logic to catch a ddl that might jump in the middle of the
// above loop and invalidate the various table control structures
// which are needed to properly update the indexes. For example
// the above loop would corrupt an index added midway through
// the loop if not properly handled. See DERBY-1188.
nested_tc.commit();
} finally {
/* Clean up before we leave */
if (base_group_fetch_cc != null) {
base_group_fetch_cc.close();
base_group_fetch_cc = null;
}
if (num_indexes > 0) {
for (int i = 0; i < num_indexes; i++) {
if (index_scan != null && index_scan[i] != null) {
index_scan[i].close();
index_scan[i] = null;
}
if (index_cc != null && index_cc[i] != null) {
index_cc[i].close();
index_cc[i] = null;
}
}
}
if (nested_tc != null) {
nested_tc.destroy();
}
}
}
use of org.apache.derby.iapi.store.access.TransactionController in project derby by apache.
the class GenericLanguageConnectionContext method setIsolationLevel.
/**
* @see LanguageConnectionContext#setIsolationLevel
*/
public void setIsolationLevel(int isolationLevel) throws StandardException {
StatementContext stmtCtxt = getStatementContext();
if (stmtCtxt != null && stmtCtxt.inTrigger())
throw StandardException.newException(SQLState.LANG_NO_XACT_IN_TRIGGER, getTriggerExecutionContext().toString());
// shouldn't rely on transaction state.
if (this.isolationLevel != isolationLevel) {
if (!verifyAllHeldResultSetsAreClosed()) {
throw StandardException.newException(SQLState.LANG_CANT_CHANGE_ISOLATION_HOLD_CURSOR);
}
}
/* Commit and set to new isolation level.
* NOTE: We commit first in case there's some kind
* of error, like can't commit within a server side jdbc call.
*/
TransactionController tc = getTransactionExecute();
if (!tc.isIdle()) {
// transaction.
if (tc.isGlobal())
throw StandardException.newException(SQLState.LANG_NO_SET_TRAN_ISO_IN_GLOBAL_CONNECTION);
userCommit();
}
this.isolationLevel = isolationLevel;
this.isolationLevelExplicitlySet = true;
this.isolationLevelSetUsingSQLorJDBC = true;
}
use of org.apache.derby.iapi.store.access.TransactionController in project derby by apache.
the class GenericLanguageConnectionContext method tempTablesXApostCommit.
private void tempTablesXApostCommit() throws StandardException {
TransactionController tc = getTransactionExecute();
// transaction boundary.
for (int i = 0; i < allDeclaredGlobalTempTables.size(); i++) {
// remove all temp tables from this context.
TableDescriptor td = allDeclaredGlobalTempTables.get(i).getTableDescriptor();
// remove the conglomerate created for this temp table
tc.dropConglomerate(td.getHeapConglomerateId());
// remove it from the list of temp tables
allDeclaredGlobalTempTables.remove(i);
}
tc.commit();
}
use of org.apache.derby.iapi.store.access.TransactionController in project derby by apache.
the class GenericLanguageConnectionContext method doCommit.
/**
* This is where the work on internalCommit(), userCOmmit() and
* internalCommitNoSync() actually takes place.
* <p>
* When a commit happens, the language connection context
* will close all open activations/cursors and commit the
* Store transaction.
* <p>
* REVISIT: we talked about having a LanguageTransactionContext,
* but since store transaction management is currently in flux
* and our context might want to delegate to that context,
* for now all commit/rollback actions are handled directly by
* the language connection context.
* REVISIT: this may need additional alterations when
* RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up.
* <P>
* Since the access manager's own context takes care of its own
* resources on commit, and the transaction stays open, there is
* nothing that this context has to do with the transaction controller.
* <p>
* Also, tell the data dictionary that the transaction is finished,
* if necessary (that is, if the data dictionary was put into
* DDL mode in this transaction.
*
* @param commitStore true if we should commit the Store transaction
* @param sync true means do a synchronized commit,
* false means do an unsynchronized commit
* @param commitflag if this is an unsynchronized commit, the flags to
* pass to commitNoSync in the store's
* TransactionController. If this is a synchronized
* commit, this flag is overloaded for xacommit.
* @param requestedByUser False iff the commit is for internal use and
* we should ignore the check to prevent commits
* in an atomic statement.
*
* @exception StandardException Thrown on error
*/
protected void doCommit(boolean commitStore, boolean sync, int commitflag, boolean requestedByUser) throws StandardException {
StatementContext statementContext = getStatementContext();
if (requestedByUser && (statementContext != null) && statementContext.inUse() && statementContext.isAtomic()) {
throw StandardException.newException(SQLState.LANG_NO_COMMIT_IN_NESTED_CONNECTION);
}
checkIntegrity();
// Log commit to error log, if appropriate
if (logStatementText) {
if (istream == null) {
istream = Monitor.getStream();
}
String xactId = tran.getTransactionIdString();
istream.printlnWithHeader(LanguageConnectionContext.xidStr + xactId + "), " + LanguageConnectionContext.lccStr + instanceNumber + "), " + LanguageConnectionContext.dbnameStr + dbname + "), " + LanguageConnectionContext.drdaStr + drdaID + "), Committing");
}
endTransactionActivationHandling(false);
// Do clean up work required for temporary tables at commit time.
if (allDeclaredGlobalTempTables != null) {
tempTablesAndCommit(commitflag != NON_XA);
}
// reset the current savepoint level for the connection to 0 at the end
// of commit work for temp tables
currentSavepointLevel = 0;
// which could be rolled back in case of a system crash.
if (sync) {
finishDDTransaction();
}
// before a commit.
if (SanityManager.DEBUG) {
if (readOnlyNestedTransaction != null) {
SanityManager.THROWASSERT("Nested transaction active!");
}
}
// now commit the Store transaction
TransactionController tc = getTransactionExecute();
if (tc != null && commitStore) {
if (sync) {
if (commitflag == NON_XA) {
// regular commit
tc.commit();
} else {
if (SanityManager.DEBUG)
SanityManager.ASSERT(commitflag == XA_ONE_PHASE || commitflag == XA_TWO_PHASE, "invalid commit flag");
((XATransactionController) tc).xa_commit(commitflag == XA_ONE_PHASE);
}
} else {
tc.commitNoSync(commitflag);
}
// reset the savepoints to the new
// location, since any outer nesting
// levels expect there to be a savepoint
resetSavepoints();
// Do post commit XA temp table cleanup if necessary.
if ((allDeclaredGlobalTempTables != null) && (commitflag != NON_XA)) {
tempTablesXApostCommit();
}
}
}
use of org.apache.derby.iapi.store.access.TransactionController in project derby by apache.
the class GenericLanguageConnectionContext method doRollback.
/**
* When a rollback happens, the language connection context
* will close all open activations and invalidate
* their prepared statements. Then the language will abort the
* Store transaction.
* <p>
* The invalidated statements can revalidate themselves without
* a full recompile if they verify their dependencies' providers still
* exist unchanged. REVISIT when invalidation types are created.
* <p>
* REVISIT: this may need additional alterations when
* RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT show up.
* <p>
* Also, tell the data dictionary that the transaction is finished,
* if necessary (that is, if the data dictionary was put into
* DDL mode in this transaction.
*
* @param xa true if this is an xa rollback
* @param requestedByUser true if requested by user
*
* @exception StandardException thrown on failure
*/
private void doRollback(boolean xa, boolean requestedByUser) throws StandardException {
StatementContext statementContext = getStatementContext();
if (requestedByUser && (statementContext != null) && statementContext.inUse() && statementContext.isAtomic()) {
throw StandardException.newException(SQLState.LANG_NO_ROLLBACK_IN_NESTED_CONNECTION);
}
clearDeferreds();
// Log rollback to error log, if appropriate
if (logStatementText) {
if (istream == null) {
istream = Monitor.getStream();
}
String xactId = tran.getTransactionIdString();
istream.printlnWithHeader(LanguageConnectionContext.xidStr + xactId + "), " + LanguageConnectionContext.lccStr + instanceNumber + "), " + LanguageConnectionContext.dbnameStr + dbname + "), " + LanguageConnectionContext.drdaStr + drdaID + "), Rolling back");
}
endTransactionActivationHandling(true);
// reset the current savepoint level for the connection to 0 at the beginning of rollback work for temp tables
currentSavepointLevel = 0;
if (allDeclaredGlobalTempTables != null)
tempTablesAndRollback();
finishDDTransaction();
// with the user transaction.
if (readOnlyNestedTransaction != null) {
readOnlyNestedTransaction.destroy();
readOnlyNestedTransaction = null;
queryNestingDepth = 0;
}
// now rollback the Store transaction
TransactionController tc = getTransactionExecute();
if (tc != null) {
if (xa)
((XATransactionController) tc).xa_rollback();
else
tc.abort();
// reset the savepoints to the new
// location, since any outer nesting
// levels expet there to be a savepoint
resetSavepoints();
}
}
Aggregations