mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-25 08:00:22 +00:00
134 lines
2.9 KiB
C++
134 lines
2.9 KiB
C++
#pragma once
|
|
|
|
#include <xrpl/protocol/Protocol.h>
|
|
|
|
#include <condition_variable>
|
|
#include <map>
|
|
#include <mutex>
|
|
|
|
namespace xrpl {
|
|
|
|
/**
|
|
* Keeps track of which ledgers haven't been fully saved.
|
|
*
|
|
* During the ledger building process this collection will keep
|
|
* track of those ledgers that are being built but have not yet
|
|
* been completely written.
|
|
*/
|
|
class PendingSaves
|
|
{
|
|
private:
|
|
std::mutex mutable mutex_;
|
|
std::map<LedgerIndex, bool> map_;
|
|
std::condition_variable await_;
|
|
|
|
public:
|
|
/**
|
|
* Start working on a ledger
|
|
*
|
|
* This is called prior to updating the SQLite indexes.
|
|
*
|
|
* @return 'true' if work should be done
|
|
*/
|
|
bool
|
|
startWork(LedgerIndex seq)
|
|
{
|
|
std::scoped_lock const lock(mutex_);
|
|
|
|
auto it = map_.find(seq);
|
|
|
|
if ((it == map_.end()) || it->second)
|
|
{
|
|
// Work done or another thread is doing it
|
|
return false;
|
|
}
|
|
|
|
it->second = true;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Finish working on a ledger
|
|
*
|
|
* This is called after updating the SQLite indexes.
|
|
* The tracking of the work in progress is removed and
|
|
* threads awaiting completion are notified.
|
|
*/
|
|
void
|
|
finishWork(LedgerIndex seq)
|
|
{
|
|
std::scoped_lock const lock(mutex_);
|
|
|
|
map_.erase(seq);
|
|
await_.notify_all();
|
|
}
|
|
|
|
/**
|
|
* Return `true` if a ledger is in the progress of being saved.
|
|
*/
|
|
bool
|
|
pending(LedgerIndex seq)
|
|
{
|
|
std::scoped_lock const lock(mutex_);
|
|
return map_.contains(seq);
|
|
}
|
|
|
|
/**
|
|
* Check if a ledger should be dispatched
|
|
*
|
|
* Called to determine whether work should be done or
|
|
* dispatched. If work is already in progress and the
|
|
* call is synchronous, wait for work to be completed.
|
|
*
|
|
* @return 'true' if work should be done or dispatched
|
|
*/
|
|
bool
|
|
shouldWork(LedgerIndex seq, bool isSynchronous)
|
|
{
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
do
|
|
{
|
|
auto it = map_.find(seq);
|
|
|
|
if (it == map_.end())
|
|
{
|
|
map_.emplace(seq, false);
|
|
return true;
|
|
}
|
|
|
|
if (!isSynchronous)
|
|
{
|
|
// Already dispatched
|
|
return false;
|
|
}
|
|
|
|
if (!it->second)
|
|
{
|
|
// Scheduled, but not dispatched
|
|
return true;
|
|
}
|
|
|
|
// Already in progress, just need to wait
|
|
await_.wait(lock);
|
|
|
|
} while (true);
|
|
}
|
|
|
|
/**
|
|
* Get a snapshot of the pending saves
|
|
*
|
|
* Each entry in the returned map corresponds to a ledger
|
|
* that is in progress or dispatched. The boolean indicates
|
|
* whether work is currently in progress.
|
|
*/
|
|
std::map<LedgerIndex, bool>
|
|
getSnapshot() const
|
|
{
|
|
std::scoped_lock const lock(mutex_);
|
|
|
|
return map_;
|
|
}
|
|
};
|
|
|
|
} // namespace xrpl
|