Commit 3fb1614e authored by jan.koester's avatar jan.koester
Browse files

test

parent 20d00405
Loading
Loading
Loading
Loading
Loading
+7 −10
Changes for src/backend.cpp: 7 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -69,22 +69,19 @@ void authdb::AuthBackend::write(const unsigned char* dest, size_t destsize){
}

void authdb::AuthBackend::lock(){
    // Cluster sync (network I/O) runs BEFORE acquiring the backend mutex.
    // This prevents distributed deadlocks where two nodes hold their
    // backend locks and wait for each other's peer fetch to complete.
    _Api->lock();
    if (!_Lock.try_lock_for(std::chrono::seconds(5))) {
        // If we can't get the lock, undo the cluster fetch
        _Api->unlock();
    if (!_Lock.try_lock_for(std::chrono::seconds(5)))
        throw AuthBackendError("backend lock timeout");
    try {
        _Api->lock();
    } catch (...) {
        _Lock.unlock();
        throw;
    }
}

void authdb::AuthBackend::unlock(){
    // Release the backend mutex BEFORE cluster push (network I/O)
    // so other local threads can proceed while replication happens.
    _Lock.unlock();
    _Api->unlock();
    _Lock.unlock();
}

void authdb::AuthBackend::setPos(size_t pos){
+3 −18
Changes for src/backends/cluster.cpp: 3 added lines, 18 removed lines.
Original line number Diff line number Diff line
@@ -187,31 +187,16 @@ namespace authdb {
    }

    void ClusterBackend::lock() {
        // 1. Acquire _BufMtx first to protect _Buffer during fetch merge
        _BufLock = std::unique_lock<std::mutex>(_BufMtx);
        // 2. Fetch latest data (network I/O + merge into _Buffer)
        //    _BufLock stays held after this so read/write are safe
        fetchFromCluster();
    }

    void ClusterBackend::unlock() {
        // 1. Prepare push data while still holding _BufLock
        //    pushToCluster() copies _Buffer internally before network I/O
        bool dirty = _Dirty;
        std::vector<uint8_t> buf_copy;
        uint64_t dgid = 0;
        if (dirty) {
        if (_Dirty) {
            newRevesion();
            dgid = domainGroupId();
            buf_copy = _Buffer;
            uint64_t dgid = domainGroupId();
            pushToClusterAsync(dgid, _Buffer);
            _Dirty = false;
        }
        // 2. Release _BufMtx — other requests can now lock()
        if (_BufLock.owns_lock())
            _BufLock.unlock();
        // 3. Network I/O: push to peers (no locks held)
        if (dirty)
            pushToClusterAsync(dgid, buf_copy);
    }

    void ClusterBackend::pushToClusterAsync(uint64_t dgid, const std::vector<uint8_t> &buf) {
+3 −3
Changes for src/backends/cluster.h: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@

#include <vector>
#include <cstdint>
#include <atomic>
#include <chrono>

#include "../backend.h"
#include "../authdb.h"
@@ -70,9 +72,7 @@ namespace authdb {
        std::string              _Domain;
        std::vector<uint8_t>     _Buffer;
        size_t                   _Pos;
        bool                     _Dirty;
        std::atomic<bool>        _Dirty;
        std::chrono::steady_clock::time_point _LastPeerFetch{};
        std::mutex               _BufMtx;
        std::unique_lock<std::mutex> _BufLock;  // held between lock() and unlock()
    };
};