Skip to content

crdt/crdt_data_filter.hpp

Header file of the CRDT Filter class. More...

Namespaces

Name
sgns
sgns::crdt

Classes

Name
class sgns::crdt::CRDTDataFilter
struct sgns::crdt::CRDTDataFilter::ElementFilterResult
Result of a single element-filter evaluation.
struct sgns::crdt::CRDTDataFilter::FilterCallbackEntry

Detailed Description

Header file of the CRDT Filter class.

Date: 2025-04-07 Henrique A. Klein ([email protected])

Source code

#ifndef _CRDT_DATA_FILTER_HPP_
#define _CRDT_DATA_FILTER_HPP_

#include <functional>
#include <optional>
#include <string>
#include <memory>
#include <regex>
#include <shared_mutex>
#include <system_error>
#include <utility>
#include <vector>

#include "crdt/proto/delta.pb.h"

namespace sgns::crdt
{
    class CRDTWorkJournal;

    class CRDTDataFilter
    {
    public:
        struct ElementFilterResult
        {
            enum class Decision
            {
                kAccept, 
                kReject, 
                kStall,  
            };

            Decision                 decision = Decision::kAccept;
            std::vector<pb::Element> additional_elements_to_remove; 

            static ElementFilterResult Accept()
            {
                return {};
            }
            static ElementFilterResult Reject( std::vector<pb::Element> extra = {} )
            {
                return ElementFilterResult{ Decision::kReject, std::move( extra ) };
            }
            static ElementFilterResult Stall()
            {
                return ElementFilterResult{ Decision::kStall, {} };
            }
            static ElementFilterResult FromOptional( std::optional<std::vector<pb::Element>> legacy )
            {
                if ( legacy.has_value() )
                {
                    return Reject( std::move( legacy.value() ) );
                }
                return Accept();
            }
        };

        using ElementFilterCallback = std::function<ElementFilterResult( const pb::Element & )>;

        struct FilterCallbackEntry
        {
            std::string           pattern;
            std::regex            regex;
            ElementFilterCallback filter;
        };

        using FilterCallbackRegistry = std::vector<std::shared_ptr<const FilterCallbackEntry>>;

        explicit CRDTDataFilter( std::shared_ptr<CRDTWorkJournal> work_journal, bool accept_by_default = true );

        ~CRDTDataFilter() = default;

        bool RegisterElementFilter( const std::string &pattern, ElementFilterCallback filter );

        bool RegisterTombstoneFilter( const std::string &pattern, ElementFilterCallback filter );

        void UnregisterElementFilter( const std::string &pattern );

        void UnregisterTombstoneFilter( const std::string &pattern );

        bool FilterElementsOnDelta( pb::Delta &delta ) const;

        void FilterTombstonesOnDelta( pb::Delta &delta );

    private:
        std::shared_ptr<CRDTWorkJournal> work_journal_;
        const bool                accept_by_default_;      
        mutable std::shared_mutex element_registry_mutex_; 
        std::shared_mutex         tombstone_registry_mutex_; 
        FilterCallbackRegistry    element_registry_;         
        FilterCallbackRegistry    tombstone_registry_;       
    };

}

#endif

Updated on 2026-09-17 at 06:29:15 +0000