45 lines
996 B
Go
45 lines
996 B
Go
package agent
|
|
|
|
import (
|
|
"path/filepath"
|
|
"sync"
|
|
)
|
|
|
|
// Recovery and result-journal instances share a root but are constructed by
|
|
// different call/recovery paths. Locks exist only while a path is in use; they
|
|
// are not a permanent identity history and do not serialize independent files.
|
|
type privateStateLock struct {
|
|
mu sync.Mutex
|
|
users int
|
|
}
|
|
|
|
var privateStateLocks = struct {
|
|
sync.Mutex
|
|
paths map[string]*privateStateLock
|
|
}{paths: make(map[string]*privateStateLock)}
|
|
|
|
func holdPrivateState(path string) (func(), error) {
|
|
key, err := filepath.Abs(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
privateStateLocks.Lock()
|
|
lock := privateStateLocks.paths[key]
|
|
if lock == nil {
|
|
lock = &privateStateLock{}
|
|
privateStateLocks.paths[key] = lock
|
|
}
|
|
lock.users++
|
|
privateStateLocks.Unlock()
|
|
lock.mu.Lock()
|
|
return func() {
|
|
lock.mu.Unlock()
|
|
privateStateLocks.Lock()
|
|
lock.users--
|
|
if lock.users == 0 {
|
|
delete(privateStateLocks.paths, key)
|
|
}
|
|
privateStateLocks.Unlock()
|
|
}, nil
|
|
}
|