mirror of https://github.com/etcd-io/bbolt.git
add PreLoadFreelist to support loading free pages in readonly mode
Signed-off-by: Benjamin Wang <wachao@vmware.com>pull/381/head
parent
51c763c4e9
commit
6bc57389f0
|
@ -195,7 +195,10 @@ func (cmd *CheckCommand) Run(args ...string) error {
|
|||
}
|
||||
|
||||
// Open database.
|
||||
db, err := bolt.Open(path, 0666, &bolt.Options{ReadOnly: true})
|
||||
db, err := bolt.Open(path, 0666, &bolt.Options{
|
||||
ReadOnly: true,
|
||||
PreLoadFreelist: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -644,7 +647,10 @@ func (cmd *PagesCommand) Run(args ...string) error {
|
|||
}
|
||||
|
||||
// Open database.
|
||||
db, err := bolt.Open(path, 0666, &bolt.Options{ReadOnly: true})
|
||||
db, err := bolt.Open(path, 0666, &bolt.Options{
|
||||
ReadOnly: true,
|
||||
PreLoadFreelist: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -255,6 +255,37 @@ func TestGetCommand_Run(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure the "pages" command neither panic, nor change the db file.
|
||||
func TestPagesCommand_Run(t *testing.T) {
|
||||
db := btesting.MustCreateDB(t)
|
||||
|
||||
err := db.Update(func(tx *bolt.Tx) error {
|
||||
for _, name := range []string{"foo", "bar"} {
|
||||
b, err := tx.CreateBucket([]byte(name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < 3; i++ {
|
||||
key := fmt.Sprintf("%s-%d", name, i)
|
||||
val := fmt.Sprintf("val-%s-%d", name, i)
|
||||
if err := b.Put([]byte(key), []byte(val)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
db.Close()
|
||||
|
||||
defer requireDBNoChange(t, dbData(t, db.Path()), db.Path())
|
||||
|
||||
// Run the command.
|
||||
m := NewMain()
|
||||
err = m.Run("pages", db.Path())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Main represents a test wrapper for main.Main that records output.
|
||||
type Main struct {
|
||||
*main.Main
|
||||
|
|
20
db.go
20
db.go
|
@ -95,6 +95,11 @@ type DB struct {
|
|||
// https://github.com/boltdb/bolt/issues/284
|
||||
NoGrowSync bool
|
||||
|
||||
// When `true`, bbolt will always load the free pages when opening the DB.
|
||||
// When opening db in write mode, this flag will always automatically
|
||||
// set to `true`.
|
||||
PreLoadFreelist bool
|
||||
|
||||
// If you want to read the entire database fast, you can set MmapFlag to
|
||||
// syscall.MAP_POPULATE on Linux 2.6.23+ for sequential read-ahead.
|
||||
MmapFlags int
|
||||
|
@ -196,6 +201,7 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
|||
db.NoGrowSync = options.NoGrowSync
|
||||
db.MmapFlags = options.MmapFlags
|
||||
db.NoFreelistSync = options.NoFreelistSync
|
||||
db.PreLoadFreelist = options.PreLoadFreelist
|
||||
db.FreelistType = options.FreelistType
|
||||
db.Mlock = options.Mlock
|
||||
|
||||
|
@ -208,6 +214,9 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
|||
if options.ReadOnly {
|
||||
flag = os.O_RDONLY
|
||||
db.readOnly = true
|
||||
} else {
|
||||
// always load free pages in write mode
|
||||
db.PreLoadFreelist = true
|
||||
}
|
||||
|
||||
db.openFile = options.OpenFile
|
||||
|
@ -277,12 +286,14 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if db.PreLoadFreelist {
|
||||
db.loadFreelist()
|
||||
}
|
||||
|
||||
if db.readOnly {
|
||||
return db, nil
|
||||
}
|
||||
|
||||
db.loadFreelist()
|
||||
|
||||
// Flush freelist when transitioning from no sync to sync so
|
||||
// NoFreelistSync unaware boltdb can open the db later.
|
||||
if !db.NoFreelistSync && !db.hasSyncedFreelist() {
|
||||
|
@ -1163,6 +1174,11 @@ type Options struct {
|
|||
// under normal operation, but requires a full database re-sync during recovery.
|
||||
NoFreelistSync bool
|
||||
|
||||
// PreLoadFreelist sets whether to load the free pages when opening
|
||||
// the db file. Note when opening db in write mode, bbolt will always
|
||||
// load the free pages.
|
||||
PreLoadFreelist bool
|
||||
|
||||
// FreelistType sets the backend freelist type. There are two options. Array which is simple but endures
|
||||
// dramatic performance degradation if database is large and framentation in freelist is common.
|
||||
// The alternative one is using hashmap, it is faster in almost all circumstances
|
||||
|
|
Loading…
Reference in New Issue