📄 storedpage.java
字号:
StandardException.newException( SQLState.DATA_CORRUPT_PAGE, ioe, getPageId())); } } /** * Is there minimal space for insert? * <p> * Does quick calculation to see if average size row on this page could * be inserted on the page. This is done because the actual row size * being inserted isn't known until we actually copy the columns from * their object form into their on disk form which is expensive. So * we use this calculation so that in the normal case we only do one * copy of the row directly onto the page. * <p> * * @return true if we think the page will allow an insert, false otherwise. * * @exception StandardException Standard exception policy. **/ public boolean spaceForInsert() throws StandardException { // is this an empty page if (slotsInUse == 0) return(true); if (!allowInsert()) return(false); int usedSpace = totalSpace - freeSpace; int bytesPerRow = usedSpace / slotsInUse; return(bytesPerRow <= freeSpace); } /** * Is row guaranteed to be inserted successfully on this page? * <p> * Return true if this record is guaranteed to be inserted successfully * using insert() or insertAtSlot(). This guarantee is only valid while * the row remains unchanged and the page latch is held. * <p> * * @return bolean indicating if row can be inserted on this page. * * @param row The row to check for insert. * @param validColumns bit map to interpret valid columns in row. * @param overflowThreshold The percentage of the page to use for the * insert. 100 means use 100% of the page, * 50 means use 50% of page (ie. make sure * 2 rows fit per page). * * @exception StandardException Standard exception policy. **/ public boolean spaceForInsert( Object[] row, FormatableBitSet validColumns, int overflowThreshold) throws StandardException { // is this an empty page if (slotsInUse == 0) return true; // does the estimate think it won't fit, if not return false to avoid // cost of calling logRow() just to figure out if the row will fit. if (!allowInsert()) return false; DynamicByteArrayOutputStream out = new DynamicByteArrayOutputStream(); try { // This is a public call, start column is rawstore only. // set the starting Column for the row to be 0. logRow( 0, true, nextId, row, validColumns, out, 0, Page.INSERT_DEFAULT, -1, -1, overflowThreshold); } catch (NoSpaceOnPage nsop) { return false; } catch (IOException ioe) { throw StandardException.newException( SQLState.DATA_UNEXPECTED_EXCEPTION, ioe); } return true; } /** * Is row guaranteed to be inserted successfully on this page? * <p> * Return true if this record is guaranteed to be inserted successfully * using insert() or insertAtSlot(). This guarantee is only valid while * the row remains unchanged and the page latch is held. * <p> * This is a private call only used when calculating whether an overflow * page can be used to insert part of an overflow row/column. * * @return bolean indicating if row can be inserted on this page. * * @param row The row to check for insert. * @param validColumns bit map to interpret valid columns in row. * @param overflowThreshold The percentage of the page to use for the * insert. 100 means use 100% of the page, * 50 means use 50% of page (ie. make sure * 2 rows fit per page). * * @exception StandardException Standard exception policy. **/ private boolean spaceForInsert( Object[] row, FormatableBitSet validColumns, int spaceNeeded, int startColumn, int overflowThreshold) throws StandardException { if (!(spaceForInsert() && (freeSpace >= spaceNeeded))) return false; DynamicByteArrayOutputStream out = new DynamicByteArrayOutputStream(); try { logRow( 0, true, nextId, row, validColumns, out, startColumn, Page.INSERT_DEFAULT, -1, -1, overflowThreshold); } catch (NoSpaceOnPage nsop) { return false; } catch (IOException ioe) { throw StandardException.newException( SQLState.DATA_UNEXPECTED_EXCEPTION, ioe); } return true; } /** * Is this page unfilled? * <p> * Returns true if page is relatively unfilled, * which means the page is < 1/2 full and has enough space to insert an * "average" sized row onto the page. * <p> * * @return true if page is relatively unfilled. **/ public boolean unfilled() { return (allowInsert() && (freeSpace > (getPageSize() / 2))); } /** * Is there enough space on the page to insert a minimum size row? * <p> * Calculate whether there is enough space on the page to insert a * minimum size row. The calculation includes maintaining the required * reserved space on the page for existing rows to grow on the page. * <p> * * @return boolean indicating if a minimum sized row can be inserted. **/ public boolean allowInsert() { // is this an empty page if (slotsInUse == 0) return true; int spaceAvailable = freeSpace; spaceAvailable -= slotEntrySize; // need to account new slot entry if (spaceAvailable < minimumRecordSize) return false; // see that we reserve enough space for existing rows to grow on page if (((spaceAvailable * 100) / totalSpace) < spareSpace) return false; return true; } /** * Does this page have enough space to insert the input rows? * <p> * Can the rows with lengths spaceNeeded[0..num_rows-1] be copied onto * this page? * <p> * * @return true if the sum of the lengths will fit on the page. * * @param num_rows number of rows to check for. * @param spaceNeeded array of lengths of the rows to insert. **/ public boolean spaceForCopy(int num_rows, int[] spaceNeeded) { // determine how many more bytes are needed for the slot entries int bytesNeeded = slotEntrySize * num_rows; for (int i = 0; i < num_rows; i++) { if (spaceNeeded[i] > 0) { // add up the space needed by the rows, add in minimumRecordSize // if length of actual row is less than minimumRecordSize. bytesNeeded += (spaceNeeded[i] >= minimumRecordSize ? spaceNeeded[i] : minimumRecordSize); } } return((freeSpace - bytesNeeded) >= 0); } protected boolean spaceForCopy(int spaceNeeded) { // add up the space needed by the rows, add in minimumRecordSize // if length of actual row is less than minimumRecordSize. int bytesNeeded = slotEntrySize + (spaceNeeded >= minimumRecordSize ? spaceNeeded : minimumRecordSize); return((freeSpace - bytesNeeded) >= 0); } /** * 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 Cloudscape 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); } } } // call routine to do the real work. Note that // readRecordFromStream() may return false for non-overflow // record, this is in the case where caller requests more // columns than exist on disk. In that case we still return // true at this point as there are no more columns that we // can return. if (fetchDesc != null) { readRecordFromArray( row, (fetchDesc.getValidColumns() == null) ? row.length -1 : fetchDesc.getMaxFetchColumnId(), fetchDesc.getValidColumnsArray(), fetchDesc.getMaterializedColumns(), lrdi, recordHeader, (ErrorObjectInput) null /* always null */, recordToLock); } else { readRecordFromArray( row, row.length - 1, (int[]) null, (int[]) null, lrdi, recordHeader, (ErrorObjectInput) null /* always null */, recordToLock); } return(true); } else { if (fetchDesc != null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -