📄 basepage.java
字号:
protected final void setHeaderAtSlot(int slot, StoredRecordHeader rh) { if (slot < headers.length) { // check that array "cache" of headers is big enough. if (rh != null) { headers[slot] = rh; } } else { // need to grow the array, just allocate new array and copy. StoredRecordHeader[] new_headers = new StoredRecordHeader[slot + 1]; System.arraycopy(headers, 0, new_headers, 0, headers.length); headers = new_headers; headers[slot] = rh; } } protected final void bumpRecordCount(int number) { recordCount += number; } public final StoredRecordHeader getHeaderAtSlot(int slot) { if (slot < headers.length) { StoredRecordHeader rh = headers[slot]; return((rh != null) ? rh : recordHeaderOnDemand(slot)); } else { return recordHeaderOnDemand(slot); } } /** Returns true if the entire record of that slot fits inside of this page. Returns false if part of the record on this slot overflows to other pages, either due to long row or long column. <BR> MT - latched @exception StandardException Standard Cloudscape error policy */ public abstract boolean entireRecordOnPage(int slot) throws StandardException; public abstract StoredRecordHeader recordHeaderOnDemand(int slot); /** Is the given slot number on the page? <BR> MT - latched */ private final void checkSlotOnPage(int slot) throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } if (slot >= FIRST_SLOT_NUMBER && slot < recordCount) { return; } throw StandardException.newException(SQLState.DATA_SLOT_NOT_ON_PAGE); } /** Mark the record at the passed in slot as deleted. return code comes from StoredRecordHeader class: return 1, if delete status from not deleted to deleted return -1, if delete status from deleted to not deleted return 0, if status unchanged. <BR> <B>Any sub-class must call this method when deleting a record.</B> <BR> MT - latched @exception StandardException Standard Cloudscape error policy @exception IOException IO error accessing page */ public int setDeleteStatus(int slot, boolean delete) throws StandardException, IOException { if (SanityManager.DEBUG) { // latch check performed in checkSlotOnPage checkSlotOnPage(slot);; } return (getHeaderAtSlot(slot).setDeleted(delete)); } /** Mark this page as being deallocated @exception StandardException Cloudscape Standard error policy */ public void deallocatePage() throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } if (!owner.updateOK()) { throw StandardException.newException( SQLState.DATA_CONTAINER_READ_ONLY); } RawTransaction t = owner.getTransaction(); owner.getActionSet().actionInvalidatePage(t, this); } /** Mark this page as being allocated and initialize it to a pristine page @exception StandardException Cloudscape Standard error policy */ public void initPage(int initFlag, long pageOffset) throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } if (!owner.updateOK()) { throw StandardException.newException( SQLState.DATA_CONTAINER_READ_ONLY); } RawTransaction t = owner.getTransaction(); owner.getActionSet().actionInitPage( t, this, initFlag, getTypeFormatId(), pageOffset); } /** Find the slot for the record with the passed in identifier. <BR> This method returns the record regardless of its deleted status. <BR> The "slotHint" argument is a hint about what slot the record id might be in. Callers may save the last slot where the record was across latch/unlatches to the page, and then pass that slot back as a hint - if the page has not shuffled slots since the last reference then the hint will succeed and a linear search is saved. If the caller has no idea where it may be, then FIRST_SLOT_NUMBER is passed in and a linear search is performed. <BR> MT - latched @param recordId record id of the record to search for. @param slotHint "hint" about which slot the record might be in. */ public int findRecordById(int recordId, int slotHint) { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } if (slotHint == FIRST_SLOT_NUMBER) slotHint = recordId - RecordHandle.FIRST_RECORD_ID; int maxSlot = recordCount(); if ((slotHint > FIRST_SLOT_NUMBER) && (slotHint < maxSlot) && (recordId == getHeaderAtSlot(slotHint).getId())) { return(slotHint); } else { for (int slot = FIRST_SLOT_NUMBER; slot < maxSlot; slot++) { if (recordId == getHeaderAtSlot(slot).getId()) { return slot; } } } return -1; } /** Find the slot for the first record on the page with an id greater than the passed in identifier. <BR> Returns the slot of the first record on the page with an id greater than the one passed in. Usefulness of this functionality depends on the clients use of the raw store interfaces. If all "new" records are always inserted at the end of the page, and the raw store continues to guarantee that all record id's will be allocated in increasing order on a given page, then a page is always sorted in record id order. For instance current heap tables function this way. If the client ever inserts at a particular slot number, rather than at the "end" then the record id's will not be sorted. <BR> In the case where all record id's are always sorted on a page, then this routine can be used by scan's which "lose" their position because the row they have as a position was purged. They can reposition their scan at the "next" row after the row that is now missing from the table. <BR> This method returns the record regardless of its deleted status. <BR> MT - latched @param recordId record id of the first record on the page with a record id higher than the one passed in. If no such record exists, -1 is returned. */ private int findNextRecordById(int recordId) { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } int maxSlot = recordCount(); for (int slot = FIRST_SLOT_NUMBER; slot < maxSlot; slot++) { if (getHeaderAtSlot(slot).getId() > recordId) { return(slot); } } return -1; } /** Copy num_rows from srcPage, src_slot into this page starting at dest_slot. This is destination page of the the copy half of copy and Purge. @return An array of the new record identifiers. @see Page#copyAndPurge */ private void copyInto(BasePage srcPage, int src_slot, int num_rows, int dest_slot) throws StandardException { if ((dest_slot < 0) || dest_slot > recordCount) { throw StandardException.newException( SQLState.DATA_SLOT_NOT_ON_PAGE); } RawTransaction t = owner.getTransaction(); // get num_rows row locks, need to predict what those recordIds will be int[] recordIds = new int[num_rows]; PageKey pageId = getPageId(); // RESOLVE - MT problem ? // get new recordIds for the rows from this page // RESOLVE: we should also record the amount of reserved space for (int i = 0; i < num_rows; i++) { if (i == 0) recordIds[i] = newRecordId(); else recordIds[i] = newRecordId(recordIds[i-1]); RecordHandle handle = new RecordId(pageId, recordIds[i], i); owner.getLockingPolicy().lockRecordForWrite(t, handle, false, true); } // RESOLVE: need try block here to invalidate self and crash the system owner.getActionSet().actionCopyRows(t, this, srcPage, dest_slot, num_rows, src_slot, recordIds); } /** Remove record at slot. <p> Remove the slot at the in-memory slot table, i.e., slots from 0 to deleteSlot-1 is untouched, deleteSlot is removed from in memory slot table, deleteSlot+1 .. recordCount()-1 move to down one slot. <BR> MT - latched */ protected void removeAndShiftDown(int slot) { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); SanityManager.ASSERT(slot >= 0 && slot < recordCount); } // just copy the records down in the array (copying over the slot // entry that is being eliminated) and null out the last entry, // it is ok for the array to be larger than necessary. // // source of copy: slot + 1 // dest of copy: slot // length of copy: (length of array - source of copy) System.arraycopy( headers, slot + 1, headers, slot, headers.length - (slot + 1)); headers[headers.length - 1] = null; recordCount--; } /** Shift all records in the in-memory slot table up one slot, starting at and including the record in slot 'low' A new slot is added to accomdate the move. <BR> MT - latched */ protected StoredRecordHeader shiftUp(int low) { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); if ((low < 0) || (low > recordCount)) { SanityManager.THROWASSERT( "shiftUp failed, low must be between 0 and recordCount." + " low = " + low + ", recordCount = " + recordCount); } } if (low < headers.length) { // just copy the records up in the array (copying over the slot // entry that is being eliminated) and null out the entry at "low", // it is ok for the array to be shorter than necessary. // // This code throws away the "last" entry in // the array, which will cause a record header cache miss if it // is needed. This delays the object allocation of a new array // object until we really need that entry, vs. doing it on the // insert. // // source of copy: low // dest of copy: low + 1 // length of copy: (length of array - dest of copy) // adding in the middle System.arraycopy( headers, low, headers, low + 1, headers.length - (low + 1)); headers[low] = null; } return(null); } /** Try to compact this record. Deleted record are treated the same way as nondeleted record. This page must not be an overflow page. The record may already have been purged from the page. <P> <B>Locking Policy</B> <P> No locks are obtained. <BR> MT - latched <P> <B>NOTE : CAVEAT </B><BR> This operation will physically get rid of any reserved space this record may have, or it may compact the record by merging strung out row pieces together. Since the freed reserved space is immediately usable by other transactions which latched the page, it is only safe to use this operation if the caller knows that it has exclusive access to the page for the duration of the transaction, i.e., effectively holding a page lock on the page, AND that the record has no uncommitted updates. @param handle Handle to deleted or non-deleted record @see ContainerHandle#compactRecord @exception StandardException Standard Cloudscape error policy */ public void compactRecord(RecordHandle handle) throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } if (!owner.updateOK()) { throw StandardException.newException( SQLState.DATA_CONTAINER_READ_ONLY); } if (handle.getId() < RecordHandle.FIRST_RECORD_ID) { throw StandardException.newException( SQLState.DATA_INVALID_RECORD_HANDLE, handle); } if (handle.getPageNumber() != getPageNumber()) { throw StandardException.newException( SQLState.DATA_WRONG_PAGE_FOR_HANDLE, handle); } if (isOverflowPage()) { throw StandardException.newException( SQLState.DATA_UNEXPECTED_OVERFLOW_PAGE, handle); } int slot = findRecordById(handle.getId(), handle.getSlotNumberHint()); if (slot >= 0) { compactRecord(owner.getTransaction(), slot, handle.getId()); } // else record gone, no compaction necessary } /* ** Methods that read/store records/fields based upon calling methods ** a sub-calls provides to do the actual storage work. */ /* ** Page LastLog Instant control */ public final LogInstant getLastLogInstant() { return lastLog; } protected final void clearLastLogInstant() { lastLog = nul
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -