Skip to content

Commit

Permalink
Merge pull request #783 from ahrtr/refactor_freelist_20240701
Browse files Browse the repository at this point in the history
Move method freePages into freelist.go
  • Loading branch information
ahrtr authored Jul 2, 2024
2 parents cc78a5a + 263e75d commit d537eff
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 28 deletions.
35 changes: 7 additions & 28 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"io"
"os"
"runtime"
"sort"
"sync"
"time"
"unsafe"
Expand Down Expand Up @@ -797,6 +796,9 @@ func (db *DB) beginTx() (*Tx, error) {
// Keep track of transaction until it closes.
db.txs = append(db.txs, t)
n := len(db.txs)
if db.freelist != nil {
db.freelist.addReadonlyTXID(t.meta.Txid())
}

// Unlock the meta pages.
db.metalock.Unlock()
Expand Down Expand Up @@ -841,36 +843,10 @@ func (db *DB) beginRWTx() (*Tx, error) {
t := &Tx{writable: true}
t.init(db)
db.rwtx = t
db.freePages()
db.freelist.freePages()
return t, nil
}

// freePages releases any pages associated with closed read-only transactions.
func (db *DB) freePages() {
// Free all pending pages prior to earliest open transaction.
sort.Sort(txsById(db.txs))
minid := common.Txid(0xFFFFFFFFFFFFFFFF)
if len(db.txs) > 0 {
minid = db.txs[0].meta.Txid()
}
if minid > 0 {
db.freelist.release(minid - 1)
}
// Release unused txid extents.
for _, t := range db.txs {
db.freelist.releaseRange(minid, t.meta.Txid()-1)
minid = t.meta.Txid() + 1
}
db.freelist.releaseRange(minid, common.Txid(0xFFFFFFFFFFFFFFFF))
// Any page both allocated and freed in an extent is safe to release.
}

type txsById []*Tx

func (t txsById) Len() int { return len(t) }
func (t txsById) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
func (t txsById) Less(i, j int) bool { return t[i].meta.Txid() < t[j].meta.Txid() }

// removeTx removes a transaction from the database.
func (db *DB) removeTx(tx *Tx) {
// Release the read lock on the mmap.
Expand All @@ -890,6 +866,9 @@ func (db *DB) removeTx(tx *Tx) {
}
}
n := len(db.txs)
if db.freelist != nil {
db.freelist.removeReadonlyTXID(tx.meta.Txid())
}

// Unlock the meta pages.
db.metalock.Unlock()
Expand Down
43 changes: 43 additions & 0 deletions freelist.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bbolt

import (
"fmt"
"math"
"sort"
"unsafe"

Expand All @@ -24,6 +25,7 @@ type pidSet map[common.Pgid]struct{}
type freelist struct {
freelistType FreelistType // freelist type
ids []common.Pgid // all free and available free page ids.
readonlyTXIDs []common.Txid // all readonly transaction IDs.
allocs map[common.Pgid]common.Txid // mapping of Txid that allocated a pgid.
pending map[common.Txid]*txPending // mapping of soon-to-be free page ids by tx.
cache map[common.Pgid]struct{} // fast lookup of all free and pending page ids.
Expand Down Expand Up @@ -326,3 +328,44 @@ func (f *freelist) reindex() {
}
}
}

func (f *freelist) addReadonlyTXID(tid common.Txid) {
f.readonlyTXIDs = append(f.readonlyTXIDs, tid)
}

func (f *freelist) removeReadonlyTXID(tid common.Txid) {
for i := range f.readonlyTXIDs {
if f.readonlyTXIDs[i] == tid {
last := len(f.readonlyTXIDs) - 1
f.readonlyTXIDs[i] = f.readonlyTXIDs[last]
f.readonlyTXIDs = f.readonlyTXIDs[:last]
break
}
}
}

type txIDx []common.Txid

func (t txIDx) Len() int { return len(t) }
func (t txIDx) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
func (t txIDx) Less(i, j int) bool { return t[i] < t[j] }

// freePages releases any pages associated with closed read-only transactions.
func (f *freelist) freePages() {
// Free all pending pages prior to the earliest open transaction.
sort.Sort(txIDx(f.readonlyTXIDs))
minid := common.Txid(math.MaxUint64)
if len(f.readonlyTXIDs) > 0 {
minid = f.readonlyTXIDs[0]
}
if minid > 0 {
f.release(minid - 1)
}
// Release unused txid extents.
for _, tid := range f.readonlyTXIDs {
f.releaseRange(minid, tid-1)
minid = tid + 1
}
f.releaseRange(minid, common.Txid(math.MaxUint64))
// Any page both allocated and freed in an extent is safe to release.
}

0 comments on commit d537eff

Please sign in to comment.