mirror of https://github.com/etcd-io/bbolt.git
commit
a6c45c18c3
|
@ -1214,7 +1214,7 @@ func TestBucket_Stats(t *testing.T) {
|
|||
}
|
||||
|
||||
// Only check allocations for 4KB pages.
|
||||
if os.Getpagesize() == 4096 {
|
||||
if db.Info().PageSize == 4096 {
|
||||
if stats.BranchAlloc != 4096 {
|
||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||
} else if stats.LeafAlloc != 36864 {
|
||||
|
@ -1347,7 +1347,7 @@ func TestBucket_Stats_Small(t *testing.T) {
|
|||
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
||||
}
|
||||
|
||||
if os.Getpagesize() == 4096 {
|
||||
if db.Info().PageSize == 4096 {
|
||||
if stats.BranchAlloc != 0 {
|
||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||
} else if stats.LeafAlloc != 0 {
|
||||
|
@ -1406,7 +1406,7 @@ func TestBucket_Stats_EmptyBucket(t *testing.T) {
|
|||
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
||||
}
|
||||
|
||||
if os.Getpagesize() == 4096 {
|
||||
if db.Info().PageSize == 4096 {
|
||||
if stats.BranchAlloc != 0 {
|
||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||
} else if stats.LeafAlloc != 0 {
|
||||
|
@ -1508,7 +1508,7 @@ func TestBucket_Stats_Nested(t *testing.T) {
|
|||
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
||||
}
|
||||
|
||||
if os.Getpagesize() == 4096 {
|
||||
if db.Info().PageSize == 4096 {
|
||||
if stats.BranchAlloc != 0 {
|
||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||
} else if stats.LeafAlloc != 8192 {
|
||||
|
@ -1581,7 +1581,7 @@ func TestBucket_Stats_Large(t *testing.T) {
|
|||
t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
|
||||
}
|
||||
|
||||
if os.Getpagesize() == 4096 {
|
||||
if db.Info().PageSize == 4096 {
|
||||
if stats.BranchAlloc != 53248 {
|
||||
t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
|
||||
} else if stats.LeafAlloc != 4898816 {
|
||||
|
|
36
db.go
36
db.go
|
@ -199,6 +199,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
|
||||
|
@ -210,20 +215,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 = os.Getpagesize()
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,9 +379,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 = os.Getpagesize()
|
||||
|
||||
// Create two meta pages on a buffer.
|
||||
buf := make([]byte, db.pageSize*4)
|
||||
for i := 0; i < 2; i++ {
|
||||
|
@ -1002,6 +1005,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().
|
||||
|
|
19
db_test.go
19
db_test.go
|
@ -339,12 +339,13 @@ func TestOpen_FileTooSmall(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pageSize := int64(db.Info().PageSize)
|
||||
if err := db.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// corrupt the database
|
||||
if err := os.Truncate(path, int64(os.Getpagesize())); err != nil {
|
||||
if err := os.Truncate(path, pageSize); err != nil {
|
||||
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
|
||||
// write-out after no free list sync will recover the free list
|
||||
// and write it out.
|
||||
|
|
Loading…
Reference in New Issue