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:
parent
46049b4236
commit
aa5bc39311
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user