Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snapshot on each block #2723

Merged
merged 34 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
22a7319
Add snapshot support
Bushstar Nov 17, 2023
f5ec14a
Generate snapshot on ConnectTip
Bushstar Nov 21, 2023
297ff52
Get snapshot on demand
Bushstar Nov 22, 2023
b378acd
Get changed map under lock
Bushstar Nov 23, 2023
53d44ec
Merge branch 'master' into bush/test-snapshot
Bushstar Nov 23, 2023
adc22c6
Update snapshot based on height
Bushstar Nov 23, 2023
86481f9
Revert "Update snapshot based on height"
Bushstar Nov 23, 2023
3913a4f
Do not Discard or Flush snapshot
Bushstar Nov 25, 2023
40f4348
Use snapshot in getblockcount
Bushstar Nov 26, 2023
d2de1a0
Merge branch 'master' into bush/test-snapshot
Bushstar Nov 27, 2023
8c6ea78
Snapshot on each block
Bushstar Nov 27, 2023
2bd966c
Merge branch 'master' into bush/snapshot-on-blk
Bushstar Dec 2, 2023
b48eb52
Resolve issues post-merge
Bushstar Dec 2, 2023
6a740ff
lint: circular deps
Bushstar Dec 2, 2023
384094c
Only snapshot on each block near tip
Bushstar Dec 4, 2023
1414018
Use IBD
Bushstar Dec 7, 2023
2688235
Merge branch 'master' into bush/snapshot-on-blk
Bushstar Mar 7, 2024
a54e6e4
Merge branch 'master' into bush/snapshot-on-blk
prasannavl Mar 22, 2024
01b1569
Merge branch 'master' into bush/snapshot-on-blk
prasannavl Mar 22, 2024
7e35d5c
Snapshot when current block near the current time
Bushstar Mar 22, 2024
aa86da1
Merge branch 'master' into bush/snapshot-on-blk
Bushstar Jun 12, 2024
b967635
lint: circular deps
Bushstar Jun 12, 2024
087f62c
Merge branch 'master' into bush/snapshot-on-blk
Bushstar Jun 17, 2024
8fa0cab
Merge branch 'master' into bush/snapshot-on-blk
Bushstar Jun 25, 2024
94253d3
Add history snapshots
Bushstar Jun 27, 2024
b7991dd
Merge branch 'master' into bush/snapshot-on-blk
Bushstar Jun 28, 2024
4e8424f
lint: circular deps
Bushstar Jun 29, 2024
063fa3b
Add vault snapshots
Bushstar Jun 29, 2024
b6612a4
Add GetVaultSnapshot wrapper
Bushstar Jun 29, 2024
654147b
lint: circular deps
Bushstar Jul 1, 2024
3a2ee85
Pass vaultDB
Bushstar Jul 4, 2024
308fd87
Merge branch 'master' into bush/snapshot-on-blk
Bushstar Jul 5, 2024
9a84497
Get all snapshots at once
Bushstar Jul 5, 2024
f90c2cd
Merge branch 'master' into bush/snapshot-on-blk
prasannavl Jul 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ DEFI_CORE_H = \
dfi/oracles.h \
dfi/poolpairs.h \
dfi/proposals.h \
dfi/snapshotmanager.h \
dfi/tokens.h \
dfi/threadpool.h \
dfi/coinselect.h \
Expand Down Expand Up @@ -460,6 +461,7 @@ libdefi_server_a_SOURCES = \
dfi/rpc_tokens.cpp \
dfi/rpc_vault.cpp \
dfi/skipped_txs.cpp \
dfi/snapshotmanager.cpp \
dfi/tokens.cpp \
dfi/threadpool.cpp \
dfi/undos.cpp \
Expand Down
8 changes: 6 additions & 2 deletions src/dbwrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,12 @@ class CDBWrapper
return new CDBIterator(*this, pdb->NewIterator(readOptions));
}

[[nodiscard]] std::shared_ptr<CStorageSnapshot> GetStorageSnapshot() const {
return std::make_shared<CStorageSnapshot>(pdb);
[[nodiscard]] const leveldb::Snapshot* CreateLevelDBSnapshot() const {
return pdb->GetSnapshot();
}

void ReleaseSnapshot(const leveldb::Snapshot* snapshot) const {
pdb->ReleaseSnapshot(snapshot);
}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/dfi/accountshistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ Res CAccountsHistoryView::EraseAccountHistoryHeight(uint32_t height) {
CAccountHistoryStorage::CAccountHistoryStorage(const fs::path &dbName, std::size_t cacheSize, bool fMemory, bool fWipe)
: CStorageView(new CStorageLevelDB(dbName, cacheSize, fMemory, fWipe)) {}

CAccountHistoryStorage::CAccountHistoryStorage(std::shared_ptr<CDBWrapper> &db,
std::unique_ptr<CCheckedOutSnapshot> &otherSnapshot)
: CStorageView(new CStorageLevelDB(db, otherSnapshot)) {}

CBurnHistoryStorage::CBurnHistoryStorage(const fs::path &dbName, std::size_t cacheSize, bool fMemory, bool fWipe)
: CStorageView(new CStorageLevelDB(dbName, cacheSize, fMemory, fWipe)) {}

Expand Down
8 changes: 6 additions & 2 deletions src/dfi/accountshistory.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ class CAccountsHistoryView : public virtual CStorageView {

class CAccountHistoryStorage : public CAccountsHistoryView, public CAuctionHistoryView {
public:
CAccountHistoryStorage(CAccountHistoryStorage &accountHistory)
: CStorageView(new CFlushableStorageKV(accountHistory.DB())) {}
CAccountHistoryStorage(const fs::path &dbName, std::size_t cacheSize, bool fMemory = false, bool fWipe = false);

explicit CAccountHistoryStorage(std::shared_ptr<CDBWrapper> &db,
std::unique_ptr<CCheckedOutSnapshot> &otherSnapshot);

CStorageLevelDB &GetStorage() { return static_cast<CStorageLevelDB &>(DB()); }
};

class CBurnHistoryStorage : public CAccountsHistoryView {
Expand Down Expand Up @@ -75,5 +78,6 @@ extern std::unique_ptr<CAccountHistoryStorage> paccountHistoryDB;
extern std::unique_ptr<CBurnHistoryStorage> pburnHistoryDB;

static constexpr bool DEFAULT_ACINDEX = true;
static constexpr bool DEFAULT_SNAPSHOT = false;

#endif // DEFI_DFI_ACCOUNTSHISTORY_H
10 changes: 1 addition & 9 deletions src/dfi/masternodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ CCustomCSView::CCustomCSView(CStorageKV &st)
CheckPrefixes();
}

CCustomCSView::CCustomCSView(std::unique_ptr<CStorageLevelDB> &st, const MapKV &changed)
CCustomCSView::CCustomCSView(std::unique_ptr<CStorageLevelDB> &st, MapKV &changed)
: CStorageView(new CFlushableStorageKV(st, changed)) {
CheckPrefixes();
}
Expand Down Expand Up @@ -1413,11 +1413,3 @@ void CalcMissingRewardTempFix(CCustomCSView &mnview, const uint32_t targetHeight
}
}
}

std::unique_ptr<CCustomCSView> GetViewSnapshot() {
// Get database snapshot and flushable storage changed map
auto [changed, snapshotDB] = pcustomcsview->GetStorage().GetSnapshotPair();

// Create new view using snapshot and change map
return std::make_unique<CCustomCSView>(snapshotDB, changed);
}
4 changes: 1 addition & 3 deletions src/dfi/masternodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ class CCustomCSView : public CMasternodesView,
explicit CCustomCSView(CStorageKV &st);

// Snapshot constructor
explicit CCustomCSView(std::unique_ptr<CStorageLevelDB> &st, const MapKV &changed);
explicit CCustomCSView(std::unique_ptr<CStorageLevelDB> &st, MapKV &changed);

// Cache-upon-a-cache constructors
CCustomCSView(CCustomCSView &other);
Expand Down Expand Up @@ -628,8 +628,6 @@ class CCustomCSView : public CMasternodesView,

std::map<CKeyID, CKey> AmISignerNow(int height, const CAnchorData::CTeam &team);

std::unique_ptr<CCustomCSView> GetViewSnapshot();

/** Global DB and view that holds enhanced chainstate data (should be protected by cs_main) */
extern std::unique_ptr<CStorageLevelDB> pcustomcsDB;
extern std::unique_ptr<CCustomCSView> pcustomcsview;
Expand Down
264 changes: 264 additions & 0 deletions src/dfi/snapshotmanager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
#include <dfi/snapshotmanager.h>

#include <dfi/accountshistory.h>
#include <dfi/masternodes.h>
#include <dfi/vaulthistory.h>

template <typename T>
static void CheckoutSnapshot(T &checkedOutMap, const CBlockSnapshot &snapshot) {
const auto checkOutKey = snapshot.GetKey();
const auto dbSnapshot = snapshot.GetLevelDBSnapshot();
if (checkedOutMap.count(checkOutKey)) {
++checkedOutMap.at(checkOutKey).count;
} else {
checkedOutMap[checkOutKey] = {dbSnapshot, 1};
}
}

SnapshotCollection GetSnapshots() {
return psnapshotManager->GetSnapshots();
}

SnapshotCollection CSnapshotManager::GetSnapshots() {
if (auto currentSnapshots = GetCurrentSnapshots()) {
return std::move(*currentSnapshots);
}
return GetGlobalSnapshots();
}

std::optional<SnapshotCollection> CSnapshotManager::GetCurrentSnapshots() {
std::unique_lock lock(mtx);

if (!currentViewSnapshot || (historyDB && !currentHistorySnapshot) || (vaultDB && !currentVaultSnapshot)) {
return {};
}

auto [changed, snapshotDB] = CheckoutViewSnapshot();
auto viewSnapshot = std::make_unique<CCustomCSView>(snapshotDB, changed);

std::unique_ptr<CAccountHistoryStorage> historySnapshot{};
if (historyDB) {
auto snapshot = CheckoutHistorySnapshot();
historySnapshot = std::make_unique<CAccountHistoryStorage>(historyDB, snapshot);
}

std::unique_ptr<CVaultHistoryStorage> vaultSnapshot{};
if (vaultDB) {
auto snapshot = CheckoutVaultSnapshot();
vaultSnapshot = std::make_unique<CVaultHistoryStorage>(vaultDB, snapshot);
}

return std::make_tuple(std::move(viewSnapshot), std::move(historySnapshot), std::move(vaultSnapshot));
}

SnapshotCollection CSnapshotManager::GetGlobalSnapshots() {
// Same lock order as ConnectBlock
LOCK(cs_main);
std::unique_lock lock(mtx);

auto [changed, snapshotDB] = GetGlobalViewSnapshot();
auto viewSnapshot = std::make_unique<CCustomCSView>(snapshotDB, changed);

std::unique_ptr<CAccountHistoryStorage> historySnapshot{};
if (historyDB) {
auto snapshot = GetGlobalHistorySnapshot();
historySnapshot = std::make_unique<CAccountHistoryStorage>(historyDB, snapshot);
}

std::unique_ptr<CVaultHistoryStorage> vaultSnapshot{};
if (vaultDB) {
auto snapshot = GetGlobalVaultSnapshot();
vaultSnapshot = std::make_unique<CVaultHistoryStorage>(vaultDB, snapshot);
}

return std::make_tuple(std::move(viewSnapshot), std::move(historySnapshot), std::move(vaultSnapshot));
}

CCheckedOutSnapshot::~CCheckedOutSnapshot() {
// Check snapshot back in
psnapshotManager->ReturnSnapshot(key);
}

CSnapshotManager::CSnapshotManager(std::unique_ptr<CCustomCSView> &otherViewDB,
std::unique_ptr<CAccountHistoryStorage> &otherHistoryDB,
std::unique_ptr<CVaultHistoryStorage> &otherVaultDB) {
viewDB = otherViewDB->GetStorage().GetStorageLevelDB()->GetDB();

// acindex index might be disabled
if (otherHistoryDB) {
historyDB = otherHistoryDB->GetStorage().GetDB();
}

// vault index index might be disabled
if (otherVaultDB) {
vaultDB = otherVaultDB->GetStorage().GetDB();
}
}

template <typename T, typename U, typename V>
static void ReturnSnapshot(T &db, U &snapshot, V &checkedMap) {
if (db && snapshot) {
if (snapshot->GetLevelDBSnapshot() && (!checkedMap.count(snapshot->GetKey()) || // Not in map
(checkedMap.count(snapshot->GetKey()) && // Is in map...
!checkedMap.at(snapshot->GetKey()).count))) { // ..but not in use
checkedMap.erase(snapshot->GetKey());
db->ReleaseSnapshot(snapshot->GetLevelDBSnapshot());
}
snapshot.reset();
}
}

template <typename T, typename U>
static void SetCurrentSnapshot(T &db, U &currentSnapshot, SnapshotType type, const CBlockIndex *block) {
if (db) {
// Get database snapshot
const auto snapshot = db->GetStorage().CreateLevelDBSnapshot();

// Set current snapshot
currentSnapshot = std::make_unique<CBlockSnapshot>(
snapshot, MapKV{}, CBlockSnapshotKey{type, block->nHeight, block->GetBlockHash()});
}
}

void CSnapshotManager::SetBlockSnapshots(CFlushableStorageKV &viewStorge,
CAccountHistoryStorage *historyView,
CVaultHistoryStorage *vaultView,
const CBlockIndex *block,
const bool nearTip) {
std::unique_lock lock(mtx);

// Return current snapshots
::ReturnSnapshot(viewDB, currentViewSnapshot, checkedOutViewMap);
::ReturnSnapshot(historyDB, currentHistorySnapshot, checkedOutHistoryMap);
::ReturnSnapshot(vaultDB, currentVaultSnapshot, checkedOutVaultMap);

// Do not create current snapshots if snapshots are disabled or not near tip
if (!gArgs.GetBoolArg("-enablesnapshots", DEFAULT_SNAPSHOT) || !nearTip) {
return;
}

// Get view database snapshot and flushable storage changed map
auto [changedView, snapshotView] = viewStorge.CreateSnapshotData();

// Set current view snapshot
currentViewSnapshot = std::make_unique<CBlockSnapshot>(
snapshotView, changedView, CBlockSnapshotKey{SnapshotType::VIEW, block->nHeight, block->GetBlockHash()});

// Set current snapshots
::SetCurrentSnapshot(historyView, currentHistorySnapshot, SnapshotType::HISTORY, block);
::SetCurrentSnapshot(vaultView, currentVaultSnapshot, SnapshotType::VAULT, block);
}

std::pair<MapKV, std::unique_ptr<CStorageLevelDB>> CSnapshotManager::GetGlobalViewSnapshot() {
// Get database snapshot and flushable storage changed map
auto [changedMap, snapshot] = pcustomcsview->GetStorage().CreateSnapshotData();

// Create checked out snapshot
const auto blockIndex = ::ChainActive().Tip();
CBlockSnapshotKey key{SnapshotType::VIEW, blockIndex->nHeight, blockIndex->GetBlockHash()};
auto globalSnapshot = std::make_unique<CCheckedOutSnapshot>(snapshot, key);

// Set global as current snapshot
currentViewSnapshot = std::make_unique<CBlockSnapshot>(globalSnapshot->GetLevelDBSnapshot(), changedMap, key);

// Track checked out snapshot
::CheckoutSnapshot(checkedOutViewMap, *currentViewSnapshot);

return {changedMap, std::make_unique<CStorageLevelDB>(viewDB, globalSnapshot)};
}

std::unique_ptr<CCheckedOutSnapshot> CSnapshotManager::GetGlobalHistorySnapshot() {
// Get database snapshot and flushable storage changed map
auto snapshot = paccountHistoryDB->GetStorage().CreateLevelDBSnapshot();

const auto blockIndex = ::ChainActive().Tip();
CBlockSnapshotKey key{SnapshotType::HISTORY, blockIndex->nHeight, blockIndex->GetBlockHash()};
auto globalSnapshot = std::make_unique<CCheckedOutSnapshot>(snapshot, key);

// Set global as current snapshot
currentHistorySnapshot = std::make_unique<CBlockSnapshot>(globalSnapshot->GetLevelDBSnapshot(), MapKV{}, key);

// Track checked out snapshot
::CheckoutSnapshot(checkedOutHistoryMap, *currentHistorySnapshot);

// Create checked out snapshot
return globalSnapshot;
}

std::unique_ptr<CCheckedOutSnapshot> CSnapshotManager::GetGlobalVaultSnapshot() {
// Get database snapshot and flushable storage changed map
auto snapshot = pvaultHistoryDB->GetStorage().CreateLevelDBSnapshot();

const auto blockIndex = ::ChainActive().Tip();
CBlockSnapshotKey key{SnapshotType::VAULT, blockIndex->nHeight, blockIndex->GetBlockHash()};
auto globalSnapshot = std::make_unique<CCheckedOutSnapshot>(snapshot, key);

// Set global as current snapshot
currentVaultSnapshot = std::make_unique<CBlockSnapshot>(globalSnapshot->GetLevelDBSnapshot(), MapKV{}, key);

// Track checked out snapshot
::CheckoutSnapshot(checkedOutVaultMap, *currentVaultSnapshot);

// Create checked out snapshot
return globalSnapshot;
}

std::pair<MapKV, std::unique_ptr<CStorageLevelDB>> CSnapshotManager::CheckoutViewSnapshot() {
// Create checked out snapshot
auto snapshot =
std::make_unique<CCheckedOutSnapshot>(currentViewSnapshot->GetLevelDBSnapshot(), currentViewSnapshot->GetKey());

// Track checked out snapshot
::CheckoutSnapshot(checkedOutViewMap, *currentViewSnapshot);

return {currentViewSnapshot->GetChanged(), std::make_unique<CStorageLevelDB>(viewDB, snapshot)};
}

std::unique_ptr<CCheckedOutSnapshot> CSnapshotManager::CheckoutHistorySnapshot() {
// Create checked out snapshot
auto snapshot = std::make_unique<CCheckedOutSnapshot>(currentHistorySnapshot->GetLevelDBSnapshot(),
currentHistorySnapshot->GetKey());

// Track checked out snapshot
::CheckoutSnapshot(checkedOutHistoryMap, *currentHistorySnapshot);

return snapshot;
}

std::unique_ptr<CCheckedOutSnapshot> CSnapshotManager::CheckoutVaultSnapshot() {
// Create checked out snapshot
auto snapshot = std::make_unique<CCheckedOutSnapshot>(currentVaultSnapshot->GetLevelDBSnapshot(),
currentVaultSnapshot->GetKey());

// Track checked out snapshot
::CheckoutSnapshot(checkedOutVaultMap, *currentVaultSnapshot);

return snapshot;
}

template <typename T, typename U, typename V>
static void DestructSnapshot(const CBlockSnapshotKey &key, T &checkedOutMap, U &currentSnapshot, V &db) {
if (checkedOutMap.count(key)) {
--checkedOutMap.at(key).count;

bool isCurrentKey{};
if (currentSnapshot) {
isCurrentKey = currentSnapshot->GetKey().hash == key.hash;
}

// Release if not in use and not the current block
if (!checkedOutMap.at(key).count && !isCurrentKey) {
db->ReleaseSnapshot(checkedOutMap.at(key).snapshot);
checkedOutMap.erase(key);
}
}
}

void CSnapshotManager::ReturnSnapshot(const CBlockSnapshotKey &key) {
std::unique_lock lock(mtx);
::DestructSnapshot(key, checkedOutViewMap, currentViewSnapshot, viewDB);
::DestructSnapshot(key, checkedOutHistoryMap, currentHistorySnapshot, historyDB);
::DestructSnapshot(key, checkedOutVaultMap, currentVaultSnapshot, vaultDB);
}

std::unique_ptr<CSnapshotManager> psnapshotManager;
Loading
Loading