2
2
mirror of https://github.com/octoleo/restic.git synced 2024-12-23 11:28:54 +00:00

swift: Use semaphore

This commit is contained in:
Alexander Neumann 2017-06-06 00:33:25 +02:00
parent 46049b4236
commit aa5bc39311
3 changed files with 50 additions and 20 deletions

View File

@ -3,6 +3,7 @@ package swift
import ( import (
"os" "os"
"restic/errors" "restic/errors"
"restic/options"
"strings" "strings"
) )
@ -24,6 +25,19 @@ type Config struct {
Container string Container string
Prefix string Prefix string
DefaultContainerPolicy 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. // 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:] prefix = prefix[1:]
cfg := Config{ cfg := NewConfig()
Container: container, cfg.Container = container
Prefix: prefix, cfg.Prefix = prefix
}
return cfg, nil return cfg, nil
} }

View File

@ -6,9 +6,28 @@ var configTests = []struct {
s string s string
cfg Config cfg Config
}{ }{
{"swift:cnt1:/", Config{Container: "cnt1", Prefix: ""}}, {
{"swift:cnt2:/prefix", Config{Container: "cnt2", Prefix: "prefix"}}, "swift:cnt1:/",
{"swift:cnt3:/prefix/longer", Config{Container: "cnt3", Prefix: "prefix/longer"}}, 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) { func TestParseConfig(t *testing.T) {

View File

@ -21,7 +21,7 @@ const connLimit = 10
// beSwift is a backend which stores the data on a swift endpoint. // beSwift is a backend which stores the data on a swift endpoint.
type beSwift struct { type beSwift struct {
conn *swift.Connection conn *swift.Connection
connChan chan struct{} sem *backend.Semaphore
container string // Container name container string // Container name
prefix string // Prefix of object names in the container prefix string // Prefix of object names in the container
backend.Layout backend.Layout
@ -32,6 +32,11 @@ type beSwift struct {
func Open(cfg Config) (restic.Backend, error) { func Open(cfg Config) (restic.Backend, error) {
debug.Log("config %#v", cfg) debug.Log("config %#v", cfg)
sem, err := backend.NewSemaphore(cfg.Connections)
if err != nil {
return nil, err
}
be := &beSwift{ be := &beSwift{
conn: &swift.Connection{ conn: &swift.Connection{
UserName: cfg.UserName, UserName: cfg.UserName,
@ -50,6 +55,7 @@ func Open(cfg Config) (restic.Backend, error) {
Transport: backend.Transport(), Transport: backend.Transport(),
}, },
sem: sem,
container: cfg.Container, container: cfg.Container,
prefix: cfg.Prefix, prefix: cfg.Prefix,
Layout: &backend.DefaultLayout{ Layout: &backend.DefaultLayout{
@ -57,7 +63,6 @@ func Open(cfg Config) (restic.Backend, error) {
Join: path.Join, Join: path.Join,
}, },
} }
be.createConnections()
// Authenticate if needed // Authenticate if needed
if !be.conn.Authenticated() { if !be.conn.Authenticated() {
@ -94,13 +99,6 @@ func Open(cfg Config) (restic.Backend, error) {
return be, nil 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 { func (be *beSwift) createContainer(policy string) error {
var h swift.Headers var h swift.Headers
if policy != "" { if policy != "" {
@ -136,9 +134,9 @@ func (be *beSwift) Load(h restic.Handle, length int, offset int64) (io.ReadClose
objName := be.Filename(h) objName := be.Filename(h)
<-be.connChan be.sem.GetToken()
defer func() { defer func() {
be.connChan <- struct{}{} be.sem.ReleaseToken()
}() }()
headers := swift.Headers{} 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") return errors.Wrap(err, "conn.Object")
} }
<-be.connChan be.sem.GetToken()
defer func() { defer func() {
be.connChan <- struct{}{} be.sem.ReleaseToken()
}() }()
encoding := "binary/octet-stream" encoding := "binary/octet-stream"