Skip to content

Commit 1d9adbe

Browse files
committed
Replace generic CScopedDBTransaction with specialized CEvoDBScopedCommitter (#3292)
This has the wanted side effect of proper locking of "cs" inside CommitCurTransaction and RollbackCurTransaction, which was not easily possible to implement in the generic version. This fixes some rare crashes.
1 parent 8fd486c commit 1d9adbe

File tree

3 files changed

+61
-49
lines changed

3 files changed

+61
-49
lines changed

src/dbwrapper.h

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -724,49 +724,4 @@ class CDBTransaction {
724724
}
725725
};
726726

727-
template<typename Parent, typename CommitTarget>
728-
class CScopedDBTransaction {
729-
public:
730-
typedef CDBTransaction<Parent, CommitTarget> Transaction;
731-
732-
private:
733-
Transaction &dbTransaction;
734-
std::function<void ()> commitHandler;
735-
std::function<void ()> rollbackHandler;
736-
bool didCommitOrRollback{};
737-
738-
public:
739-
CScopedDBTransaction(Transaction &dbTx) : dbTransaction(dbTx) {}
740-
~CScopedDBTransaction() {
741-
if (!didCommitOrRollback)
742-
Rollback();
743-
}
744-
void Commit() {
745-
assert(!didCommitOrRollback);
746-
didCommitOrRollback = true;
747-
dbTransaction.Commit();
748-
if (commitHandler)
749-
commitHandler();
750-
}
751-
void Rollback() {
752-
assert(!didCommitOrRollback);
753-
didCommitOrRollback = true;
754-
dbTransaction.Clear();
755-
if (rollbackHandler)
756-
rollbackHandler();
757-
}
758-
759-
static std::unique_ptr<CScopedDBTransaction<Parent, CommitTarget>> Begin(Transaction &dbTx) {
760-
assert(dbTx.IsClean());
761-
return std::make_unique<CScopedDBTransaction<Parent, CommitTarget>>(dbTx);
762-
}
763-
764-
void SetCommitHandler(const std::function<void ()> &h) {
765-
commitHandler = h;
766-
}
767-
void SetRollbackHandler(const std::function<void ()> &h) {
768-
rollbackHandler = h;
769-
}
770-
};
771-
772727
#endif // BITCOIN_DBWRAPPER_H

src/evo/evodb.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@
66

77
CEvoDB* evoDb;
88

9+
CEvoDBScopedCommitter::CEvoDBScopedCommitter(CEvoDB &_evoDB) :
10+
evoDB(_evoDB)
11+
{
12+
}
13+
14+
CEvoDBScopedCommitter::~CEvoDBScopedCommitter()
15+
{
16+
if (!didCommitOrRollback)
17+
Rollback();
18+
}
19+
20+
void CEvoDBScopedCommitter::Commit()
21+
{
22+
assert(!didCommitOrRollback);
23+
didCommitOrRollback = true;
24+
evoDB.CommitCurTransaction();
25+
}
26+
27+
void CEvoDBScopedCommitter::Rollback()
28+
{
29+
assert(!didCommitOrRollback);
30+
didCommitOrRollback = true;
31+
evoDB.RollbackCurTransaction();
32+
}
33+
934
CEvoDB::CEvoDB(size_t nCacheSize, bool fMemory, bool fWipe) :
1035
db(fMemory ? "" : (GetDataDir() / "evodb"), nCacheSize, fMemory, fWipe),
1136
rootBatch(db),
@@ -14,6 +39,18 @@ CEvoDB::CEvoDB(size_t nCacheSize, bool fMemory, bool fWipe) :
1439
{
1540
}
1641

42+
void CEvoDB::CommitCurTransaction()
43+
{
44+
LOCK(cs);
45+
curDBTransaction.Commit();
46+
}
47+
48+
void CEvoDB::RollbackCurTransaction()
49+
{
50+
LOCK(cs);
51+
curDBTransaction.Clear();
52+
}
53+
1754
bool CEvoDB::CommitRootTransaction()
1855
{
1956
assert(curDBTransaction.IsClean());

src/evo/evodb.h

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@
1313
// "b_b2" was used after compact diffs were introduced
1414
static const std::string EVODB_BEST_BLOCK = "b_b2";
1515

16+
class CEvoDB;
17+
18+
class CEvoDBScopedCommitter
19+
{
20+
private:
21+
CEvoDB& evoDB;
22+
bool didCommitOrRollback{false};
23+
24+
public:
25+
explicit CEvoDBScopedCommitter(CEvoDB& _evoDB);
26+
~CEvoDBScopedCommitter();
27+
28+
void Commit();
29+
void Rollback();
30+
};
31+
1632
class CEvoDB
1733
{
1834
private:
@@ -21,7 +37,6 @@ class CEvoDB
2137

2238
typedef CDBTransaction<CDBWrapper, CDBBatch> RootTransaction;
2339
typedef CDBTransaction<RootTransaction, RootTransaction> CurTransaction;
24-
typedef CScopedDBTransaction<RootTransaction, RootTransaction> ScopedTransaction;
2540

2641
CDBBatch rootBatch;
2742
RootTransaction rootDBTransaction;
@@ -30,11 +45,10 @@ class CEvoDB
3045
public:
3146
CEvoDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
3247

33-
std::unique_ptr<ScopedTransaction> BeginTransaction()
48+
std::unique_ptr<CEvoDBScopedCommitter> BeginTransaction()
3449
{
3550
LOCK(cs);
36-
auto t = ScopedTransaction::Begin(curDBTransaction);
37-
return t;
51+
return std::make_unique<CEvoDBScopedCommitter>(*this);
3852
}
3953

4054
CurTransaction& GetCurTransaction()
@@ -84,6 +98,12 @@ class CEvoDB
8498

8599
bool VerifyBestBlock(const uint256& hash);
86100
void WriteBestBlock(const uint256& hash);
101+
102+
private:
103+
// only CEvoDBScopedCommitter is allowed to invoke these
104+
friend class CEvoDBScopedCommitter;
105+
void CommitCurTransaction();
106+
void RollbackCurTransaction();
87107
};
88108

89109
extern CEvoDB* evoDb;

0 commit comments

Comments
 (0)