package file import ( "io/fs" "os" "path/filepath" "skapp/pkg/logger" "sync" ) type Manager struct { FileManager *sync.Map lock *sync.RWMutex } func NewManager() *Manager { return &Manager{ FileManager: &sync.Map{}, lock: &sync.RWMutex{}, } } func (m *Manager) Len() (count int64) { defer func() { m.lock.RUnlock() }() m.lock.RLock() m.Each(func(file *os.File) bool { count++ return true }) return } func (m *Manager) Each(cb func(*os.File) bool) { defer func() { m.lock.RUnlock() }() m.lock.RLock() m.FileManager.Range(func(key, value any) bool { flagManager := value.(*sync.Map) flagManager.Range(func(key, value any) bool { fileModeManager := value.(*sync.Map) fileModeManager.Range(func(key, value any) bool { f := (value).(*os.File) return cb(f) }) return true }) return true }) } func (m *Manager) Remove(path string, flag int, perm fs.FileMode) { if m.Get(path, flag, perm) == nil { return } defer func() { m.lock.Unlock() }() m.lock.Lock() absPath, err := filepath.Abs(path) if err != nil { return } logger.Log.Infof("Remove %+v %+v %+v\n", absPath, flag, perm) var value interface{} value, _ = m.FileManager.Load(absPath) flagManager := value.(*sync.Map) value, _ = flagManager.Load(flag) fileModeManager := value.(*sync.Map) value, _ = fileModeManager.LoadAndDelete(perm.String()) f := value.(*os.File) _ = f.Close() } func (m *Manager) Get(path string, flag int, perm fs.FileMode) *os.File { defer func() { m.lock.RUnlock() }() m.lock.RLock() absPath, err := filepath.Abs(path) if err != nil { return nil } logger.Log.Infof("Get %+v %+v %+v\n", absPath, flag, perm) value, ok := m.FileManager.Load(absPath) if !ok { return nil } switch flagManager := value.(type) { case *sync.Map: value, ok := flagManager.Load(flag) if !ok { return nil } switch fileModeManager := value.(type) { case *sync.Map: f, ok := fileModeManager.Load(perm.String()) if !ok { return nil } return f.(*os.File) } } return nil } func (m *Manager) Close() { m.Each(func(f *os.File) bool { _ = f.Close() return true }) } func (m *Manager) Set(file *os.File, path string, flag int, perm fs.FileMode) { defer func() { m.lock.Unlock() }() m.lock.Lock() absPath, err := filepath.Abs(path) if err != nil { return } logger.Log.Infof("Set %+v %+v %+v\n", absPath, flag, perm) value, ok := m.FileManager.Load(path) if !ok { flagManager := sync.Map{} fileModeManager := sync.Map{} fileModeManager.Store(perm.String(), file) flagManager.Store(flag, &fileModeManager) m.FileManager.Store(absPath, &flagManager) return } switch flagManager := value.(type) { case *sync.Map: value, ok := flagManager.Load(flag) if !ok { fileModeManager := sync.Map{} fileModeManager.Store(perm.String(), file) flagManager.Store(flag, &fileModeManager) } switch fileModeManager := value.(type) { case *sync.Map: _, ok := fileModeManager.Load(perm.String()) if !ok { fileModeManager.Store(perm.String(), file) } } } }