diff --git a/event.go b/event.go index da676cf..314ec6a 100644 --- a/event.go +++ b/event.go @@ -133,14 +133,19 @@ func (event * BaseEvent) LockResources() error { } func (event * BaseEvent) Finish() error { + log.Printf("EVENT_FINISH: %s", event.Name()) for _, resource := range(event.RequiredResources()) { err := resource.Unlock(event) if err != nil { panic(err) } - resource.Update("unlocking after event finish") + resource.NotifyUnlocked() } - return event.DoneResource().Unlock(event) + err := event.DoneResource().Unlock(event) + if err != nil { + return err + } + return event.DoneResource().NotifyUnlocked() } func (event * BaseEvent) LockDone() { @@ -180,10 +185,6 @@ func (event * BaseEvent) Run() error { event.Update(update_str) } - err = event.DoneResource().Unlock(event) - if err != nil { - return err - } return nil } diff --git a/manager.go b/manager.go index 636feb9..d636e14 100644 --- a/manager.go +++ b/manager.go @@ -38,6 +38,7 @@ func NewEventManager(root_event Event, dag_nodes []Resource) * EventManager { // Connect to all resources(in a thread to handle reconnections), and start the first event func (manager * EventManager) Run() error { + log.Printf("MANAGER_START") aborts := []chan error{} for _, resource := range(manager.dag_nodes) { abort := make(chan error, 1) @@ -54,12 +55,23 @@ func (manager * EventManager) Run() error { c <- nil } }(abort, aborts) - err := manager.root_event.Run() + err := manager.root_event.LockResources() + if err != nil { + return err + } + + err = manager.root_event.Run() abort <- nil if err != nil { return err } + err = manager.root_event.Finish() + if err != nil { + return err + } + log.Printf("MANAGER_DONE") + return nil } diff --git a/manager_test.go b/manager_test.go index 45de337..4ac3cae 100644 --- a/manager_test.go +++ b/manager_test.go @@ -9,39 +9,21 @@ import ( type graph_tester testing.T const listner_timeout = 100 * time.Millisecond -func (t * graph_tester) CheckForNil(listener chan error) { +func (t * graph_tester) CheckForValue(listener chan string, str string) { timeout := time.After(listner_timeout) select { - case msg := <-listener: - if msg == nil { - return - } else { - t.Fatal("non-nil message on channel") - } - case <-timeout: - t.Fatal("timeout waiting for message on channel") - } -} - -func (t * graph_tester) CheckForNonNil(listener chan error) { - timeout := time.After(listner_timeout) - select { - case msg := <- listener: - if msg != nil { - return - } else { - t.Fatal("nil message on channel") - } + case <- listener: + return case <-timeout: - t.Fatal("timeout waiting for message on channel") + t.Fatal(str) } } -func (t * graph_tester) CheckForNone(listener chan error) { +func (t * graph_tester) CheckForNone(listener chan string, str string) { timeout := time.After(listner_timeout) select { case <- listener: - t.Fatal("message on channel") + t.Fatal(str) case <-timeout: } } @@ -117,25 +99,25 @@ func TestResourceUpdate(t * testing.T) { r4_l := r4.UpdateChannel() // Calling Update() on the parent with no other parents should only notify node listeners - r3.Update() - (*graph_tester)(t).CheckForNone(r1_l) - (*graph_tester)(t).CheckForNone(r2_l) - (*graph_tester)(t).CheckForNil(r3_l) - (*graph_tester)(t).CheckForNil(r4_l) + r3.Update("test") + (*graph_tester)(t).CheckForNone(r1_l, "Update on r1 after updating r3") + (*graph_tester)(t).CheckForNone(r2_l, "Update on r2 after updating r3") + (*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r3") + (*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r3") // Calling Update() on a child should notify listeners of the parent and child, but not siblings - r2.Update() - (*graph_tester)(t).CheckForNone(r1_l) - (*graph_tester)(t).CheckForNil(r2_l) - (*graph_tester)(t).CheckForNil(r3_l) - (*graph_tester)(t).CheckForNil(r4_l) + r2.Update("test") + (*graph_tester)(t).CheckForNone(r1_l, "Update on r1 after updating r2") + (*graph_tester)(t).CheckForValue(r2_l, "No update on r2 after updating r2") + (*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r2") + (*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r2") // Calling Update() on a child should notify listeners of the parent and child, but not siblings - r1.Update() - (*graph_tester)(t).CheckForNil(r1_l) - (*graph_tester)(t).CheckForNone(r2_l) - (*graph_tester)(t).CheckForNil(r3_l) - (*graph_tester)(t).CheckForNil(r4_l) + r1.Update("test") + (*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after updating r1") + (*graph_tester)(t).CheckForNone(r2_l, "Update on r2 after updating r1") + (*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r1") + (*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r1") } func TestAddEvent(t * testing.T) { @@ -197,8 +179,14 @@ func TestLockResource(t * testing.T) { if err != nil { t.Fatal("Failed to lock r3") } - (*graph_tester)(t).CheckForNil(r1_l) - (*graph_tester)(t).CheckForNil(rel) + + err = r3.NotifyLocked() + if err != nil { + t.Fatal("Failed to notify r3 of lock") + } + + (*graph_tester)(t).CheckForValue(r1_l, "No value on r1 update channel") + (*graph_tester)(t).CheckForValue(rel, "No value on root_event update channel") err = r3.Lock(root_event) if err == nil { @@ -224,22 +212,38 @@ func TestLockResource(t * testing.T) { if err != nil { t.Fatal("Failed to unlock r3") } - (*graph_tester)(t).CheckForNil(r1_l) - (*graph_tester)(t).CheckForNil(rel) + + err = r3.NotifyUnlocked() + if err != nil { + t.Fatal("Failed to notify r3 it was unlocked") + } + + (*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after unlocking r3") + (*graph_tester)(t).CheckForValue(rel, "No update on rel after unlocking r3") err = r4.Lock(root_event) if err != nil { t.Fatal("Failed to lock r4 after unlocking r3") } - (*graph_tester)(t).CheckForNil(r1_l) - (*graph_tester)(t).CheckForNil(rel) + + err = r4.NotifyLocked() + if err != nil { + t.Fatal("Failed to notify r4 it was locked") + } + (*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after locking r4") + (*graph_tester)(t).CheckForValue(rel, "No update on rel after locking r4") err = r4.Unlock(root_event) if err != nil { t.Fatal("Failed to unlock r4") } - (*graph_tester)(t).CheckForNil(r1_l) - (*graph_tester)(t).CheckForNil(rel) + + err = r4.NotifyUnlocked() + if err != nil { + t.Fatal("Failed to notify r4 it was unlocked") + } + (*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after unlocking r4") + (*graph_tester)(t).CheckForValue(rel, "No update on rel after unlocking r4") } func TestAddToEventQueue(t * testing.T) { @@ -270,8 +274,8 @@ func TestStartBaseEvent(t * testing.T) { e_l := event_1.UpdateChannel() r_l := r.UpdateChannel() - (*graph_tester)(t).CheckForNone(e_l) - (*graph_tester)(t).CheckForNone(r_l) + (*graph_tester)(t).CheckForNone(e_l, "Update on event_1 before starting") + (*graph_tester)(t).CheckForNone(r_l, "Update on r_1 before starting") if r.Owner() != event_1 { t.Fatal("r is not owned by event_1") @@ -282,8 +286,8 @@ func TestStartBaseEvent(t * testing.T) { t.Fatal(err) } // Check that the update channels for the event and resource have updates - (*graph_tester)(t).CheckForNil(e_l) - (*graph_tester)(t).CheckForNil(r_l) + (*graph_tester)(t).CheckForValue(e_l, "No update on event_1 after starting") + (*graph_tester)(t).CheckForValue(r_l, "No update on r_l after starting") if r.Owner() != nil { t.Fatal("r still owned after event completed") @@ -342,7 +346,7 @@ func TestStartEventQueue(t * testing.T) { if err != nil { t.Fatal("Failed to add e1 to manager") } - (*graph_tester)(t).CheckForNil(rel) + (*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e1") e2 := NewEvent("1", "", []Resource{res_1}) e2_r := e2.DoneResource() @@ -351,7 +355,7 @@ func TestStartEventQueue(t * testing.T) { if err != nil { t.Fatal("Failed to add e2 to manager") } - (*graph_tester)(t).CheckForNil(rel) + (*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e2") e3 := NewEvent("1", "", []Resource{res_2}) e3_r := e3.DoneResource() @@ -360,7 +364,7 @@ func TestStartEventQueue(t * testing.T) { if err != nil { t.Fatal("Failed to add e3 to manager") } - (*graph_tester)(t).CheckForNil(rel) + (*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e3") e1_l := e1.UpdateChannel(); e2_l := e2.UpdateChannel(); @@ -387,15 +391,15 @@ func TestStartEventQueue(t * testing.T) { if e1_r.Owner() != nil { t.Fatal("e1 was not completed") } - (*graph_tester)(t).CheckForNil(e1_l) + (*graph_tester)(t).CheckForValue(e1_l, "No update on e1 after running") if e2_r.Owner() != nil { t.Fatal("e2 was not completed") } - (*graph_tester)(t).CheckForNil(e2_l) + (*graph_tester)(t).CheckForValue(e2_l, "No update on e2 after running") if e3_r.Owner() != nil { t.Fatal("e3 was not completed") } - (*graph_tester)(t).CheckForNil(e3_l) + (*graph_tester)(t).CheckForValue(e3_l, "No update on e3 after running") } diff --git a/resource.go b/resource.go index 48743e8..8c6b9a1 100644 --- a/resource.go +++ b/resource.go @@ -37,6 +37,7 @@ type Resource interface { Parents() []Resource Lock(event Event) error NotifyLocked() error + NotifyUnlocked() error Unlock(event Event) error Owner() Event Connect(abort chan error) bool @@ -60,6 +61,22 @@ func (resource * BaseResource) Owner() Event { return resource.lock_holder } +func (resource * BaseResource) NotifyUnlocked() error { + err := resource.Update("finalize_unlock") + if err != nil { + return err + } + + for _, child := range(resource.children) { + err = child.NotifyUnlocked() + if err != nil { + return err + } + } + + return nil +} + func (resource * BaseResource) NotifyLocked() error { err := resource.Update("finalize_lock") if err != nil { @@ -73,6 +90,8 @@ func (resource * BaseResource) NotifyLocked() error { } } + resource.lock_holder.Update("finalize_lock") + return nil } diff --git a/vex.go b/vex.go index 6617494..d00649c 100644 --- a/vex.go +++ b/vex.go @@ -200,15 +200,13 @@ func NewMatch(alliance0 * Alliance, alliance1 * Alliance, arena * Arena) * Match match.LockDone() match.actions["start"] = func() (string, error) { - log.Printf("Starting match %s", match.Name()) - log.Printf("%s", match.RequiredResources()[2].Owner().Name()) + log.Printf("STARTING_MATCH %s", match.Name()) match.control = "none" match.state = "scheduled" return "wait", nil } match.actions["queue_autonomous"] = func() (string, error) { - log.Printf("queue_autonomous") match.control = "none" match.state = "autonomous_queued" match.control_start = time.Now().Add(start_slack) @@ -216,7 +214,6 @@ func NewMatch(alliance0 * Alliance, alliance1 * Alliance, arena * Arena) * Match } match.actions["start_autonomous"] = func() (string, error) { - log.Printf("start_autonomous") match.control = "autonomous" match.state = "autonomous_running" return "wait", nil