mirror of
https://github.com/samuelncui/acp.git
synced 2026-01-05 10:54:52 +00:00
feat: add error mapping
This commit is contained in:
45
copy.go
45
copy.go
@@ -10,7 +10,6 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
@@ -24,9 +23,6 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
sha256Pool = &sync.Pool{New: func() interface{} { return sha256.New() }}
|
sha256Pool = &sync.Pool{New: func() interface{} { return sha256.New() }}
|
||||||
|
|
||||||
ErrTargetNoSpace = fmt.Errorf("acp: target have no space")
|
|
||||||
ErrTargetDropToReadonly = fmt.Errorf("acp: target droped into readonly")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Copyer) copy(ctx context.Context, prepared <-chan *writeJob) <-chan *baseJob {
|
func (c *Copyer) copy(ctx context.Context, prepared <-chan *writeJob) <-chan *baseJob {
|
||||||
@@ -126,37 +122,14 @@ func (c *Copyer) write(ctx context.Context, job *writeJob, ch chan<- *baseJob, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(path.Dir(target), os.ModePerm); err != nil {
|
if err := os.MkdirAll(path.Dir(target), os.ModePerm); err != nil {
|
||||||
// if no space
|
job.fail(target, fmt.Errorf("mkdir dst dir fail, %w", mappingError(err)))
|
||||||
if errors.Is(err, syscall.ENOSPC) {
|
|
||||||
noSpaceDevices.Add(dev)
|
|
||||||
job.fail(target, fmt.Errorf("%w, mkdir dst dir fail", ErrTargetNoSpace))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if errors.Is(err, syscall.EROFS) {
|
|
||||||
noSpaceDevices.Add(dev)
|
|
||||||
job.fail(target, fmt.Errorf("%w, mkdir dst dir fail", ErrTargetDropToReadonly))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
job.fail(target, fmt.Errorf("mkdir dst dir fail, %w", err))
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.OpenFile(target, c.createFlag, job.mode)
|
file, err := os.OpenFile(target, c.createFlag, job.mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// if no space
|
// if no space
|
||||||
if errors.Is(err, syscall.ENOSPC) {
|
job.fail(target, fmt.Errorf("open dst file fail, %w", mappingError(err)))
|
||||||
noSpaceDevices.Add(dev)
|
|
||||||
job.fail(target, fmt.Errorf("%w, open dst file fail", ErrTargetNoSpace))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if errors.Is(err, syscall.EROFS) {
|
|
||||||
noSpaceDevices.Add(dev)
|
|
||||||
job.fail(target, fmt.Errorf("%w, open dst file fail", ErrTargetDropToReadonly))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
job.fail(target, fmt.Errorf("open dst file fail, %w", err))
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,19 +155,7 @@ func (c *Copyer) write(ctx context.Context, job *writeJob, ch chan<- *baseJob, c
|
|||||||
c.reportError(job.path, target, fmt.Errorf("delete failed file has error, %w", err))
|
c.reportError(job.path, target, fmt.Errorf("delete failed file has error, %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no space
|
job.fail(target, fmt.Errorf("write dst file fail, %w", mappingError(rerr)))
|
||||||
if errors.Is(rerr, syscall.ENOSPC) {
|
|
||||||
noSpaceDevices.Add(dev)
|
|
||||||
job.fail(target, fmt.Errorf("%w, write dst file fail", ErrTargetNoSpace))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if errors.Is(rerr, syscall.EROFS) {
|
|
||||||
noSpaceDevices.Add(dev)
|
|
||||||
job.fail(target, fmt.Errorf("%w, write dst file fail", ErrTargetDropToReadonly))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
job.fail(target, fmt.Errorf("write dst file fail, %w", rerr))
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package acp
|
package acp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/samuelncui/godf"
|
"github.com/samuelncui/godf"
|
||||||
)
|
)
|
||||||
@@ -11,6 +13,22 @@ const (
|
|||||||
defaultDiskUsageFreshInterval = 1024 * 1024 * 1024 * 2
|
defaultDiskUsageFreshInterval = 1024 * 1024 * 1024 * 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrTargetNoSpace = fmt.Errorf("acp: target have no space")
|
||||||
|
ErrTargetDropToReadonly = fmt.Errorf("acp: target droped into readonly")
|
||||||
|
|
||||||
|
errorMapping = []errorPair{
|
||||||
|
{from: syscall.ENOSPC, to: ErrTargetNoSpace},
|
||||||
|
{from: syscall.EROFS, to: ErrTargetDropToReadonly},
|
||||||
|
{from: syscall.EIO, to: ErrTargetDropToReadonly},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type errorPair struct {
|
||||||
|
from error
|
||||||
|
to error
|
||||||
|
}
|
||||||
|
|
||||||
type diskUsageCache struct {
|
type diskUsageCache struct {
|
||||||
mountPoint string
|
mountPoint string
|
||||||
freshInterval int64
|
freshInterval int64
|
||||||
@@ -49,3 +67,17 @@ func (m *diskUsageCache) check(need int64) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mappingError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range errorMapping {
|
||||||
|
if errors.Is(err, p.from) {
|
||||||
|
return fmt.Errorf("%w: %w", p.to, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user