From 5010e95c231eaa7471de16baa23a3476e701d72a Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 6 Jun 2017 00:17:21 +0200 Subject: [PATCH 1/5] Add error handling to semaphore --- src/restic/backend/b2/b2.go | 14 ++++++++++++-- src/restic/backend/b2/config.go | 2 +- src/restic/backend/semaphore.go | 9 +++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/restic/backend/b2/b2.go b/src/restic/backend/b2/b2.go index c209c13ab..8fe18bcd9 100644 --- a/src/restic/backend/b2/b2.go +++ b/src/restic/backend/b2/b2.go @@ -50,6 +50,11 @@ func Open(cfg Config) (restic.Backend, error) { return nil, errors.Wrap(err, "Bucket") } + sem, err := backend.NewSemaphore(cfg.Connections) + if err != nil { + return nil, err + } + be := &b2Backend{ client: client, bucket: bucket, @@ -58,7 +63,7 @@ func Open(cfg Config) (restic.Backend, error) { Join: path.Join, Path: cfg.Prefix, }, - sem: backend.NewSemaphore(cfg.Connections), + sem: sem, } return be, nil @@ -85,6 +90,11 @@ func Create(cfg Config) (restic.Backend, error) { return nil, errors.Wrap(err, "NewBucket") } + sem, err := backend.NewSemaphore(cfg.Connections) + if err != nil { + return nil, err + } + be := &b2Backend{ client: client, bucket: bucket, @@ -93,7 +103,7 @@ func Create(cfg Config) (restic.Backend, error) { Join: path.Join, Path: cfg.Prefix, }, - sem: backend.NewSemaphore(cfg.Connections), + sem: sem, } present, err := be.Test(restic.Handle{Type: restic.ConfigFile}) diff --git a/src/restic/backend/b2/config.go b/src/restic/backend/b2/config.go index 221e4ff02..922605636 100644 --- a/src/restic/backend/b2/config.go +++ b/src/restic/backend/b2/config.go @@ -17,7 +17,7 @@ type Config struct { Bucket string Prefix string - Connections int `option:"connections" help:"set a limit for the number of concurrent connections (default: 5)"` + Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 5)"` } // NewConfig returns a new config with default options applied. diff --git a/src/restic/backend/semaphore.go b/src/restic/backend/semaphore.go index dbbd72966..4bb1ad3ab 100644 --- a/src/restic/backend/semaphore.go +++ b/src/restic/backend/semaphore.go @@ -1,15 +1,20 @@ package backend +import "restic/errors" + // Semaphore limits access to a restricted resource. type Semaphore struct { ch chan struct{} } // NewSemaphore returns a new semaphore with capacity n. -func NewSemaphore(n int) *Semaphore { +func NewSemaphore(n uint) (*Semaphore, error) { + if n <= 0 { + return nil, errors.New("must be a positive number") + } return &Semaphore{ ch: make(chan struct{}, n), - } + }, nil } // GetToken blocks until a Token is available. From 683ebef6c658efd09eee3896edab09a50068f8bc Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 6 Jun 2017 00:17:39 +0200 Subject: [PATCH 2/5] s3: Use semaphore --- src/restic/backend/s3/config.go | 21 ++++-- src/restic/backend/s3/config_test.go | 106 +++++++++++++++------------ src/restic/backend/s3/s3.go | 35 ++++----- src/restic/backend/s3/s3_test.go | 15 ++-- 4 files changed, 96 insertions(+), 81 deletions(-) diff --git a/src/restic/backend/s3/config.go b/src/restic/backend/s3/config.go index 6cf7db9c1..3ae6038ab 100644 --- a/src/restic/backend/s3/config.go +++ b/src/restic/backend/s3/config.go @@ -18,6 +18,15 @@ type Config struct { Bucket string Prefix string Layout string `option:"layout" help:"use this backend layout (default: auto-detect)"` + + Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 20)"` +} + +// NewConfig returns a new Config with the default values filled in. +func NewConfig() Config { + return Config{ + Connections: 20, + } } func init() { @@ -70,10 +79,10 @@ func createConfig(endpoint string, p []string, useHTTP bool) (interface{}, error default: prefix = path.Clean(p[1]) } - return Config{ - Endpoint: endpoint, - UseHTTP: useHTTP, - Bucket: p[0], - Prefix: prefix, - }, nil + cfg := NewConfig() + cfg.Endpoint = endpoint + cfg.UseHTTP = useHTTP + cfg.Bucket = p[0] + cfg.Prefix = prefix + return cfg, nil } diff --git a/src/restic/backend/s3/config_test.go b/src/restic/backend/s3/config_test.go index 3a04d59a2..67611f3cc 100644 --- a/src/restic/backend/s3/config_test.go +++ b/src/restic/backend/s3/config_test.go @@ -7,78 +7,92 @@ var configTests = []struct { cfg Config }{ {"s3://eu-central-1/bucketname", Config{ - Endpoint: "eu-central-1", - Bucket: "bucketname", - Prefix: "restic", + Endpoint: "eu-central-1", + Bucket: "bucketname", + Prefix: "restic", + Connections: 20, }}, {"s3://eu-central-1/bucketname/", Config{ - Endpoint: "eu-central-1", - Bucket: "bucketname", - Prefix: "restic", + Endpoint: "eu-central-1", + Bucket: "bucketname", + Prefix: "restic", + Connections: 20, }}, {"s3://eu-central-1/bucketname/prefix/directory", Config{ - Endpoint: "eu-central-1", - Bucket: "bucketname", - Prefix: "prefix/directory", + Endpoint: "eu-central-1", + Bucket: "bucketname", + Prefix: "prefix/directory", + Connections: 20, }}, {"s3://eu-central-1/bucketname/prefix/directory/", Config{ - Endpoint: "eu-central-1", - Bucket: "bucketname", - Prefix: "prefix/directory", + Endpoint: "eu-central-1", + Bucket: "bucketname", + Prefix: "prefix/directory", + Connections: 20, }}, {"s3:eu-central-1/foobar", Config{ - Endpoint: "eu-central-1", - Bucket: "foobar", - Prefix: "restic", + Endpoint: "eu-central-1", + Bucket: "foobar", + Prefix: "restic", + Connections: 20, }}, {"s3:eu-central-1/foobar/", Config{ - Endpoint: "eu-central-1", - Bucket: "foobar", - Prefix: "restic", + Endpoint: "eu-central-1", + Bucket: "foobar", + Prefix: "restic", + Connections: 20, }}, {"s3:eu-central-1/foobar/prefix/directory", Config{ - Endpoint: "eu-central-1", - Bucket: "foobar", - Prefix: "prefix/directory", + Endpoint: "eu-central-1", + Bucket: "foobar", + Prefix: "prefix/directory", + Connections: 20, }}, {"s3:eu-central-1/foobar/prefix/directory/", Config{ - Endpoint: "eu-central-1", - Bucket: "foobar", - Prefix: "prefix/directory", + Endpoint: "eu-central-1", + Bucket: "foobar", + Prefix: "prefix/directory", + Connections: 20, }}, {"s3:https://hostname:9999/foobar", Config{ - Endpoint: "hostname:9999", - Bucket: "foobar", - Prefix: "restic", + Endpoint: "hostname:9999", + Bucket: "foobar", + Prefix: "restic", + Connections: 20, }}, {"s3:https://hostname:9999/foobar/", Config{ - Endpoint: "hostname:9999", - Bucket: "foobar", - Prefix: "restic", + Endpoint: "hostname:9999", + Bucket: "foobar", + Prefix: "restic", + Connections: 20, }}, {"s3:http://hostname:9999/foobar", Config{ - Endpoint: "hostname:9999", - Bucket: "foobar", - Prefix: "restic", - UseHTTP: true, + Endpoint: "hostname:9999", + Bucket: "foobar", + Prefix: "restic", + UseHTTP: true, + Connections: 20, }}, {"s3:http://hostname:9999/foobar/", Config{ - Endpoint: "hostname:9999", - Bucket: "foobar", - Prefix: "restic", - UseHTTP: true, + Endpoint: "hostname:9999", + Bucket: "foobar", + Prefix: "restic", + UseHTTP: true, + Connections: 20, }}, {"s3:http://hostname:9999/bucket/prefix/directory", Config{ - Endpoint: "hostname:9999", - Bucket: "bucket", - Prefix: "prefix/directory", - UseHTTP: true, + Endpoint: "hostname:9999", + Bucket: "bucket", + Prefix: "prefix/directory", + UseHTTP: true, + Connections: 20, }}, {"s3:http://hostname:9999/bucket/prefix/directory/", Config{ - Endpoint: "hostname:9999", - Bucket: "bucket", - Prefix: "prefix/directory", - UseHTTP: true, + Endpoint: "hostname:9999", + Bucket: "bucket", + Prefix: "prefix/directory", + UseHTTP: true, + Connections: 20, }}, } diff --git a/src/restic/backend/s3/s3.go b/src/restic/backend/s3/s3.go index 960258392..93b476b86 100644 --- a/src/restic/backend/s3/s3.go +++ b/src/restic/backend/s3/s3.go @@ -23,7 +23,7 @@ const connLimit = 10 // s3 is a backend which stores the data on an S3 endpoint. type s3 struct { client *minio.Client - connChan chan struct{} + sem *backend.Semaphore bucketname string prefix string cacheMutex sync.RWMutex @@ -43,8 +43,14 @@ func Open(cfg Config) (restic.Backend, error) { return nil, errors.Wrap(err, "minio.New") } + sem, err := backend.NewSemaphore(cfg.Connections) + if err != nil { + return nil, err + } + be := &s3{ client: client, + sem: sem, bucketname: cfg.Bucket, prefix: cfg.Prefix, cacheObjSize: make(map[string]int64), @@ -59,8 +65,6 @@ func Open(cfg Config) (restic.Backend, error) { be.Layout = l - be.createConnections() - found, err := client.BucketExists(cfg.Bucket) if err != nil { debug.Log("BucketExists(%v) returned err %v", cfg.Bucket, err) @@ -78,13 +82,6 @@ func Open(cfg Config) (restic.Backend, error) { return be, nil } -func (be *s3) createConnections() { - be.connChan = make(chan struct{}, connLimit) - for i := 0; i < connLimit; i++ { - be.connChan <- struct{}{} - } -} - // IsNotExist returns true if the error is caused by a not existing file. func (be *s3) IsNotExist(err error) bool { debug.Log("IsNotExist(%T, %#v)", err, err) @@ -222,7 +219,7 @@ func (be *s3) Save(h restic.Handle, rd io.Reader) (err error) { return errors.New("key already exists") } - <-be.connChan + be.sem.GetToken() // wrap the reader so that net/http client cannot close the reader, return // the token instead. @@ -234,11 +231,10 @@ func (be *s3) Save(h restic.Handle, rd io.Reader) (err error) { } debug.Log("PutObject(%v, %v)", be.bucketname, objName) - coreClient := minio.Core{be.client} + coreClient := minio.Core{Client: be.client} info, err := coreClient.PutObject(be.bucketname, objName, size, rd, nil, nil, nil) - // return token - be.connChan <- struct{}{} + be.sem.ReleaseToken() debug.Log("%v -> %v bytes, err %#v", objName, info.Size, err) return errors.Wrap(err, "client.PutObject") @@ -275,8 +271,7 @@ func (be *s3) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, er objName := be.Filename(h) - // get token for connection - <-be.connChan + be.sem.GetToken() byteRange := fmt.Sprintf("bytes=%d-", offset) if length > 0 { @@ -286,11 +281,10 @@ func (be *s3) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, er headers.Add("Range", byteRange) debug.Log("Load(%v) send range %v", h, byteRange) - coreClient := minio.Core{be.client} + coreClient := minio.Core{Client: be.client} rd, _, err := coreClient.GetObject(be.bucketname, objName, headers) if err != nil { - // return token - be.connChan <- struct{}{} + be.sem.ReleaseToken() return nil, err } @@ -298,8 +292,7 @@ func (be *s3) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, er ReadCloser: rd, f: func() { debug.Log("Close()") - // return token - be.connChan <- struct{}{} + be.sem.ReleaseToken() }, } diff --git a/src/restic/backend/s3/s3_test.go b/src/restic/backend/s3/s3_test.go index 787166994..ea453cf13 100644 --- a/src/restic/backend/s3/s3_test.go +++ b/src/restic/backend/s3/s3_test.go @@ -114,14 +114,13 @@ func newMinioTestSuite(ctx context.Context, t testing.TB) *test.Suite { key, secret := newRandomCredentials(t) cfg.stopServer = runMinio(ctx, t, cfg.tempdir, key, secret) - cfg.Config = s3.Config{ - Endpoint: "localhost:9000", - Bucket: "restictestbucket", - Prefix: fmt.Sprintf("test-%d", time.Now().UnixNano()), - UseHTTP: true, - KeyID: key, - Secret: secret, - } + cfg.Config = s3.NewConfig() + cfg.Config.Endpoint = "localhost:9000" + cfg.Config.Bucket = "restictestbucket" + cfg.Config.Prefix = fmt.Sprintf("test-%d", time.Now().UnixNano()) + cfg.Config.UseHTTP = true + cfg.Config.KeyID = key + cfg.Config.Secret = secret return cfg, nil }, From 46049b423645c0943747ac179d322e1f48bc9a2e Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 6 Jun 2017 00:25:22 +0200 Subject: [PATCH 3/5] rest: Use semaphore --- src/restic/backend/rest/config.go | 18 +++++++++-- src/restic/backend/rest/config_test.go | 3 +- src/restic/backend/rest/rest.go | 44 +++++++++++++------------- src/restic/backend/rest/rest_test.go | 5 ++- 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/restic/backend/rest/config.go b/src/restic/backend/rest/config.go index 929fda120..e1ad4e726 100644 --- a/src/restic/backend/rest/config.go +++ b/src/restic/backend/rest/config.go @@ -5,11 +5,24 @@ import ( "strings" "restic/errors" + "restic/options" ) // Config contains all configuration necessary to connect to a REST server. type Config struct { - URL *url.URL + URL *url.URL + Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 20)"` +} + +func init() { + options.Register("rest", Config{}) +} + +// NewConfig returns a new Config with the default values filled in. +func NewConfig() Config { + return Config{ + Connections: 20, + } } // ParseConfig parses the string s and extracts the REST server URL. @@ -25,6 +38,7 @@ func ParseConfig(s string) (interface{}, error) { return nil, errors.Wrap(err, "url.Parse") } - cfg := Config{URL: u} + cfg := NewConfig() + cfg.URL = u return cfg, nil } diff --git a/src/restic/backend/rest/config_test.go b/src/restic/backend/rest/config_test.go index 937204a57..0f27d1c09 100644 --- a/src/restic/backend/rest/config_test.go +++ b/src/restic/backend/rest/config_test.go @@ -20,7 +20,8 @@ var configTests = []struct { cfg Config }{ {"rest:http://localhost:1234", Config{ - URL: parseURL("http://localhost:1234"), + URL: parseURL("http://localhost:1234"), + Connections: 20, }}, } diff --git a/src/restic/backend/rest/rest.go b/src/restic/backend/rest/rest.go index cb3fdadc8..852b9ce1a 100644 --- a/src/restic/backend/rest/rest.go +++ b/src/restic/backend/rest/rest.go @@ -23,21 +23,21 @@ const connLimit = 40 var _ restic.Backend = &restBackend{} type restBackend struct { - url *url.URL - connChan chan struct{} - client http.Client + url *url.URL + sem *backend.Semaphore + client http.Client backend.Layout } // Open opens the REST backend with the given config. func Open(cfg Config) (restic.Backend, error) { - connChan := make(chan struct{}, connLimit) - for i := 0; i < connLimit; i++ { - connChan <- struct{}{} - } - client := http.Client{Transport: backend.Transport()} + sem, err := backend.NewSemaphore(cfg.Connections) + if err != nil { + return nil, err + } + // use url without trailing slash for layout url := cfg.URL.String() if url[len(url)-1] == '/' { @@ -45,10 +45,10 @@ func Open(cfg Config) (restic.Backend, error) { } be := &restBackend{ - url: cfg.URL, - connChan: connChan, - client: client, - Layout: &backend.RESTLayout{URL: url, Join: path.Join}, + url: cfg.URL, + client: client, + Layout: &backend.RESTLayout{URL: url, Join: path.Join}, + sem: sem, } return be, nil @@ -108,9 +108,9 @@ func (b *restBackend) Save(h restic.Handle, rd io.Reader) (err error) { // backend.Closer, which has a noop method. rd = backend.Closer{Reader: rd} - <-b.connChan + b.sem.GetToken() resp, err := b.client.Post(b.Filename(h), "binary/octet-stream", rd) - b.connChan <- struct{}{} + b.sem.ReleaseToken() if resp != nil { defer func() { @@ -163,9 +163,9 @@ func (b *restBackend) Load(h restic.Handle, length int, offset int64) (io.ReadCl req.Header.Add("Range", byteRange) debug.Log("Load(%v) send range %v", h, byteRange) - <-b.connChan + b.sem.GetToken() resp, err := b.client.Do(req) - b.connChan <- struct{}{} + b.sem.ReleaseToken() if err != nil { if resp != nil { @@ -190,9 +190,9 @@ func (b *restBackend) Stat(h restic.Handle) (restic.FileInfo, error) { return restic.FileInfo{}, err } - <-b.connChan + b.sem.GetToken() resp, err := b.client.Head(b.Filename(h)) - b.connChan <- struct{}{} + b.sem.ReleaseToken() if err != nil { return restic.FileInfo{}, errors.Wrap(err, "client.Head") } @@ -237,9 +237,9 @@ func (b *restBackend) Remove(h restic.Handle) error { if err != nil { return errors.Wrap(err, "http.NewRequest") } - <-b.connChan + b.sem.GetToken() resp, err := b.client.Do(req) - b.connChan <- struct{}{} + b.sem.ReleaseToken() if err != nil { return errors.Wrap(err, "client.Do") @@ -264,9 +264,9 @@ func (b *restBackend) List(t restic.FileType, done <-chan struct{}) <-chan strin url += "/" } - <-b.connChan + b.sem.GetToken() resp, err := b.client.Get(url) - b.connChan <- struct{}{} + b.sem.ReleaseToken() if resp != nil { defer func() { diff --git a/src/restic/backend/rest/rest_test.go b/src/restic/backend/rest/rest_test.go index d951eea05..d8a7afbe3 100644 --- a/src/restic/backend/rest/rest_test.go +++ b/src/restic/backend/rest/rest_test.go @@ -76,9 +76,8 @@ func newTestSuite(ctx context.Context, t testing.TB) *test.Suite { t.Fatal(err) } - cfg := rest.Config{ - URL: url, - } + cfg := rest.NewConfig() + cfg.URL = url return cfg, nil }, From aa5bc39311442b39d5695ea167465d8665e85722 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 6 Jun 2017 00:33:25 +0200 Subject: [PATCH 4/5] swift: Use semaphore --- src/restic/backend/swift/config.go | 21 +++++++++++++++++---- src/restic/backend/swift/config_test.go | 25 ++++++++++++++++++++++--- src/restic/backend/swift/swift.go | 24 +++++++++++------------- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/src/restic/backend/swift/config.go b/src/restic/backend/swift/config.go index 78765e56d..6ef2d4d6f 100644 --- a/src/restic/backend/swift/config.go +++ b/src/restic/backend/swift/config.go @@ -3,6 +3,7 @@ package swift import ( "os" "restic/errors" + "restic/options" "strings" ) @@ -24,6 +25,19 @@ type Config struct { Container string Prefix string DefaultContainerPolicy string + + Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 20)"` +} + +func init() { + options.Register("swift", Config{}) +} + +// NewConfig returns a new config with the default values filled in. +func NewConfig() Config { + return Config{ + Connections: 20, + } } // ParseConfig parses the string s and extract swift's container name and prefix. @@ -47,10 +61,9 @@ func ParseConfig(s string) (interface{}, error) { } prefix = prefix[1:] - cfg := Config{ - Container: container, - Prefix: prefix, - } + cfg := NewConfig() + cfg.Container = container + cfg.Prefix = prefix return cfg, nil } diff --git a/src/restic/backend/swift/config_test.go b/src/restic/backend/swift/config_test.go index bd087bd47..2c1f4c4aa 100644 --- a/src/restic/backend/swift/config_test.go +++ b/src/restic/backend/swift/config_test.go @@ -6,9 +6,28 @@ var configTests = []struct { s string cfg Config }{ - {"swift:cnt1:/", Config{Container: "cnt1", Prefix: ""}}, - {"swift:cnt2:/prefix", Config{Container: "cnt2", Prefix: "prefix"}}, - {"swift:cnt3:/prefix/longer", Config{Container: "cnt3", Prefix: "prefix/longer"}}, + { + "swift:cnt1:/", + Config{ + Container: "cnt1", + Prefix: "", + Connections: 20, + }, + }, + { + "swift:cnt2:/prefix", + Config{Container: "cnt2", + Prefix: "prefix", + Connections: 20, + }, + }, + { + "swift:cnt3:/prefix/longer", + Config{Container: "cnt3", + Prefix: "prefix/longer", + Connections: 20, + }, + }, } func TestParseConfig(t *testing.T) { diff --git a/src/restic/backend/swift/swift.go b/src/restic/backend/swift/swift.go index 733dc3221..9c459f03d 100644 --- a/src/restic/backend/swift/swift.go +++ b/src/restic/backend/swift/swift.go @@ -21,7 +21,7 @@ const connLimit = 10 // beSwift is a backend which stores the data on a swift endpoint. type beSwift struct { conn *swift.Connection - connChan chan struct{} + sem *backend.Semaphore container string // Container name prefix string // Prefix of object names in the container backend.Layout @@ -32,6 +32,11 @@ type beSwift struct { func Open(cfg Config) (restic.Backend, error) { debug.Log("config %#v", cfg) + sem, err := backend.NewSemaphore(cfg.Connections) + if err != nil { + return nil, err + } + be := &beSwift{ conn: &swift.Connection{ UserName: cfg.UserName, @@ -50,6 +55,7 @@ func Open(cfg Config) (restic.Backend, error) { Transport: backend.Transport(), }, + sem: sem, container: cfg.Container, prefix: cfg.Prefix, Layout: &backend.DefaultLayout{ @@ -57,7 +63,6 @@ func Open(cfg Config) (restic.Backend, error) { Join: path.Join, }, } - be.createConnections() // Authenticate if needed if !be.conn.Authenticated() { @@ -94,13 +99,6 @@ func Open(cfg Config) (restic.Backend, error) { return be, nil } -func (be *beSwift) createConnections() { - be.connChan = make(chan struct{}, connLimit) - for i := 0; i < connLimit; i++ { - be.connChan <- struct{}{} - } -} - func (be *beSwift) createContainer(policy string) error { var h swift.Headers if policy != "" { @@ -136,9 +134,9 @@ func (be *beSwift) Load(h restic.Handle, length int, offset int64) (io.ReadClose objName := be.Filename(h) - <-be.connChan + be.sem.GetToken() defer func() { - be.connChan <- struct{}{} + be.sem.ReleaseToken() }() headers := swift.Headers{} @@ -186,9 +184,9 @@ func (be *beSwift) Save(h restic.Handle, rd io.Reader) (err error) { return errors.Wrap(err, "conn.Object") } - <-be.connChan + be.sem.GetToken() defer func() { - be.connChan <- struct{}{} + be.sem.ReleaseToken() }() encoding := "binary/octet-stream" From 48c1e7b00debb29a52b8aa39d09a649595f000d0 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 6 Jun 2017 21:12:38 +0200 Subject: [PATCH 5/5] Fix location tests --- src/restic/backend/location/location_test.go | 71 +++++++++++--------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/restic/backend/location/location_test.go b/src/restic/backend/location/location_test.go index 46bb6b187..09e45cecd 100644 --- a/src/restic/backend/location/location_test.go +++ b/src/restic/backend/location/location_test.go @@ -120,9 +120,10 @@ var parseTests = []struct { "s3://eu-central-1/bucketname", Location{Scheme: "s3", Config: s3.Config{ - Endpoint: "eu-central-1", - Bucket: "bucketname", - Prefix: "restic", + Endpoint: "eu-central-1", + Bucket: "bucketname", + Prefix: "restic", + Connections: 20, }, }, }, @@ -130,9 +131,10 @@ var parseTests = []struct { "s3://hostname.foo/bucketname", Location{Scheme: "s3", Config: s3.Config{ - Endpoint: "hostname.foo", - Bucket: "bucketname", - Prefix: "restic", + Endpoint: "hostname.foo", + Bucket: "bucketname", + Prefix: "restic", + Connections: 20, }, }, }, @@ -140,9 +142,10 @@ var parseTests = []struct { "s3://hostname.foo/bucketname/prefix/directory", Location{Scheme: "s3", Config: s3.Config{ - Endpoint: "hostname.foo", - Bucket: "bucketname", - Prefix: "prefix/directory", + Endpoint: "hostname.foo", + Bucket: "bucketname", + Prefix: "prefix/directory", + Connections: 20, }, }, }, @@ -150,9 +153,10 @@ var parseTests = []struct { "s3:eu-central-1/repo", Location{Scheme: "s3", Config: s3.Config{ - Endpoint: "eu-central-1", - Bucket: "repo", - Prefix: "restic", + Endpoint: "eu-central-1", + Bucket: "repo", + Prefix: "restic", + Connections: 20, }, }, }, @@ -160,9 +164,10 @@ var parseTests = []struct { "s3:eu-central-1/repo/prefix/directory", Location{Scheme: "s3", Config: s3.Config{ - Endpoint: "eu-central-1", - Bucket: "repo", - Prefix: "prefix/directory", + Endpoint: "eu-central-1", + Bucket: "repo", + Prefix: "prefix/directory", + Connections: 20, }, }, }, @@ -170,9 +175,10 @@ var parseTests = []struct { "s3:https://hostname.foo/repo", Location{Scheme: "s3", Config: s3.Config{ - Endpoint: "hostname.foo", - Bucket: "repo", - Prefix: "restic", + Endpoint: "hostname.foo", + Bucket: "repo", + Prefix: "restic", + Connections: 20, }, }, }, @@ -180,9 +186,10 @@ var parseTests = []struct { "s3:https://hostname.foo/repo/prefix/directory", Location{Scheme: "s3", Config: s3.Config{ - Endpoint: "hostname.foo", - Bucket: "repo", - Prefix: "prefix/directory", + Endpoint: "hostname.foo", + Bucket: "repo", + Prefix: "prefix/directory", + Connections: 20, }, }, }, @@ -190,10 +197,11 @@ var parseTests = []struct { "s3:http://hostname.foo/repo", Location{Scheme: "s3", Config: s3.Config{ - Endpoint: "hostname.foo", - Bucket: "repo", - Prefix: "restic", - UseHTTP: true, + Endpoint: "hostname.foo", + Bucket: "repo", + Prefix: "restic", + UseHTTP: true, + Connections: 20, }, }, }, @@ -201,8 +209,9 @@ var parseTests = []struct { "swift:container17:/", Location{Scheme: "swift", Config: swift.Config{ - Container: "container17", - Prefix: "", + Container: "container17", + Prefix: "", + Connections: 20, }, }, }, @@ -210,8 +219,9 @@ var parseTests = []struct { "swift:container17:/prefix97", Location{Scheme: "swift", Config: swift.Config{ - Container: "container17", - Prefix: "prefix97", + Container: "container17", + Prefix: "prefix97", + Connections: 20, }, }, }, @@ -219,7 +229,8 @@ var parseTests = []struct { "rest:http://hostname.foo:1234/", Location{Scheme: "rest", Config: rest.Config{ - URL: parseURL("http://hostname.foo:1234/"), + URL: parseURL("http://hostname.foo:1234/"), + Connections: 20, }, }, },