txn: don't attempt to close transactions from older db generations

This commit is contained in:
William Casarin
2024-01-26 11:58:48 -08:00
parent d3c75ce42b
commit d04a29405d
2 changed files with 16 additions and 1 deletions

View File

@@ -31,6 +31,7 @@ class Ndb {
var ndb: ndb_t var ndb: ndb_t
let path: String? let path: String?
let owns_db: Bool let owns_db: Bool
var generation: Int
var closed: Bool var closed: Bool
static func safemode() -> Ndb? { static func safemode() -> Ndb? {
@@ -125,6 +126,7 @@ class Ndb {
return nil return nil
} }
self.generation = 0
self.path = path self.path = path
self.owns_db = owns_db_file self.owns_db = owns_db_file
self.ndb = db self.ndb = db
@@ -170,6 +172,7 @@ class Ndb {
init(ndb: ndb_t) { init(ndb: ndb_t) {
self.ndb = ndb self.ndb = ndb
self.generation = 0
self.path = nil self.path = nil
self.owns_db = true self.owns_db = true
self.closed = false self.closed = false
@@ -189,6 +192,7 @@ class Ndb {
return false return false
} }
self.generation += 1
self.closed = false self.closed = false
self.ndb = db self.ndb = db
return true return true

View File

@@ -18,10 +18,12 @@ class NdbTxn<T> {
var moved: Bool var moved: Bool
var inherited: Bool var inherited: Bool
var ndb: Ndb var ndb: Ndb
var generation: Int
init?(ndb: Ndb, with: (NdbTxn<T>) -> T = { _ in () }) { init?(ndb: Ndb, with: (NdbTxn<T>) -> T = { _ in () }) {
guard !ndb.closed else { return nil } guard !ndb.closed else { return nil }
self.ndb = ndb self.ndb = ndb
self.generation = ndb.generation
#if TXNDEBUG #if TXNDEBUG
txn_count += 1 txn_count += 1
print("opening transaction \(txn_count)") print("opening transaction \(txn_count)")
@@ -30,14 +32,18 @@ class NdbTxn<T> {
// some parent thread is active, use that instead // some parent thread is active, use that instead
self.txn = active_txn self.txn = active_txn
self.inherited = true self.inherited = true
self.generation = Thread.current.threadDictionary["txn_generation"] as! Int
} else { } else {
self.txn = ndb_txn() self.txn = ndb_txn()
guard !ndb.closed else { return nil } guard !ndb.closed else { return nil }
self.generation = ndb.generation
let ok = ndb_begin_query(ndb.ndb.ndb, &self.txn) != 0 let ok = ndb_begin_query(ndb.ndb.ndb, &self.txn) != 0
if !ok { if !ok {
return nil return nil
} }
self.generation = ndb.generation
Thread.current.threadDictionary["ndb_txn"] = self.txn Thread.current.threadDictionary["ndb_txn"] = self.txn
Thread.current.threadDictionary["txn_generation"] = ndb.generation
self.inherited = false self.inherited = false
} }
self.moved = false self.moved = false
@@ -50,6 +56,7 @@ class NdbTxn<T> {
self.moved = false self.moved = false
self.inherited = false self.inherited = false
self.ndb = ndb self.ndb = ndb
self.generation = 0
} }
/// Only access temporarily! Do not store database references for longterm use. If it's a primitive type you /// Only access temporarily! Do not store database references for longterm use. If it's a primitive type you
@@ -60,6 +67,10 @@ class NdbTxn<T> {
} }
deinit { deinit {
if self.generation != ndb.generation {
//print("txn: OLD GENERATION (\(self.generation) != \(ndb.generation)), IGNORING")
return
}
if moved || inherited || ndb.closed { if moved || inherited || ndb.closed {
return return
} }