mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
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.
This commit is contained in:
parent
5edaad4b29
commit
5b4fe43c25
@ -724,49 +724,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Parent, typename CommitTarget>
|
|
||||||
class CScopedDBTransaction {
|
|
||||||
public:
|
|
||||||
typedef CDBTransaction<Parent, CommitTarget> Transaction;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Transaction &dbTransaction;
|
|
||||||
std::function<void ()> commitHandler;
|
|
||||||
std::function<void ()> rollbackHandler;
|
|
||||||
bool didCommitOrRollback{};
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CScopedDBTransaction(Transaction &dbTx) : dbTransaction(dbTx) {}
|
|
||||||
~CScopedDBTransaction() {
|
|
||||||
if (!didCommitOrRollback)
|
|
||||||
Rollback();
|
|
||||||
}
|
|
||||||
void Commit() {
|
|
||||||
assert(!didCommitOrRollback);
|
|
||||||
didCommitOrRollback = true;
|
|
||||||
dbTransaction.Commit();
|
|
||||||
if (commitHandler)
|
|
||||||
commitHandler();
|
|
||||||
}
|
|
||||||
void Rollback() {
|
|
||||||
assert(!didCommitOrRollback);
|
|
||||||
didCommitOrRollback = true;
|
|
||||||
dbTransaction.Clear();
|
|
||||||
if (rollbackHandler)
|
|
||||||
rollbackHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::unique_ptr<CScopedDBTransaction<Parent, CommitTarget>> Begin(Transaction &dbTx) {
|
|
||||||
assert(dbTx.IsClean());
|
|
||||||
return std::make_unique<CScopedDBTransaction<Parent, CommitTarget>>(dbTx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetCommitHandler(const std::function<void ()> &h) {
|
|
||||||
commitHandler = h;
|
|
||||||
}
|
|
||||||
void SetRollbackHandler(const std::function<void ()> &h) {
|
|
||||||
rollbackHandler = h;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BITCOIN_DBWRAPPER_H
|
#endif // BITCOIN_DBWRAPPER_H
|
||||||
|
@ -6,6 +6,31 @@
|
|||||||
|
|
||||||
CEvoDB* evoDb;
|
CEvoDB* evoDb;
|
||||||
|
|
||||||
|
CEvoDBScopedCommitter::CEvoDBScopedCommitter(CEvoDB &_evoDB) :
|
||||||
|
evoDB(_evoDB)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CEvoDBScopedCommitter::~CEvoDBScopedCommitter()
|
||||||
|
{
|
||||||
|
if (!didCommitOrRollback)
|
||||||
|
Rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEvoDBScopedCommitter::Commit()
|
||||||
|
{
|
||||||
|
assert(!didCommitOrRollback);
|
||||||
|
didCommitOrRollback = true;
|
||||||
|
evoDB.CommitCurTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEvoDBScopedCommitter::Rollback()
|
||||||
|
{
|
||||||
|
assert(!didCommitOrRollback);
|
||||||
|
didCommitOrRollback = true;
|
||||||
|
evoDB.RollbackCurTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
CEvoDB::CEvoDB(size_t nCacheSize, bool fMemory, bool fWipe) :
|
CEvoDB::CEvoDB(size_t nCacheSize, bool fMemory, bool fWipe) :
|
||||||
db(fMemory ? "" : (GetDataDir() / "evodb"), nCacheSize, fMemory, fWipe),
|
db(fMemory ? "" : (GetDataDir() / "evodb"), nCacheSize, fMemory, fWipe),
|
||||||
rootBatch(db),
|
rootBatch(db),
|
||||||
@ -14,6 +39,18 @@ CEvoDB::CEvoDB(size_t nCacheSize, bool fMemory, bool fWipe) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CEvoDB::CommitCurTransaction()
|
||||||
|
{
|
||||||
|
LOCK(cs);
|
||||||
|
curDBTransaction.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEvoDB::RollbackCurTransaction()
|
||||||
|
{
|
||||||
|
LOCK(cs);
|
||||||
|
curDBTransaction.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool CEvoDB::CommitRootTransaction()
|
bool CEvoDB::CommitRootTransaction()
|
||||||
{
|
{
|
||||||
assert(curDBTransaction.IsClean());
|
assert(curDBTransaction.IsClean());
|
||||||
|
@ -13,6 +13,22 @@
|
|||||||
// "b_b2" was used after compact diffs were introduced
|
// "b_b2" was used after compact diffs were introduced
|
||||||
static const std::string EVODB_BEST_BLOCK = "b_b2";
|
static const std::string EVODB_BEST_BLOCK = "b_b2";
|
||||||
|
|
||||||
|
class CEvoDB;
|
||||||
|
|
||||||
|
class CEvoDBScopedCommitter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
CEvoDB& evoDB;
|
||||||
|
bool didCommitOrRollback{false};
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CEvoDBScopedCommitter(CEvoDB& _evoDB);
|
||||||
|
~CEvoDBScopedCommitter();
|
||||||
|
|
||||||
|
void Commit();
|
||||||
|
void Rollback();
|
||||||
|
};
|
||||||
|
|
||||||
class CEvoDB
|
class CEvoDB
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -21,7 +37,6 @@ private:
|
|||||||
|
|
||||||
typedef CDBTransaction<CDBWrapper, CDBBatch> RootTransaction;
|
typedef CDBTransaction<CDBWrapper, CDBBatch> RootTransaction;
|
||||||
typedef CDBTransaction<RootTransaction, RootTransaction> CurTransaction;
|
typedef CDBTransaction<RootTransaction, RootTransaction> CurTransaction;
|
||||||
typedef CScopedDBTransaction<RootTransaction, RootTransaction> ScopedTransaction;
|
|
||||||
|
|
||||||
CDBBatch rootBatch;
|
CDBBatch rootBatch;
|
||||||
RootTransaction rootDBTransaction;
|
RootTransaction rootDBTransaction;
|
||||||
@ -30,11 +45,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
explicit CEvoDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
explicit CEvoDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
||||||
|
|
||||||
std::unique_ptr<ScopedTransaction> BeginTransaction()
|
std::unique_ptr<CEvoDBScopedCommitter> BeginTransaction()
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
auto t = ScopedTransaction::Begin(curDBTransaction);
|
return std::make_unique<CEvoDBScopedCommitter>(*this);
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CurTransaction& GetCurTransaction()
|
CurTransaction& GetCurTransaction()
|
||||||
@ -84,6 +98,12 @@ public:
|
|||||||
|
|
||||||
bool VerifyBestBlock(const uint256& hash);
|
bool VerifyBestBlock(const uint256& hash);
|
||||||
void WriteBestBlock(const uint256& hash);
|
void WriteBestBlock(const uint256& hash);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// only CEvoDBScopedCommitter is allowed to invoke these
|
||||||
|
friend class CEvoDBScopedCommitter;
|
||||||
|
void CommitCurTransaction();
|
||||||
|
void RollbackCurTransaction();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CEvoDB* evoDb;
|
extern CEvoDB* evoDb;
|
||||||
|
Loading…
Reference in New Issue
Block a user