123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package pageview
- import (
- "devt.de/krotik/eliasdb/storage/file"
- "devt.de/krotik/eliasdb/storage/paging/view"
- "devt.de/krotik/eliasdb/storage/util"
- )
- // OFFSET_COUNT / OFFSET_DATA declared in freephysicalslotpage
- /*
- FreeLogicalSlotPage data structure
- */
- type FreeLogicalSlotPage struct {
- *SlotInfoPage
- maxSlots uint16 // Max number of slots
- prevFoundFreeSlot uint16 // Previous found free slot
- prevFoundAllocatedSlot uint16 // Previous allocated slot
- }
- /*
- NewFreeLogicalSlotPage creates a new page which can manage free slots.
- */
- func NewFreeLogicalSlotPage(record *file.Record) *FreeLogicalSlotPage {
- checkFreeLogicalSlotPageMagic(record)
- maxSlots := (len(record.Data()) - OffsetData) / util.LocationSize
- return &FreeLogicalSlotPage{NewSlotInfoPage(record), uint16(maxSlots), 0, 0}
- }
- /*
- checkFreeLogicalSlotPageMagic checks if the magic number at the beginning of
- the wrapped record is valid.
- */
- func checkFreeLogicalSlotPageMagic(record *file.Record) bool {
- magic := record.ReadInt16(0)
- if magic == view.ViewPageHeader+view.TypeFreeLogicalSlotPage {
- return true
- }
- panic("Unexpected header found in FreeLogicalSlotPage")
- }
- /*
- MaxSlots returns the maximum number of slots which can be allocated.
- */
- func (flsp *FreeLogicalSlotPage) MaxSlots() uint16 {
- return flsp.maxSlots
- }
- /*
- FreeSlotCount returns the number of free slots on this page.
- */
- func (flsp *FreeLogicalSlotPage) FreeSlotCount() uint16 {
- return flsp.Record.ReadUInt16(OffsetCount)
- }
- /*
- SlotInfoLocation returns contents of a stored slotinfo as a location. Lookup is via a
- given slotinfo id.
- */
- func (flsp *FreeLogicalSlotPage) SlotInfoLocation(slotinfo uint16) uint64 {
- offset := flsp.slotinfoToOffset(slotinfo)
- return util.PackLocation(flsp.SlotInfoRecord(offset), flsp.SlotInfoOffset(offset))
- }
- /*
- AllocateSlotInfo allocates a place for a slotinfo and returns the offset for it.
- */
- func (flsp *FreeLogicalSlotPage) AllocateSlotInfo(slotinfo uint16) uint16 {
- offset := flsp.slotinfoToOffset(slotinfo)
- // Set slotinfo to initial values
- flsp.SetSlotInfo(offset, 1, 1)
- // Increase counter for allocated slotinfos
- flsp.Record.WriteUInt16(OffsetCount, flsp.FreeSlotCount()+1)
- // Update prevFoundAllocatedSlot if necessary
- if slotinfo < flsp.prevFoundAllocatedSlot {
- flsp.prevFoundAllocatedSlot = slotinfo
- }
- return offset
- }
- /*
- ReleaseSlotInfo releases a place for a slotinfo and return its offset.
- */
- func (flsp *FreeLogicalSlotPage) ReleaseSlotInfo(slotinfo uint16) uint16 {
- offset := flsp.slotinfoToOffset(slotinfo)
- // Set slotinfo to empty values
- flsp.SetSlotInfo(offset, 0, 0)
- // Decrease counter for allocated slotinfos
- flsp.Record.WriteUInt16(OffsetCount, flsp.FreeSlotCount()-1)
- // Update prevFoundFreeSlot if necessary
- if slotinfo < flsp.prevFoundFreeSlot {
- flsp.prevFoundFreeSlot = slotinfo
- }
- return offset
- }
- /*
- FirstFreeSlotInfo returns the id for the first available slotinfo or -1 if
- nothing is available.
- */
- func (flsp *FreeLogicalSlotPage) FirstFreeSlotInfo() int {
- for flsp.prevFoundFreeSlot < flsp.maxSlots {
- if !flsp.isAllocatedSlot(flsp.prevFoundFreeSlot) {
- return int(flsp.prevFoundFreeSlot)
- }
- flsp.prevFoundFreeSlot++
- }
- return -1
- }
- /*
- FirstAllocatedSlotInfo returns the id for the first allocated slotinfo or -1 if
- nothing is allocated.
- */
- func (flsp *FreeLogicalSlotPage) FirstAllocatedSlotInfo() int {
- for flsp.prevFoundAllocatedSlot < flsp.maxSlots {
- if flsp.isAllocatedSlot(flsp.prevFoundAllocatedSlot) {
- return int(flsp.prevFoundAllocatedSlot)
- }
- flsp.prevFoundAllocatedSlot++
- }
- return -1
- }
- /*
- isAllocatedSlot checks if a given slotinfo is allocated.
- */
- func (flsp *FreeLogicalSlotPage) isAllocatedSlot(slotinfo uint16) bool {
- offset := flsp.slotinfoToOffset(slotinfo)
- return flsp.SlotInfoRecord(offset) != 0 || flsp.SlotInfoOffset(offset) != 0
- }
- /*
- slotinfoToOffset converts a slotinfo number into an offset on the record.
- */
- func (flsp *FreeLogicalSlotPage) slotinfoToOffset(slotinfo uint16) uint16 {
- return OffsetData + slotinfo*util.LocationSize
- }
|