diff --git a/go.mod b/go.mod index 2a7f950..26f18c6 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/asticode/go-astikit v0.8.0 github.com/asticode/go-astilectron v0.16.0 github.com/asticode/go-astilectron-bootstrap v0.4.1 + github.com/avast/retry-go v2.6.1+incompatible github.com/boltdb/bolt v1.3.1 github.com/go-openapi/strfmt v0.19.2 // indirect github.com/jedib0t/go-pretty v4.3.0+incompatible diff --git a/go.sum b/go.sum index d1f0ebd..28fac46 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,8 @@ github.com/asticode/go-astilectron-bundler v0.7.0 h1:P5Ot4loRUMSgHMEkH+DIQ0adKvE github.com/asticode/go-astilectron-bundler v0.7.0/go.mod h1:dHgXoS/SzrIcMIqzH9rhiWbZjUvjj4HNfUg+7sLeV1Q= github.com/asticode/go-bindata v1.0.0 h1:5whO0unjdx2kbAbzoBMS3307jKAEf3oQ1lJcx5RdgA8= github.com/asticode/go-bindata v1.0.0/go.mod h1:t/Y+/iCLrvaYkv8Y6PscRnyUeYzy9y9+8JC9CMcKdHY= +github.com/avast/retry-go v2.6.1+incompatible h1:quvLI98pOPWtTq7xnbX4TI5l9PmRJooM2AI1T7mOFUA= +github.com/avast/retry-go v2.6.1+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/switchfs/splitFileReader.go b/switchfs/splitFileReader.go index e4b8f43..8cdc864 100644 --- a/switchfs/splitFileReader.go +++ b/switchfs/splitFileReader.go @@ -2,6 +2,7 @@ package switchfs import ( "errors" + "github.com/avast/retry-go" "io" "io/ioutil" "os" @@ -22,6 +23,38 @@ type splitFile struct { chunkSize int64 } +type fileWrapper struct { + file ReadAtCloser + path string +} + +func NewFileWrapper(filePath string) (*fileWrapper, error) { + result := fileWrapper{} + result.path = filePath + file, err := _openFile(filePath) + if err != nil { + return nil, err + } + result.file = file + return &result, nil +} + +func (sp *fileWrapper) ReadAt(p []byte, off int64) (n int, err error) { + if sp.file != nil { + return sp.file.ReadAt(p, off) + } + return 0, errors.New("file is not opened") +} + +func (sp *fileWrapper) Close() error { + + if sp.file != nil { + return sp.file.Close() + } + + return nil +} + func NewSplitFileReader(filePath string) (*splitFile, error) { result := splitFile{} index := strings.LastIndex(filePath, string(os.PathSeparator)) @@ -51,7 +84,7 @@ func (sp *splitFile) ReadAt(p []byte, off int64) (n int, err error) { } if len(sp.files) == 0 || sp.files[part] == nil { - file, _ := os.Open(path.Join(sp.path, sp.info[part].Name())) + file, _ := _openFile(path.Join(sp.path, sp.info[part].Name())) sp.files[part] = file } off = off - sp.chunkSize*int64(part) @@ -62,6 +95,19 @@ func (sp *splitFile) ReadAt(p []byte, off int64) (n int, err error) { return sp.files[part].ReadAt(p, off) } +func _openFile(path string) (*os.File, error) { + var file *os.File + var err error + retry.Attempts(5) + err = retry.Do( + func() error { + file, err = os.Open(path) + return err + }, + ) + return file, err +} + func (sp *splitFile) Close() error { for _, file := range sp.files { if file != nil { @@ -76,6 +122,6 @@ func OpenFile(filePath string) (ReadAtCloser, error) { if _, err := strconv.Atoi(filePath[len(filePath)-1:]); err == nil { return NewSplitFileReader(filePath) } else { - return os.Open(filePath) + return NewFileWrapper(filePath) } }