forked from TrueCloudLab/rclone
Implement --low-level-retries flag - fixes #266
This commit is contained in:
parent
3890105cdc
commit
867a26fe4f
5 changed files with 53 additions and 32 deletions
|
@ -363,6 +363,22 @@ Log all of rclone's output to FILE. This is not active by default.
|
||||||
This can be useful for tracking down problems with syncs in
|
This can be useful for tracking down problems with syncs in
|
||||||
combination with the `-v` flag.
|
combination with the `-v` flag.
|
||||||
|
|
||||||
|
### --low-level-retries NUMBER ###
|
||||||
|
|
||||||
|
This controls the number of low level retries rclone does.
|
||||||
|
|
||||||
|
A low level retry is used to retry a failing operation - typically one
|
||||||
|
HTTP request. This might be uploading a chunk of a big file for
|
||||||
|
example. You will see low level retries in the log with the `-v`
|
||||||
|
flag.
|
||||||
|
|
||||||
|
This shouldn't need to be changed from the default in normal
|
||||||
|
operations, however if you get a lot of low level retries you may wish
|
||||||
|
to reduce the value so rclone moves on to a high level retry (see the
|
||||||
|
`--retries` flag) quicker.
|
||||||
|
|
||||||
|
Disable low level retries with `--low-level-retries 1`.
|
||||||
|
|
||||||
### --modify-window=TIME ###
|
### --modify-window=TIME ###
|
||||||
|
|
||||||
When checking whether a file has been modified, this is the maximum
|
When checking whether a file has been modified, this is the maximum
|
||||||
|
|
|
@ -80,6 +80,7 @@ var (
|
||||||
deleteBefore = pflag.BoolP("delete-before", "", false, "When synchronizing, delete files on destination before transfering")
|
deleteBefore = pflag.BoolP("delete-before", "", false, "When synchronizing, delete files on destination before transfering")
|
||||||
deleteDuring = pflag.BoolP("delete-during", "", false, "When synchronizing, delete files during transfer (default)")
|
deleteDuring = pflag.BoolP("delete-during", "", false, "When synchronizing, delete files during transfer (default)")
|
||||||
deleteAfter = pflag.BoolP("delete-after", "", false, "When synchronizing, delete files on destination after transfering")
|
deleteAfter = pflag.BoolP("delete-after", "", false, "When synchronizing, delete files on destination after transfering")
|
||||||
|
lowLevelRetries = pflag.IntP("low-level-retries", "", 10, "Number of low level retries to do.")
|
||||||
bwLimit SizeSuffix
|
bwLimit SizeSuffix
|
||||||
|
|
||||||
// Key to use for password en/decryption.
|
// Key to use for password en/decryption.
|
||||||
|
@ -197,6 +198,7 @@ type ConfigInfo struct {
|
||||||
DeleteBefore bool // Delete before checking
|
DeleteBefore bool // Delete before checking
|
||||||
DeleteDuring bool // Delete during checking/transfer
|
DeleteDuring bool // Delete during checking/transfer
|
||||||
DeleteAfter bool // Delete after successful transfer.
|
DeleteAfter bool // Delete after successful transfer.
|
||||||
|
LowLevelRetries int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transport returns an http.RoundTripper with the correct timeouts
|
// Transport returns an http.RoundTripper with the correct timeouts
|
||||||
|
@ -285,6 +287,7 @@ func LoadConfig() {
|
||||||
Config.DumpHeaders = *dumpHeaders
|
Config.DumpHeaders = *dumpHeaders
|
||||||
Config.DumpBodies = *dumpBodies
|
Config.DumpBodies = *dumpBodies
|
||||||
Config.InsecureSkipVerify = *skipVerify
|
Config.InsecureSkipVerify = *skipVerify
|
||||||
|
Config.LowLevelRetries = *lowLevelRetries
|
||||||
|
|
||||||
ConfigPath = *configFile
|
ConfigPath = *configFile
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ func removeFailedCopy(dst Object) bool {
|
||||||
// call Copy() with dst nil on a pre-existing file then some filing
|
// call Copy() with dst nil on a pre-existing file then some filing
|
||||||
// systems (eg Drive) may duplicate the file.
|
// systems (eg Drive) may duplicate the file.
|
||||||
func Copy(f Fs, dst, src Object) {
|
func Copy(f Fs, dst, src Object) {
|
||||||
const maxTries = 10
|
maxTries := Config.LowLevelRetries
|
||||||
tries := 0
|
tries := 0
|
||||||
doUpdate := dst != nil
|
doUpdate := dst != nil
|
||||||
var err, inErr error
|
var err, inErr error
|
||||||
|
@ -231,7 +231,7 @@ tryAgain:
|
||||||
// Retry if err returned a retry error
|
// Retry if err returned a retry error
|
||||||
if r, ok := err.(Retry); ok && r.Retry() && tries < maxTries {
|
if r, ok := err.(Retry); ok && r.Retry() && tries < maxTries {
|
||||||
tries++
|
tries++
|
||||||
Log(src, "Received error: %v - retrying %d/%d", err, tries, maxTries)
|
Log(src, "Received error: %v - low level retry %d/%d", err, tries, maxTries)
|
||||||
if removeFailedCopy(dst) {
|
if removeFailedCopy(dst) {
|
||||||
// If we removed dst, then nil it out and note we are not updating
|
// If we removed dst, then nil it out and note we are not updating
|
||||||
dst = nil
|
dst = nil
|
||||||
|
|
|
@ -45,6 +45,7 @@ var (
|
||||||
DumpHeaders = flag.Bool("dump-headers", false, "Set to dump headers (needs -verbose)")
|
DumpHeaders = flag.Bool("dump-headers", false, "Set to dump headers (needs -verbose)")
|
||||||
DumpBodies = flag.Bool("dump-bodies", false, "Set to dump bodies (needs -verbose)")
|
DumpBodies = flag.Bool("dump-bodies", false, "Set to dump bodies (needs -verbose)")
|
||||||
Individual = flag.Bool("individual", false, "Make individual bucket/container/directory for each test - much slower")
|
Individual = flag.Bool("individual", false, "Make individual bucket/container/directory for each test - much slower")
|
||||||
|
LowLevelRetries = flag.Int("low-level-retries", 10, "Number of low level retries")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Some times used in the tests
|
// Some times used in the tests
|
||||||
|
@ -103,7 +104,7 @@ func newRun() *Run {
|
||||||
fs.Config.Quiet = !*Verbose
|
fs.Config.Quiet = !*Verbose
|
||||||
fs.Config.DumpHeaders = *DumpHeaders
|
fs.Config.DumpHeaders = *DumpHeaders
|
||||||
fs.Config.DumpBodies = *DumpBodies
|
fs.Config.DumpBodies = *DumpBodies
|
||||||
|
fs.Config.LowLevelRetries = *LowLevelRetries
|
||||||
var err error
|
var err error
|
||||||
r.fremote, r.cleanRemote, err = fstest.RandomRemote(*RemoteName, *SubDir)
|
r.fremote, r.cleanRemote, err = fstest.RandomRemote(*RemoteName, *SubDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -61,7 +61,7 @@ func New() *Pacer {
|
||||||
minSleep: 10 * time.Millisecond,
|
minSleep: 10 * time.Millisecond,
|
||||||
maxSleep: 2 * time.Second,
|
maxSleep: 2 * time.Second,
|
||||||
decayConstant: 2,
|
decayConstant: 2,
|
||||||
retries: 10,
|
retries: fs.Config.LowLevelRetries,
|
||||||
pacer: make(chan struct{}, 1),
|
pacer: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
p.sleepTime = p.minSleep
|
p.sleepTime = p.minSleep
|
||||||
|
@ -231,7 +231,7 @@ func (p *Pacer) acdPacer(retry bool) {
|
||||||
if p.sleepTime < p.minSleep {
|
if p.sleepTime < p.minSleep {
|
||||||
p.sleepTime = p.minSleep
|
p.sleepTime = p.minSleep
|
||||||
}
|
}
|
||||||
fs.Debug("pacer", "Rate limited, sleeping for %v (%d retries)", p.sleepTime, consecutiveRetries)
|
fs.Debug("pacer", "Rate limited, sleeping for %v (%d consecutive low level retries)", p.sleepTime, consecutiveRetries)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,13 +256,14 @@ func (p *Pacer) endCall(retry bool) {
|
||||||
// call implements Call but with settable retries
|
// call implements Call but with settable retries
|
||||||
func (p *Pacer) call(fn Paced, retries int) (err error) {
|
func (p *Pacer) call(fn Paced, retries int) (err error) {
|
||||||
var retry bool
|
var retry bool
|
||||||
for i := 0; i < retries; i++ {
|
for i := 1; i <= retries; i++ {
|
||||||
p.beginCall()
|
p.beginCall()
|
||||||
retry, err = fn()
|
retry, err = fn()
|
||||||
p.endCall(retry)
|
p.endCall(retry)
|
||||||
if !retry {
|
if !retry {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
fs.Debug("pacer", "low level retry %d/%d", i, retries)
|
||||||
}
|
}
|
||||||
if retry {
|
if retry {
|
||||||
err = fs.RetryError(err)
|
err = fs.RetryError(err)
|
||||||
|
|
Loading…
Add table
Reference in a new issue