// Copyright 2020, Chef. All rights reserved. // https://github.com/q191201771/lal // // Use of this source code is governed by a MIT-style license // that can be found in the License file. // // Author: Chef (191201771@qq.com) package datamanager import ( "sync" "time" "github.com/q191201771/naza/pkg/nazalog" ) type DataManagerMemory struct { serverTimeoutSec int mutex sync.Mutex serverID2pubStreams map[string]map[string]struct{} serverID2AliveTS map[string]int64 } func NewDataManagerMemory(serverTimeoutSec int) *DataManagerMemory { d := &DataManagerMemory{ serverTimeoutSec: serverTimeoutSec, serverID2pubStreams: make(map[string]map[string]struct{}), serverID2AliveTS: make(map[string]int64), } // TODO chef: release goroutine go func() { var count int for { time.Sleep(1 * time.Second) count++ now := time.Now().Unix() d.mutex.Lock() // 清除长时间没有update报活的节点 for serverID, ts := range d.serverID2AliveTS { if now > ts && now-ts > int64(d.serverTimeoutSec)*1000 { nazalog.Warnf("server timeout. serverID=%s", serverID) delete(d.serverID2pubStreams, serverID) } } // 定时打印数据日志 if count%60 == 0 { nazalog.Infof("data info. %+v", d.serverID2pubStreams) } d.mutex.Unlock() } }() return d } func (d *DataManagerMemory) AddPub(streamName, serverID string) { d.mutex.Lock() defer d.mutex.Unlock() pss, _ := d.serverID2pubStreams[serverID] if pss == nil { pss = make(map[string]struct{}) } pss[streamName] = struct{}{} } func (d *DataManagerMemory) DelPub(streamName, serverID string) { d.mutex.Lock() defer d.mutex.Unlock() actualServerID, _ := d.queryPub(streamName) if actualServerID != serverID { return } delete(d.serverID2pubStreams[serverID], streamName) } func (d *DataManagerMemory) QueryPub(streamName string) (serverID string, exist bool) { d.mutex.Lock() defer d.mutex.Unlock() return d.queryPub(streamName) } func (d *DataManagerMemory) UpdatePub(serverID string, streamNameList []string) { // 3. server超时,去掉所有上面所有的pub d.mutex.Lock() defer d.mutex.Unlock() d.markAlive(serverID) // 更新serverID对应的stream列表 pss := make(map[string]struct{}) for _, s := range streamNameList { pss[s] = struct{}{} } cpss := d.serverID2pubStreams[serverID] d.serverID2pubStreams[serverID] = pss // only for log for s := range pss { if _, exist := cpss[s]; !exist { nazalog.Warnf("update pub, add. serverID=%s, streamName=%s", serverID, s) } } for s := range cpss { if _, exist := pss[s]; !exist { nazalog.Warnf("update pub, del. serverID=%s, streamName=%s", serverID, s) } } } func (d *DataManagerMemory) queryPub(streamName string) (string, bool) { for serverID, pss := range d.serverID2pubStreams { if _, exist := pss[streamName]; exist { return serverID, true } } return "", false } func (d *DataManagerMemory) markAlive(serverID string) { d.serverID2AliveTS[serverID] = time.Now().Unix() }