Example #1
0
func (scan *HeapScan) getBuffer(blockNum system.BlockNumber) (storage.Buffer, system.BlockNumber, error) {

	// release previous scan buffer, if any
	if scan.cBuf.IsValid() {
		scan.bufMgr.ReleaseBuffer(scan.cBuf)
		scan.cBuf = storage.InvalidBuffer()
	}

	// read page
	buf, err := scan.bufMgr.ReadBuffer(scan.rel.RelNode, blockNum)
	if err != nil {
		return storage.InvalidBuffer(), system.InvalidBlockNumber, err
	}
	return buf, blockNum, nil
}
Example #2
0
func (scan *HeapScan) Next() (Tuple, error) {

	var lineOff system.OffsetNumber
	var cBlock system.BlockNumber = system.InvalidBlockNumber
	tuple := scan.cTuple

	if !scan.inited {
		// return immediately if relation is empty
		if scan.nBlocks == 0 {
			tuple.SetData(nil, system.InvalidItemPointer)
			return nil, nil
		}

		cBlock = scan.startBlock
		if buf, block, err := scan.getBuffer(cBlock); err != nil {
			return nil, err
		} else {
			scan.cBuf, scan.cBlock = buf, block
		}
		lineOff = system.FirstOffsetNumber
		scan.inited = true
	} else {
		// continue from previously returned page/tuple
		cBlock = scan.cBlock
		lineOff = tuple.self.OffsetNumber().Next()
	}

	scan.cBuf.RLock()

	page := scan.cBuf.GetPage()
	nLines := page.MaxOffsetNumber()
	linesLeft := nLines - lineOff + 1

	itemId := page.ItemId(lineOff)
	for {
		for linesLeft > 0 {
			if itemId.IsNormal() {
				tid := system.MakeItemPointer(cBlock, lineOff)
				tuple.SetData(page.Item(itemId), tid)

				// TODO: valid = HeapTupleSatisfyiesVisibility()

				scan.cBuf.Unlock()
			}

			// otherwise move to the next item on the page
			linesLeft--

			lineOff++
			itemId = page.ItemId(lineOff)
		}

		// if we get here, it means we've exhausted the items on this page and
		// it's time to move to the next.
		scan.cBuf.Unlock()

		cBlock++
		if cBlock >= scan.nBlocks {
			cBlock = 0
		}
		finished := cBlock == scan.startBlock

		if finished {
			if scan.cBuf.IsValid() {
				scan.bufMgr.ReleaseBuffer(scan.cBuf)
			}
			scan.cBuf = storage.InvalidBuffer()
			scan.cBlock = system.InvalidBlockNumber
			tuple.SetData(nil, system.InvalidItemPointer)
			scan.inited = false
			return nil, nil
		}

		if buf, block, err := scan.getBuffer(cBlock); err != nil {
			return nil, err
		} else {
			scan.cBuf, scan.cBlock = buf, block
		}

		scan.cBuf.RLock()

		page = scan.cBuf.GetPage()
		nLines = page.MaxOffsetNumber()
		linesLeft = nLines
		lineOff = system.FirstOffsetNumber
		itemId = page.ItemId(lineOff)
	}
}