Commit d55e65da authored by jan.koester's avatar jan.koester
Browse files

test

parent 295e89cf
Loading
Loading
Loading
Loading
Loading
+56 −21
Changes for src/backends/cluster.cpp: 56 added lines, 21 removed lines.
Original line number Diff line number Diff line
@@ -112,39 +112,74 @@ namespace authdb {
            }
        }

        // Merge into _Buffer — caller (lock()) holds _BufLock after this returns
        size_t local_rev = bufferRevision(local_data);
        size_t peer_rev  = bufferRevision(peer_data);
        size_t cur_rev   = bufferRevision(_Buffer);

        // Reject corrupt buffers before considering them
        if (!bufferValid(local_data))
            local_data.clear();
        if (!bufferValid(peer_data))
            peer_data.clear();

        std::vector<uint8_t> *best = nullptr;
        size_t best_rev = cur_rev;
        // Merge into _Buffer — caller (lock()) holds _BufLock after this returns.
        // Instead of picking a single "best revision" buffer, merge records from
        // ALL sources (in-memory, local store, peers) so that records created on
        // remote nodes become visible locally.  vacuum() deduplicates by
        // (ruid, fieldname, type), keeping the last occurrence.
        size_t local_rev = bufferRevision(local_data);
        size_t peer_rev  = bufferRevision(peer_data);
        size_t cur_rev   = bufferRevision(_Buffer);

        bool local_has_records = (!local_data.empty() && local_data.size() > sizeof(AuthHeader));
        bool peer_has_records  = (!peer_data.empty()  && peer_data.size()  > sizeof(AuthHeader));

        // Quick check: skip merge when local store matches in-memory buffer
        // and no peer data is available
        bool local_same = (!_Buffer.empty() &&
                           local_data.size() == _Buffer.size() &&
                           (local_data.empty() ||
                            std::memcmp(local_data.data(), _Buffer.data(), _Buffer.size()) == 0));

        if (local_same && !peer_has_records)
            return;

        if (peer_rev > best_rev && !peer_data.empty()) {
            best = &peer_data;
            best_rev = peer_rev;
        // Ensure _Buffer has at least a valid header as merge base
        if (_Buffer.size() < sizeof(AuthHeader)) {
            if (local_data.size() >= sizeof(AuthHeader))
                _Buffer.assign(local_data.begin(),
                               local_data.begin() + sizeof(AuthHeader));
            else if (peer_data.size() >= sizeof(AuthHeader))
                _Buffer.assign(peer_data.begin(),
                               peer_data.begin() + sizeof(AuthHeader));
            else
                return; // no usable data anywhere
        }
        if (local_rev > best_rev && !local_data.empty()) {
            best = &local_data;
            best_rev = local_rev;

        // Append records from local store and peer store into _Buffer.
        // vacuum() will deduplicate afterwards.
        bool merged = false;

        if (local_has_records) {
            _Buffer.insert(_Buffer.end(),
                           local_data.begin() + sizeof(AuthHeader),
                           local_data.end());
            merged = true;
        }

        if (best) {
            _Buffer = std::move(*best);
        if (peer_has_records) {
            _Buffer.insert(_Buffer.end(),
                           peer_data.begin() + sizeof(AuthHeader),
                           peer_data.end());
            merged = true;
        }

        if (merged) {
            // Use the highest revision from any source
            size_t max_rev = std::max({cur_rev, local_rev, peer_rev});
            AuthHeader head;
            std::memcpy(&head, _Buffer.data(), sizeof(AuthHeader));
            head.Revesion = max_rev;
            std::memcpy(_Buffer.data(), &head, sizeof(AuthHeader));

            vacuum();
            store.store(dgid, 0, _Buffer.data(), _Buffer.size());
        } else if (_Buffer.empty() && !local_data.empty()) {
            _Buffer = std::move(local_data);
            vacuum();
        } else if (_Buffer.empty() && !peer_data.empty()) {
            _Buffer = std::move(peer_data);
            vacuum();
        }
    }