src/crdt/crdt_set.hpp¶
Namespaces¶
| Name |
|---|
| sgns |
| sgns::crdt |
Classes¶
| Name | |
|---|---|
| class | sgns::crdt::CrdtSet CrdtSet implements an Add-Wins Observed-Remove Set using delta-CRDTs (https://arxiv.org/abs/1410.2803) and backing all the data in a datastore. It is fully agnostic to MerkleCRDTs or the delta distribution layer. It chooses the Value with most priority for a Key as the current Value. When two values have the same priority, it chooses by alphabetically sorting their unique IDs alphabetically. |
Source code¶
#ifndef SUPERGENIUS_CRDT_SET_HPP
#define SUPERGENIUS_CRDT_SET_HPP
#include <mutex>
#include <storage/rocksdb/rocksdb.hpp>
#include "crdt/hierarchical_key.hpp"
#include "crdt/proto/delta.pb.h"
namespace sgns::crdt
{
class CrdtSet
{
public:
using Delta = pb::Delta;
using Element = pb::Element;
using Buffer = base::Buffer;
using DataStore = storage::rocksdb;
using QueryResult = DataStore::QueryResult;
enum class QuerySuffix
{
QUERY_ALL,
QUERY_VALUESUFFIX,
QUERY_PRIORITYSUFFIX,
};
using PutHookPtr = std::function<void( const std::string &k, const Buffer &v, const std::string &cid )>;
using DeleteHookPtr = std::function<void( const std::string &k, const std::string &cid )>;
CrdtSet( std::shared_ptr<DataStore> aDatastore,
const HierarchicalKey &aNamespace,
PutHookPtr aPutHookPtr = nullptr,
DeleteHookPtr aDeleteHookPtr = nullptr );
CrdtSet( const CrdtSet & );
virtual ~CrdtSet() = default;
bool operator==( const CrdtSet & ) const;
bool operator!=( const CrdtSet & ) const;
CrdtSet &operator=( const CrdtSet & );
static std::string GetPrioritySuffix()
{
return std::string( prioritySuffix_ );
}
static std::string GetValueSuffix()
{
return std::string( valueSuffix_ );
}
outcome::result<std::string> GetValueFromDatastore( const HierarchicalKey &aKey ) const;
static outcome::result<std::shared_ptr<Delta>> CreateDeltaToAdd( const std::string &aKey,
const std::string &aValue );
outcome::result<std::shared_ptr<Delta>> CreateDeltaToRemove( const std::string &aKey ) const;
outcome::result<Buffer> GetElement( const std::string &aKey ) const;
outcome::result<QueryResult> QueryElements( std::string_view aPrefix,
const QuerySuffix &aSuffix = QuerySuffix::QUERY_ALL ) const;
outcome::result<QueryResult> QueryElements( const std::string &prefix_base,
const std::string &middle_part,
const std::string &remainder_prefix,
const QuerySuffix &aSuffix = QuerySuffix::QUERY_ALL ) const;
// TODO: Need to implement query with prefix from datastore
//func (s *set) Elements(q query.Query) (query.Results, error) {
outcome::result<bool> IsValueInSet( const std::string &aKey ) const;
outcome::result<bool> InElemsNotTombstoned( const std::string &aKey ) const;
HierarchicalKey KeyPrefix( const std::string &aKey ) const;
HierarchicalKey ElemsPrefix( const std::string &aKey ) const;
HierarchicalKey TombsPrefix( const std::string &aKey ) const;
HierarchicalKey KeysKey( std::string_view aKey ) const;
HierarchicalKey ValueKey( const std::string &aKey ) const;
HierarchicalKey PriorityKey( const std::string &aKey ) const;
outcome::result<uint64_t> GetPriority( const std::string &aKey ) const;
outcome::result<void> SetPriority( const std::string &aKey, uint64_t aPriority );
outcome::result<void> SetValue( const std::string &aKey,
const std::string &aID,
const Buffer &aValue,
uint64_t aPriority );
outcome::result<void> SetValue( const std::unique_ptr<storage::BufferBatch> &aDataStore,
const std::string &aKey,
const std::string &aID,
const Buffer &aValue,
uint64_t aPriority );
outcome::result<void> PutElems( std::vector<Element> &aElems, const std::string &aID, uint64_t aPriority );
outcome::result<void> PutTombs( const std::vector<Element> &aTombs, const std::string &aID ) const;
outcome::result<void> Merge( const Delta &aDelta, const std::string &aID );
outcome::result<bool> InTombsKeyID( const std::string &aKey, const std::string &aID ) const;
void SetPutHook( const PutHookPtr &putHookPtr );
void SetDeleteHook( const DeleteHookPtr &deleteHookPtr );
outcome::result<void> DataStoreSync( const std::vector<HierarchicalKey> &aKeyList );
void PrintDataStore() const;
private:
CrdtSet() = default;
static void PrintTombs( const std::vector<Element> &aTombs );
std::shared_ptr<DataStore> dataStore_ = nullptr;
HierarchicalKey namespaceKey_;
std::mutex mutex_;
PutHookPtr putHookFunc_ = nullptr;
DeleteHookPtr deleteHookFunc_ = nullptr;
static constexpr std::string_view elemsNamespace_ = "s"; // "s" -> elements namespace /set/s/<key>/<block>
static constexpr std::string_view tombsNamespace_ = "t"; // "t" -> tombstones namespace /set/t/<key>/<block>
static constexpr std::string_view keysNamespace_ = "k"; // "k" -> keys namespace /set/k/<key>/{v,p}
static constexpr std::string_view valueSuffix_ = "v"; // "v" for /keys namespace
static constexpr std::string_view prioritySuffix_ = "p"; // "p" for /keys namespace
};
} // namespace sgns::crdt
#endif //SUPERGENIUS_CRDT_SET_HPP
Updated on 2026-03-04 at 13:10:44 -0800