예제 #1
0
static const unsigned char *PageHeader(DbPage *pPage){
  if( pPage->pgno==1 ){
    const unsigned nDatabaseHeader = 100;
    return PageData(pPage, nDatabaseHeader);
  }else{
    return PageData(pPage, 0);
  }
}
예제 #2
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;
	}
예제 #3
0
	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;
	}
예제 #4
0
	// 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;
				}
			}
		}
	}
예제 #5
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;
}
예제 #6
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());
}
예제 #8
0
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;
}
예제 #9
0
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;
}
예제 #10
0
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;
}