Пример #1
0
// Initializes the content of a page.
func (page *Page) Init(specialSize uintptr) {
	copy(page.bytes[:], _PageZero)

	specialSize = system.MaxAlign(specialSize)
	offsetSpecial := uint16(system.BlockSize - specialSize)
	page.SetLower(sizeOfPageHeader)
	page.SetUpper(offsetSpecial)
	page.SetSpecial(offsetSpecial)
	page.SetPageSizeAndVersion(system.BlockSize, LayoutVersion)
}
Пример #2
0
func FormHeapTuple(values []system.Datum, tupdesc *TupleDesc) *HeapTuple {
	natts := len(tupdesc.Attrs)
	hasnull := false
	for _, value := range values {
		if value == nil {
			hasnull = true
			//} else if att.attlen == -1
			// TODO: flatten toast value
		}
	}

	length := unsafe.Offsetof(HeapTupleHeader{}.bits)

	if hasnull {
		length += uintptr(bitmapLength(natts))
	}
	if tupdesc.hasOid {
		length += unsafe.Sizeof(system.Oid(0))
	}

	length = system.MaxAlign(length)
	hoff := uint8(length)

	data_len := computeHeapDataSize(values, tupdesc)
	length += data_len

	tuple_data := make([]byte, length)
	tuple := &HeapTuple{
		tupdesc:  tupdesc,
		tableOid: system.InvalidOid,
	}
	tuple.SetData(tuple_data, system.InvalidItemPointer)

	td := tuple.data
	td.SetNatts(system.AttrNumber(natts))
	td.hoff = hoff

	if tupdesc.hasOid {
		td.infomask = heapHasOid
	}

	bits := []byte(nil)
	if hasnull {
		bits = tuple.bytes[unsafe.Offsetof(td.bits):hoff]
	}
	data := tuple.bytes[hoff:]
	td.fill(values, tupdesc, bits, data)

	return tuple
}
Пример #3
0
func (page *Page) AddItem(item []byte, offset system.OffsetNumber, overwrite, is_heap bool) system.OffsetNumber {
	// Be wary about corrupted page pointers
	if page.Lower() < sizeOfPageHeader ||
		page.Lower() > page.Upper() ||
		page.Upper() > page.Special() ||
		page.Special() > system.BlockSize {
		log.Panicf("corrupted page pointers: lower = %d, upper = %d, special = %d",
			page.Lower(), page.Upper(), page.Special())
	}

	// Select offset to place the new item at
	limit := page.MaxOffsetNumber().Next()

	needshuffle := false

	// was offset passed in?
	if offset.IsValid() {
		// yes, check it
		if overwrite {
			if offset < limit {
				itemId := page.ItemId(offset)
				if itemId.IsUsed() || itemId.HasStorage() {
					log.Println("WARNING: will not overwrite a used ItemId")
					return system.InvalidOffsetNumber
				}
			}
		} else {
			if offset < limit {
				// need to move existing linp's
				needshuffle = true
			}
		}
	} else {
		if page.HasFreeLinePointers() {
			for offset = 1; offset < limit; offset = offset.Next() {
				itemId := page.ItemId(offset)
				if !itemId.IsUsed() && !itemId.HasStorage() {
					break
				}
			}
			if offset >= limit {
				page.ClearHasFreeLinePointers()
			}
		} else {
			// don't bother searching if hint says there's no free slot
			offset = limit
		}
	}

	if offset > limit {
		log.Println("WARNING: specified item offset is too large")
		return system.InvalidOffsetNumber
	}

	// if is_heap && offset > MaxHeapTuplesPerPage {
	// 	log.Println("WARNING: can't put more than MaxHeapTuplesPerPage items in a heap page")
	// 	return InvalidOffsetNumber
	// }

	// Compute new lower and upper pointers for page, see if it'll fit.
	// Note: do arithmetic as signed ints, to avoid mistakes if, say,
	// alignedSize > upper.
	lower := int(page.Lower())
	if offset == limit || needshuffle {
		lower = lower + int(unsafe.Sizeof(ItemId(0)))
	}

	alignedSize := system.MaxAlign(uintptr(len(item)))

	upper := int(page.Upper()) - int(alignedSize)

	if lower > upper {
		return system.InvalidOffsetNumber
	}

	// OK to insert the item.  First, shuffle the existing pointers if needed.
	itemId := page.ItemId(offset)

	if needshuffle {
		destItemId := page.ItemId(offset + 1)
		base := uintptr(unsafe.Pointer(&page.bytes[0]))
		destStart := uintptr(unsafe.Pointer(destItemId)) - base
		srcStart := uintptr(unsafe.Pointer(itemId)) - base
		copyLen := uintptr(limit-offset) * unsafe.Sizeof(ItemId(0))
		dest := page.bytes[destStart : destStart+copyLen]
		src := page.bytes[srcStart : srcStart+copyLen]
		copy(dest, src)
	}

	// set the item pointer
	itemId.SetNormal(uint(upper), uint(len(item)))

	// copy the item's data onto the page
	if l := copy(page.bytes[upper:], item); l != len(item) {
		panic("unexpected copy result")
	}

	page.SetLower(uint16(lower))
	page.SetUpper(uint16(upper))

	return offset
}