mirror of https://github.com/etcd-io/bbolt.git
parent
ba5a58dde0
commit
bdfe4158f8
43
db.go
43
db.go
|
@ -116,9 +116,11 @@ type DB struct {
|
||||||
opened bool
|
opened bool
|
||||||
rwtx *Tx
|
rwtx *Tx
|
||||||
txs []*Tx
|
txs []*Tx
|
||||||
freelist *freelist
|
|
||||||
stats Stats
|
stats Stats
|
||||||
|
|
||||||
|
freelist *freelist
|
||||||
|
freelistLoad sync.Once
|
||||||
|
|
||||||
pagePool sync.Pool
|
pagePool sync.Pool
|
||||||
|
|
||||||
batchMu sync.Mutex
|
batchMu sync.Mutex
|
||||||
|
@ -157,8 +159,9 @@ func (db *DB) String() string {
|
||||||
// If the file does not exist then it will be created automatically.
|
// If the file does not exist then it will be created automatically.
|
||||||
// Passing in nil options will cause Bolt to open the database with the default options.
|
// Passing in nil options will cause Bolt to open the database with the default options.
|
||||||
func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
||||||
var db = &DB{opened: true}
|
db := &DB{
|
||||||
|
opened: true,
|
||||||
|
}
|
||||||
// Set default options if no options are provided.
|
// Set default options if no options are provided.
|
||||||
if options == nil {
|
if options == nil {
|
||||||
options = DefaultOptions
|
options = DefaultOptions
|
||||||
|
@ -254,20 +257,11 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
db.freelist = newFreelist()
|
db.loadFreelist()
|
||||||
noFreeList := db.meta().freelist == pgidNoFreelist
|
|
||||||
if noFreeList {
|
|
||||||
// Reconstruct free list by scanning the DB.
|
|
||||||
db.freelist.readIDs(db.freepages())
|
|
||||||
} else {
|
|
||||||
// Read free list from freelist page.
|
|
||||||
db.freelist.read(db.page(db.meta().freelist))
|
|
||||||
}
|
|
||||||
db.stats.FreePageN = len(db.freelist.ids)
|
|
||||||
|
|
||||||
// Flush freelist when transitioning from no sync to sync so
|
// Flush freelist when transitioning from no sync to sync so
|
||||||
// NoFreelistSync unaware boltdb can open the db later.
|
// NoFreelistSync unaware boltdb can open the db later.
|
||||||
if !db.NoFreelistSync && noFreeList {
|
if !db.NoFreelistSync && !db.hasSyncedFreelist() {
|
||||||
tx, err := db.Begin(true)
|
tx, err := db.Begin(true)
|
||||||
if tx != nil {
|
if tx != nil {
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
|
@ -282,6 +276,27 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loadFreelist reads the freelist if it is synced, or reconstructs it
|
||||||
|
// by scanning the DB if it is not synced. It assumes there are no
|
||||||
|
// concurrent accesses being made to the freelist.
|
||||||
|
func (db *DB) loadFreelist() {
|
||||||
|
db.freelistLoad.Do(func() {
|
||||||
|
db.freelist = newFreelist()
|
||||||
|
if !db.hasSyncedFreelist() {
|
||||||
|
// Reconstruct free list by scanning the DB.
|
||||||
|
db.freelist.readIDs(db.freepages())
|
||||||
|
} else {
|
||||||
|
// Read free list from freelist page.
|
||||||
|
db.freelist.read(db.page(db.meta().freelist))
|
||||||
|
}
|
||||||
|
db.stats.FreePageN = len(db.freelist.ids)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) hasSyncedFreelist() bool {
|
||||||
|
return db.meta().freelist != pgidNoFreelist
|
||||||
|
}
|
||||||
|
|
||||||
// mmap opens the underlying memory-mapped file and initializes the meta references.
|
// mmap opens the underlying memory-mapped file and initializes the meta references.
|
||||||
// minsz is the minimum size that the new mmap can be.
|
// minsz is the minimum size that the new mmap can be.
|
||||||
func (db *DB) mmap(minsz int) error {
|
func (db *DB) mmap(minsz int) error {
|
||||||
|
|
3
tx.go
3
tx.go
|
@ -395,6 +395,9 @@ func (tx *Tx) Check() <-chan error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Tx) check(ch chan error) {
|
func (tx *Tx) check(ch chan error) {
|
||||||
|
// Force loading free list if opened in ReadOnly mode.
|
||||||
|
tx.db.loadFreelist()
|
||||||
|
|
||||||
// Check if any pages are double freed.
|
// Check if any pages are double freed.
|
||||||
freed := make(map[pgid]bool)
|
freed := make(map[pgid]bool)
|
||||||
all := make([]pgid, tx.db.freelist.count())
|
all := make([]pgid, tx.db.freelist.count())
|
||||||
|
|
Loading…
Reference in New Issue