mirror of https://github.com/etcd-io/bbolt.git
Refactor meta.copy() and page.init().
parent
d38be1d25b
commit
4fc84daf2a
|
@ -39,7 +39,6 @@ func (c *Cursor) Get(key []byte) []byte {
|
|||
func (c *Cursor) Goto(key []byte) bool {
|
||||
// TODO(benbjohnson): Optimize for specific use cases.
|
||||
|
||||
// TODO: Check if len(key) > 0.
|
||||
// TODO: Start from root page and traverse to correct page.
|
||||
|
||||
return false
|
||||
|
|
23
db.go
23
db.go
|
@ -91,11 +91,11 @@ func (db *DB) Open(path string, mode os.FileMode) error {
|
|||
// Read the first meta page to determine the page size.
|
||||
var buf [minPageSize]byte
|
||||
if _, err := db.file.ReadAt(buf[:], 0); err == nil {
|
||||
if m, err := db.pageInBuffer(buf[:], 0).meta(); err != nil {
|
||||
return &Error{"meta bootstrap error", err}
|
||||
} else if m != nil {
|
||||
db.pageSize = int(m.pageSize)
|
||||
m := db.pageInBuffer(buf[:], 0).meta()
|
||||
if err := m.validate(); err != nil {
|
||||
return &Error{"meta error", err}
|
||||
}
|
||||
db.pageSize = int(m.pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,10 +126,14 @@ func (db *DB) mmap() error {
|
|||
}
|
||||
|
||||
// Save references to the meta pages.
|
||||
if db.meta0, err = db.page(0).meta(); err != nil {
|
||||
db.meta0 = db.page(0).meta()
|
||||
db.meta1 = db.page(1).meta()
|
||||
|
||||
// Validate the meta pages.
|
||||
if err := db.meta0.validate(); err != nil {
|
||||
return &Error{"meta0 error", err}
|
||||
}
|
||||
if db.meta1, err = db.page(1).meta(); err != nil {
|
||||
if err := db.meta1.validate(); err != nil {
|
||||
return &Error{"meta1 error", err}
|
||||
}
|
||||
|
||||
|
@ -146,7 +150,12 @@ func (db *DB) init() error {
|
|||
for i := 0; i < 2; i++ {
|
||||
p := db.pageInBuffer(buf[:], pgid(i))
|
||||
p.id = pgid(i)
|
||||
p.init(db.pageSize)
|
||||
p.flags = p_meta
|
||||
|
||||
m := p.meta()
|
||||
m.magic = magic
|
||||
m.version = Version
|
||||
m.pageSize = uint32(db.pageSize)
|
||||
}
|
||||
|
||||
// Write the buffer to our data file.
|
||||
|
|
16
db_test.go
16
db_test.go
|
@ -121,13 +121,18 @@ func TestDBMmapError(t *testing.T) {
|
|||
// Ensure that corrupt meta0 page errors get returned.
|
||||
func TestDBCorruptMeta0(t *testing.T) {
|
||||
withMockDB(func(db *DB, mockos *mockos, mocksyscall *mocksyscall, path string) {
|
||||
var m meta
|
||||
m.magic = magic
|
||||
m.version = Version
|
||||
m.pageSize = 0x8000
|
||||
|
||||
// Create a file with bad magic.
|
||||
b := make([]byte, 0x10000)
|
||||
p0, p1 := (*page)(unsafe.Pointer(&b[0x0000])), (*page)(unsafe.Pointer(&b[0x8000]))
|
||||
p0.init(0x8000)
|
||||
p1.init(0x8000)
|
||||
m, _ := p0.meta()
|
||||
m.magic = 0
|
||||
p0.meta().magic = 0
|
||||
p0.meta().version = Version
|
||||
p1.meta().magic = magic
|
||||
p1.meta().version = Version
|
||||
|
||||
// Mock file access.
|
||||
file, metafile := &mockfile{}, &mockfile{}
|
||||
|
@ -141,7 +146,8 @@ func TestDBCorruptMeta0(t *testing.T) {
|
|||
|
||||
// Open the database.
|
||||
err := db.Open(path, 0666)
|
||||
assert.Equal(t, err, &Error{"meta bootstrap error", InvalidMetaPageError})
|
||||
warn(err)
|
||||
assert.Equal(t, err, &Error{"meta error", InvalidError})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
11
meta.go
11
meta.go
|
@ -3,7 +3,6 @@ package bolt
|
|||
var (
|
||||
InvalidError = &Error{"Invalid database", nil}
|
||||
VersionMismatchError = &Error{"version mismatch", nil}
|
||||
InvalidMetaPageError = &Error{"invalid meta page", nil}
|
||||
)
|
||||
|
||||
const magic uint32 = 0xC0DEC0DE
|
||||
|
@ -12,10 +11,10 @@ const version uint32 = 1
|
|||
type meta struct {
|
||||
magic uint32
|
||||
version uint32
|
||||
sys bucket
|
||||
pageSize uint32
|
||||
pgid pgid
|
||||
txnid txnid
|
||||
sys bucket
|
||||
}
|
||||
|
||||
// validate checks the marker bytes and version of the meta page to ensure it matches this binary.
|
||||
|
@ -27,3 +26,11 @@ func (m *meta) validate() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// copy copies one meta object to another.
|
||||
func (m *meta) copy(dest *meta) {
|
||||
dest.pageSize = m.pageSize
|
||||
dest.pgid = m.pgid
|
||||
dest.txnid = m.txnid
|
||||
dest.sys = m.sys
|
||||
}
|
||||
|
|
30
page.go
30
page.go
|
@ -27,32 +27,16 @@ type page struct {
|
|||
}
|
||||
|
||||
// meta returns a pointer to the metadata section of the page.
|
||||
func (p *page) meta() (*meta, error) {
|
||||
// Exit if page is not a meta page.
|
||||
if (p.flags & p_meta) == 0 {
|
||||
return nil, InvalidMetaPageError
|
||||
}
|
||||
|
||||
// Cast the meta section and validate before returning.
|
||||
m := (*meta)(unsafe.Pointer(&p.ptr))
|
||||
if err := m.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// init initializes a page as a new meta page.
|
||||
func (p *page) init(pageSize int) {
|
||||
p.flags = p_meta
|
||||
m := (*meta)(unsafe.Pointer(&p.ptr))
|
||||
m.magic = magic
|
||||
m.version = version
|
||||
m.pageSize = uint32(pageSize)
|
||||
m.pgid = 1
|
||||
m.sys.root = 0
|
||||
func (p *page) meta() *meta {
|
||||
return (*meta)(unsafe.Pointer(&p.ptr))
|
||||
}
|
||||
|
||||
// lnode retrieves the leaf node by index
|
||||
func (p *page) lnode(index int) *lnode {
|
||||
return &((*[maxNodesPerPage]lnode)(unsafe.Pointer(&p.ptr)))[index]
|
||||
}
|
||||
|
||||
// bnode retrieves the branch node by index
|
||||
func (p *page) bnode(index int) *bnode {
|
||||
return &((*[maxNodesPerPage]bnode)(unsafe.Pointer(&p.ptr)))[index]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue