use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class TabInfoImpl method insertRowListImpl.
/**
* Insert logic to insert a list of rows into a table. This logic has two
* odd features.
*
* <OL>
* <LI>Returns an indication if any returned row was a duplicate.
* <LI>Returns the RowLocation of the last row inserted.
* </OL>
* @param rowList the list of rows to insert
* @param tc transaction controller
* @param rowLocationOut on output rowLocationOut[0] is set to the
* last RowLocation inserted.
* @return row number (>= 0) if duplicate row inserted into an index
* ROWNOTDUPLICATE otherwise
*/
private int insertRowListImpl(ExecRow[] rowList, TransactionController tc, RowLocation[] rowLocationOut) throws StandardException {
ConglomerateController heapController;
RowLocation heapLocation;
ExecIndexRow indexableRow;
int insertRetCode;
int retCode = ROWNOTDUPLICATE;
int indexCount = crf.getNumIndexes();
ConglomerateController[] indexControllers = new ConglomerateController[indexCount];
// Open the conglomerates
heapController = tc.openConglomerate(getHeapConglomerate(), false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ);
for (int ictr = 0; ictr < indexCount; ictr++) {
long conglomNumber = getIndexConglomerate(ictr);
if (conglomNumber > -1) {
indexControllers[ictr] = tc.openConglomerate(conglomNumber, false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ);
}
}
heapLocation = heapController.newRowLocationTemplate();
rowLocationOut[0] = heapLocation;
// loop through rows on this list, inserting them into system table
for (int rowNumber = 0; rowNumber < rowList.length; rowNumber++) {
ExecRow row = rowList[rowNumber];
// insert the base row and get its new location
heapController.insertAndFetchLocation(row.getRowArray(), heapLocation);
for (int ictr = 0; ictr < indexCount; ictr++) {
if (indexControllers[ictr] == null) {
continue;
}
// Get an index row based on the base row
indexableRow = getIndexRowFromHeapRow(getIndexRowGenerator(ictr), heapLocation, row);
insertRetCode = indexControllers[ictr].insert(indexableRow.getRowArray());
if (insertRetCode == ConglomerateController.ROWISDUPLICATE) {
retCode = rowNumber;
}
}
}
// Close the open conglomerates
for (int ictr = 0; ictr < indexCount; ictr++) {
if (indexControllers[ictr] == null) {
continue;
}
indexControllers[ictr].close();
}
heapController.close();
return retCode;
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class IndexStatisticsDaemonImpl method updateIndexStatsMinion.
/**
* Updates the index statistics for the given table and the specified
* indexes.
* <p>
* <strong>API note</strong>: Using {@code null} to update the statistics
* for all conglomerates is preferred over explicitly passing an array with
* all the conglomerates for the table. Doing so allows for some
* optimizations, and will cause a disposable statistics check to be
* performed.
*
* @param lcc language connection context used to perform the work
* @param td the table to update index stats for
* @param cds the conglomerates to update statistics for (non-index
* conglomerates will be ignored), {@code null} means all indexes
* @param asBackgroundTask whether the updates are done automatically as
* part of a background task or if explicitly invoked by the user
* @throws StandardException if something goes wrong
*/
private void updateIndexStatsMinion(LanguageConnectionContext lcc, TableDescriptor td, ConglomerateDescriptor[] cds, boolean asBackgroundTask) throws StandardException {
// can only properly identify disposable stats if cds == null,
// which means we are processing all indexes on the conglomerate.
final boolean identifyDisposableStats = (cds == null);
// Fetch descriptors if we're updating statistics for all indexes.
if (cds == null) {
cds = td.getConglomerateDescriptors();
}
// Extract/derive information from the table descriptor
long[] conglomerateNumber = new long[cds.length];
ExecIndexRow[] indexRow = new ExecIndexRow[cds.length];
TransactionController tc = lcc.getTransactionExecute();
ConglomerateController heapCC = tc.openConglomerate(td.getHeapConglomerateId(), false, 0, TransactionController.MODE_RECORD, asBackgroundTask ? TransactionController.ISOLATION_READ_UNCOMMITTED : TransactionController.ISOLATION_REPEATABLE_READ);
// create a list of indexes that should have statistics, by looking
// at all indexes on the conglomerate, and conditionally skipping
// unique single column indexes. This set is the "non disposable
// stat list".
UUID[] non_disposable_objectUUID = new UUID[cds.length];
try {
for (int i = 0; i < cds.length; i++) {
// Skip non-index conglomerates
if (!cds[i].isIndex()) {
conglomerateNumber[i] = -1;
continue;
}
IndexRowGenerator irg = cds[i].getIndexDescriptor();
// or we are running in soft-upgrade-mode on a pre 10.9 db.
if (skipDisposableStats) {
if (irg.isUnique() && irg.numberOfOrderedColumns() == 1) {
conglomerateNumber[i] = -1;
continue;
}
}
// at this point have found a stat for an existing
// index which is not a single column unique index, add it
// to the list of "non disposable stats"
conglomerateNumber[i] = cds[i].getConglomerateNumber();
non_disposable_objectUUID[i] = cds[i].getUUID();
indexRow[i] = irg.getNullIndexRow(td.getColumnDescriptorList(), heapCC.newRowLocationTemplate());
}
} finally {
heapCC.close();
}
if (identifyDisposableStats) {
// Note this loop is not controlled by the skipDisposableStats
// flag. The above loop controls if we drop single column unique
// index stats or not. In all cases we are going to drop
// stats with no associated index (orphaned stats).
List<StatisticsDescriptor> existingStats = td.getStatistics();
StatisticsDescriptor[] stats = (StatisticsDescriptor[]) existingStats.toArray(new StatisticsDescriptor[existingStats.size()]);
// those entries that don't have a matching conglomerate in the
for (int si = 0; si < stats.length; si++) {
UUID referencedIndex = stats[si].getReferenceID();
boolean isValid = false;
for (int ci = 0; ci < conglomerateNumber.length; ci++) {
if (referencedIndex.equals(non_disposable_objectUUID[ci])) {
isValid = true;
break;
}
}
// mechanism in case of another bug like DERBY-5681 in Derby.
if (!isValid) {
String msg = "dropping disposable statistics entry " + stats[si].getUUID() + " for index " + stats[si].getReferenceID() + " (cols=" + stats[si].getColumnCount() + ")";
logAlways(td, null, msg);
trace(1, msg + " on table " + stats[si].getTableUUID());
DataDictionary dd = lcc.getDataDictionary();
if (!lcc.dataDictionaryInWriteMode()) {
dd.startWriting(lcc);
}
dd.dropStatisticsDescriptors(td.getUUID(), stats[si].getReferenceID(), tc);
if (asBackgroundTask) {
lcc.internalCommit(true);
}
}
}
}
// [x][0] = conglomerate number, [x][1] = start time, [x][2] = stop time
long[][] scanTimes = new long[conglomerateNumber.length][3];
int sci = 0;
for (int indexNumber = 0; indexNumber < conglomerateNumber.length; indexNumber++) {
if (conglomerateNumber[indexNumber] == -1)
continue;
// Check if daemon has been disabled.
if (asBackgroundTask) {
if (isShuttingDown()) {
break;
}
}
scanTimes[sci][0] = conglomerateNumber[indexNumber];
scanTimes[sci][1] = System.currentTimeMillis();
// Subtract one for the RowLocation added for indexes.
int numCols = indexRow[indexNumber].nColumns() - 1;
long[] cardinality = new long[numCols];
KeyComparator cmp = new KeyComparator(indexRow[indexNumber]);
/* Read uncommitted, with record locking. Actually CS store may
not hold record locks */
GroupFetchScanController gsc = tc.openGroupFetchScan(conglomerateNumber[indexNumber], // hold
false, 0, // locking
TransactionController.MODE_RECORD, TransactionController.ISOLATION_READ_UNCOMMITTED, // scancolumnlist-- want everything.
null, // startkeyvalue-- start from the beginning.
null, 0, // qualifiers, none!
null, // stopkeyvalue,
null, 0);
try {
int rowsFetched = 0;
boolean giving_up_on_shutdown = false;
while ((rowsFetched = cmp.fetchRows(gsc)) > 0) {
// I/O that is processed as a convenient point.
if (asBackgroundTask) {
if (isShuttingDown()) {
giving_up_on_shutdown = true;
break;
}
}
for (int i = 0; i < rowsFetched; i++) {
int whichPositionChanged = cmp.compareWithPrevKey(i);
if (whichPositionChanged >= 0) {
for (int j = whichPositionChanged; j < numCols; j++) cardinality[j]++;
}
}
}
if (giving_up_on_shutdown)
break;
gsc.setEstimatedRowCount(cmp.getRowCount());
} finally // try
{
gsc.close();
gsc = null;
}
scanTimes[sci++][2] = System.currentTimeMillis();
// We have scanned the indexes, so let's give this a few attempts
// before giving up.
int retries = 0;
while (true) {
try {
writeUpdatedStats(lcc, td, non_disposable_objectUUID[indexNumber], cmp.getRowCount(), cardinality, asBackgroundTask);
break;
} catch (StandardException se) {
retries++;
if (se.isLockTimeout() && retries < 3) {
trace(2, "lock timeout when writing stats, retrying");
sleep(100 * retries);
} else {
// o too many lock timeouts
throw se;
}
}
}
}
log(asBackgroundTask, td, fmtScanTimes(scanTimes));
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class AlterTableConstantAction method updateIndex.
private void updateIndex(long newHeapConglom, DataDictionary dd, int index, long[] newIndexCongloms) throws StandardException {
Properties properties = new Properties();
// Get the ConglomerateDescriptor for the index
ConglomerateDescriptor cd = td.getConglomerateDescriptor(indexConglomerateNumbers[index]);
// Build the properties list for the new conglomerate
ConglomerateController indexCC = tc.openConglomerate(indexConglomerateNumbers[index], false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE);
// Get the properties on the old index
indexCC.getInternalTablePropertySet(properties);
/* Create the properties that language supplies when creating the
* the index. (The store doesn't preserve these.)
*/
int indexRowLength = indexRows[index].nColumns();
properties.put("baseConglomerateId", Long.toString(newHeapConglom));
if (cd.getIndexDescriptor().isUnique()) {
properties.put("nUniqueColumns", Integer.toString(indexRowLength - 1));
} else {
properties.put("nUniqueColumns", Integer.toString(indexRowLength));
}
if (cd.getIndexDescriptor().isUniqueWithDuplicateNulls() && !cd.getIndexDescriptor().hasDeferrableChecking()) {
properties.put("uniqueWithDuplicateNulls", Boolean.toString(true));
}
properties.put("rowLocationColumn", Integer.toString(indexRowLength - 1));
properties.put("nKeyFields", Integer.toString(indexRowLength));
indexCC.close();
// We can finally drain the sorter and rebuild the index
// Populate the index.
RowLocationRetRowSource cCount;
boolean statisticsExist = false;
if (!truncateTable) {
sorters[index].completedInserts();
sorters[index] = null;
if (td.statisticsExist(cd)) {
cCount = new CardinalityCounter(tc.openSortRowSource(sortIds[index]));
statisticsExist = true;
} else {
cCount = new CardinalityCounter(tc.openSortRowSource(sortIds[index]));
}
newIndexCongloms[index] = tc.createAndLoadConglomerate("BTREE", indexRows[index].getRowArray(), ordering[index], collation[index], properties, TransactionController.IS_DEFAULT, cCount, (long[]) null);
// is not empty.
if (statisticsExist)
dd.dropStatisticsDescriptors(td.getUUID(), cd.getUUID(), tc);
long numRows;
if ((numRows = ((CardinalityCounter) cCount).getRowCount()) > 0) {
long[] c = ((CardinalityCounter) cCount).getCardinality();
for (int i = 0; i < c.length; i++) {
StatisticsDescriptor statDesc = new StatisticsDescriptor(dd, dd.getUUIDFactory().createUUID(), cd.getUUID(), td.getUUID(), "I", new StatisticsImpl(numRows, c[i]), i + 1);
dd.addDescriptor(statDesc, // no parent descriptor
null, DataDictionary.SYSSTATISTICS_CATALOG_NUM, // no error on duplicate.
true, tc);
}
}
} else {
newIndexCongloms[index] = tc.createConglomerate("BTREE", indexRows[index].getRowArray(), ordering[index], collation[index], properties, TransactionController.IS_DEFAULT);
// rowscount is zero and existing statistic will be invalid.
if (td.statisticsExist(cd))
dd.dropStatisticsDescriptors(td.getUUID(), cd.getUUID(), tc);
}
/* Update the DataDictionary
*
* Update sys.sysconglomerates with new conglomerate #, we need to
* update all (if any) duplicate index entries sharing this same
* conglomerate.
*/
dd.updateConglomerateDescriptor(td.getConglomerateDescriptors(indexConglomerateNumbers[index]), newIndexCongloms[index], tc);
// Drop the old conglomerate
tc.dropConglomerate(indexConglomerateNumbers[index]);
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class DDLConstantAction method lockTableForDDL.
/**
* Lock the table in exclusive or share mode to prevent deadlocks.
*
* @param tc The TransactionController
* @param heapConglomerateNumber The conglomerate number for the heap.
* @param exclusiveMode Whether or not to lock the table in exclusive mode.
*
* @exception StandardException if schema is system schema
*/
final void lockTableForDDL(TransactionController tc, long heapConglomerateNumber, boolean exclusiveMode) throws StandardException {
ConglomerateController cc;
cc = tc.openConglomerate(heapConglomerateNumber, false, (exclusiveMode) ? (TransactionController.OPENMODE_FORUPDATE | TransactionController.OPENMODE_FOR_LOCK_ONLY) : TransactionController.OPENMODE_FOR_LOCK_ONLY, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE);
cc.close();
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class DDLSingleTableConstantAction method loadIndexProperties.
/**
* Get any table properties that exist for the received
* index descriptor.
*/
private void loadIndexProperties(LanguageConnectionContext lcc, ConglomerateDescriptor congDesc, Properties ixProps) throws StandardException {
ConglomerateController cc = lcc.getTransactionExecute().openConglomerate(congDesc.getConglomerateNumber(), false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE);
cc.getInternalTablePropertySet(ixProps);
cc.close();
return;
}
Aggregations