/* * 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 view contains general page view constants and functions. PageView is the super-struct for all page views. A page view is special object attached to a particular StorageFile record. A view provides specialised functions for the record it is attached to. Use GetPageView() if the record has already view information stored on it or NewPageView() to initialise or reassign a given record. */ package view import ( "fmt" "devt.de/krotik/eliasdb/storage/file" ) /* ViewPageHeader is the header magic number to identify view pages */ const ViewPageHeader = 0x1990 /* OffsetNextPage is the offset for next page id */ const OffsetNextPage = file.SizeShort /* OffsetPrevPage is the offset for previous page id */ const OffsetPrevPage = OffsetNextPage + file.SizeLong /* OffsetData is the offset for page specific data */ const OffsetData = OffsetPrevPage + file.SizeLong /* PageView data structure */ type PageView struct { Record *file.Record // Record which is wrapped by the PageView } /* GetPageView returns the page view of a given record. */ func GetPageView(record *file.Record) *PageView { rpv := record.PageView() pv, ok := rpv.(*PageView) if ok { return pv } pv = &PageView{record} pv.checkMagic() record.SetPageView(pv) return pv } /* NewPageView creates a new page view for a given record. */ func NewPageView(record *file.Record, pagetype int16) *PageView { pv := &PageView{record} record.SetPageView(pv) pv.SetType(pagetype) return pv } /* Type gets the type of this page view which is stored on the record. */ func (pv *PageView) Type() int16 { return pv.Record.ReadInt16(0) - ViewPageHeader } /* SetType sets the type of this page view which is stored on the record. */ func (pv *PageView) SetType(pagetype int16) { pv.Record.WriteInt16(0, ViewPageHeader+pagetype) } /* checkMagic checks if the magic number at the beginning of the wrapped record is valid. */ func (pv *PageView) checkMagic() bool { magic := pv.Record.ReadInt16(0) if magic >= ViewPageHeader && magic <= ViewPageHeader+TypeFreePhysicalSlotPage { return true } panic("Unexpected header found in PageView") } /* NextPage returns the id of the next page. */ func (pv *PageView) NextPage() uint64 { pv.checkMagic() return pv.Record.ReadUInt64(OffsetNextPage) } /* SetNextPage sets the id of the next page. */ func (pv *PageView) SetNextPage(val uint64) { pv.checkMagic() pv.Record.WriteUInt64(OffsetNextPage, val) } /* PrevPage returns the id of the previous page. */ func (pv *PageView) PrevPage() uint64 { pv.checkMagic() return pv.Record.ReadUInt64(OffsetPrevPage) } /* SetPrevPage sets the id of the previous page. */ func (pv *PageView) SetPrevPage(val uint64) { pv.checkMagic() pv.Record.WriteUInt64(OffsetPrevPage, val) } func (pv *PageView) String() string { return fmt.Sprintf("PageView: %v (type:%v previous page:%v next page:%v)", pv.Record.ID(), pv.Type(), pv.PrevPage(), pv.NextPage()) }