diff --git a/lockable.go b/lockable.go index 5522ab5..a040eaf 100644 --- a/lockable.go +++ b/lockable.go @@ -111,7 +111,7 @@ func (ext *LockableExt) HandleLinkSignal(ctx *Context, node *Node, source NodeID messages = append(messages, SendMsg{source, NewErrorSignal(signal.ID(), "unknown_action")}) } default: - messages = append(messages, SendMsg{source, NewErrorSignal(signal.ID(), "not_unlocked")}) + messages = append(messages, SendMsg{source, NewErrorSignal(signal.ID(), "not_unlocked: %s", ext.State)}) } return messages, changes @@ -135,7 +135,6 @@ func (ext *LockableExt) HandleUnlockSignal(ctx *Context, node *Node, source Node ext.PendingOwner = nil - ctx.Log.Logf("lockable", "%s transition to Unlocked", node.ID) ext.State = Unlocked messages = append(messages, SendMsg{source, NewSuccessSignal(signal.Id)}) @@ -147,7 +146,6 @@ func (ext *LockableExt) HandleUnlockSignal(ctx *Context, node *Node, source Node ext.ReqID = new(uuid.UUID) *ext.ReqID = signal.Id - ctx.Log.Logf("lockable", "%s transition to Unlocking", node.ID) ext.State = Unlocking for id := range(ext.Requirements) { unlock_signal := NewUnlockSignal() @@ -183,7 +181,6 @@ func (ext *LockableExt) HandleLockSignal(ctx *Context, node *Node, source NodeID ext.PendingOwner = new(NodeID) *ext.PendingOwner = source - ctx.Log.Logf("lockable", "%s transition to Locked", node.ID) ext.State = Locked messages = append(messages, SendMsg{source, NewSuccessSignal(signal.Id)}) } else { @@ -195,7 +192,6 @@ func (ext *LockableExt) HandleLockSignal(ctx *Context, node *Node, source NodeID ext.ReqID = new(uuid.UUID) *ext.ReqID = signal.Id - ctx.Log.Logf("lockable", "%s transition to Locking", node.ID) ext.State = Locking for id := range(ext.Requirements) { lock_signal := NewLockSignal() @@ -207,7 +203,7 @@ func (ext *LockableExt) HandleLockSignal(ctx *Context, node *Node, source NodeID } } default: - messages = append(messages, SendMsg{source, NewErrorSignal(signal.Id, "not_unlocked")}) + messages = append(messages, SendMsg{source, NewErrorSignal(signal.Id, "not_unlocked: %s", ext.State)}) } return messages, changes @@ -225,11 +221,8 @@ func (ext *LockableExt) HandleErrorSignal(ctx *Context, node *Node, source NodeI switch ext.State { case Locking: - changes = append(changes, "state", "pending_owner", "requirements", "req_id") - messages = append(messages, SendMsg{*ext.PendingOwner, NewErrorSignal(*ext.ReqID, signal.Error)}) + changes = append(changes, "state", "requirements") - ext.ReqID = nil - ext.PendingOwner = nil ext.Requirements[id] = Unlocked unlocked := 0 @@ -250,15 +243,19 @@ func (ext *LockableExt) HandleErrorSignal(ctx *Context, node *Node, source NodeI if unlocked == len(ext.Requirements) { changes = append(changes, "owner", "state") - ctx.Log.Logf("lockable", "%s transition to Unlocked", node.ID) ext.State = Unlocked ext.Owner = nil } else { - ctx.Log.Logf("lockable", "%s transition to Unlocking", node.ID) - ext.State = Unlocking + changes = append(changes, "state") + ext.State = AbortingLock } case Unlocking: + unlock_signal := NewUnlockSignal() + ext.Waiting[unlock_signal.Id] = id + messages = append(messages, SendMsg{id, unlock_signal}) + + case AbortingLock: req_state := ext.Requirements[id] // Mark failed lock as Unlocked, or retry unlock switch req_state { @@ -275,7 +272,6 @@ func (ext *LockableExt) HandleErrorSignal(ctx *Context, node *Node, source NodeI if unlocked == len(ext.Requirements) { changes = append(changes, "owner", "state") - ctx.Log.Logf("lockable", "%s transition to Unlocked", node.ID) ext.State = Unlocked ext.Owner = nil } @@ -301,30 +297,19 @@ func (ext *LockableExt) HandleSuccessSignal(ctx *Context, node *Node, source Nod delete(ext.Waiting, signal.ReqID) changes = append(changes, "waiting") - req_state := ext.Requirements[id] - switch req_state { + switch ext.State { case Locking: ext.Requirements[id] = Locked - case Unlocking: - ext.Requirements[id] = Unlocked - } - - locked := 0 - unlocked := 0 - for _, req_state := range(ext.Requirements) { - switch req_state { - case Locked: - locked += 1 - case Unlocked: - unlocked += 1 + locked := 0 + for _, req_state := range(ext.Requirements) { + switch req_state { + case Locked: + locked += 1 + } } - } - switch ext.State { - case Locking: if locked == len(ext.Requirements) { changes = append(changes, "state", "owner", "req_id") - ctx.Log.Logf("lockable", "%s transition to Locked", node.ID) ext.State = Locked ext.Owner = new(NodeID) @@ -333,19 +318,54 @@ func (ext *LockableExt) HandleSuccessSignal(ctx *Context, node *Node, source Nod messages = append(messages, SendMsg{*ext.Owner, NewSuccessSignal(*ext.ReqID)}) ext.ReqID = nil } - case Unlocking: - if unlocked == len(ext.Requirements) { - changes = append(changes, "state", "owner", "req_id") - ctx.Log.Logf("lockable", "%s transition to Unlocked", node.ID) - ext.State = Unlocked + case AbortingLock: + req_state := ext.Requirements[id] + switch req_state { + case Locking: + ext.Requirements[id] = Unlocking + unlock_signal := NewUnlockSignal() + ext.Waiting[unlock_signal.Id] = id + messages = append(messages, SendMsg{id, unlock_signal}) + case Unlocking: + ext.Requirements[id] = Unlocked + + unlocked := 0 + for _, req_state := range(ext.Requirements) { + switch req_state { + case Unlocked: + unlocked += 1 + } + } - if ext.Owner != nil { - messages = append(messages, SendMsg{*ext.Owner, NewSuccessSignal(*ext.ReqID)}) + if unlocked == len(ext.Requirements) { + changes = append(changes, "state", "pending_owner", "req_id") + messages = append(messages, SendMsg{*ext.PendingOwner, NewErrorSignal(*ext.ReqID, "not_unlocked: %s", ext.State)}) + ext.State = Unlocked ext.ReqID = nil - ext.Owner = nil + ext.PendingOwner = nil } } + + + case Unlocking: + ext.Requirements[id] = Unlocked + unlocked := 0 + for _, req_state := range(ext.Requirements) { + switch req_state { + case Unlocked: + unlocked += 1 + } + } + + if unlocked == len(ext.Requirements) { + changes = append(changes, "state", "owner", "req_id") + + messages = append(messages, SendMsg{*ext.Owner, NewSuccessSignal(*ext.ReqID)}) + ext.State = Unlocked + ext.ReqID = nil + ext.Owner = nil + } } } diff --git a/lockable_test.go b/lockable_test.go index ae4d789..8f7728c 100644 --- a/lockable_test.go +++ b/lockable_test.go @@ -79,7 +79,7 @@ func Test1000Lock(t *testing.T) { } func TestLock(t *testing.T) { - ctx := logTestContext(t, []string{"test", "lockable", "signal"}) + ctx := logTestContext(t, []string{"test", "lockable"}) NewLockable := func(reqs []NodeID)(*Node, *ListenerExt) { listener := NewListenerExt(1000) @@ -102,24 +102,28 @@ func TestLock(t *testing.T) { ctx.Log.Logf("test", "l4: %s", l4.ID) ctx.Log.Logf("test", "l5: %s", l5.ID) + ctx.Log.Logf("test", "locking l0") id_1, err := LockLockable(ctx, l0) fatalErr(t, err) response, _, err := WaitForResponse(l0_listener.Chan, time.Millisecond*10, id_1) fatalErr(t, err) ctx.Log.Logf("test", "l0 lock: %+v", response) + ctx.Log.Logf("test", "locking l1") id_2, err := LockLockable(ctx, l1) fatalErr(t, err) - response, _, err = WaitForResponse(l1_listener.Chan, time.Millisecond*10, id_2) + response, _, err = WaitForResponse(l1_listener.Chan, time.Millisecond*1000, id_2) fatalErr(t, err) ctx.Log.Logf("test", "l1 lock: %+v", response) + ctx.Log.Logf("test", "unlocking l0") id_3, err := UnlockLockable(ctx, l0) fatalErr(t, err) response, _, err = WaitForResponse(l0_listener.Chan, time.Millisecond*10, id_3) fatalErr(t, err) ctx.Log.Logf("test", "l0 unlock: %+v", response) + ctx.Log.Logf("test", "locking l1") id_4, err := LockLockable(ctx, l1) fatalErr(t, err) response, _, err = WaitForResponse(l1_listener.Chan, time.Millisecond*10, id_4)