mirror of
https://github.com/rclone/rclone.git
synced 2024-11-24 01:14:30 +01:00
16d91246c4
Because there is a period of time between checking a directory needs creating and creating it, the leads to errors where directories are attempting to be created twice. Add locking on a per directory basis to fix while doing mkdir.
52 lines
988 B
Go
52 lines
988 B
Go
package sftp
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/ncw/rclone/fs"
|
|
)
|
|
|
|
// stringLock locks for string IDs passed in
|
|
type stringLock struct {
|
|
mu sync.Mutex // mutex to protect below
|
|
locks map[string]chan struct{} // map of locks
|
|
}
|
|
|
|
// newStringLock creates a stringLock
|
|
func newStringLock() *stringLock {
|
|
return &stringLock{
|
|
locks: make(map[string]chan struct{}),
|
|
}
|
|
}
|
|
|
|
// Lock locks on the id passed in
|
|
func (l *stringLock) Lock(ID string) {
|
|
l.mu.Lock()
|
|
for {
|
|
ch, ok := l.locks[ID]
|
|
if !ok {
|
|
break
|
|
}
|
|
// Wait for the channel to be closed
|
|
l.mu.Unlock()
|
|
fs.Log(nil, "Waiting for stringLock on %q", ID)
|
|
<-ch
|
|
l.mu.Lock()
|
|
}
|
|
l.locks[ID] = make(chan struct{})
|
|
l.mu.Unlock()
|
|
}
|
|
|
|
// Unlock unlocks on the id passed in. Will panic if Lock with the
|
|
// given id wasn't called first.
|
|
func (l *stringLock) Unlock(ID string) {
|
|
l.mu.Lock()
|
|
ch, ok := l.locks[ID]
|
|
if !ok {
|
|
panic("stringLock: Unlock before Lock")
|
|
}
|
|
close(ch)
|
|
delete(l.locks, ID)
|
|
l.mu.Unlock()
|
|
}
|