mirror of
https://github.com/etcd-io/bbolt.git
synced 2025-04-28 13:59:43 +00:00
Merge pull request #16 from heyitsanthony/config-page-size
Options.PageSize
This commit is contained in:
commit
a6c45c18c3
@ -1214,7 +1214,7 @@ func TestBucket_Stats(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only check allocations for 4KB pages.
|
// Only check allocations for 4KB pages.
|
||||||
if os.Getpagesize() == 4096 {
|
if db.Info().PageSize == 4096 {
|
||||||
if stats.BranchAlloc != 4096 {
|
if stats.BranchAlloc != 4096 {
|
||||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||||
} else if stats.LeafAlloc != 36864 {
|
} else if stats.LeafAlloc != 36864 {
|
||||||
@ -1347,7 +1347,7 @@ func TestBucket_Stats_Small(t *testing.T) {
|
|||||||
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getpagesize() == 4096 {
|
if db.Info().PageSize == 4096 {
|
||||||
if stats.BranchAlloc != 0 {
|
if stats.BranchAlloc != 0 {
|
||||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||||
} else if stats.LeafAlloc != 0 {
|
} else if stats.LeafAlloc != 0 {
|
||||||
@ -1406,7 +1406,7 @@ func TestBucket_Stats_EmptyBucket(t *testing.T) {
|
|||||||
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getpagesize() == 4096 {
|
if db.Info().PageSize == 4096 {
|
||||||
if stats.BranchAlloc != 0 {
|
if stats.BranchAlloc != 0 {
|
||||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||||
} else if stats.LeafAlloc != 0 {
|
} else if stats.LeafAlloc != 0 {
|
||||||
@ -1508,7 +1508,7 @@ func TestBucket_Stats_Nested(t *testing.T) {
|
|||||||
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getpagesize() == 4096 {
|
if db.Info().PageSize == 4096 {
|
||||||
if stats.BranchAlloc != 0 {
|
if stats.BranchAlloc != 0 {
|
||||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||||
} else if stats.LeafAlloc != 8192 {
|
} else if stats.LeafAlloc != 8192 {
|
||||||
@ -1581,7 +1581,7 @@ func TestBucket_Stats_Large(t *testing.T) {
|
|||||||
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getpagesize() == 4096 {
|
if db.Info().PageSize == 4096 {
|
||||||
if stats.BranchAlloc != 53248 {
|
if stats.BranchAlloc != 53248 {
|
||||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||||
} else if stats.LeafAlloc != 4898816 {
|
} else if stats.LeafAlloc != 4898816 {
|
||||||
|
28
db.go
28
db.go
@ -199,6 +199,11 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
|||||||
// Default values for test hooks
|
// Default values for test hooks
|
||||||
db.ops.writeAt = db.file.WriteAt
|
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.
|
// Initialize the database if it doesn't exist.
|
||||||
if info, err := db.file.Stat(); err != nil {
|
if info, err := db.file.Stat(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -210,20 +215,21 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
|||||||
} else {
|
} else {
|
||||||
// Read the first meta page to determine the page size.
|
// Read the first meta page to determine the page size.
|
||||||
var buf [0x1000]byte
|
var buf [0x1000]byte
|
||||||
if _, err := db.file.ReadAt(buf[:], 0); err == nil {
|
// If we can't read the page size, but can read a page, assume
|
||||||
m := db.pageInBuffer(buf[:], 0).meta()
|
// it's the same as the OS or one given -- since that's how the
|
||||||
if err := m.validate(); err != nil {
|
// page size was chosen in the first place.
|
||||||
// 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
|
// If the first page is invalid and this OS uses a different
|
||||||
// page size than what the database was created with then we
|
// page size than what the database was created with then we
|
||||||
// are out of luck and cannot access the database.
|
// are out of luck and cannot access the database.
|
||||||
db.pageSize = os.Getpagesize()
|
//
|
||||||
} else {
|
// 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)
|
db.pageSize = int(m.pageSize)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return nil, ErrInvalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,9 +379,6 @@ func (db *DB) mmapSize(size int) (int, error) {
|
|||||||
|
|
||||||
// init creates a new database file and initializes its meta pages.
|
// init creates a new database file and initializes its meta pages.
|
||||||
func (db *DB) init() error {
|
func (db *DB) init() error {
|
||||||
// Set the page size to the OS page size.
|
|
||||||
db.pageSize = os.Getpagesize()
|
|
||||||
|
|
||||||
// Create two meta pages on a buffer.
|
// Create two meta pages on a buffer.
|
||||||
buf := make([]byte, db.pageSize*4)
|
buf := make([]byte, db.pageSize*4)
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
@ -1002,6 +1005,9 @@ type Options struct {
|
|||||||
// If initialMmapSize is smaller than the previous database size,
|
// If initialMmapSize is smaller than the previous database size,
|
||||||
// it takes no effect.
|
// it takes no effect.
|
||||||
InitialMmapSize int
|
InitialMmapSize int
|
||||||
|
|
||||||
|
// PageSize overrides the default OS page size.
|
||||||
|
PageSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultOptions represent the options used if nil options are passed into Open().
|
// DefaultOptions represent the options used if nil options are passed into Open().
|
||||||
|
19
db_test.go
19
db_test.go
@ -339,12 +339,13 @@ func TestOpen_FileTooSmall(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
pageSize := int64(db.Info().PageSize)
|
||||||
if err := db.Close(); err != nil {
|
if err := db.Close(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// corrupt the database
|
// corrupt the database
|
||||||
if err := os.Truncate(path, int64(os.Getpagesize())); err != nil {
|
if err := os.Truncate(path, pageSize); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,6 +415,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
|
// TestOpen_RecoverFreeList tests opening the DB with free-list
|
||||||
// write-out after no free list sync will recover the free list
|
// write-out after no free list sync will recover the free list
|
||||||
// and write it out.
|
// and write it out.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user