mirror of https://github.com/hak5/bolt.git
Consolidate code for clarity.
This commit consolidates some of the smaller files into some of the larger files. The smaller files cluttered the file tree and made it harder to see the logical groupings of structs.master
parent
383ddb246a
commit
c3903d38a1
30
bolt.go
30
bolt.go
|
@ -1,29 +1,9 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
package bolt
|
package bolt
|
||||||
|
|
||||||
import (
|
import "os"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrorList represents a slice of errors.
|
func fdatasync(f *os.File) error {
|
||||||
type ErrorList []error
|
return f.Sync()
|
||||||
|
|
||||||
// Error returns a readable count of the errors in the list.
|
|
||||||
func (l ErrorList) Error() string {
|
|
||||||
return fmt.Sprintf("%d errors occurred", len(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
// _assert will panic with a given formatted message if the given condition is false.
|
|
||||||
func _assert(condition bool, msg string, v ...interface{}) {
|
|
||||||
if !condition {
|
|
||||||
panic(fmt.Sprintf("assertion failed: "+msg, v...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func warn(v ...interface{}) {
|
|
||||||
fmt.Fprintln(os.Stderr, v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func warnf(msg string, v ...interface{}) {
|
|
||||||
fmt.Fprintf(os.Stderr, msg+"\n", v...)
|
|
||||||
}
|
}
|
||||||
|
|
15
bucket.go
15
bucket.go
|
@ -7,6 +7,14 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MaxKeySize is the maximum length of a key, in bytes.
|
||||||
|
MaxKeySize = 32768
|
||||||
|
|
||||||
|
// MaxValueSize is the maximum length of a value, in bytes.
|
||||||
|
MaxValueSize = 4294967295
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrBucketNotFound is returned when trying to access a bucket that has
|
// ErrBucketNotFound is returned when trying to access a bucket that has
|
||||||
// not been created yet.
|
// not been created yet.
|
||||||
|
@ -37,6 +45,13 @@ var (
|
||||||
ErrSequenceOverflow = errors.New("sequence overflow")
|
ErrSequenceOverflow = errors.New("sequence overflow")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxUint = ^uint(0)
|
||||||
|
minUint = 0
|
||||||
|
maxInt = int(^uint(0) >> 1)
|
||||||
|
minInt = -maxInt - 1
|
||||||
|
)
|
||||||
|
|
||||||
// Bucket represents a collection of key/value pairs inside the database.
|
// Bucket represents a collection of key/value pairs inside the database.
|
||||||
type Bucket struct {
|
type Bucket struct {
|
||||||
*bucket
|
*bucket
|
||||||
|
|
18
const.go
18
const.go
|
@ -1,18 +0,0 @@
|
||||||
package bolt
|
|
||||||
|
|
||||||
const version = 2
|
|
||||||
|
|
||||||
const (
|
|
||||||
maxUint = ^uint(0)
|
|
||||||
minUint = 0
|
|
||||||
maxInt = int(^uint(0) >> 1)
|
|
||||||
minInt = -maxInt - 1
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// MaxKeySize is the maximum length of a key, in bytes.
|
|
||||||
MaxKeySize = 32768
|
|
||||||
|
|
||||||
// MaxValueSize is the maximum length of a value, in bytes.
|
|
||||||
MaxValueSize = 4294967295
|
|
||||||
)
|
|
88
db.go
88
db.go
|
@ -3,6 +3,7 @@ package bolt
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -16,6 +17,12 @@ const minMmapSize = 1 << 22 // 4MB
|
||||||
// The largest step that can be taken when remapping the mmap.
|
// The largest step that can be taken when remapping the mmap.
|
||||||
const maxMmapStep = 1 << 30 // 1GB
|
const maxMmapStep = 1 << 30 // 1GB
|
||||||
|
|
||||||
|
// The data file format version.
|
||||||
|
const version = 2
|
||||||
|
|
||||||
|
// Represents a marker value to indicate that a file is a Bolt DB.
|
||||||
|
const magic uint32 = 0xED0CDAED
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrDatabaseNotOpen is returned when a DB instance is accessed before it
|
// ErrDatabaseNotOpen is returned when a DB instance is accessed before it
|
||||||
// is opened or after it is closed.
|
// is opened or after it is closed.
|
||||||
|
@ -24,6 +31,16 @@ var (
|
||||||
// ErrDatabaseOpen is returned when opening a database that is
|
// ErrDatabaseOpen is returned when opening a database that is
|
||||||
// already open.
|
// already open.
|
||||||
ErrDatabaseOpen = errors.New("database already open")
|
ErrDatabaseOpen = errors.New("database already open")
|
||||||
|
|
||||||
|
// ErrInvalid is returned when a data file is not a Bolt-formatted database.
|
||||||
|
ErrInvalid = errors.New("invalid database")
|
||||||
|
|
||||||
|
// ErrVersionMismatch is returned when the data file was created with a
|
||||||
|
// different version of Bolt.
|
||||||
|
ErrVersionMismatch = errors.New("version mismatch")
|
||||||
|
|
||||||
|
// ErrChecksum is returned when either meta page checksum does not match.
|
||||||
|
ErrChecksum = errors.New("checksum error")
|
||||||
)
|
)
|
||||||
|
|
||||||
// DB represents a collection of buckets persisted to a file on disk.
|
// DB represents a collection of buckets persisted to a file on disk.
|
||||||
|
@ -652,3 +669,74 @@ type Info struct {
|
||||||
Data []byte
|
Data []byte
|
||||||
PageSize int
|
PageSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type meta struct {
|
||||||
|
magic uint32
|
||||||
|
version uint32
|
||||||
|
pageSize uint32
|
||||||
|
flags uint32
|
||||||
|
root bucket
|
||||||
|
freelist pgid
|
||||||
|
pgid pgid
|
||||||
|
txid txid
|
||||||
|
checksum uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate checks the marker bytes and version of the meta page to ensure it matches this binary.
|
||||||
|
func (m *meta) validate() error {
|
||||||
|
if m.checksum != 0 && m.checksum != m.sum64() {
|
||||||
|
return ErrChecksum
|
||||||
|
} else if m.magic != magic {
|
||||||
|
return ErrInvalid
|
||||||
|
} else if m.version != version {
|
||||||
|
return ErrVersionMismatch
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy copies one meta object to another.
|
||||||
|
func (m *meta) copy(dest *meta) {
|
||||||
|
*dest = *m
|
||||||
|
}
|
||||||
|
|
||||||
|
// write writes the meta onto a page.
|
||||||
|
func (m *meta) write(p *page) {
|
||||||
|
// Page id is either going to be 0 or 1 which we can determine by the transaction ID.
|
||||||
|
p.id = pgid(m.txid % 2)
|
||||||
|
p.flags |= metaPageFlag
|
||||||
|
|
||||||
|
// Calculate the checksum.
|
||||||
|
m.checksum = m.sum64()
|
||||||
|
|
||||||
|
m.copy(p.meta())
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates the checksum for the meta.
|
||||||
|
func (m *meta) sum64() uint64 {
|
||||||
|
var h = fnv.New64a()
|
||||||
|
_, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:])
|
||||||
|
return h.Sum64()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorList represents a slice of errors.
|
||||||
|
type ErrorList []error
|
||||||
|
|
||||||
|
// Error returns a readable count of the errors in the list.
|
||||||
|
func (l ErrorList) Error() string {
|
||||||
|
return fmt.Sprintf("%d errors occurred", len(l))
|
||||||
|
}
|
||||||
|
|
||||||
|
// _assert will panic with a given formatted message if the given condition is false.
|
||||||
|
func _assert(condition bool, msg string, v ...interface{}) {
|
||||||
|
if !condition {
|
||||||
|
panic(fmt.Sprintf("assertion failed: "+msg, v...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func warn(v ...interface{}) {
|
||||||
|
fmt.Fprintln(os.Stderr, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func warnf(msg string, v ...interface{}) {
|
||||||
|
fmt.Fprintf(os.Stderr, msg+"\n", v...)
|
||||||
|
}
|
||||||
|
|
12
db_test.go
12
db_test.go
|
@ -353,6 +353,18 @@ func TestDBStats_Sub(t *testing.T) {
|
||||||
assert.Equal(t, 7, diff.TxStats.PageCount)
|
assert.Equal(t, 7, diff.TxStats.PageCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that meta with bad magic is invalid.
|
||||||
|
func TestMeta_validate_magic(t *testing.T) {
|
||||||
|
m := &meta{magic: 0x01234567}
|
||||||
|
assert.Equal(t, m.validate(), ErrInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that meta with a bad version is invalid.
|
||||||
|
func TestMeta_validate_version(t *testing.T) {
|
||||||
|
m := &meta{magic: magic, version: 200}
|
||||||
|
assert.Equal(t, m.validate(), ErrVersionMismatch)
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleDB_Update() {
|
func ExampleDB_Update() {
|
||||||
// Open the database.
|
// Open the database.
|
||||||
db, _ := Open(tempfile(), 0666)
|
db, _ := Open(tempfile(), 0666)
|
||||||
|
|
69
meta.go
69
meta.go
|
@ -1,69 +0,0 @@
|
||||||
package bolt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"hash/fnv"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const magic uint32 = 0xED0CDAED
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrInvalid is returned when a data file is not a Bolt-formatted database.
|
|
||||||
ErrInvalid = errors.New("invalid database")
|
|
||||||
|
|
||||||
// ErrVersionMismatch is returned when the data file was created with a
|
|
||||||
// different version of Bolt.
|
|
||||||
ErrVersionMismatch = errors.New("version mismatch")
|
|
||||||
|
|
||||||
// ErrChecksum is returned when either meta page checksum does not match.
|
|
||||||
ErrChecksum = errors.New("checksum error")
|
|
||||||
)
|
|
||||||
|
|
||||||
type meta struct {
|
|
||||||
magic uint32
|
|
||||||
version uint32
|
|
||||||
pageSize uint32
|
|
||||||
flags uint32
|
|
||||||
root bucket
|
|
||||||
freelist pgid
|
|
||||||
pgid pgid
|
|
||||||
txid txid
|
|
||||||
checksum uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate checks the marker bytes and version of the meta page to ensure it matches this binary.
|
|
||||||
func (m *meta) validate() error {
|
|
||||||
if m.checksum != 0 && m.checksum != m.sum64() {
|
|
||||||
return ErrChecksum
|
|
||||||
} else if m.magic != magic {
|
|
||||||
return ErrInvalid
|
|
||||||
} else if m.version != version {
|
|
||||||
return ErrVersionMismatch
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy copies one meta object to another.
|
|
||||||
func (m *meta) copy(dest *meta) {
|
|
||||||
*dest = *m
|
|
||||||
}
|
|
||||||
|
|
||||||
// write writes the meta onto a page.
|
|
||||||
func (m *meta) write(p *page) {
|
|
||||||
// Page id is either going to be 0 or 1 which we can determine by the transaction ID.
|
|
||||||
p.id = pgid(m.txid % 2)
|
|
||||||
p.flags |= metaPageFlag
|
|
||||||
|
|
||||||
// Calculate the checksum.
|
|
||||||
m.checksum = m.sum64()
|
|
||||||
|
|
||||||
m.copy(p.meta())
|
|
||||||
}
|
|
||||||
|
|
||||||
// generates the checksum for the meta.
|
|
||||||
func (m *meta) sum64() uint64 {
|
|
||||||
var h = fnv.New64a()
|
|
||||||
_, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:])
|
|
||||||
return h.Sum64()
|
|
||||||
}
|
|
18
meta_test.go
18
meta_test.go
|
@ -1,18 +0,0 @@
|
||||||
package bolt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ensure that meta with bad magic is invalid.
|
|
||||||
func TestMeta_validate_magic(t *testing.T) {
|
|
||||||
m := &meta{magic: 0x01234567}
|
|
||||||
assert.Equal(t, m.validate(), ErrInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that meta with a bad version is invalid.
|
|
||||||
func TestMeta_validate_version(t *testing.T) {
|
|
||||||
m := &meta{magic: magic, version: 200}
|
|
||||||
assert.Equal(t, m.validate(), ErrVersionMismatch)
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
// +build !linux
|
|
||||||
|
|
||||||
package bolt
|
|
||||||
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
func fdatasync(f *os.File) error {
|
|
||||||
return f.Sync()
|
|
||||||
}
|
|
Loading…
Reference in New Issue