📄 basepage.java
字号:
if (rh != null) SanityManager.ASSERT(getSlotNumber(rh) == slot); } checkSlotOnPage(slot); StoredRecordHeader recordHeader = getHeaderAtSlot(slot); if (rh == null) rh = recordHeader.getHandle(getPageId(), slot); if (!ignoreDelete && recordHeader.isDeleted()) return null; /* SanityManager.DEBUG_PRINT("fetchFromSlot", "before."); SanityManager.showTrace(new Throwable()); SanityManager.DEBUG_PRINT("fetchFromSlot", "fetchDesc = " + fetchDesc); if (fetchDesc != null) { SanityManager.DEBUG_PRINT("fetchFromSlot", ";fetchDesc.getMaxFetchColumnId() = " + fetchDesc.getMaxFetchColumnId() + ";fetchDesc.getValidColumns() = " + fetchDesc.getValidColumns() + ";fetchDesc.getQualifierList() = " + fetchDesc.getQualifierList() ); } */ return( restoreRecordFromSlot( slot, row, fetchDesc, rh, recordHeader, true) ? rh : null); } /** @exception StandardException Standard Cloudscape error policy @see Page#fetchFieldFromSlot */ public final RecordHandle fetchFieldFromSlot( int slot, int fieldId, Object column) throws StandardException { // need to allocate row with fieldId cols because of sparse row change // needs to be RESOLVED Object[] row = new Object[fieldId + 1]; row[fieldId] = column; FormatableBitSet singleColumn = new FormatableBitSet(fieldId + 1); singleColumn.set(fieldId); FetchDescriptor fetchDesc = new FetchDescriptor(fieldId + 1, singleColumn,(Qualifier[][]) null); return(fetchFromSlot(null, slot, row, fetchDesc, true)); } /** @exception StandardException Record does not exist on this page. @see Page#getSlotNumber */ public final int getSlotNumber(RecordHandle handle) throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } int slot = findRecordById(handle.getId(), handle.getSlotNumberHint()); if (slot < 0) { throw StandardException.newException( SQLState.RAWSTORE_RECORD_VANISHED, handle); } return slot; } /** @exception StandardException Record does not exist on this page. @see Page#getNextSlotNumber */ public final int getNextSlotNumber(RecordHandle handle) throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } int slot = findNextRecordById(handle.getId()); return slot; } /** @see Page#insertAtSlot @exception StandardException Standard Cloudscape error policy */ public RecordHandle insertAtSlot( int slot, Object[] row, FormatableBitSet validColumns, LogicalUndo undo, byte insertFlag, int overflowThreshold) throws StandardException { if (SanityManager.DEBUG) { if (overflowThreshold == 0) SanityManager.THROWASSERT("overflowThreshold cannot be 0"); } if ((insertFlag & Page.INSERT_DEFAULT) == Page.INSERT_DEFAULT) { return (insertNoOverflow(slot, row, validColumns, undo, insertFlag, overflowThreshold)); } else { if (SanityManager.DEBUG) { if (undo != null) SanityManager.THROWASSERT("logical undo with overflow allowed on insert " + undo.toString()); } return (insertAllowOverflow(slot, row, validColumns, 0, insertFlag, overflowThreshold, (RecordHandle) null)); } } protected RecordHandle insertNoOverflow( int slot, Object[] row, FormatableBitSet validColumns, LogicalUndo undo, byte insertFlag, int overflowThreshold) throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(isLatched()); } if (!owner.updateOK()) { throw StandardException.newException( SQLState.DATA_CONTAINER_READ_ONLY); } if (slot < FIRST_SLOT_NUMBER || slot > recordCount) { throw StandardException.newException( SQLState.DATA_SLOT_NOT_ON_PAGE); } if (!allowInsert()) return null; RawTransaction t = owner.getTransaction(); // logical operations not allowed in internal transactions. if (undo != null) { t.checkLogicalOperationOk(); } int recordId; RecordHandle handle; do { // loop until we get a new record id we can get a lock on. // If we can't get the lock without waiting then assume the record // id is owned by another xact. The current heap overflow // algorithm makes this likely, as it first try's to insert a row // telling raw store to fail if it doesn't fit on the page getting // a lock on an id that never makes it to disk. The inserting // transaction will hold a lock on this "unused" record id until // it commits. The page can leave the cache at this point, and // the inserting transaction has not dirtied the page (it failed // after getting the lock but before logging anything), another // inserting transaction will then get the same id as the // previous inserter - thus the loop on lock waits. // // The lock we request indicates that this is a lock for insert, // which the locking policy may use to perform locking concurrency // optimizations. recordId = newRecordIdAndBump(); handle = new RecordId(getPageId(), recordId, slot); } while(!owner.getLockingPolicy().lockRecordForWrite( t, handle, true /* lock is for insert */, false /* don't wait for grant */)); owner.getActionSet().actionInsert(t, this, slot, recordId, row, validColumns, undo, insertFlag, 0, false, -1, (DynamicByteArrayOutputStream) null, -1, overflowThreshold); // at this point the insert has been logged and made on the physical // page the in-memory manipulation of the slot table is also performed // by the PageActions object that implements actionInsert. return handle; } /** @see Page#insert @exception StandardException Standard Cloudscape error policy */ public final RecordHandle insert( Object[] row, FormatableBitSet validColumns, byte insertFlag, int overflowThreshold) throws StandardException { if (SanityManager.DEBUG) { if (overflowThreshold == 0) SanityManager.THROWASSERT("overflowThreshold much be greater than 0"); } if (((insertFlag & Page.INSERT_DEFAULT) == Page.INSERT_DEFAULT)) { return (insertAtSlot(recordCount, row, validColumns, (LogicalUndo) null, insertFlag, overflowThreshold)); } else { return (insertAllowOverflow(recordCount, row, validColumns, 0, insertFlag, overflowThreshold, (RecordHandle) null)); } } /** Insert a row allowing overflow. If handle is supplied then the record at that hanlde will be updated to indicate it is a partial row and it has an overflow portion. @exception StandardException Standard Cloudscape error policy */ public RecordHandle insertAllowOverflow( int slot, Object[] row, FormatableBitSet validColumns, int startColumn, byte insertFlag, int overflowThreshold, RecordHandle nextPortionHandle) throws StandardException { BasePage curPage = this; if (!curPage.owner.updateOK()) { throw StandardException.newException( SQLState.DATA_CONTAINER_READ_ONLY); } // Handle of the first portion of the chain RecordHandle headHandle = null; RecordHandle handleToUpdate = null; RawTransaction t = curPage.owner.getTransaction(); for (;;) { if (SanityManager.DEBUG) { SanityManager.ASSERT(curPage.isLatched()); } if (!curPage.allowInsert()) return null; // 'this' is the head page if (curPage != this) slot = curPage.recordCount; boolean isLongColumns = false; int realStartColumn = -1; int realSpaceOnPage = -1; DynamicByteArrayOutputStream logBuffer = null; // allocate new record id and handle int recordId = curPage.newRecordIdAndBump(); RecordHandle handle = new RecordId(curPage.getPageId(), recordId, slot); if (curPage == this) { // Lock the row, if it is the very first portion of the record. if (handleToUpdate == null) { while (!owner.getLockingPolicy().lockRecordForWrite( t, handle, true /* lock is for insert */, false /* don't wait for grant */)) { // loop until we get a new record id we can get a lock // on. If we can't get the lock without waiting then // assume the record id is owned by another xact. The // current heap overflow algorithm makes this likely, // as it first try's to insert a row telling raw store // to fail if it doesn't fit on the page getting a lock // on an id that never makes it to disk. The // inserting transaction will hold a lock on this // "unused" record id until it commits. The page can // leave the cache at this point, and the inserting // transaction has not dirtied the page (it failed // after getting the lock but before logging anything), // another inserting transaction will then get the // same id as the previous inserter - thus the loop on // lock waits. // // The lock we request indicates that this is a lock // for insert, which the locking policy may use to // perform locking concurrency optimizations. // allocate new record id and handle recordId = curPage.newRecordIdAndBump(); handle = new RecordId(curPage.getPageId(), recordId, slot); } } headHandle = handle; } do { // do this loop at least once. If we caught a long Column, // then, we redo the insert with saved logBuffer. try { startColumn = owner.getActionSet().actionInsert( t, curPage, slot, recordId, row, validColumns, (LogicalUndo) null, insertFlag, startColumn, false, realStartColumn, logBuffer, realSpaceOnPage, overflowThreshold); isLongColumns = false; } catch (LongColumnException lce) { // we caught a long column exception // three things should happen here: // 1. insert the long column into overflow pages. // 2. append the overflow field header in the main chain. // 3. continue the insert in the main data chain. logBuffer = new DynamicByteArrayOutputStream(lce.getLogBuffer()); // step 1: insert the long column ... use the same // insertFlag as the rest of the row. RecordHandle longColumnHandle = insertLongColumn(curPage, lce, insertFlag); // step 2: append the overflow field header to the log buffer int overflowFieldLen = 0; try { overflowFieldLen += appendOverflowFieldHeader((DynamicByteArrayOutputStream)logBuffer, longColumnHandle); } catch (IOException ioe) { // YYZ: revisit... ioexception, insert failed... return null; } // step 3: continue the insert in the main data chain // need to pass the log buffer, and start column to the next insert. realStartColumn = lce.getNextColumn() + 1; realSpaceOnPage = lce.getRealSpaceOnPage() - overflowFieldLen; isLongColumns = true; } } while (isLongColumns); if (handleToUpdate != null) { // update the recordheader on the previous page updateOverflowDetails(handleToUpdate, handle); } // all done if (startColumn == -1) { if (curPage != this) curPage.unlatch(); if (nextPortionHandle != null) { // need to update the overflow details of the last portion // to point to the existing portion updateOverflowDetails(handle, nextPortionHandle); } return headHandle; } handleToUpdate = handle; BasePage nextPage = curPage.getOverflowPageForInsert( slot, row, validColumns,startColumn); if (curPage != this) curPage.unlatch(); curPage = nextPage; } } /** When we update a column, it turned into a long column. Need to change the update to effectively insert a new long column chain. @exception StandardException Unexpected exception from the implementation */ protected RecordHandle insertLongColumn(BasePage mainChainPage, LongColumnException lce, byte insertFlag) throws StandardException { // Object[] row = new Object[1]; // row[0] = (Object) lce.getColumn(); Object[] row = new Object[1]; row[0] = lce.getColumn(); RecordHandle firstHandle = null; RecordHandle handle = null; RecordHandle prevHandle = null; BasePage curPage = mainChainPage; BasePage prevPage = null; boolean isFirstPage = true; // when inserting a long column startCOlumn is just used // as a flag. -1 means the insert is complete, != -1 indicates // more inserts are required. int startColumn = 0; RawTransaction t = curPage.owner.getTransaction(); do { // in this loop, we do 3 things: // 1. get a new overflow page // 2. insert portion of a long column // 3. update previous handle, release latch on previous page if (!isFirstPage) { prevPage = curPage; prevHandle = handle; } // step 1. get a new overflow page curPage = (BasePage) getNewOverflowPage(); if (SanityManager.DEBUG) { SanityManager.ASSERT(curPage.isLatched()); SanityManager.ASSERT(curPage.allowInsert()); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -