This repository has been archived by the owner on Dec 3, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
page.go
55 lines (45 loc) · 1.46 KB
/
page.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package writeaheadlog
import (
"encoding/binary"
"fmt"
"math"
)
// page is linked list of on-disk pages that comprise a set of Updates.
type page struct {
// nextPage points to the logical next page in the logFile for this
// transaction. The page may not appear in the file in-order. When
// marshalled, this value is encoded as nextPage.offset. If nextPage is
// nil, it is encoded as math.MaxUint64.
nextPage *page
// offset is the offset in the file that this page has. It is not
// marshalled to disk.
offset uint64
// payload contains the marshalled Updates, which may be spread over
// multiple pages. If spread over multiple pages, the full payload can be
// assembled via concatenation.
payload []byte
}
func (p page) size() int { return pageMetaSize + len(p.payload) }
func (p page) nextOffset() uint64 {
if p.nextPage == nil {
return math.MaxUint64
}
return p.nextPage.offset
}
// appendTo appends the marshalled bytes of p to buf, returning the new slice.
func (p *page) appendTo(buf []byte) []byte {
if p.size() > pageSize {
panic(fmt.Sprintf("sanity check failed: page is %d bytes too large", p.size()-pageSize))
}
// if buf has enough capacity to hold p, use it; otherwise allocate
var b []byte
if rest := buf[len(buf):]; cap(rest) >= p.size() {
b = rest[:p.size()]
} else {
b = make([]byte, p.size())
}
// write page contents
binary.LittleEndian.PutUint64(b[0:], p.nextOffset())
copy(b[8:], p.payload)
return append(buf, b...)
}