mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-22 02:47:26 +08:00
129 lines
2.3 KiB
Go
129 lines
2.3 KiB
Go
package hypergraph
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
type SyncController struct {
|
|
globalSync atomic.Bool
|
|
statusMu sync.RWMutex
|
|
syncStatus map[string]*SyncInfo
|
|
maxActiveSessions int32
|
|
activeSessions atomic.Int32
|
|
}
|
|
|
|
func (s *SyncController) TryEstablishSyncSession(peerID string) bool {
|
|
if peerID == "" {
|
|
return !s.globalSync.Swap(true)
|
|
}
|
|
|
|
info := s.getOrCreate(peerID)
|
|
if info.inProgress.Swap(true) {
|
|
return false
|
|
}
|
|
|
|
if !s.incrementActiveSessions() {
|
|
info.inProgress.Store(false)
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func (s *SyncController) EndSyncSession(peerID string) {
|
|
if peerID == "" {
|
|
s.globalSync.Store(false)
|
|
return
|
|
}
|
|
|
|
s.statusMu.RLock()
|
|
info := s.syncStatus[peerID]
|
|
s.statusMu.RUnlock()
|
|
if info != nil {
|
|
if info.inProgress.Swap(false) {
|
|
s.decrementActiveSessions()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *SyncController) GetStatus(peerID string) (*SyncInfo, bool) {
|
|
s.statusMu.RLock()
|
|
defer s.statusMu.RUnlock()
|
|
info, ok := s.syncStatus[peerID]
|
|
return info, ok
|
|
}
|
|
|
|
func (s *SyncController) SetStatus(peerID string, info *SyncInfo) {
|
|
s.statusMu.Lock()
|
|
existing := s.syncStatus[peerID]
|
|
if existing == nil {
|
|
s.syncStatus[peerID] = info
|
|
} else {
|
|
existing.Unreachable = info.Unreachable
|
|
existing.LastSynced = info.LastSynced
|
|
}
|
|
s.statusMu.Unlock()
|
|
}
|
|
|
|
func (s *SyncController) getOrCreate(peerID string) *SyncInfo {
|
|
s.statusMu.Lock()
|
|
defer s.statusMu.Unlock()
|
|
info, ok := s.syncStatus[peerID]
|
|
if !ok {
|
|
info = &SyncInfo{}
|
|
s.syncStatus[peerID] = info
|
|
}
|
|
return info
|
|
}
|
|
|
|
type SyncInfo struct {
|
|
Unreachable bool
|
|
LastSynced time.Time
|
|
inProgress atomic.Bool
|
|
}
|
|
|
|
func NewSyncController(maxActiveSessions int) *SyncController {
|
|
var max int32
|
|
if maxActiveSessions > 0 {
|
|
max = int32(maxActiveSessions)
|
|
}
|
|
return &SyncController{
|
|
syncStatus: map[string]*SyncInfo{},
|
|
maxActiveSessions: max,
|
|
}
|
|
}
|
|
|
|
func (s *SyncController) incrementActiveSessions() bool {
|
|
if s.maxActiveSessions <= 0 {
|
|
return true
|
|
}
|
|
|
|
for {
|
|
current := s.activeSessions.Load()
|
|
if current >= s.maxActiveSessions {
|
|
return false
|
|
}
|
|
if s.activeSessions.CompareAndSwap(current, current+1) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *SyncController) decrementActiveSessions() {
|
|
if s.maxActiveSessions <= 0 {
|
|
return
|
|
}
|
|
|
|
for {
|
|
current := s.activeSessions.Load()
|
|
if current == 0 {
|
|
return
|
|
}
|
|
if s.activeSessions.CompareAndSwap(current, current-1) {
|
|
return
|
|
}
|
|
}
|
|
}
|