mirror of
https://github.com/samuelncui/acp.git
synced 2025-12-23 05:05:15 +00:00
feat: disk usage add cache
This commit is contained in:
10
acp.go
10
acp.go
@@ -9,9 +9,10 @@ import (
|
||||
|
||||
type Copyer struct {
|
||||
*option
|
||||
running sync.WaitGroup
|
||||
eventCh chan Event
|
||||
getDevice func(in string) string
|
||||
running sync.WaitGroup
|
||||
eventCh chan Event
|
||||
getDevice func(in string) string
|
||||
getDiskUsageCache func(mountPoint string) *diskUsageCache
|
||||
}
|
||||
|
||||
func New(ctx context.Context, opts ...Option) (*Copyer, error) {
|
||||
@@ -35,6 +36,9 @@ func New(ctx context.Context, opts ...Option) (*Copyer, error) {
|
||||
option: opt,
|
||||
eventCh: make(chan Event, 128),
|
||||
getDevice: getDevice,
|
||||
getDiskUsageCache: Cache(func(mountPoint string) *diskUsageCache {
|
||||
return newDiskUsageCache(mountPoint, defaultDiskUsageFreshInterval)
|
||||
}),
|
||||
}
|
||||
|
||||
c.running.Add(1)
|
||||
|
||||
6
cache.go
6
cache.go
@@ -1,8 +1,8 @@
|
||||
package acp
|
||||
|
||||
func Cache[i comparable, o any](f func(in i) o) func(in i) o {
|
||||
cache := make(map[i]o, 0)
|
||||
return func(in i) o {
|
||||
func Cache[K comparable, V any](f func(in K) V) func(in K) V {
|
||||
cache := make(map[K]V, 0)
|
||||
return func(in K) V {
|
||||
cached, has := cache[in]
|
||||
if has {
|
||||
return cached
|
||||
|
||||
15
copy.go
15
copy.go
@@ -16,7 +16,6 @@ import (
|
||||
mapset "github.com/deckarep/golang-set/v2"
|
||||
sha256 "github.com/minio/sha256-simd"
|
||||
"github.com/samber/lo"
|
||||
"github.com/samuelncui/godf"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -117,14 +116,12 @@ func (c *Copyer) write(ctx context.Context, job *writeJob, ch chan<- *baseJob, c
|
||||
continue
|
||||
}
|
||||
|
||||
diskUsage, err := godf.NewDiskUsage(dev)
|
||||
if err != nil {
|
||||
job.fail(target, fmt.Errorf("read disk usage fail, dev= '%s', %w", dev, err))
|
||||
continue
|
||||
}
|
||||
if int64(diskUsage.Free()) < job.size {
|
||||
noSpaceDevices.Add(dev)
|
||||
job.fail(target, fmt.Errorf("%w, want= %d have= %d", ErrTargetNoSpace, job.size, diskUsage.Free()))
|
||||
if err := c.getDiskUsageCache(dev).check(job.size); err != nil {
|
||||
if errors.Is(err, ErrTargetNoSpace) {
|
||||
noSpaceDevices.Add(dev)
|
||||
}
|
||||
|
||||
job.fail(target, fmt.Errorf("check disk usage have error, %w", err))
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
51
disk_usage.go
Normal file
51
disk_usage.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package acp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/samuelncui/godf"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultDiskUsageFreshInterval = 1024 * 1024 * 1024 * 2
|
||||
)
|
||||
|
||||
type diskUsageCache struct {
|
||||
mountPoint string
|
||||
freshInterval int64
|
||||
|
||||
lock sync.Mutex
|
||||
freeSpace int64
|
||||
used int64
|
||||
}
|
||||
|
||||
func newDiskUsageCache(mountPoint string, freshInterval int64) *diskUsageCache {
|
||||
return &diskUsageCache{
|
||||
mountPoint: mountPoint,
|
||||
freshInterval: freshInterval,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *diskUsageCache) check(need int64) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
m.used += need
|
||||
if m.used <= m.freeSpace && m.used < m.freshInterval {
|
||||
return nil
|
||||
}
|
||||
|
||||
usage, err := godf.NewDiskUsage(m.mountPoint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get disk usage fail, mount_point= %s", m.mountPoint)
|
||||
}
|
||||
|
||||
m.freeSpace = int64(usage.Available())
|
||||
m.used = need
|
||||
if m.used > m.freeSpace {
|
||||
return fmt.Errorf("%w, want= %d have= %d", ErrTargetNoSpace, m.used, m.freeSpace)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user