use of org.apache.derby.iapi.services.io.ArrayInputStream in project derby by apache.
the class StoredPage method isColumnOrphaned.
/**
* See if there is a orphaned long colum chain or not.
* <p>
* See if there is a orphaned long colum chain or not. This is a helper
* function for removeOrphanedChain. This page, which may be a head page
* or overflow page, contains the column specified in columnId. It used to
* point to a long column chain at oldPageId and oldRecordId. Returns true
* if it no longer points to that long column chain.
* <p>
*
* @return true if page no longer points to the long column chain.
*
* @param recordHeader record header which used to point at the long column
* @param columnId column id of the long column in head.
* @param oldPageId the page id where the long column used to be.
* @param oldRecordId the record id where the long column used to be.
*
* @exception StandardException Standard exception policy.
*/
private boolean isColumnOrphaned(StoredRecordHeader recordHeader, int columnId, long oldPageId, long oldRecordId) throws StandardException, IOException {
int slot = findRecordById(recordHeader.getId(), Page.FIRST_SLOT_NUMBER);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(slot >= 0, "overflow row chain truncated");
SanityManager.ASSERT(columnId >= recordHeader.getFirstField(), "first column on page > expected");
}
// these reads are always against the page array
ArrayInputStream lrdi = rawDataIn;
// set read position to data portion of record to check.
int offset = getRecordOffset(slot);
lrdi.setPosition(offset + recordHeader.size());
// skip until you get to the record in question.
for (int i = recordHeader.getFirstField(); i < columnId; i++) skipField(lrdi);
// read in the info of the column we are interested in.
int fieldStatus = StoredFieldHeader.readStatus(lrdi);
int fieldLength = StoredFieldHeader.readFieldDataLength(lrdi, fieldStatus, slotFieldSize);
if (StoredFieldHeader.isOverflow(fieldStatus)) {
// it is still an overflow field, check if it still points to
// overflow column in question.
long ovflowPage = CompressedNumber.readLong((InputStream) lrdi);
int ovflowRid = CompressedNumber.readInt((InputStream) lrdi);
if (ovflowPage == oldPageId && ovflowRid == oldRecordId) {
// update must have rolled back.
return false;
}
}
// point to oldPageId, oldRecordId. The column chain is orphaned.
return true;
}
use of org.apache.derby.iapi.services.io.ArrayInputStream in project derby by apache.
the class StoredPage method restoreRecordFromSlot.
/**
* Read the record at the given slot into the given row.
* <P>
* This reads and initializes the columns in the row array from the raw
* bytes stored in the page associated with the given slot. If validColumns
* is non-null then it will only read those columns indicated by the bit
* set, otherwise it will try to read into every column in row[].
* <P>
* If there are more columns than entries in row[] then it just stops after
* every entry in row[] is full.
* <P>
* If there are more entries in row[] than exist on disk, the requested
* excess columns will be set to null by calling the column's object's
* restoreToNull() routine (ie. ((Object) column).restoreToNull() ).
* <P>
* If a qualifier list is provided then the row will only be read from
* disk if all of the qualifiers evaluate true. Some of the columns may
* have been read into row[] in the process of evaluating the qualifier.
* <p>
* This routine should only be called on the head portion of a row, it
* will call a utility routine to read the rest of the row if it is a
* long row.
*
* @param slot the slot number
* @param row (out) filled in sparse row
* @param fetchDesc Information describing fetch, including what
* columns to fetch and qualifiers.
* @param recordToLock the record handle for the row at top level,
* and is used in OverflowInputStream to lock the
* row for Blobs/Clobs.
* @param isHeadRow The row on this page includes the head record
* handle. Will be false for the overflow portions
* of a "long" row, where columns of a row span
* multiple pages.
*
* @return false if a qualifier_list is provided and the row does not
* qualifier (no row read in that case), else true.
*
* @exception StandardException Standard Derby error policy
*/
protected boolean restoreRecordFromSlot(int slot, Object[] row, FetchDescriptor fetchDesc, RecordHandle recordToLock, StoredRecordHeader recordHeader, boolean isHeadRow) throws StandardException {
try {
int offset_to_row_data = getRecordOffset(slot) + recordHeader.size();
if (SanityManager.DEBUG) {
if (getRecordOffset(slot) < (PAGE_HEADER_OFFSET + PAGE_HEADER_SIZE)) {
SanityManager.THROWASSERT("Incorrect offset. offset = " + getRecordOffset(slot) + ", offset should be < " + "(PAGE_HEADER_OFFSET + PAGE_HEADER_SIZE) = " + (PAGE_HEADER_OFFSET + PAGE_HEADER_SIZE) + ", current slot = " + slot + ", total slotsInUse = " + slotsInUse);
}
SanityManager.ASSERT(isHeadRow, "restoreRecordFromSlot called on a non-headrow");
SanityManager.ASSERT(!isOverflowPage(), "restoreRecordFromSlot called on an overflow page.");
}
// position the array reading stream at beginning of row data just
// past the record header.
ArrayInputStream lrdi = rawDataIn;
lrdi.setPosition(offset_to_row_data);
if (!recordHeader.hasOverflow()) {
if (isHeadRow) {
if (fetchDesc != null && fetchDesc.getQualifierList() != null) {
fetchDesc.reset();
if (!qualifyRecordFromSlot(row, offset_to_row_data, fetchDesc, recordHeader, recordToLock)) {
return (false);
} else {
// reset position back for subsequent record read.
lrdi.setPosition(offset_to_row_data);
}
}
}
// can return.
if (fetchDesc != null) {
readRecordFromArray(row, (fetchDesc.getValidColumns() == null) ? row.length - 1 : fetchDesc.getMaxFetchColumnId(), fetchDesc.getValidColumnsArray(), fetchDesc.getMaterializedColumns(), lrdi, recordHeader, recordToLock);
} else {
readRecordFromArray(row, row.length - 1, (int[]) null, (int[]) null, lrdi, recordHeader, recordToLock);
}
return (true);
} else {
if (fetchDesc != null) {
if (fetchDesc.getQualifierList() != null) {
fetchDesc.reset();
}
readRecordFromArray(row, (fetchDesc.getValidColumns() == null) ? row.length - 1 : fetchDesc.getMaxFetchColumnId(), fetchDesc.getValidColumnsArray(), fetchDesc.getMaterializedColumns(), lrdi, recordHeader, recordToLock);
} else {
readRecordFromArray(row, row.length - 1, (int[]) null, (int[]) null, lrdi, recordHeader, recordToLock);
}
// the row, reading it into "row".
while (recordHeader != null) {
// The record is a long row, loop callng code to read the
// pieces of the row located in a linked list of rows on
// overflow pages.
StoredPage overflowPage = getOverflowPage(recordHeader.getOverflowPage());
if (SanityManager.DEBUG) {
if (overflowPage == null)
SanityManager.THROWASSERT("cannot get overflow page");
}
// This call reads in the columns of the row that reside
// on "overflowPage", and if there is another piece it
// returns the recordHeader of the row on overFlowPage,
// from which we can find the next piece of the row. A
// null return means that we have read in the entire row,
// and are done.
recordHeader = overflowPage.restoreLongRecordFromSlot(row, fetchDesc, recordToLock, recordHeader);
overflowPage.unlatch();
overflowPage = null;
}
if ((fetchDesc != null) && (fetchDesc.getQualifierList() != null)) {
if (!qualifyRecordFromRow(row, fetchDesc.getQualifierList())) {
return (false);
}
}
return (true);
}
} catch (IOException ioe) {
if (SanityManager.DEBUG) {
if (pageData == null) {
SanityManager.DEBUG_PRINT("DEBUG_TRACE", "caught an IOException in restoreRecordFromSlot " + (PageKey) getIdentity() + " slot " + slot + ", pageData is null");
} else {
SanityManager.DEBUG_PRINT("DEBUG_TRACE", "caught an IOException in reestoreRecordFromSlot, " + (PageKey) getIdentity() + " slot " + slot + ", pageData.length = " + pageData.length + " pageSize = " + getPageSize());
SanityManager.DEBUG_PRINT("DEBUG_TRACE", "Hex dump of pageData \n " + "--------------------------------------------------\n" + pagedataToHexDump(pageData) + "--------------------------------------------------\n");
SanityManager.DEBUG_PRINT("DEBUG_TRACE", "Attempt to dump page " + this.toString());
}
}
// i/o methods on the byte array have thrown an IOException
throw dataFactory.markCorrupt(StandardException.newException(SQLState.DATA_CORRUPT_PAGE, ioe, getPageId()));
}
}
use of org.apache.derby.iapi.services.io.ArrayInputStream in project derby by apache.
the class StoredPage method readOneColumnFromPage.
/**
* Read just one column from stream into row.
* <p>
* The routine reads just one column from the row, it is mostly code
* taken from readRecordFromStream, but highly optimized to just get
* one column from a non-overflow row. It can only be called to read
* a row from the pageData array as it directly accesses the page array
* to avoid the Stream overhead while processing non-user data which
* does not need the limit functionality.
* <p>
* It is expected that this code will be called to read in a column
* associated with a qualifiers which are applied one column at a time,
* and has been specialized to proved the greatest peformance for
* processing qualifiers. This kind of access is done when scanning
* large datasets while applying qualifiers and thus any performance
* gain at this low level is multiplied by the large number of rows that
* may be iterated over.
* <p>
* The column is read into the object located in row[qual_colid].
*
* @param row col is read into object in row[qual_colid].
* @param offset_to_field_data offset in bytes from top of page to field
* @param colid the column id to read, colid N is row[N]
* @param recordHeader record header of row to read column from.
* @param recordToLock record handle to lock,
* used by overflow column code.
*
* @exception StandardException Standard exception policy.
*/
private final void readOneColumnFromPage(Object[] row, int colid, int offset_to_field_data, StoredRecordHeader recordHeader, RecordHandle recordToLock) throws StandardException, IOException {
ErrorObjectInput inUserCode = null;
// Reads in this routine are always against the raw data in the
// pageData array, thus it can assume array access to page data array.
ArrayInputStream lrdi = rawDataIn;
try {
if (SanityManager.DEBUG) {
if (colid >= row.length)
SanityManager.THROWASSERT("colid = " + colid + ";row length = " + row.length);
// currently this routine will not work on long rows.
if (recordHeader.getFirstField() != 0) {
SanityManager.THROWASSERT("recordHeader.getFirstField() = " + recordHeader.getFirstField());
}
}
Object column = row[colid];
// if the column id exists on this page.
if (colid <= (recordHeader.getNumberFields() - 1)) {
for (int columnId = colid; columnId > 0; columnId--) {
offset_to_field_data += StoredFieldHeader.readTotalFieldLength(pageData, offset_to_field_data);
}
// read the field header
// read the status byte.
int fieldStatus = StoredFieldHeader.readStatus(pageData, offset_to_field_data);
// read the field data length, and position on 1st byte of data.
int fieldDataLength = StoredFieldHeader.readFieldLengthAndSetStreamPosition(pageData, offset_to_field_data + StoredFieldHeader.STORED_FIELD_HEADER_STATUS_SIZE, fieldStatus, slotFieldSize, lrdi);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(!StoredFieldHeader.isExtensible(fieldStatus), "extensible fields not supported yet");
}
if (!StoredFieldHeader.isNonexistent(fieldStatus)) {
boolean isOverflow = StoredFieldHeader.isOverflow(fieldStatus);
OverflowInputStream overflowIn = null;
if (isOverflow) {
// A fetched long column is returned as a stream
long overflowPage = CompressedNumber.readLong((InputStream) lrdi);
int overflowId = CompressedNumber.readInt((InputStream) lrdi);
// Prepare the stream for results...
// create the byteHolder the size of a page, so, that it
// will fit the field Data that would fit on a page.
MemByteHolder byteHolder = new MemByteHolder(pageData.length);
overflowIn = new OverflowInputStream(byteHolder, owner, overflowPage, overflowId, recordToLock);
}
// Deal with Storable columns
if (column instanceof DataValueDescriptor) {
DataValueDescriptor sColumn = (DataValueDescriptor) column;
// is the column null ?
if (StoredFieldHeader.isNull(fieldStatus)) {
sColumn.restoreToNull();
} else {
// set the limit for the user read
if (!isOverflow) {
// normal, non-overflow column case.
lrdi.setLimit(fieldDataLength);
inUserCode = lrdi;
sColumn.readExternalFromArray(lrdi);
inUserCode = null;
int unread = lrdi.clearLimit();
if (unread != 0)
DataInputUtil.skipFully(lrdi, unread);
} else {
// fetched column is a Storable long column.
FormatIdInputStream newIn = new FormatIdInputStream(overflowIn);
if ((sColumn instanceof StreamStorable)) {
((StreamStorable) sColumn).setStream(newIn);
} else {
inUserCode = newIn;
sColumn.readExternal(newIn);
inUserCode = null;
}
}
}
} else {
if (StoredFieldHeader.isNull(fieldStatus)) {
throw StandardException.newException(SQLState.DATA_NULL_STORABLE_COLUMN, Integer.toString(colid));
}
// This is a non-extensible field, which means the
// caller must know the correct type and thus the
// element in row is the correct type or null. It must
// be Serializable.
//
// We do not support Externalizable here.
lrdi.setLimit(fieldDataLength);
inUserCode = lrdi;
// RESOLVE (no non-storables?)
row[colid] = (Object) lrdi.readObject();
inUserCode = null;
int unread = lrdi.clearLimit();
if (unread != 0)
DataInputUtil.skipFully(lrdi, unread);
}
} else {
if (column instanceof DataValueDescriptor) {
// RESOLVE - This is in place for 1.2. In the future
// we may want to return this column as non-existent
// even if it is a storable column, or maybe use a
// supplied default.
((DataValueDescriptor) column).restoreToNull();
} else {
row[colid] = null;
}
}
} else {
if (column instanceof DataValueDescriptor) {
// RESOLVE - This is in place for 1.2. In the future
// we may want to return this column as non-existent
// even if it is a storable column, or maybe use a
// supplied default.
((DataValueDescriptor) column).restoreToNull();
} else {
row[colid] = null;
}
}
} catch (IOException ioe) {
if (inUserCode != null) {
lrdi.clearLimit();
if (ioe instanceof EOFException) {
if (SanityManager.DEBUG) {
SanityManager.DEBUG_PRINT("DEBUG_TRACE", "StoredPage.readOneColumnFromPage - EOF while restoring record: " + recordHeader + "Page dump = " + this);
SanityManager.showTrace(ioe);
}
// an EOFException when it sees the -1 from a read
throw StandardException.newException(SQLState.DATA_STORABLE_READ_MISMATCH, ioe, inUserCode.getErrorInfo());
}
// some SQLData error reporting
Exception ne = inUserCode.getNestedException();
if (ne != null) {
if (ne instanceof InstantiationException) {
throw StandardException.newException(SQLState.DATA_SQLDATA_READ_INSTANTIATION_EXCEPTION, ne, inUserCode.getErrorInfo());
}
if (ne instanceof IllegalAccessException) {
throw StandardException.newException(SQLState.DATA_SQLDATA_READ_ILLEGAL_ACCESS_EXCEPTION, ne, inUserCode.getErrorInfo());
}
if (ne instanceof StandardException) {
throw (StandardException) ne;
}
}
throw StandardException.newException(SQLState.DATA_STORABLE_READ_EXCEPTION, ioe, inUserCode.getErrorInfo());
}
// re-throw to higher levels so they can put it in correct context.
throw ioe;
} catch (ClassNotFoundException cnfe) {
lrdi.clearLimit();
// make the database corrupt, just that this field is inaccessable
throw StandardException.newException(SQLState.DATA_STORABLE_READ_MISSING_CLASS, cnfe, inUserCode.getErrorInfo());
} catch (LinkageError le) {
// Some error during the link of a user class
if (inUserCode != null) {
lrdi.clearLimit();
throw StandardException.newException(SQLState.DATA_STORABLE_READ_EXCEPTION, le, inUserCode.getErrorInfo());
}
throw le;
}
}
use of org.apache.derby.iapi.services.io.ArrayInputStream in project derby by apache.
the class StoredPage method readRecordFromArray.
private final boolean readRecordFromArray(Object[] row, int max_colid, int[] vCols, int[] mCols, ArrayInputStream dataIn, StoredRecordHeader recordHeader, RecordHandle recordToLock) throws StandardException, IOException {
ErrorObjectInput inUserCode = null;
try {
// Get the number of columns in the row.
int numberFields = recordHeader.getNumberFields();
int startColumn = recordHeader.getFirstField();
if (startColumn > max_colid) {
// done if the startColumn is higher than highest column.
return true;
}
// For each column in the row, restore the column from
// the corresponding field in the record. If the field
// is missing or not set, set the column to null.
int highestColumnOnPage = numberFields + startColumn;
int vColsSize = (vCols == null) ? 0 : vCols.length;
int offset_to_field_data = dataIn.getPosition();
for (int columnId = startColumn; columnId <= max_colid; columnId++) {
// that have already been read.
if (((vCols != null) && (!(vColsSize > columnId && (vCols[columnId] != 0)))) || ((mCols != null) && (mCols[columnId] != 0))) {
if (columnId < highestColumnOnPage) {
// If the field exists in the row on the page, but the
// partial row being returned does not include it,
// skip the field ...
offset_to_field_data += StoredFieldHeader.readTotalFieldLength(pageData, offset_to_field_data);
}
continue;
} else if (columnId < highestColumnOnPage) {
// the column is on this page.
// read the field header
// read the status byte.
int fieldStatus = StoredFieldHeader.readStatus(pageData, offset_to_field_data);
// read the field data length, position on 1st byte of data
int fieldDataLength = StoredFieldHeader.readFieldLengthAndSetStreamPosition(pageData, offset_to_field_data + StoredFieldHeader.STORED_FIELD_HEADER_STATUS_SIZE, fieldStatus, slotFieldSize, dataIn);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(!StoredFieldHeader.isExtensible(fieldStatus), "extensible fields not supported yet");
}
Object column = row[columnId];
OverflowInputStream overflowIn = null;
if ((fieldStatus & StoredFieldHeader.FIELD_NONEXISTENT) != StoredFieldHeader.FIELD_NONEXISTENT) {
// normal path - field exists.
boolean isOverflow = ((fieldStatus & StoredFieldHeader.FIELD_OVERFLOW) != 0);
if (isOverflow) {
// A fetched long column is returned as a stream
long overflowPage = CompressedNumber.readLong((InputStream) dataIn);
int overflowId = CompressedNumber.readInt((InputStream) dataIn);
// Prepare the stream for results...
// create the byteHolder the size of a page, so,
// that it will fit the field Data that would fit
// on a page.
MemByteHolder byteHolder = new MemByteHolder(pageData.length);
overflowIn = new OverflowInputStream(byteHolder, owner, overflowPage, overflowId, recordToLock);
}
// Deal with Object columns
if (column instanceof DataValueDescriptor) {
DataValueDescriptor sColumn = (DataValueDescriptor) column;
// is the column null ?
if ((fieldStatus & StoredFieldHeader.FIELD_NULL) == 0) {
// set the limit for the user read
if (!isOverflow) {
// normal, non-overflow column case.
dataIn.setLimit(fieldDataLength);
inUserCode = dataIn;
sColumn.readExternalFromArray(dataIn);
inUserCode = null;
int unread = dataIn.clearLimit();
if (unread != 0)
DataInputUtil.skipFully(dataIn, unread);
} else {
// column being fetched is a long column.
FormatIdInputStream newIn = new FormatIdInputStream(overflowIn);
// long columns are fetched as a stream.
boolean fetchStream = true;
if (!(sColumn instanceof StreamStorable)) {
fetchStream = false;
}
if (fetchStream) {
((StreamStorable) sColumn).setStream(newIn);
} else {
inUserCode = newIn;
sColumn.readExternal(newIn);
inUserCode = null;
}
}
} else {
sColumn.restoreToNull();
}
} else {
if (StoredFieldHeader.isNull(fieldStatus)) {
throw StandardException.newException(SQLState.DATA_NULL_STORABLE_COLUMN, Integer.toString(columnId));
}
// This is a non-extensible field, which means the
// caller must know the correct type and thus the
// element in row is the correct type or null. It
// must be Serializable.
//
// We do not support Externalizable here.
dataIn.setLimit(fieldDataLength);
inUserCode = dataIn;
// RESOLVE (no non-storables?)
row[columnId] = (Object) dataIn.readObject();
inUserCode = null;
int unread = dataIn.clearLimit();
if (unread != 0)
DataInputUtil.skipFully(dataIn, unread);
}
} else {
if (column instanceof DataValueDescriptor) {
// RESOLVE - This is in place for 1.2. In the future
// we may want to return this column as non-existent
// even if it is a storable column, or maybe use a
// supplied default.
((DataValueDescriptor) column).restoreToNull();
} else {
row[columnId] = null;
}
}
// move the counter to point to beginning of next field.
offset_to_field_data = dataIn.getPosition();
} else {
// field is non-existent
Object column = row[columnId];
if (column instanceof DataValueDescriptor) {
// RESOLVE - This is in place for 1.2. In the future
// we may want to return this column as non-existent
// even if it is a storable column, or maybe use a
// supplied default.
((DataValueDescriptor) column).restoreToNull();
} else {
row[columnId] = null;
}
}
}
if ((numberFields + startColumn) > max_colid)
return true;
else
return false;
} catch (IOException ioe) {
if (inUserCode != null) {
dataIn.clearLimit();
if (ioe instanceof EOFException) {
if (SanityManager.DEBUG) {
SanityManager.DEBUG_PRINT("DEBUG_TRACE", "StoredPage - EOF while restoring record: " + recordHeader + "Page dump = " + this);
}
// an EOFException when it sees the -1 from a read
throw StandardException.newException(SQLState.DATA_STORABLE_READ_MISMATCH, ioe, inUserCode.getErrorInfo());
}
// some SQLData error reporting
Exception ne = inUserCode.getNestedException();
if (ne != null) {
if (ne instanceof InstantiationException) {
throw StandardException.newException(SQLState.DATA_SQLDATA_READ_INSTANTIATION_EXCEPTION, ne, inUserCode.getErrorInfo());
}
if (ne instanceof IllegalAccessException) {
throw StandardException.newException(SQLState.DATA_SQLDATA_READ_ILLEGAL_ACCESS_EXCEPTION, ne, inUserCode.getErrorInfo());
}
if (ne instanceof StandardException) {
throw (StandardException) ne;
}
}
throw StandardException.newException(SQLState.DATA_STORABLE_READ_EXCEPTION, ioe, inUserCode.getErrorInfo());
}
// re-throw to higher levels so they can put it in correct context.
throw ioe;
} catch (ClassNotFoundException cnfe) {
dataIn.clearLimit();
// make the database corrupt, just that this field is inaccessable
throw StandardException.newException(SQLState.DATA_STORABLE_READ_MISSING_CLASS, cnfe, inUserCode.getErrorInfo());
} catch (LinkageError le) {
// Some error during the link of a user class
if (inUserCode != null) {
dataIn.clearLimit();
throw StandardException.newException(SQLState.DATA_STORABLE_READ_EXCEPTION, le, inUserCode.getErrorInfo());
}
throw le;
}
}
use of org.apache.derby.iapi.services.io.ArrayInputStream in project derby by apache.
the class StoredPage method getRecordPortionLength.
/**
* Return length of row on this page.
* <p>
* Return the total length of data and header stored on this page for
* this record. This length is stored as the second "field" of the
* slot table entry.
*
* @return The length of the row on this page.
*
* @param slot the slot of the row to look up the length of.
*/
protected int getRecordPortionLength(int slot) throws IOException {
if (SanityManager.DEBUG) {
if (getRecordOffset(slot) <= 0) {
SanityManager.DEBUG_PRINT("DEBUG_TRACE", "getRecordPortionLength failed with getRecordOffset(" + slot + ") = " + getRecordOffset(slot) + " must be greater than 0." + "page dump = \n" + toUncheckedString());
SanityManager.THROWASSERT("bad record offset found in getRecordPortionLength()");
}
}
// these reads are always against the page array
ArrayInputStream lrdi = rawDataIn;
lrdi.setPosition(slotTableOffsetToFirstRecordLengthField - (slot * slotEntrySize));
return ((slotFieldSize == SMALL_SLOT_SIZE) ? lrdi.readUnsignedShort() : lrdi.readInt());
}
Aggregations