Loading src/backends/cluster.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -101,7 +101,7 @@ namespace authdb { if (client) { try { auto &cmtx = g_Cluster->getClientMutex(); std::unique_lock<std::timed_mutex> lock(cmtx, std::chrono::seconds(3)); std::unique_lock<std::timed_mutex> lock(cmtx, std::try_to_lock); if (lock.owns_lock()) { peer_data = client->retrieve(dgid); _LastPeerFetch = now; Loading src/cluster.cpp +46 −19 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ #include <iostream> #include <algorithm> #include <set> #include <unordered_map> #ifdef _WIN32 #include <winsock2.h> Loading Loading @@ -209,35 +210,61 @@ namespace authdb { return true; } // --- Deterministic session group_id --- // --- Deterministic session group_id (cached) --- uint64_t sessionGroupId(const uuid::uuid &uid, const uuid::uuid &did) { // SHA-256(uid || did) → take first 8 bytes as uint64_t std::vector<uint8_t> input(32); std::memcpy(input.data(), uid.value, 16); std::memcpy(input.data() + 16, did.value, 16); auto hash = netplus::sha256_hash(input); static std::mutex g_sgidCacheMtx; static std::unordered_map<uint64_t, uint64_t> g_sgidCache; static uint64_t hashUuids(const uint8_t *data, size_t len) { auto hash = netplus::sha256_hash(std::vector<uint8_t>(data, data + len)); uint64_t id = 0; for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) id = (id << 8) | hash[i]; return id; } static uint64_t simpleCacheKey(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen) { uint64_t k = 0xcbf29ce484222325ULL; for (size_t i = 0; i < alen; ++i) k = (k ^ a[i]) * 0x100000001b3ULL; for (size_t i = 0; i < blen; ++i) k = (k ^ b[i]) * 0x100000001b3ULL; return k; } uint64_t sessionGroupId(const uuid::uuid &uid, const uuid::uuid &did) { uint64_t ckey = simpleCacheKey(uid.value, 16, did.value, 16); { std::lock_guard<std::mutex> g(g_sgidCacheMtx); auto it = g_sgidCache.find(ckey); if (it != g_sgidCache.end()) return it->second; } uint8_t input[32]; std::memcpy(input, uid.value, 16); std::memcpy(input + 16, did.value, 16); uint64_t id = hashUuids(input, 32); { std::lock_guard<std::mutex> g(g_sgidCacheMtx); g_sgidCache[ckey] = id; } return id; } uint64_t sidGroupId(const uuid::uuid &sid) { // SHA-256(0xFF || sid) → take first 8 bytes // 0xFF prefix avoids collision with sessionGroupId(uid||did) std::vector<uint8_t> input(17); static const uint8_t prefix = 0xFF; uint64_t ckey = simpleCacheKey(&prefix, 1, sid.value, 16); { std::lock_guard<std::mutex> g(g_sgidCacheMtx); auto it = g_sgidCache.find(ckey); if (it != g_sgidCache.end()) return it->second; } uint8_t input[17]; input[0] = 0xFF; std::memcpy(input.data() + 1, sid.value, 16); auto hash = netplus::sha256_hash(input); uint64_t id = 0; for (int i = 0; i < 8; i++) { id = (id << 8) | hash[i]; std::memcpy(input + 1, sid.value, 16); uint64_t id = hashUuids(input, 17); { std::lock_guard<std::mutex> g(g_sgidCacheMtx); g_sgidCache[ckey] = id; } return id; } Loading src/session.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ namespace authdb { authdb::SessionData::SessionData(){ _next=nullptr; _created=std::chrono::steady_clock::now(); _lastClusterSync=std::chrono::steady_clock::time_point{}; } authdb::SessionData::SessionData(const SessionData& src) : SessionData() { Loading Loading @@ -485,8 +486,10 @@ const authdb::SessionData *authdb::ClusterSession::getSession(uuid::uuid session cleanupExpired(); SessionData *cur = findLocal(sessionid); if (cur) { // Sync with cluster session_store_ (local memory only, no network) if (g_Cluster && g_Cluster->isRunning()) { // Only re-sync with cluster if local data is older than 60 seconds auto age = std::chrono::duration_cast<std::chrono::seconds>( std::chrono::steady_clock::now() - cur->_lastClusterSync).count(); if (age >= 60 && g_Cluster && g_Cluster->isRunning()) { uuid::uuid c_sid, c_uid, c_did; std::vector<uuid::uuid> c_members; std::string c_username; Loading @@ -497,8 +500,7 @@ const authdb::SessionData *authdb::ClusterSession::getSession(uuid::uuid session cur->_username = c_username; cur->setGPOResults(c_gpo); } // If fetch fails (peers unreachable), just use the local session as-is. // Do NOT remove — the session is valid locally even if cluster is down. cur->_lastClusterSync = std::chrono::steady_clock::now(); } return cur; } Loading src/session.h +1 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ namespace authdb { std::string _username; std::chrono::steady_clock::time_point _created; std::chrono::steady_clock::time_point _lastClusterSync; SessionData *_next; friend class Session; Loading Loading
src/backends/cluster.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -101,7 +101,7 @@ namespace authdb { if (client) { try { auto &cmtx = g_Cluster->getClientMutex(); std::unique_lock<std::timed_mutex> lock(cmtx, std::chrono::seconds(3)); std::unique_lock<std::timed_mutex> lock(cmtx, std::try_to_lock); if (lock.owns_lock()) { peer_data = client->retrieve(dgid); _LastPeerFetch = now; Loading
src/cluster.cpp +46 −19 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ #include <iostream> #include <algorithm> #include <set> #include <unordered_map> #ifdef _WIN32 #include <winsock2.h> Loading Loading @@ -209,35 +210,61 @@ namespace authdb { return true; } // --- Deterministic session group_id --- // --- Deterministic session group_id (cached) --- uint64_t sessionGroupId(const uuid::uuid &uid, const uuid::uuid &did) { // SHA-256(uid || did) → take first 8 bytes as uint64_t std::vector<uint8_t> input(32); std::memcpy(input.data(), uid.value, 16); std::memcpy(input.data() + 16, did.value, 16); auto hash = netplus::sha256_hash(input); static std::mutex g_sgidCacheMtx; static std::unordered_map<uint64_t, uint64_t> g_sgidCache; static uint64_t hashUuids(const uint8_t *data, size_t len) { auto hash = netplus::sha256_hash(std::vector<uint8_t>(data, data + len)); uint64_t id = 0; for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) id = (id << 8) | hash[i]; return id; } static uint64_t simpleCacheKey(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen) { uint64_t k = 0xcbf29ce484222325ULL; for (size_t i = 0; i < alen; ++i) k = (k ^ a[i]) * 0x100000001b3ULL; for (size_t i = 0; i < blen; ++i) k = (k ^ b[i]) * 0x100000001b3ULL; return k; } uint64_t sessionGroupId(const uuid::uuid &uid, const uuid::uuid &did) { uint64_t ckey = simpleCacheKey(uid.value, 16, did.value, 16); { std::lock_guard<std::mutex> g(g_sgidCacheMtx); auto it = g_sgidCache.find(ckey); if (it != g_sgidCache.end()) return it->second; } uint8_t input[32]; std::memcpy(input, uid.value, 16); std::memcpy(input + 16, did.value, 16); uint64_t id = hashUuids(input, 32); { std::lock_guard<std::mutex> g(g_sgidCacheMtx); g_sgidCache[ckey] = id; } return id; } uint64_t sidGroupId(const uuid::uuid &sid) { // SHA-256(0xFF || sid) → take first 8 bytes // 0xFF prefix avoids collision with sessionGroupId(uid||did) std::vector<uint8_t> input(17); static const uint8_t prefix = 0xFF; uint64_t ckey = simpleCacheKey(&prefix, 1, sid.value, 16); { std::lock_guard<std::mutex> g(g_sgidCacheMtx); auto it = g_sgidCache.find(ckey); if (it != g_sgidCache.end()) return it->second; } uint8_t input[17]; input[0] = 0xFF; std::memcpy(input.data() + 1, sid.value, 16); auto hash = netplus::sha256_hash(input); uint64_t id = 0; for (int i = 0; i < 8; i++) { id = (id << 8) | hash[i]; std::memcpy(input + 1, sid.value, 16); uint64_t id = hashUuids(input, 17); { std::lock_guard<std::mutex> g(g_sgidCacheMtx); g_sgidCache[ckey] = id; } return id; } Loading
src/session.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ namespace authdb { authdb::SessionData::SessionData(){ _next=nullptr; _created=std::chrono::steady_clock::now(); _lastClusterSync=std::chrono::steady_clock::time_point{}; } authdb::SessionData::SessionData(const SessionData& src) : SessionData() { Loading Loading @@ -485,8 +486,10 @@ const authdb::SessionData *authdb::ClusterSession::getSession(uuid::uuid session cleanupExpired(); SessionData *cur = findLocal(sessionid); if (cur) { // Sync with cluster session_store_ (local memory only, no network) if (g_Cluster && g_Cluster->isRunning()) { // Only re-sync with cluster if local data is older than 60 seconds auto age = std::chrono::duration_cast<std::chrono::seconds>( std::chrono::steady_clock::now() - cur->_lastClusterSync).count(); if (age >= 60 && g_Cluster && g_Cluster->isRunning()) { uuid::uuid c_sid, c_uid, c_did; std::vector<uuid::uuid> c_members; std::string c_username; Loading @@ -497,8 +500,7 @@ const authdb::SessionData *authdb::ClusterSession::getSession(uuid::uuid session cur->_username = c_username; cur->setGPOResults(c_gpo); } // If fetch fails (peers unreachable), just use the local session as-is. // Do NOT remove — the session is valid locally even if cluster is down. cur->_lastClusterSync = std::chrono::steady_clock::now(); } return cur; } Loading
src/session.h +1 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ namespace authdb { std::string _username; std::chrono::steady_clock::time_point _created; std::chrono::steady_clock::time_point _lastClusterSync; SessionData *_next; friend class Session; Loading