static const unsigned char *PageHeader(DbPage *pPage){ if( pPage->pgno==1 ){ const unsigned nDatabaseHeader = 100; return PageData(pPage, nDatabaseHeader); }else{ return PageData(pPage, 0); } }
//--------------------------------------------------------------------- WorkQueue::Response* Page::handleRequest(const WorkQueue::Request* req, const WorkQueue* srcQ) { // Background thread (maybe) PageRequest preq = any_cast<PageRequest>(req->getData()); // only deal with own requests; we shouldn't ever get here though if (preq.srcPage != this) return 0; PageResponse res; res.pageData = OGRE_NEW PageData(); WorkQueue::Response* response = 0; try { prepareImpl(res.pageData); response = OGRE_NEW WorkQueue::Response(req, true, Any(res)); } catch (Exception& e) { // oops response = OGRE_NEW WorkQueue::Response(req, false, Any(res), e.getFullDescription()); } return response; }
u8* Miss(u16 paddr) { u8 n = _head; if (_flags[n]) { u16 spm = sp >> (CACHEBITS-1); u16 a = _addrs[n]; if (a >= spm) // Don't flush old stack junk FlushSector(a); } u8* dst = PageData(n); memcpy(dst,Seek(paddr),CACHELINE); // LOAD _addrs[n] = paddr; _flags[n] = 1; return dst; }
// Need to write back this sector void FlushSector(u16 addr) { u16 s = ToSector(addr); int n = CACHESLOTS; while (n--) { if (_flags[n]) // Flush all { if (s == ToSector(_addrs[n])) { Seek(_addrs[n]); u8* d = PageData(n); _file->Write(d,CACHELINE); _flags[n] = 0; } } } }
static unsigned interiorCursorChildPage(RecoverInteriorCursor *pCursor){ const unsigned char *pPageHeader; const unsigned char *pCellOffsets; unsigned iCellOffset; assert( pCursor->iChild<pCursor->nChildren ); pPageHeader = PageHeader(pCursor->pPage); if( pCursor->iChild==pCursor->nChildren-1 ){ return decodeUnsigned32(pPageHeader + kiPageRightChildOffset); } pCellOffsets = pPageHeader + kiPageInteriorHeaderBytes; iCellOffset = decodeUnsigned16(pCellOffsets + pCursor->iChild*2); if( iCellOffset<=pCursor->nPageSize-4 ){ return decodeUnsigned32(PageData(pCursor->pPage, iCellOffset)); } return 0; }
u8* Get(u16 addr, bool w) { u8 prev = 0xFF; u8 slot = _head; for (;;) { if (_addrs[slot] == addr) // LRU { _flags[slot] |= w; BringToFront(slot,prev); return PageData(slot); } if (_next[slot] == 0xFF) break; prev = slot; slot = _next[slot]; } if (!w) return Seek(addr); BringToFront(slot,prev); // keep return Miss(addr); }
/** @param nPage The page to ensure exists */ void CCPrintData::EnsurePage(int nPage) { while ((int)m_pages.size() < nPage) m_pages.push_back(PageData()); }
static int leafCursorCellDecode(RecoverLeafCursor *pCursor){ const unsigned char *pPageHeader; const unsigned char *pCellOffsets; unsigned iCellOffset; const unsigned char *pCell; unsigned nCellMaxBytes; unsigned iEndOffset; u64 nRecordBytes; u64 iRowid; unsigned nRead; unsigned nRecordHeaderRead; u64 nRecordHeaderBytes; unsigned nRecordCols; u64 nRecordColBytes; unsigned i; int rc; assert( pCursor->iCell<pCursor->nCells ); leafCursorDestroyCellData(pCursor); pPageHeader = PageHeader(pCursor->pPage); pCellOffsets = pPageHeader + knPageLeafHeaderBytes; iCellOffset = decodeUnsigned16(pCellOffsets + pCursor->iCell*2); if( iCellOffset>=pCursor->nPageSize ){ return ValidateError(); } pCell = PageData(pCursor->pPage, iCellOffset); nCellMaxBytes = pCursor->nPageSize - iCellOffset; if( !checkVarints(pCell, nCellMaxBytes, 3) ){ return ValidateError(); } nRead = getVarint(pCell, &nRecordBytes); assert( iCellOffset+nRead<=pCursor->nPageSize ); pCursor->nRecordBytes = nRecordBytes; nRead += getVarint(pCell + nRead, &iRowid); assert( iCellOffset+nRead<=pCursor->nPageSize ); pCursor->iRowid = (i64)iRowid; pCursor->iRecordOffset = iCellOffset + nRead; rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize, pCursor->iRecordOffset, pCursor->nRecordBytes, &pCursor->nLocalRecordBytes, &pCursor->pOverflow); if( rc!=SQLITE_OK ){ return ValidateError(); } iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes; for( i=0; i<pCursor->nCells; ++i ){ const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2); if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){ return ValidateError(); } } nRecordHeaderRead = getVarint(pCell + nRead, &nRecordHeaderBytes); assert( nRecordHeaderBytes<=nRecordBytes ); pCursor->nRecordHeaderBytes = nRecordHeaderBytes; rc = overflowGetSegment(pCursor->pPage, pCursor->iRecordOffset, pCursor->nLocalRecordBytes, pCursor->pOverflow, 0, nRecordHeaderBytes, &pCursor->pRecordHeader, &pCursor->bFreeRecordHeader); if( rc!=SQLITE_OK ){ return ValidateError(); } nRecordCols = 0; nRecordColBytes = 0; while( nRecordHeaderRead<nRecordHeaderBytes ){ u64 iSerialType; if( !checkVarint(pCursor->pRecordHeader + nRecordHeaderRead, nRecordHeaderBytes - nRecordHeaderRead) ){ return ValidateError(); } nRecordHeaderRead += getVarint(pCursor->pRecordHeader + nRecordHeaderRead, &iSerialType); if( iSerialType==10 || iSerialType==11 ){ return ValidateError(); } nRecordColBytes += SerialTypeLength(iSerialType); nRecordCols++; } pCursor->nRecordCols = nRecordCols; if( nRecordHeaderRead!=nRecordHeaderBytes ){ return ValidateError(); } if( nRecordHeaderBytes+nRecordColBytes!=nRecordBytes ){ return ValidateError(); } return SQLITE_OK; }
static int overflowGetSegment(DbPage *pPage, unsigned iRecordOffset, unsigned nLocalRecordBytes, RecoverOverflow *pOverflow, unsigned iRequestOffset, unsigned nRequestBytes, unsigned char **ppBase, int *pbFree){ unsigned nBase; unsigned char *pBase; while( iRequestOffset>=nLocalRecordBytes && pOverflow ){ iRequestOffset -= nLocalRecordBytes; pPage = pOverflow->pPage; iRecordOffset = 4; nLocalRecordBytes = pOverflow->nPageSize - iRecordOffset; pOverflow = pOverflow->pNextOverflow; } if( iRequestOffset+nRequestBytes<=nLocalRecordBytes ){ *ppBase = (unsigned char *)PageData(pPage, iRecordOffset + iRequestOffset); *pbFree = 0; return SQLITE_OK; } if( !pOverflow ){ assert(NULL); return SQLITE_ERROR; } nBase = 0; pBase = sqlite3_malloc(nRequestBytes); if( !pBase ){ return SQLITE_NOMEM; } while( nBase<nRequestBytes ){ unsigned nCopyBytes = nRequestBytes - nBase; if( nLocalRecordBytes-iRequestOffset<nCopyBytes ){ nCopyBytes = nLocalRecordBytes - iRequestOffset; } memcpy(pBase + nBase, PageData(pPage, iRecordOffset + iRequestOffset), nCopyBytes); nBase += nCopyBytes; if( pOverflow ){ iRequestOffset = 0; pPage = pOverflow->pPage; iRecordOffset = 4; nLocalRecordBytes = pOverflow->nPageSize - iRecordOffset; pOverflow = pOverflow->pNextOverflow; }else if( nBase<nRequestBytes ){ assert(NULL); sqlite3_free(pBase); return SQLITE_ERROR; } } assert( nBase==nRequestBytes ); *ppBase = pBase; *pbFree = 1; return SQLITE_OK; }
static int overflowMaybeCreate(DbPage *pPage, unsigned nPageSize, unsigned iRecordOffset, unsigned nRecordBytes, unsigned *pnLocalRecordBytes, RecoverOverflow **ppOverflow){ unsigned nLocalRecordBytes; unsigned iNextPage; unsigned nBytes; int rc; RecoverOverflow *pFirstOverflow; RecoverOverflow *pLastOverflow; const unsigned maxLocal = nPageSize - 35; const unsigned minLocal = ((nPageSize-12)*32/255)-23; if( nRecordBytes<=maxLocal ){ *pnLocalRecordBytes = nRecordBytes; *ppOverflow = NULL; return SQLITE_OK; } nLocalRecordBytes = minLocal+((nRecordBytes-minLocal)%(nPageSize-4)); if( maxLocal<nLocalRecordBytes ){ nLocalRecordBytes = minLocal; } if( iRecordOffset+nLocalRecordBytes+4>nPageSize ){ return SQLITE_CORRUPT; } iNextPage = decodeUnsigned32(PageData(pPage, iRecordOffset + nLocalRecordBytes)); nBytes = nLocalRecordBytes; pFirstOverflow = pLastOverflow = NULL; rc = SQLITE_OK; while( iNextPage && nBytes<nRecordBytes ){ RecoverOverflow *pOverflow; rc = sqlite3PagerAcquire(pPage->pPager, iNextPage, &pPage, 0); if( rc!=SQLITE_OK ){ break; } pOverflow = sqlite3_malloc(sizeof(RecoverOverflow)); if( !pOverflow ){ sqlite3PagerUnref(pPage); rc = SQLITE_NOMEM; break; } memset(pOverflow, 0, sizeof(*pOverflow)); pOverflow->pPage = pPage; pOverflow->nPageSize = nPageSize; if( !pFirstOverflow ){ pFirstOverflow = pOverflow; }else{ pLastOverflow->pNextOverflow = pOverflow; } pLastOverflow = pOverflow; iNextPage = decodeUnsigned32(pPage->pData); nBytes += nPageSize-4; if( overflowPageInUse(pFirstOverflow, iNextPage) ){ fprintf(stderr, "Overflow loop detected at %d\n", iNextPage); rc = SQLITE_CORRUPT; break; } } if( rc==SQLITE_OK && (nBytes<nRecordBytes || iNextPage) ){ rc = SQLITE_CORRUPT; } if( rc==SQLITE_OK ){ *ppOverflow = pFirstOverflow; *pnLocalRecordBytes = nLocalRecordBytes; }else if( pFirstOverflow ){ overflowDestroy(pFirstOverflow); } return rc; }