1Panel/agent/utils/psutil/disk.go
2025-11-26 16:33:47 +08:00

92 lines
1.9 KiB
Go

package psutil
import (
"sync"
"time"
"github.com/shirou/gopsutil/v4/disk"
)
const (
diskUsageCacheInterval = 30 * time.Second
diskPartitionCacheInterval = 10 * time.Minute
)
type DiskUsageEntry struct {
lastSampleTime time.Time
cachedUsage *disk.UsageStat
}
type DiskState struct {
usageMu sync.RWMutex
usageCache map[string]*DiskUsageEntry
partitionMu sync.RWMutex
lastPartitionTime time.Time
cachedPartitions []disk.PartitionStat
}
func (d *DiskState) GetUsage(path string, forceRefresh bool) (*disk.UsageStat, error) {
d.usageMu.RLock()
if entry, ok := d.usageCache[path]; ok {
if time.Since(entry.lastSampleTime) < diskUsageCacheInterval && !forceRefresh {
defer d.usageMu.RUnlock()
return entry.cachedUsage, nil
}
}
d.usageMu.RUnlock()
usage, err := disk.Usage(path)
if err != nil {
return nil, err
}
d.usageMu.Lock()
if d.usageCache == nil {
d.usageCache = make(map[string]*DiskUsageEntry)
}
d.usageCache[path] = &DiskUsageEntry{
lastSampleTime: time.Now(),
cachedUsage: usage,
}
d.usageMu.Unlock()
return usage, nil
}
func (d *DiskState) GetPartitions(all bool, forceRefresh bool) ([]disk.PartitionStat, error) {
d.partitionMu.RLock()
if d.cachedPartitions != nil && time.Since(d.lastPartitionTime) < diskPartitionCacheInterval && !forceRefresh {
defer d.partitionMu.RUnlock()
return d.cachedPartitions, nil
}
d.partitionMu.RUnlock()
partitions, err := disk.Partitions(all)
if err != nil {
return nil, err
}
d.partitionMu.Lock()
d.cachedPartitions = partitions
d.lastPartitionTime = time.Now()
d.partitionMu.Unlock()
return partitions, nil
}
func (d *DiskState) ClearUsageCache(path string) {
d.usageMu.Lock()
delete(d.usageCache, path)
d.usageMu.Unlock()
}
func (d *DiskState) ClearAllCache() {
d.usageMu.Lock()
d.usageCache = make(map[string]*DiskUsageEntry)
d.usageMu.Unlock()
d.partitionMu.Lock()
d.cachedPartitions = nil
d.partitionMu.Unlock()
}