mirror of https://github.com/etcd-io/bbolt.git
Add 'bolt page' command.
parent
3ad30436da
commit
73a3aa1ccc
473
cmd/bolt/main.go
473
cmd/bolt/main.go
|
@ -15,6 +15,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
)
|
)
|
||||||
|
@ -45,8 +48,17 @@ var (
|
||||||
|
|
||||||
// ErrPageIDRequired is returned when a required page id is not specified.
|
// ErrPageIDRequired is returned when a required page id is not specified.
|
||||||
ErrPageIDRequired = errors.New("page id required")
|
ErrPageIDRequired = errors.New("page id required")
|
||||||
|
|
||||||
|
// ErrPageNotFound is returned when specifying a page above the high water mark.
|
||||||
|
ErrPageNotFound = errors.New("page not found")
|
||||||
|
|
||||||
|
// ErrPageFreed is returned when reading a page that has already been freed.
|
||||||
|
ErrPageFreed = errors.New("page freed")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PageHeaderSize represents the size of the bolt.page header.
|
||||||
|
const PageHeaderSize = 16
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
m := NewMain()
|
m := NewMain()
|
||||||
if err := m.Run(os.Args[1:]...); err == ErrUsage {
|
if err := m.Run(os.Args[1:]...); err == ErrUsage {
|
||||||
|
@ -94,6 +106,8 @@ func (m *Main) Run(args ...string) error {
|
||||||
return newDumpCommand(m).Run(args[1:]...)
|
return newDumpCommand(m).Run(args[1:]...)
|
||||||
case "info":
|
case "info":
|
||||||
return newInfoCommand(m).Run(args[1:]...)
|
return newInfoCommand(m).Run(args[1:]...)
|
||||||
|
case "page":
|
||||||
|
return newPageCommand(m).Run(args[1:]...)
|
||||||
case "pages":
|
case "pages":
|
||||||
return newPagesCommand(m).Run(args[1:]...)
|
return newPagesCommand(m).Run(args[1:]...)
|
||||||
case "stats":
|
case "stats":
|
||||||
|
@ -290,7 +304,6 @@ func (cmd *DumpCommand) Run(args ...string) error {
|
||||||
// Parse flags.
|
// Parse flags.
|
||||||
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
help := fs.Bool("h", false, "")
|
help := fs.Bool("h", false, "")
|
||||||
pageID := fs.Int("page", -1, "")
|
|
||||||
if err := fs.Parse(args); err != nil {
|
if err := fs.Parse(args); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if *help {
|
} else if *help {
|
||||||
|
@ -304,17 +317,21 @@ func (cmd *DumpCommand) Run(args ...string) error {
|
||||||
return ErrPathRequired
|
return ErrPathRequired
|
||||||
} else if _, err := os.Stat(path); os.IsNotExist(err) {
|
} else if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
return ErrFileNotFound
|
return ErrFileNotFound
|
||||||
} else if *pageID == -1 {
|
}
|
||||||
|
|
||||||
|
// Read page ids.
|
||||||
|
pageIDs, err := atois(fs.Args()[1:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(pageIDs) == 0 {
|
||||||
return ErrPageIDRequired
|
return ErrPageIDRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open database to retrieve page size.
|
// Open database to retrieve page size.
|
||||||
db, err := bolt.Open(path, 0666, nil)
|
pageSize, err := ReadPageSize(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pageSize := db.Info().PageSize
|
|
||||||
_ = db.Close()
|
|
||||||
|
|
||||||
// Open database file handler.
|
// Open database file handler.
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
|
@ -323,8 +340,20 @@ func (cmd *DumpCommand) Run(args ...string) error {
|
||||||
}
|
}
|
||||||
defer func() { _ = f.Close() }()
|
defer func() { _ = f.Close() }()
|
||||||
|
|
||||||
// Print page to stdout.
|
// Print each page listed.
|
||||||
return cmd.PrintPage(cmd.Stdout, f, *pageID, pageSize)
|
for i, pageID := range pageIDs {
|
||||||
|
// Print a separator.
|
||||||
|
if i > 0 {
|
||||||
|
fmt.Fprintln(cmd.Stdout, "===============================================\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print page to stdout.
|
||||||
|
if err := cmd.PrintPage(cmd.Stdout, f, pageID, pageSize); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintPage prints a given page as hexidecimal.
|
// PrintPage prints a given page as hexidecimal.
|
||||||
|
@ -381,6 +410,243 @@ Dump prints a hexidecimal dump of a single page.
|
||||||
`, "\n")
|
`, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PageCommand represents the "page" command execution.
|
||||||
|
type PageCommand struct {
|
||||||
|
Stdin io.Reader
|
||||||
|
Stdout io.Writer
|
||||||
|
Stderr io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// newPageCommand returns a PageCommand.
|
||||||
|
func newPageCommand(m *Main) *PageCommand {
|
||||||
|
return &PageCommand{
|
||||||
|
Stdin: m.Stdin,
|
||||||
|
Stdout: m.Stdout,
|
||||||
|
Stderr: m.Stderr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run executes the command.
|
||||||
|
func (cmd *PageCommand) Run(args ...string) error {
|
||||||
|
// Parse flags.
|
||||||
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
help := fs.Bool("h", false, "")
|
||||||
|
if err := fs.Parse(args); err != nil {
|
||||||
|
return err
|
||||||
|
} else if *help {
|
||||||
|
fmt.Fprintln(cmd.Stderr, cmd.Usage())
|
||||||
|
return ErrUsage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Require database path and page id.
|
||||||
|
path := fs.Arg(0)
|
||||||
|
if path == "" {
|
||||||
|
return ErrPathRequired
|
||||||
|
} else if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return ErrFileNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read page ids.
|
||||||
|
pageIDs, err := atois(fs.Args()[1:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(pageIDs) == 0 {
|
||||||
|
return ErrPageIDRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open database file handler.
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() { _ = f.Close() }()
|
||||||
|
|
||||||
|
// Print each page listed.
|
||||||
|
for i, pageID := range pageIDs {
|
||||||
|
// Print a separator.
|
||||||
|
if i > 0 {
|
||||||
|
fmt.Fprintln(cmd.Stdout, "===============================================\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve page info and page size.
|
||||||
|
p, buf, err := ReadPage(path, pageID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print basic page info.
|
||||||
|
fmt.Fprintf(cmd.Stdout, "Page ID: %d\n", p.id)
|
||||||
|
fmt.Fprintf(cmd.Stdout, "Page Type: %s\n", p.Type())
|
||||||
|
fmt.Fprintf(cmd.Stdout, "Total Size: %d bytes\n", len(buf))
|
||||||
|
|
||||||
|
// Print type-specific data.
|
||||||
|
switch p.Type() {
|
||||||
|
case "meta":
|
||||||
|
err = cmd.PrintMeta(cmd.Stdout, buf)
|
||||||
|
case "leaf":
|
||||||
|
err = cmd.PrintLeaf(cmd.Stdout, buf)
|
||||||
|
case "branch":
|
||||||
|
err = cmd.PrintBranch(cmd.Stdout, buf)
|
||||||
|
case "freelist":
|
||||||
|
err = cmd.PrintFreelist(cmd.Stdout, buf)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintMeta prints the data from the meta page.
|
||||||
|
func (cmd *PageCommand) PrintMeta(w io.Writer, buf []byte) error {
|
||||||
|
m := (*meta)(unsafe.Pointer(&buf[PageHeaderSize]))
|
||||||
|
fmt.Fprintf(w, "Version: %d\n", m.version)
|
||||||
|
fmt.Fprintf(w, "Page Size: %d bytes\n", m.pageSize)
|
||||||
|
fmt.Fprintf(w, "Flags: %08x\n", m.flags)
|
||||||
|
fmt.Fprintf(w, "Root: <pgid=%d>\n", m.root.root)
|
||||||
|
fmt.Fprintf(w, "Freelist: <pgid=%d>\n", m.freelist)
|
||||||
|
fmt.Fprintf(w, "HWM: <pgid=%d>\n", m.pgid)
|
||||||
|
fmt.Fprintf(w, "Txn ID: %d\n", m.txid)
|
||||||
|
fmt.Fprintf(w, "Checksum: %016x\n", m.checksum)
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintLeaf prints the data for a leaf page.
|
||||||
|
func (cmd *PageCommand) PrintLeaf(w io.Writer, buf []byte) error {
|
||||||
|
p := (*page)(unsafe.Pointer(&buf[0]))
|
||||||
|
|
||||||
|
// Print number of items.
|
||||||
|
fmt.Fprintf(w, "Item Count: %d\n", p.count)
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
|
||||||
|
// Print each key/value.
|
||||||
|
for i := uint16(0); i < p.count; i++ {
|
||||||
|
e := p.leafPageElement(i)
|
||||||
|
|
||||||
|
// Format key as string.
|
||||||
|
var k string
|
||||||
|
if isPrintable(string(e.key())) {
|
||||||
|
k = fmt.Sprintf("%q", string(e.key()))
|
||||||
|
} else {
|
||||||
|
k = fmt.Sprintf("%x", string(e.key()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format value as string.
|
||||||
|
var v string
|
||||||
|
if (e.flags & uint32(bucketLeafFlag)) != 0 {
|
||||||
|
b := (*bucket)(unsafe.Pointer(&e.value()[0]))
|
||||||
|
v = fmt.Sprintf("<pgid=%d,seq=%d>", b.root, b.sequence)
|
||||||
|
} else if isPrintable(string(e.value())) {
|
||||||
|
k = fmt.Sprintf("%q", string(e.value()))
|
||||||
|
} else {
|
||||||
|
k = fmt.Sprintf("%x", string(e.value()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "%s: %s\n", k, v)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintBranch prints the data for a leaf page.
|
||||||
|
func (cmd *PageCommand) PrintBranch(w io.Writer, buf []byte) error {
|
||||||
|
p := (*page)(unsafe.Pointer(&buf[0]))
|
||||||
|
|
||||||
|
// Print number of items.
|
||||||
|
fmt.Fprintf(w, "Item Count: %d\n", p.count)
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
|
||||||
|
// Print each key/value.
|
||||||
|
for i := uint16(0); i < p.count; i++ {
|
||||||
|
e := p.branchPageElement(i)
|
||||||
|
|
||||||
|
// Format key as string.
|
||||||
|
var k string
|
||||||
|
if isPrintable(string(e.key())) {
|
||||||
|
k = fmt.Sprintf("%q", string(e.key()))
|
||||||
|
} else {
|
||||||
|
k = fmt.Sprintf("%x", string(e.key()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "%s: <pgid=%d>\n", k, e.pgid)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintFreelist prints the data for a freelist page.
|
||||||
|
func (cmd *PageCommand) PrintFreelist(w io.Writer, buf []byte) error {
|
||||||
|
p := (*page)(unsafe.Pointer(&buf[0]))
|
||||||
|
|
||||||
|
// Print number of items.
|
||||||
|
fmt.Fprintf(w, "Item Count: %d\n", p.count)
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
|
||||||
|
// Print each page in the freelist.
|
||||||
|
ids := (*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr))
|
||||||
|
for i := uint16(0); i < p.count; i++ {
|
||||||
|
fmt.Fprintf(w, "%d\n", ids[i])
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintPage prints a given page as hexidecimal.
|
||||||
|
func (cmd *PageCommand) PrintPage(w io.Writer, r io.ReaderAt, pageID int, pageSize int) error {
|
||||||
|
const bytesPerLineN = 16
|
||||||
|
|
||||||
|
// Read page into buffer.
|
||||||
|
buf := make([]byte, pageSize)
|
||||||
|
addr := pageID * pageSize
|
||||||
|
if n, err := r.ReadAt(buf, int64(addr)); err != nil {
|
||||||
|
return err
|
||||||
|
} else if n != pageSize {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out to writer in 16-byte lines.
|
||||||
|
var prev []byte
|
||||||
|
var skipped bool
|
||||||
|
for offset := 0; offset < pageSize; offset += bytesPerLineN {
|
||||||
|
// Retrieve current 16-byte line.
|
||||||
|
line := buf[offset : offset+bytesPerLineN]
|
||||||
|
isLastLine := (offset == (pageSize - bytesPerLineN))
|
||||||
|
|
||||||
|
// If it's the same as the previous line then print a skip.
|
||||||
|
if bytes.Equal(line, prev) && !isLastLine {
|
||||||
|
if !skipped {
|
||||||
|
fmt.Fprintf(w, "%07x *\n", addr+offset)
|
||||||
|
skipped = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Print line as hexadecimal in 2-byte groups.
|
||||||
|
fmt.Fprintf(w, "%07x %04x %04x %04x %04x %04x %04x %04x %04x\n", addr+offset,
|
||||||
|
line[0:2], line[2:4], line[4:6], line[6:8],
|
||||||
|
line[8:10], line[10:12], line[12:14], line[14:16],
|
||||||
|
)
|
||||||
|
|
||||||
|
skipped = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the previous line.
|
||||||
|
prev = line
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, "\n")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage returns the help message.
|
||||||
|
func (cmd *PageCommand) Usage() string {
|
||||||
|
return strings.TrimLeft(`
|
||||||
|
usage: bolt page -page PATH pageid [pageid...]
|
||||||
|
|
||||||
|
Page prints one or more pages in human readable format.
|
||||||
|
`, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
// PagesCommand represents the "pages" command execution.
|
// PagesCommand represents the "pages" command execution.
|
||||||
type PagesCommand struct {
|
type PagesCommand struct {
|
||||||
Stdin io.Reader
|
Stdin io.Reader
|
||||||
|
@ -1069,3 +1335,196 @@ type PageError struct {
|
||||||
func (e *PageError) Error() string {
|
func (e *PageError) Error() string {
|
||||||
return fmt.Sprintf("page error: id=%d, err=%s", e.ID, e.Err)
|
return fmt.Sprintf("page error: id=%d, err=%s", e.ID, e.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isPrintable returns true if the string is valid unicode and contains only printable runes.
|
||||||
|
func isPrintable(s string) bool {
|
||||||
|
if !utf8.ValidString(s) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, ch := range s {
|
||||||
|
if !unicode.IsPrint(ch) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadPage reads page info & full page data from a path.
|
||||||
|
// This is not transactionally safe.
|
||||||
|
func ReadPage(path string, pageID int) (*page, []byte, error) {
|
||||||
|
// Find page size.
|
||||||
|
pageSize, err := ReadPageSize(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("read page size: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open database file.
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// Read one block into buffer.
|
||||||
|
buf := make([]byte, pageSize)
|
||||||
|
if n, err := f.ReadAt(buf, int64(pageID*pageSize)); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
} else if n != len(buf) {
|
||||||
|
return nil, nil, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine total number of blocks.
|
||||||
|
p := (*page)(unsafe.Pointer(&buf[0]))
|
||||||
|
overflowN := p.overflow
|
||||||
|
|
||||||
|
// Re-read entire page (with overflow) into buffer.
|
||||||
|
buf = make([]byte, (int(overflowN)+1)*pageSize)
|
||||||
|
if n, err := f.ReadAt(buf, int64(pageID*pageSize)); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
} else if n != len(buf) {
|
||||||
|
return nil, nil, io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
p = (*page)(unsafe.Pointer(&buf[0]))
|
||||||
|
|
||||||
|
return p, buf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadPageSize reads page size a path.
|
||||||
|
// This is not transactionally safe.
|
||||||
|
func ReadPageSize(path string) (int, error) {
|
||||||
|
// Open database file.
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// Read 4KB chunk.
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
if _, err := io.ReadFull(f, buf); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read page size from metadata.
|
||||||
|
m := (*meta)(unsafe.Pointer(&buf[PageHeaderSize]))
|
||||||
|
return int(m.pageSize), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// atois parses a slice of strings into integers.
|
||||||
|
func atois(strs []string) ([]int, error) {
|
||||||
|
var a []int
|
||||||
|
for _, str := range strs {
|
||||||
|
i, err := strconv.Atoi(str)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
a = append(a, i)
|
||||||
|
}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
const maxAllocSize = 0xFFFFFFF
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
const (
|
||||||
|
branchPageFlag = 0x01
|
||||||
|
leafPageFlag = 0x02
|
||||||
|
metaPageFlag = 0x04
|
||||||
|
freelistPageFlag = 0x10
|
||||||
|
)
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
const bucketLeafFlag = 0x01
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
type pgid uint64
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
type txid uint64
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
type meta struct {
|
||||||
|
magic uint32
|
||||||
|
version uint32
|
||||||
|
pageSize uint32
|
||||||
|
flags uint32
|
||||||
|
root bucket
|
||||||
|
freelist pgid
|
||||||
|
pgid pgid
|
||||||
|
txid txid
|
||||||
|
checksum uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
type bucket struct {
|
||||||
|
root pgid
|
||||||
|
sequence uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
type page struct {
|
||||||
|
id pgid
|
||||||
|
flags uint16
|
||||||
|
count uint16
|
||||||
|
overflow uint32
|
||||||
|
ptr uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
func (p *page) Type() string {
|
||||||
|
if (p.flags & branchPageFlag) != 0 {
|
||||||
|
return "branch"
|
||||||
|
} else if (p.flags & leafPageFlag) != 0 {
|
||||||
|
return "leaf"
|
||||||
|
} else if (p.flags & metaPageFlag) != 0 {
|
||||||
|
return "meta"
|
||||||
|
} else if (p.flags & freelistPageFlag) != 0 {
|
||||||
|
return "freelist"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("unknown<%02x>", p.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
func (p *page) leafPageElement(index uint16) *leafPageElement {
|
||||||
|
n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
func (p *page) branchPageElement(index uint16) *branchPageElement {
|
||||||
|
return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
type branchPageElement struct {
|
||||||
|
pos uint32
|
||||||
|
ksize uint32
|
||||||
|
pgid pgid
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
func (n *branchPageElement) key() []byte {
|
||||||
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
||||||
|
return buf[n.pos : n.pos+n.ksize]
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
type leafPageElement struct {
|
||||||
|
flags uint32
|
||||||
|
pos uint32
|
||||||
|
ksize uint32
|
||||||
|
vsize uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
func (n *leafPageElement) key() []byte {
|
||||||
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
||||||
|
return buf[n.pos : n.pos+n.ksize]
|
||||||
|
}
|
||||||
|
|
||||||
|
// DO NOT EDIT. Copied from the "bolt" package.
|
||||||
|
func (n *leafPageElement) value() []byte {
|
||||||
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
||||||
|
return buf[n.pos+n.ksize : n.pos+n.ksize+n.vsize]
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue