forked from TrueCloudLab/restic
Update to minio-go 4
This commit is contained in:
parent
0e7e3cb714
commit
934ae1b559
1 changed files with 42 additions and 59 deletions
|
@ -2,8 +2,8 @@ package s3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
@ -248,51 +248,20 @@ func (be *Backend) Path() string {
|
||||||
return be.cfg.Prefix
|
return be.cfg.Prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
// nopCloserFile wraps *os.File and overwrites the Close() method with method
|
// lenForFile returns the length of the file.
|
||||||
// that does nothing. In addition, the method Len() is implemented, which
|
func lenForFile(f *os.File) (int64, error) {
|
||||||
// returns the size of the file (filesize - current offset).
|
|
||||||
type nopCloserFile struct {
|
|
||||||
*os.File
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f nopCloserFile) Close() error {
|
|
||||||
debug.Log("prevented Close()")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the remaining length of the file (filesize - current offset).
|
|
||||||
func (f nopCloserFile) Len() int {
|
|
||||||
debug.Log("Len() called")
|
|
||||||
fi, err := f.Stat()
|
fi, err := f.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return 0, errors.Wrap(err, "Stat")
|
||||||
}
|
}
|
||||||
|
|
||||||
pos, err := f.Seek(0, io.SeekCurrent)
|
pos, err := f.Seek(0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return 0, errors.Wrap(err, "Seek")
|
||||||
}
|
}
|
||||||
|
|
||||||
size := fi.Size() - pos
|
size := fi.Size() - pos
|
||||||
debug.Log("returning file size %v", size)
|
return size, nil
|
||||||
return int(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
type lenner interface {
|
|
||||||
Len() int
|
|
||||||
io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
// nopCloserLenner wraps a lenner and overwrites the Close() method with method
|
|
||||||
// that does nothing. In addition, the method Size() is implemented, which
|
|
||||||
// returns the size of the file (filesize - current offset).
|
|
||||||
type nopCloserLenner struct {
|
|
||||||
lenner
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *nopCloserLenner) Close() error {
|
|
||||||
debug.Log("prevented Close()")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save stores data in the backend at the handle.
|
// Save stores data in the backend at the handle.
|
||||||
|
@ -309,26 +278,33 @@ func (be *Backend) Save(ctx context.Context, h restic.Handle, rd io.Reader) (err
|
||||||
defer be.sem.ReleaseToken()
|
defer be.sem.ReleaseToken()
|
||||||
|
|
||||||
// Check key does not already exist
|
// Check key does not already exist
|
||||||
_, err = be.client.StatObject(be.cfg.Bucket, objName)
|
_, err = be.client.StatObject(be.cfg.Bucket, objName, minio.StatObjectOptions{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
debug.Log("%v already exists", h)
|
debug.Log("%v already exists", h)
|
||||||
return errors.New("key already exists")
|
return errors.New("key already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This is a workaround once we move to minio-go 4.0.x this can be
|
var size int64 = -1
|
||||||
// removed and size can be directly provided.
|
|
||||||
if f, ok := rd.(*os.File); ok {
|
type lenner interface {
|
||||||
debug.Log("reader is %#T, using nopCloserFile{}", rd)
|
Len() int
|
||||||
rd = nopCloserFile{f}
|
|
||||||
} else if l, ok := rd.(lenner); ok {
|
|
||||||
debug.Log("reader is %#T, using nopCloserLenner{}", rd)
|
|
||||||
rd = nopCloserLenner{l}
|
|
||||||
} else {
|
|
||||||
debug.Log("reader is %#T, no specific workaround enabled", rd)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log("PutObject(%v, %v)", be.cfg.Bucket, objName)
|
// find size for reader
|
||||||
n, err := be.client.PutObject(be.cfg.Bucket, objName, rd, "application/octet-stream")
|
if f, ok := rd.(*os.File); ok {
|
||||||
|
size, err = lenForFile(f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if l, ok := rd.(lenner); ok {
|
||||||
|
size = int64(l.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := minio.PutObjectOptions{}
|
||||||
|
opts.ContentType = "application/octet-stream"
|
||||||
|
|
||||||
|
debug.Log("PutObject(%v, %v, %v)", be.cfg.Bucket, objName, size)
|
||||||
|
n, err := be.client.PutObject(be.cfg.Bucket, objName, ioutil.NopCloser(rd), size, opts)
|
||||||
|
|
||||||
debug.Log("%v -> %v bytes, err %#v: %v", objName, n, err, err)
|
debug.Log("%v -> %v bytes, err %#v: %v", objName, n, err, err)
|
||||||
|
|
||||||
|
@ -365,19 +341,24 @@ func (be *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
|
||||||
}
|
}
|
||||||
|
|
||||||
objName := be.Filename(h)
|
objName := be.Filename(h)
|
||||||
|
opts := minio.GetObjectOptions{}
|
||||||
|
|
||||||
byteRange := fmt.Sprintf("bytes=%d-", offset)
|
var err error
|
||||||
if length > 0 {
|
if length > 0 {
|
||||||
byteRange = fmt.Sprintf("bytes=%d-%d", offset, offset+int64(length)-1)
|
debug.Log("range: %v-%v", offset, offset+int64(length)-1)
|
||||||
|
err = opts.SetRange(offset, offset+int64(length)-1)
|
||||||
|
} else if offset > 0 {
|
||||||
|
debug.Log("range: %v-", offset)
|
||||||
|
err = opts.SetRange(offset, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "SetRange")
|
||||||
}
|
}
|
||||||
headers := minio.NewGetReqHeaders()
|
|
||||||
headers.Add("Range", byteRange)
|
|
||||||
|
|
||||||
be.sem.GetToken()
|
be.sem.GetToken()
|
||||||
debug.Log("Load(%v) send range %v", h, byteRange)
|
|
||||||
|
|
||||||
coreClient := minio.Core{Client: be.client}
|
coreClient := minio.Core{Client: be.client}
|
||||||
rd, _, err := coreClient.GetObject(be.cfg.Bucket, objName, headers)
|
rd, _, err := coreClient.GetObject(be.cfg.Bucket, objName, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
be.sem.ReleaseToken()
|
be.sem.ReleaseToken()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -401,8 +382,10 @@ func (be *Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInf
|
||||||
objName := be.Filename(h)
|
objName := be.Filename(h)
|
||||||
var obj *minio.Object
|
var obj *minio.Object
|
||||||
|
|
||||||
|
opts := minio.GetObjectOptions{}
|
||||||
|
|
||||||
be.sem.GetToken()
|
be.sem.GetToken()
|
||||||
obj, err = be.client.GetObject(be.cfg.Bucket, objName)
|
obj, err = be.client.GetObject(be.cfg.Bucket, objName, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("GetObject() err %v", err)
|
debug.Log("GetObject() err %v", err)
|
||||||
be.sem.ReleaseToken()
|
be.sem.ReleaseToken()
|
||||||
|
@ -433,7 +416,7 @@ func (be *Backend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
||||||
objName := be.Filename(h)
|
objName := be.Filename(h)
|
||||||
|
|
||||||
be.sem.GetToken()
|
be.sem.GetToken()
|
||||||
_, err := be.client.StatObject(be.cfg.Bucket, objName)
|
_, err := be.client.StatObject(be.cfg.Bucket, objName, minio.StatObjectOptions{})
|
||||||
be.sem.ReleaseToken()
|
be.sem.ReleaseToken()
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
Loading…
Reference in a new issue