Merge branch 'master' into fb1000

This commit is contained in:
souhailanoor 2021-12-15 13:37:15 -06:00 committed by GitHub
commit 0c65485b0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 16 deletions

View file

@ -444,15 +444,10 @@ func (db *DB) Begin(writable bool) (_ *Tx, err error) {
}
db.mu.Lock()
// note: We cannot defer db.mu.Unlock() here because
// we call tx.Rollback() before if db.readMetaPage
// returns an error, and thus we will deadlock against
// ourselves when the Rollback tries to acquire the db.mu.
// This is why db.mu.Unlock() is done manually below.
defer db.mu.Unlock()
if !db.opened {
cleanup()
db.mu.Unlock()
return nil, ErrClosed
}
@ -470,6 +465,11 @@ func (db *DB) Begin(writable bool) (_ *Tx, err error) {
DeleteEmptyContainer: true,
}
defer func() {
if err != nil {
tx.rollback(true)
}
}()
if writable {
tx.dirtyPages = make(map[uint32][]byte)
@ -480,10 +480,6 @@ func (db *DB) Begin(writable bool) (_ *Tx, err error) {
// This page is only written at the end of a dirty transaction.
page, err := db.readMetaPage()
if err != nil {
// we will deadlock in tx.Rollback()
// on db.mu.Lock unless we manually db.mu.Unlock first.
db.mu.Unlock()
tx.Rollback()
return nil, err
}
copy(tx.meta[:], page)
@ -499,13 +495,10 @@ func (db *DB) Begin(writable bool) (_ *Tx, err error) {
// this avoids recomputing the cache if there are no write txs for a while.
if db.rootRecords == nil {
if db.rootRecords, err = tx.RootRecords(); err != nil {
db.mu.Unlock()
tx.Rollback()
return nil, err
}
}
db.mu.Unlock()
return tx, nil
}

View file

@ -126,7 +126,9 @@ func (tx *Tx) Commit() error {
return tx.db.removeTx(tx)
}
func (tx *Tx) Rollback() {
func (tx *Tx) Rollback() { tx.rollback(false) }
func (tx *Tx) rollback(hasDBLock bool) {
tx.mu.Lock()
defer tx.mu.Unlock()
@ -141,8 +143,10 @@ func (tx *Tx) Rollback() {
}
// Disconnect transaction from DB.
tx.db.mu.Lock()
defer tx.db.mu.Unlock()
if !hasDBLock {
tx.db.mu.Lock()
defer tx.db.mu.Unlock()
}
vprint.PanicOn(tx.db.removeTx(tx))
}