Add job queue (fixes #629)
Request to terminate currently ongoing downloads and jump to the bumped file incoming in 3, 2, 1. Also, has a slightly strange effect where we pop a job off the queue, but the copyChannel is still busy and blocks, though it gets moved to the progress slice in the jobqueue, and looks like it's in progress which it isn't as it's waiting to be picked up from the copyChan. As a result, the progress emitter doesn't register on the task, and hence the file doesn't have a progress bar, but cannot be replaced by a bump. I guess I can fix progress bar issue by moving the progressEmiter.Register just before passing the file to the copyChan, but then we are back to the initial problem of a file with a progress bar, but no progress happening as it's stuck on write to copyChan I checked if there is a way to check for channel writeability (before popping) but got struck by lightning just for bringing the idea up in #go-nuts. My ideal scenario would be to check if copyChan is writeable, pop job from the queue and shove it down handleFile. This way jobs would stay in the queue while they cannot be handled, meaning that the `Bump` could bring your file up higher.
This commit is contained in:
committed by
Jakob Borg
parent
e94bd90782
commit
fd0a147ae6
@@ -78,6 +78,7 @@ type Puller struct {
|
||||
copiers int
|
||||
pullers int
|
||||
finishers int
|
||||
queue *JobQueue
|
||||
}
|
||||
|
||||
// Serve will run scans and pulls. It will return when Stop()ed or on a
|
||||
@@ -89,6 +90,7 @@ func (p *Puller) Serve() {
|
||||
}
|
||||
|
||||
p.stop = make(chan struct{})
|
||||
p.queue = NewJobQueue()
|
||||
|
||||
pullTimer := time.NewTimer(checkPullIntv)
|
||||
scanTimer := time.NewTimer(time.Millisecond) // The first scan should be done immediately.
|
||||
@@ -337,15 +339,22 @@ func (p *Puller) pullerIteration(checksum bool, ignores *ignore.Matcher) int {
|
||||
p.handleDir(file)
|
||||
default:
|
||||
// A new or changed file or symlink. This is the only case where we
|
||||
// do stuff in the background; the other three are done
|
||||
// synchronously.
|
||||
p.handleFile(file, copyChan, finisherChan)
|
||||
// do stuff concurrently in the background
|
||||
p.queue.Push(&file)
|
||||
}
|
||||
|
||||
changed++
|
||||
return true
|
||||
})
|
||||
|
||||
for {
|
||||
f := p.queue.Pop()
|
||||
if f == nil {
|
||||
break
|
||||
}
|
||||
p.handleFile(*f, copyChan, finisherChan)
|
||||
}
|
||||
|
||||
// Signal copy and puller routines that we are done with the in data for
|
||||
// this iteration. Wait for them to finish.
|
||||
close(copyChan)
|
||||
@@ -483,6 +492,7 @@ func (p *Puller) handleFile(file protocol.FileInfo, copyChan chan<- copyBlocksSt
|
||||
if debug {
|
||||
l.Debugln(p, "taking shortcut on", file.Name)
|
||||
}
|
||||
p.queue.Done(&file)
|
||||
if file.IsSymlink() {
|
||||
p.shortcutSymlink(curFile, file)
|
||||
} else {
|
||||
@@ -850,6 +860,7 @@ func (p *Puller) finisherRoutine(in <-chan *sharedPullerState) {
|
||||
continue
|
||||
}
|
||||
|
||||
p.queue.Done(&state.file)
|
||||
p.performFinish(state)
|
||||
p.model.receivedFile(p.folder, state.file.Name)
|
||||
if p.progressEmitter != nil {
|
||||
@@ -859,6 +870,32 @@ func (p *Puller) finisherRoutine(in <-chan *sharedPullerState) {
|
||||
}
|
||||
}
|
||||
|
||||
// Moves the given filename to the front of the job queue
|
||||
func (p *Puller) Bump(filename string) {
|
||||
p.queue.Bump(filename)
|
||||
}
|
||||
|
||||
func (p *Puller) Jobs() ([]protocol.FileInfoTruncated, []protocol.FileInfoTruncated) {
|
||||
return p.queue.Jobs()
|
||||
}
|
||||
|
||||
// clean deletes orphaned temporary files
|
||||
func (p *Puller) clean() {
|
||||
keep := time.Duration(p.model.cfg.Options().KeepTemporariesH) * time.Hour
|
||||
now := time.Now()
|
||||
filepath.Walk(p.dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.Mode().IsRegular() && defTempNamer.IsTemporary(path) && info.ModTime().Add(keep).Before(now) {
|
||||
os.Remove(path)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func invalidateFolder(cfg *config.Configuration, folderID string, err error) {
|
||||
for i := range cfg.Folders {
|
||||
folder := &cfg.Folders[i]
|
||||
|
||||
Reference in New Issue
Block a user