blob: 080b9af789dae1a75c1631b35603405b05fc0ec6 [file] [log] [blame]
Abhay Kumara2ae5992025-11-10 14:02:24 +00001package common
2
3import "unsafe"
4
5// Inode represents an internal node inside of a node.
6// It can be used to point to elements in a page or point
7// to an element which hasn't been added to a page yet.
8type Inode struct {
9 flags uint32
10 pgid Pgid
11 key []byte
12 value []byte
13}
14
15type Inodes []Inode
16
17func (in *Inode) Flags() uint32 {
18 return in.flags
19}
20
21func (in *Inode) SetFlags(flags uint32) {
22 in.flags = flags
23}
24
25func (in *Inode) Pgid() Pgid {
26 return in.pgid
27}
28
29func (in *Inode) SetPgid(id Pgid) {
30 in.pgid = id
31}
32
33func (in *Inode) Key() []byte {
34 return in.key
35}
36
37func (in *Inode) SetKey(key []byte) {
38 in.key = key
39}
40
41func (in *Inode) Value() []byte {
42 return in.value
43}
44
45func (in *Inode) SetValue(value []byte) {
46 in.value = value
47}
48
49func ReadInodeFromPage(p *Page) Inodes {
50 inodes := make(Inodes, int(p.Count()))
51 isLeaf := p.IsLeafPage()
52 for i := 0; i < int(p.Count()); i++ {
53 inode := &inodes[i]
54 if isLeaf {
55 elem := p.LeafPageElement(uint16(i))
56 inode.SetFlags(elem.Flags())
57 inode.SetKey(elem.Key())
58 inode.SetValue(elem.Value())
59 } else {
60 elem := p.BranchPageElement(uint16(i))
61 inode.SetPgid(elem.Pgid())
62 inode.SetKey(elem.Key())
63 }
64 Assert(len(inode.Key()) > 0, "read: zero-length inode key")
65 }
66
67 return inodes
68}
69
70func WriteInodeToPage(inodes Inodes, p *Page) uint32 {
71 // Loop over each item and write it to the page.
72 // off tracks the offset into p of the start of the next data.
73 off := unsafe.Sizeof(*p) + p.PageElementSize()*uintptr(len(inodes))
74 isLeaf := p.IsLeafPage()
75 for i, item := range inodes {
76 Assert(len(item.Key()) > 0, "write: zero-length inode key")
77
78 // Create a slice to write into of needed size and advance
79 // byte pointer for next iteration.
80 sz := len(item.Key()) + len(item.Value())
81 b := UnsafeByteSlice(unsafe.Pointer(p), off, 0, sz)
82 off += uintptr(sz)
83
84 // Write the page element.
85 if isLeaf {
86 elem := p.LeafPageElement(uint16(i))
87 elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
88 elem.SetFlags(item.Flags())
89 elem.SetKsize(uint32(len(item.Key())))
90 elem.SetVsize(uint32(len(item.Value())))
91 } else {
92 elem := p.BranchPageElement(uint16(i))
93 elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
94 elem.SetKsize(uint32(len(item.Key())))
95 elem.SetPgid(item.Pgid())
96 Assert(elem.Pgid() != p.Id(), "write: circular dependency occurred")
97 }
98
99 // Write data for the element to the end of the page.
100 l := copy(b, item.Key())
101 copy(b[l:], item.Value())
102 }
103
104 return uint32(off)
105}
106
107func UsedSpaceInPage(inodes Inodes, p *Page) uint32 {
108 off := unsafe.Sizeof(*p) + p.PageElementSize()*uintptr(len(inodes))
109 for _, item := range inodes {
110 sz := len(item.Key()) + len(item.Value())
111 off += uintptr(sz)
112 }
113
114 return uint32(off)
115}