package notify import ( "strconv" "strings" "sync" ) const defaultReceivedSignalCacheLimit = 256 type receivedSignalCache struct { mu sync.Mutex entries map[string]struct{} order []string limit int } func newReceivedSignalCache(limit int) *receivedSignalCache { if limit <= 0 { limit = defaultReceivedSignalCacheLimit } return &receivedSignalCache{ entries: make(map[string]struct{}), limit: limit, } } func receivedSignalCacheKey(scope string, signalID uint64) string { return normalizeFileScope(scope) + "|" + strconv.FormatUint(signalID, 10) } func (c *receivedSignalCache) seenOrRemember(scope string, signalID uint64) bool { if c == nil || signalID == 0 { return false } key := receivedSignalCacheKey(scope, signalID) c.mu.Lock() defer c.mu.Unlock() if _, ok := c.entries[key]; ok { return true } c.entries[key] = struct{}{} c.order = append(c.order, key) c.trimLocked() return false } func (c *receivedSignalCache) closeAll() { if c == nil { return } c.mu.Lock() c.entries = make(map[string]struct{}) c.order = nil c.mu.Unlock() } func (c *receivedSignalCache) closeScope(scope string) { if c == nil { return } scope = normalizeFileScope(scope) prefix := scope + "|" c.mu.Lock() defer c.mu.Unlock() for key := range c.entries { if strings.HasPrefix(key, prefix) { delete(c.entries, key) } } if len(c.order) == 0 { return } filtered := c.order[:0] for _, key := range c.order { if _, ok := c.entries[key]; !ok { continue } filtered = append(filtered, key) } c.order = filtered } func (c *receivedSignalCache) trimLocked() { if c.limit <= 0 || len(c.entries) <= c.limit { return } for len(c.entries) > c.limit && len(c.order) > 0 { key := c.order[0] c.order = c.order[1:] if _, ok := c.entries[key]; !ok { continue } delete(c.entries, key) } } func (c *receivedSignalCache) applyLimit(limit int) { if c == nil { return } if limit <= 0 { limit = defaultReceivedSignalCacheLimit } c.mu.Lock() c.limit = limit c.trimLocked() c.mu.Unlock() } func (c *ClientCommon) getReceivedSignalCache() *receivedSignalCache { return c.getLogicalSessionState().receivedSignals } func (s *ServerCommon) getReceivedSignalCache() *receivedSignalCache { return s.getLogicalSessionState().receivedSignals }