mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
127 lines
2.8 KiB
C++
127 lines
2.8 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::lock_guard 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::lock_guard 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::lock_guard 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::lock_guard const lock(mutex_);
|
|
|
|
return map_;
|
|
}
|
|
};
|
|
|
|
} // namespace xrpl
|