mirror of https://github.com/etcd-io/bbolt.git
add PageSize to Option struct
Configure the db page size at runtime. Makes cross-arch debugging a bit easier.pull/16/head
parent
78ca4fde00
commit
012f88489b
36
db.go
36
db.go
|
@ -200,6 +200,11 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
|||
// Default values for test hooks
|
||||
db.ops.writeAt = db.file.WriteAt
|
||||
|
||||
if db.pageSize = options.PageSize; db.pageSize == 0 {
|
||||
// Set the default page size to the OS page size.
|
||||
db.pageSize = defaultPageSize
|
||||
}
|
||||
|
||||
// Initialize the database if it doesn't exist.
|
||||
if info, err := db.file.Stat(); err != nil {
|
||||
return nil, err
|
||||
|
@ -211,20 +216,21 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
|||
} else {
|
||||
// Read the first meta page to determine the page size.
|
||||
var buf [0x1000]byte
|
||||
if _, err := db.file.ReadAt(buf[:], 0); err == nil {
|
||||
m := db.pageInBuffer(buf[:], 0).meta()
|
||||
if err := m.validate(); err != nil {
|
||||
// If we can't read the page size, we can assume it's the same
|
||||
// as the OS -- since that's how the page size was chosen in the
|
||||
// first place.
|
||||
//
|
||||
// If the first page is invalid and this OS uses a different
|
||||
// page size than what the database was created with then we
|
||||
// are out of luck and cannot access the database.
|
||||
db.pageSize = defaultPageSize
|
||||
} else {
|
||||
// If we can't read the page size, but can read a page, assume
|
||||
// it's the same as the OS or one given -- since that's how the
|
||||
// page size was chosen in the first place.
|
||||
//
|
||||
// If the first page is invalid and this OS uses a different
|
||||
// page size than what the database was created with then we
|
||||
// are out of luck and cannot access the database.
|
||||
//
|
||||
// TODO: scan for next page
|
||||
if bw, err := db.file.ReadAt(buf[:], 0); err == nil && bw == len(buf) {
|
||||
if m := db.pageInBuffer(buf[:], 0).meta(); m.validate() == nil {
|
||||
db.pageSize = int(m.pageSize)
|
||||
}
|
||||
} else {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,9 +376,6 @@ func (db *DB) mmapSize(size int) (int, error) {
|
|||
|
||||
// init creates a new database file and initializes its meta pages.
|
||||
func (db *DB) init() error {
|
||||
// Set the page size to the OS page size.
|
||||
db.pageSize = defaultPageSize
|
||||
|
||||
// Create two meta pages on a buffer.
|
||||
buf := make([]byte, db.pageSize*4)
|
||||
for i := 0; i < 2; i++ {
|
||||
|
@ -999,6 +1002,9 @@ type Options struct {
|
|||
// If initialMmapSize is smaller than the previous database size,
|
||||
// it takes no effect.
|
||||
InitialMmapSize int
|
||||
|
||||
// PageSize overrides the default OS page size.
|
||||
PageSize int
|
||||
}
|
||||
|
||||
// DefaultOptions represent the options used if nil options are passed into Open().
|
||||
|
|
16
db_test.go
16
db_test.go
|
@ -423,6 +423,22 @@ func TestDB_Open_InitialMmapSize(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestOpen_BigPage checks the database uses bigger pages when
|
||||
// changing PageSize.
|
||||
func TestOpen_BigPage(t *testing.T) {
|
||||
pageSize := os.Getpagesize()
|
||||
|
||||
db1 := MustOpenWithOption(&bolt.Options{PageSize: pageSize * 2})
|
||||
defer db1.MustClose()
|
||||
|
||||
db2 := MustOpenWithOption(&bolt.Options{PageSize: pageSize * 4})
|
||||
defer db2.MustClose()
|
||||
|
||||
if db1sz, db2sz := fileSize(db1.f), fileSize(db2.f); db1sz >= db2sz {
|
||||
t.Errorf("expected %d < %d", db1sz, db2sz)
|
||||
}
|
||||
}
|
||||
|
||||
// TestOpen_RecoverFreeList tests opening the DB with free-list
|
||||
// write-out after no free list sync will recover the free list
|
||||
// and write it out.
|
||||
|
|
Loading…
Reference in New Issue