lib: More contextification (#6343)
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -29,19 +30,45 @@ func newByteSemaphore(max int) *byteSemaphore {
|
||||
return &s
|
||||
}
|
||||
|
||||
func (s *byteSemaphore) takeWithContext(ctx context.Context, bytes int) error {
|
||||
done := make(chan struct{})
|
||||
var err error
|
||||
go func() {
|
||||
err = s.takeInner(ctx, bytes)
|
||||
close(done)
|
||||
}()
|
||||
select {
|
||||
case <-done:
|
||||
case <-ctx.Done():
|
||||
s.cond.Broadcast()
|
||||
<-done
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *byteSemaphore) take(bytes int) {
|
||||
_ = s.takeInner(context.Background(), bytes)
|
||||
}
|
||||
|
||||
func (s *byteSemaphore) takeInner(ctx context.Context, bytes int) error {
|
||||
s.mut.Lock()
|
||||
defer s.mut.Unlock()
|
||||
if bytes > s.max {
|
||||
bytes = s.max
|
||||
}
|
||||
for bytes > s.available {
|
||||
s.cond.Wait()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
if bytes > s.max {
|
||||
bytes = s.max
|
||||
}
|
||||
}
|
||||
s.available -= bytes
|
||||
s.mut.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *byteSemaphore) give(bytes int) {
|
||||
|
||||
+6
-2
@@ -301,7 +301,9 @@ func (f *folder) pull() bool {
|
||||
f.setState(FolderSyncWaiting)
|
||||
defer f.setState(FolderIdle)
|
||||
|
||||
f.ioLimiter.take(1)
|
||||
if err := f.ioLimiter.takeWithContext(f.ctx, 1); err != nil {
|
||||
return true
|
||||
}
|
||||
defer f.ioLimiter.give(1)
|
||||
|
||||
return f.puller.pull()
|
||||
@@ -340,7 +342,9 @@ func (f *folder) scanSubdirs(subDirs []string) error {
|
||||
f.setError(nil)
|
||||
f.setState(FolderScanWaiting)
|
||||
|
||||
f.ioLimiter.take(1)
|
||||
if err := f.ioLimiter.takeWithContext(f.ctx, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.ioLimiter.give(1)
|
||||
|
||||
for i := range subDirs {
|
||||
|
||||
@@ -1392,7 +1392,10 @@ func (f *sendReceiveFolder) pullerRoutine(in <-chan pullBlockState, out chan<- *
|
||||
state := state
|
||||
bytes := int(state.block.Size)
|
||||
|
||||
requestLimiter.take(bytes)
|
||||
if err := requestLimiter.takeWithContext(f.ctx, bytes); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -3211,6 +3211,9 @@ func TestParentOfUnignored(t *testing.T) {
|
||||
// restarts would leave more than one folder runner alive.
|
||||
func TestFolderRestartZombies(t *testing.T) {
|
||||
wrapper := createTmpWrapper(defaultCfg.Copy())
|
||||
opts := wrapper.Options()
|
||||
opts.RawMaxFolderConcurrency = -1
|
||||
wrapper.SetOptions(opts)
|
||||
folderCfg, _ := wrapper.Folder("default")
|
||||
folderCfg.FilesystemType = fs.FilesystemTypeFake
|
||||
wrapper.SetFolder(folderCfg)
|
||||
|
||||
Reference in New Issue
Block a user