// Create the btree so that it only allows 2 rows per page.
createCongloms(tc, 2, false, false, 2, create_ret);
// Open the base table
ConglomerateController base_cc =
tc.openConglomerate(
create_ret.base_conglomid,
false,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_RECORD,
TransactionController.ISOLATION_SERIALIZABLE);
// Open the secondary index
ConglomerateController index_cc =
tc.openConglomerate(
create_ret.index_conglomid,
false,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_RECORD,
TransactionController.ISOLATION_SERIALIZABLE);
if (!(index_cc instanceof B2IController))
{
throw T_Fail.testFailMsg("openConglomerate returned wrong type");
}
index_cc.checkConsistency();
// Create a row and insert into base table, remembering it's location.
DataValueDescriptor[] r1 = TemplateRow.newU8Row(2);
T_SecondaryIndexRow index_row1 = new T_SecondaryIndexRow();
RowLocation base_rowloc1 = base_cc.newRowLocationTemplate();
index_row1.init(r1, base_rowloc1, 3);
// Commit the create of the tables so that the following aborts don't
// undo that work.
tc.commit();
// Now try aborts of transactions during splits, using magic
// trace flags. This test inserts enough rows to cause a split
// and then forces the split to fail at various key points. The
// split should be backed out and also the rows before the split.
// The test makes sure that there are some inserts before the forced
// split abort.
String[] debug_strings = {
"leaf_split_growRoot1",
"leaf_split_growRoot2",
"leaf_split_growRoot3",
"leaf_split_growRoot4",
"leaf_split_growRoot5",
"leaf_split_abort1",
"leaf_split_abort2",
"leaf_split_abort3",
"leaf_split_abort4",
"branch_split_abort1",
"branch_split_abort2",
"branch_split_abort3",
"branch_split_abort4",
"BTreeController_doIns2"
};
for (int errs = 0; errs < debug_strings.length; errs++)
{
REPORT("Doing abort test: " + debug_strings[errs]);
// set the debug flag, which will cause an error
// RESOLVE (mmm) these tests should be run from the language to
// make sure error handling really works.
if (SanityManager.DEBUG)
SanityManager.DEBUG_SET(debug_strings[errs]);
try
{
// Open the base table
base_cc =
tc.openConglomerate(
create_ret.base_conglomid,
false,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_RECORD,
TransactionController.ISOLATION_SERIALIZABLE);
// Open the secondary index
index_cc =
tc.openConglomerate(
create_ret.index_conglomid,
false,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_RECORD,
TransactionController.ISOLATION_SERIALIZABLE);
// insert one row that does not cause failure.
((SQLLongint)r1[0]).setValue(2);
((SQLLongint)r1[1]).setValue(10000 + errs);
// Insert the row into the base table;remember its location.
base_cc.insertAndFetchLocation(r1, base_rowloc1);
// Insert the row into the secondary index.
if (index_cc.insert(index_row1.getRow()) != 0)
throw T_Fail.testFailMsg("insert failed");
// set the debug flag, which will cause an error
// RESOLVE (mmm) these tests should be run from the
// language to make sure error handling really works.
if (SanityManager.DEBUG)
SanityManager.DEBUG_SET(debug_strings[errs]);
// now insert enough rows to cause failure
for (int i = 100; i > 0; i -= 2)
{
((SQLLongint)r1[0]).setValue(2);
((SQLLongint)r1[1]).setValue(i);
// Insert the row into the base table;remember its location.
base_cc.insertAndFetchLocation(r1, base_rowloc1);
// Insert the row into the secondary index.
if (index_cc.insert(index_row1.getRow()) != 0)
{
throw T_Fail.testFailMsg("insert failed");
}
}
throw T_Fail.testFailMsg(
"debug flag (" + debug_strings[errs] +
")did not cause exception.");
}
catch (StandardException e)
{
ContextService contextFactory = ContextService.getFactory();
// Get the context manager.
ContextManager cm = contextFactory.getCurrentContextManager();
if (SanityManager.DEBUG)
SanityManager.ASSERT(cm != null);
cm.cleanupOnError(e);
// RESOLVE (mikem) - when split abort works come up with
// a good sanity check here.
//
// index check - there should be no records:
scan = tc.openScan(create_ret.index_conglomid, false,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_RECORD,
TransactionController.ISOLATION_SERIALIZABLE,
(FormatableBitSet) null,
null, ScanController.NA,
null,
null, ScanController.NA);
index_cc =
tc.openConglomerate(
create_ret.index_conglomid,
false,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_RECORD,
TransactionController.ISOLATION_SERIALIZABLE);
index_cc.checkConsistency();
index_cc.close();
if (scan.next())
{
throw T_Fail.testFailMsg(
"t_002: there are still rows in table.");
}
scan.close();
}
// Unset the flag.
if (SanityManager.DEBUG)
SanityManager.DEBUG_CLEAR(debug_strings[errs]);
}
// Try a simple abort. The following adds enough rows to cause a
// split. The result of the split should be a tree with no rows, but
// the splits will not be undone. It is up to the implementation
// whether the undo's cause shrinks in the tree. In the initial
// implementation it won't.
{
tc.commit();
// Open the base table
base_cc =
tc.openConglomerate(
create_ret.base_conglomid,
false,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_RECORD,
TransactionController.ISOLATION_SERIALIZABLE);
// Open the secondary index
index_cc =
tc.openConglomerate(
create_ret.index_conglomid,
false,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_RECORD,
TransactionController.ISOLATION_SERIALIZABLE);
// BTree.PROPERTY_MAX_ROWS_PER_PAGE_PARAMETER has been set to 2 so
// inserting 3 rows will cause a split at the leaf level.
// Make sure that normal abort leaves the committed split.
for (int i = 0; i < 3; i++)
{
((SQLLongint)r1[0]).setValue(2);
((SQLLongint)r1[1]).setValue(i);
// Insert the row into the base table;remember its location.
base_cc.insertAndFetchLocation(r1, base_rowloc1);
// Insert the row into the secondary index.
if (index_cc.insert(index_row1.getRow()) != 0)
throw T_Fail.testFailMsg("insert failed");
}
tc.abort();