2020-07-30 18:48:48 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/golang/glog"
|
|
|
|
)
|
|
|
|
|
|
|
|
type lockCtrl struct {
|
|
|
|
getCurrent *lockCtrlGetCurrent
|
|
|
|
take *lockCtrlTake
|
|
|
|
release *lockCtrlRelease
|
|
|
|
subscribe *lockCtrlSubscribe
|
|
|
|
bump *lockCtrlBump
|
|
|
|
}
|
|
|
|
|
|
|
|
type lockCtrlGetCurrent struct {
|
|
|
|
res chan *lockResCurrent
|
|
|
|
}
|
|
|
|
|
|
|
|
type lockCtrlTake struct {
|
|
|
|
note string
|
|
|
|
addr string
|
|
|
|
prev string
|
|
|
|
res chan bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type lockCtrlRelease struct {
|
|
|
|
addr string
|
|
|
|
force bool
|
|
|
|
res chan struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
type lockCtrlSubscribe struct {
|
|
|
|
subscriber chan *lockUpdate
|
|
|
|
}
|
|
|
|
|
|
|
|
type lockCtrlBump struct {
|
|
|
|
addr string
|
|
|
|
}
|
|
|
|
|
|
|
|
type lockResCurrent struct {
|
|
|
|
note string
|
|
|
|
addr string
|
|
|
|
deadline time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
type lockUpdate struct {
|
|
|
|
note string
|
|
|
|
addr string
|
|
|
|
}
|
|
|
|
|
2020-08-27 21:56:29 +00:00
|
|
|
func (s *service) runLocker(ctx context.Context, ctrlC chan *lockCtrl, ownershipDuration time.Duration) {
|
2020-07-30 18:48:48 +00:00
|
|
|
glog.Infof("Locker starting...")
|
|
|
|
|
|
|
|
var curNote string
|
|
|
|
var curAddr string
|
|
|
|
var curDeadline time.Time
|
|
|
|
var subscribers []chan *lockUpdate
|
|
|
|
|
|
|
|
notify := func() {
|
|
|
|
for _, sub := range subscribers {
|
|
|
|
go func() {
|
|
|
|
sub <- &lockUpdate{
|
|
|
|
note: curNote,
|
|
|
|
addr: curAddr,
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t := time.NewTicker(5 * time.Second)
|
|
|
|
defer t.Stop()
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
err := ctx.Err()
|
|
|
|
glog.Errorf("Locker stoppped: %v", err)
|
|
|
|
return
|
|
|
|
case <-t.C:
|
|
|
|
if curAddr != "" && time.Now().After(curDeadline) {
|
|
|
|
glog.Infof("Expiring lock")
|
|
|
|
curAddr = ""
|
|
|
|
curNote = ""
|
|
|
|
notify()
|
|
|
|
}
|
|
|
|
case ctrl := <-ctrlC:
|
|
|
|
switch {
|
|
|
|
case ctrl.take != nil:
|
|
|
|
won := false
|
|
|
|
if curAddr == ctrl.take.prev {
|
|
|
|
won = true
|
|
|
|
curNote = ctrl.take.note
|
|
|
|
curAddr = ctrl.take.addr
|
2020-08-27 21:56:29 +00:00
|
|
|
curDeadline = time.Now().Add(ownershipDuration)
|
2020-07-30 18:48:48 +00:00
|
|
|
notify()
|
|
|
|
glog.Infof("Lock taken by %q %q", curNote, curAddr)
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
ctrl.take.res <- won
|
|
|
|
}()
|
|
|
|
case ctrl.release != nil:
|
|
|
|
if curAddr == ctrl.release.addr || ctrl.release.force {
|
|
|
|
curAddr = ""
|
|
|
|
curNote = ""
|
|
|
|
notify()
|
|
|
|
glog.Infof("Lock relased")
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
ctrl.release.res <- struct{}{}
|
|
|
|
}()
|
|
|
|
case ctrl.getCurrent != nil:
|
|
|
|
go func() {
|
|
|
|
ctrl.getCurrent.res <- &lockResCurrent{
|
|
|
|
note: curNote,
|
|
|
|
addr: curAddr,
|
|
|
|
deadline: curDeadline,
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
case ctrl.bump != nil:
|
|
|
|
if curAddr != "" {
|
2020-08-27 21:56:29 +00:00
|
|
|
curDeadline = time.Now().Add(ownershipDuration)
|
2020-07-30 18:48:48 +00:00
|
|
|
}
|
|
|
|
case ctrl.subscribe != nil:
|
|
|
|
subscribers = append(subscribers, ctrl.subscribe.subscriber)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|