mirror of
https://github.com/moby/moby.git
synced 2026-07-22 15:32:50 +00:00
This patch updates all dependencies to match what is used in moby/moby. Making the dependencies match what is used in that repository makes sure we test with the same version as libnetwork is later built with in moby. This also gets rid of some temporary forks that were needed during the migration of Sirupsen/logrus to sirupsen/logrus. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
179 lines
4.4 KiB
Go
179 lines
4.4 KiB
Go
package bolt
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"unsafe"
|
|
)
|
|
|
|
const pageHeaderSize = int(unsafe.Offsetof(((*page)(nil)).ptr))
|
|
|
|
const minKeysPerPage = 2
|
|
|
|
const branchPageElementSize = int(unsafe.Sizeof(branchPageElement{}))
|
|
const leafPageElementSize = int(unsafe.Sizeof(leafPageElement{}))
|
|
|
|
const (
|
|
branchPageFlag = 0x01
|
|
leafPageFlag = 0x02
|
|
metaPageFlag = 0x04
|
|
freelistPageFlag = 0x10
|
|
)
|
|
|
|
const (
|
|
bucketLeafFlag = 0x01
|
|
)
|
|
|
|
type pgid uint64
|
|
|
|
type page struct {
|
|
id pgid
|
|
flags uint16
|
|
count uint16
|
|
overflow uint32
|
|
ptr uintptr
|
|
}
|
|
|
|
// typ returns a human readable page type string used for debugging.
|
|
func (p *page) typ() 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)
|
|
}
|
|
|
|
// meta returns a pointer to the metadata section of the page.
|
|
func (p *page) meta() *meta {
|
|
return (*meta)(unsafe.Pointer(&p.ptr))
|
|
}
|
|
|
|
// leafPageElement retrieves the leaf node by index
|
|
func (p *page) leafPageElement(index uint16) *leafPageElement {
|
|
n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
|
|
return n
|
|
}
|
|
|
|
// leafPageElements retrieves a list of leaf nodes.
|
|
func (p *page) leafPageElements() []leafPageElement {
|
|
if p.count == 0 {
|
|
return nil
|
|
}
|
|
return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:]
|
|
}
|
|
|
|
// branchPageElement retrieves the branch node by index
|
|
func (p *page) branchPageElement(index uint16) *branchPageElement {
|
|
return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index]
|
|
}
|
|
|
|
// branchPageElements retrieves a list of branch nodes.
|
|
func (p *page) branchPageElements() []branchPageElement {
|
|
if p.count == 0 {
|
|
return nil
|
|
}
|
|
return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:]
|
|
}
|
|
|
|
// dump writes n bytes of the page to STDERR as hex output.
|
|
func (p *page) hexdump(n int) {
|
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:n]
|
|
fmt.Fprintf(os.Stderr, "%x\n", buf)
|
|
}
|
|
|
|
type pages []*page
|
|
|
|
func (s pages) Len() int { return len(s) }
|
|
func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
func (s pages) Less(i, j int) bool { return s[i].id < s[j].id }
|
|
|
|
// branchPageElement represents a node on a branch page.
|
|
type branchPageElement struct {
|
|
pos uint32
|
|
ksize uint32
|
|
pgid pgid
|
|
}
|
|
|
|
// key returns a byte slice of the node key.
|
|
func (n *branchPageElement) key() []byte {
|
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
|
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize]
|
|
}
|
|
|
|
// leafPageElement represents a node on a leaf page.
|
|
type leafPageElement struct {
|
|
flags uint32
|
|
pos uint32
|
|
ksize uint32
|
|
vsize uint32
|
|
}
|
|
|
|
// key returns a byte slice of the node key.
|
|
func (n *leafPageElement) key() []byte {
|
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
|
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize:n.ksize]
|
|
}
|
|
|
|
// value returns a byte slice of the node value.
|
|
func (n *leafPageElement) value() []byte {
|
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
|
|
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize:n.vsize]
|
|
}
|
|
|
|
// PageInfo represents human readable information about a page.
|
|
type PageInfo struct {
|
|
ID int
|
|
Type string
|
|
Count int
|
|
OverflowCount int
|
|
}
|
|
|
|
type pgids []pgid
|
|
|
|
func (s pgids) Len() int { return len(s) }
|
|
func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
func (s pgids) Less(i, j int) bool { return s[i] < s[j] }
|
|
|
|
// merge returns the sorted union of a and b.
|
|
func (a pgids) merge(b pgids) pgids {
|
|
// Return the opposite slice if one is nil.
|
|
if len(a) == 0 {
|
|
return b
|
|
} else if len(b) == 0 {
|
|
return a
|
|
}
|
|
|
|
// Create a list to hold all elements from both lists.
|
|
merged := make(pgids, 0, len(a)+len(b))
|
|
|
|
// Assign lead to the slice with a lower starting value, follow to the higher value.
|
|
lead, follow := a, b
|
|
if b[0] < a[0] {
|
|
lead, follow = b, a
|
|
}
|
|
|
|
// Continue while there are elements in the lead.
|
|
for len(lead) > 0 {
|
|
// Merge largest prefix of lead that is ahead of follow[0].
|
|
n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] })
|
|
merged = append(merged, lead[:n]...)
|
|
if n >= len(lead) {
|
|
break
|
|
}
|
|
|
|
// Swap lead and follow.
|
|
lead, follow = follow, lead[n:]
|
|
}
|
|
|
|
// Append what's left in follow.
|
|
merged = append(merged, follow...)
|
|
|
|
return merged
|
|
}
|