Files
meta-core/internal/watcher/state.go
T
2026-02-08 21:53:42 +01:00

147 lines
3.2 KiB
Go

package watcher
import (
"sync"
)
// FileState tracks the known state of a file
type FileState struct {
Size int64
MtimeNano int64
MidHash string
}
// WatcherState tracks all files for a single watcher (in-memory)
type WatcherState struct {
mu sync.RWMutex
files map[string]*FileState // key: relative path
}
// NewWatcherState creates a new watcher state tracker
func NewWatcherState() *WatcherState {
return &WatcherState{
files: make(map[string]*FileState),
}
}
// Get returns the file state for a given path, or nil if not tracked
func (ws *WatcherState) Get(path string) *FileState {
ws.mu.RLock()
defer ws.mu.RUnlock()
return ws.files[path]
}
// Set updates or adds the file state for a given path
func (ws *WatcherState) Set(path string, state *FileState) {
ws.mu.Lock()
defer ws.mu.Unlock()
ws.files[path] = state
}
// Delete removes a file from the tracked state
func (ws *WatcherState) Delete(path string) {
ws.mu.Lock()
defer ws.mu.Unlock()
delete(ws.files, path)
}
// GetAll returns a snapshot of all tracked files
// The returned map is a copy - safe to modify
func (ws *WatcherState) GetAll() map[string]*FileState {
ws.mu.RLock()
defer ws.mu.RUnlock()
snapshot := make(map[string]*FileState, len(ws.files))
for path, state := range ws.files {
// Copy the state to avoid race conditions
stateCopy := *state
snapshot[path] = &stateCopy
}
return snapshot
}
// Clear removes all tracked files
func (ws *WatcherState) Clear() {
ws.mu.Lock()
defer ws.mu.Unlock()
ws.files = make(map[string]*FileState)
}
// Count returns the number of tracked files
func (ws *WatcherState) Count() int {
ws.mu.RLock()
defer ws.mu.RUnlock()
return len(ws.files)
}
// StateRegistry manages per-watcher state
type StateRegistry struct {
mu sync.RWMutex
states map[string]*WatcherState // key: watcher ID
}
// NewStateRegistry creates a new state registry
func NewStateRegistry() *StateRegistry {
return &StateRegistry{
states: make(map[string]*WatcherState),
}
}
// GetOrCreate returns the state for a watcher, creating one if needed
func (sr *StateRegistry) GetOrCreate(watcherID string) *WatcherState {
sr.mu.Lock()
defer sr.mu.Unlock()
state, exists := sr.states[watcherID]
if !exists {
state = NewWatcherState()
sr.states[watcherID] = state
}
return state
}
// Get returns the state for a watcher, or nil if not exists
func (sr *StateRegistry) Get(watcherID string) *WatcherState {
sr.mu.RLock()
defer sr.mu.RUnlock()
return sr.states[watcherID]
}
// Clear removes the state for a watcher
func (sr *StateRegistry) Clear(watcherID string) {
sr.mu.Lock()
defer sr.mu.Unlock()
if state, exists := sr.states[watcherID]; exists {
state.Clear()
}
}
// ClearAll removes all watcher states
func (sr *StateRegistry) ClearAll() {
sr.mu.Lock()
defer sr.mu.Unlock()
for _, state := range sr.states {
state.Clear()
}
}
// Delete removes a watcher's state completely
func (sr *StateRegistry) Delete(watcherID string) {
sr.mu.Lock()
defer sr.mu.Unlock()
delete(sr.states, watcherID)
}
// Count returns the number of files tracked for a watcher
func (sr *StateRegistry) Count(watcherID string) int {
sr.mu.RLock()
defer sr.mu.RUnlock()
if state, exists := sr.states[watcherID]; exists {
return state.Count()
}
return 0
}