2023-05-29 19:17:52 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
type EventManager struct {
|
2023-05-31 00:37:51 -06:00
|
|
|
dag_nodes map[string]Resource
|
2023-05-29 19:17:52 -06:00
|
|
|
root_event Event
|
2023-06-02 17:31:29 -06:00
|
|
|
aborts []chan error
|
2023-05-29 19:17:52 -06:00
|
|
|
}
|
|
|
|
|
2023-05-30 20:45:16 -06:00
|
|
|
// root_event's requirements must be in dag_nodes, and dag_nodes must be ordered by dependency(children first)
|
2023-05-29 19:17:52 -06:00
|
|
|
func NewEventManager(root_event Event, dag_nodes []Resource) * EventManager {
|
|
|
|
|
|
|
|
manager := &EventManager{
|
2023-05-31 00:37:51 -06:00
|
|
|
dag_nodes: map[string]Resource{},
|
2023-05-29 19:17:52 -06:00
|
|
|
root_event: nil,
|
2023-06-02 17:31:29 -06:00
|
|
|
aborts: []chan error{},
|
2023-05-29 19:17:52 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Construct the DAG
|
|
|
|
for _, resource := range dag_nodes {
|
|
|
|
err := manager.AddResource(resource)
|
|
|
|
if err != nil {
|
2023-06-04 13:18:10 -06:00
|
|
|
log.Logf("manager", "Failed to add %s to EventManager: %s", resource.Name(), err)
|
2023-05-29 19:17:52 -06:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-30 21:50:59 -06:00
|
|
|
err := manager.AddEvent(nil, root_event, nil)
|
|
|
|
if err != nil {
|
2023-06-04 13:18:10 -06:00
|
|
|
log.Logf("manager", "Failed to add %s to EventManager as root_event: %s", root_event.Name(), err)
|
2023-05-30 21:50:59 -06:00
|
|
|
}
|
2023-05-29 19:17:52 -06:00
|
|
|
|
|
|
|
return manager;
|
|
|
|
}
|
|
|
|
|
2023-06-01 13:11:32 -06:00
|
|
|
// Connect to all resources(in a thread to handle reconnections), and start the first event
|
2023-05-29 23:54:52 -06:00
|
|
|
func (manager * EventManager) Run() error {
|
2023-06-04 13:18:10 -06:00
|
|
|
log.Logf("manager", "MANAGER_START")
|
2023-06-01 13:11:32 -06:00
|
|
|
|
|
|
|
abort := make(chan error, 1)
|
2023-06-02 17:31:29 -06:00
|
|
|
go func(abort chan error, manager * EventManager) {
|
2023-06-01 13:11:32 -06:00
|
|
|
<- abort
|
2023-06-02 17:31:29 -06:00
|
|
|
for _, c := range(manager.aborts) {
|
2023-06-01 13:11:32 -06:00
|
|
|
c <- nil
|
|
|
|
}
|
2023-06-02 17:31:29 -06:00
|
|
|
}(abort, manager)
|
2023-06-01 22:42:47 -06:00
|
|
|
|
2023-06-02 17:31:29 -06:00
|
|
|
err := LockResources(manager.root_event)
|
2023-06-01 13:48:38 -06:00
|
|
|
if err != nil {
|
2023-06-04 13:18:10 -06:00
|
|
|
log.Logf("manager", "MANAGER_LOCK_ERR: %s", err)
|
2023-06-01 22:42:47 -06:00
|
|
|
abort <- nil
|
2023-06-01 13:48:38 -06:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-02 17:31:29 -06:00
|
|
|
err = RunEvent(manager.root_event)
|
2023-06-01 13:11:32 -06:00
|
|
|
abort <- nil
|
|
|
|
if err != nil {
|
2023-06-04 13:18:10 -06:00
|
|
|
log.Logf("manager", "MANAGER_RUN_ERR: %s", err)
|
2023-06-01 13:11:32 -06:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-02 17:31:29 -06:00
|
|
|
err = FinishEvent(manager.root_event)
|
2023-06-01 13:48:38 -06:00
|
|
|
if err != nil {
|
2023-06-04 13:18:10 -06:00
|
|
|
log.Logf("manager", "MANAGER_FINISH_ERR: %s", err)
|
2023-06-01 13:48:38 -06:00
|
|
|
return err
|
|
|
|
}
|
2023-06-04 13:18:10 -06:00
|
|
|
log.Logf("manager", "MANAGER_DONE")
|
2023-06-01 13:48:38 -06:00
|
|
|
|
2023-06-01 13:11:32 -06:00
|
|
|
return nil
|
2023-05-29 19:17:52 -06:00
|
|
|
}
|
|
|
|
|
2023-05-31 00:37:51 -06:00
|
|
|
func (manager * EventManager) FindResource(id string) Resource {
|
2023-05-29 19:17:52 -06:00
|
|
|
resource, exists := manager.dag_nodes[id]
|
|
|
|
if exists == false {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return resource
|
|
|
|
}
|
|
|
|
|
2023-05-31 00:37:51 -06:00
|
|
|
func (manager * EventManager) FindEvent(id string) Event {
|
2023-06-02 17:31:29 -06:00
|
|
|
event := FindChild(manager.root_event, id)
|
2023-05-29 19:17:52 -06:00
|
|
|
|
|
|
|
return event
|
|
|
|
}
|
|
|
|
|
|
|
|
func (manager * EventManager) AddResource(resource Resource) error {
|
2023-06-04 13:18:10 -06:00
|
|
|
log.Logf("manager", "Adding resource %s", resource.Name())
|
2023-05-29 19:17:52 -06:00
|
|
|
_, exists := manager.dag_nodes[resource.ID()]
|
|
|
|
if exists == true {
|
2023-05-30 21:50:59 -06:00
|
|
|
error_str := fmt.Sprintf("%s is already in the resource DAG, cannot add again", resource.Name())
|
2023-05-29 19:17:52 -06:00
|
|
|
return errors.New(error_str)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, child := range resource.Children() {
|
|
|
|
_, exists := manager.dag_nodes[child.ID()]
|
|
|
|
if exists == false {
|
2023-05-30 21:50:59 -06:00
|
|
|
error_str := fmt.Sprintf("%s is not in the resource DAG, cannot add %s to DAG", child.Name(), resource.Name())
|
2023-05-29 19:17:52 -06:00
|
|
|
return errors.New(error_str)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
manager.dag_nodes[resource.ID()] = resource
|
2023-06-02 17:31:29 -06:00
|
|
|
abort := make(chan error, 1)
|
|
|
|
abort_used := resource.Connect(abort)
|
|
|
|
if abort_used == true {
|
|
|
|
manager.aborts = append(manager.aborts, abort)
|
|
|
|
}
|
2023-05-29 19:17:52 -06:00
|
|
|
for _, child := range resource.Children() {
|
2023-06-02 17:31:29 -06:00
|
|
|
AddParent(child, resource)
|
2023-05-29 19:17:52 -06:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that the node doesn't already exist in the tree
|
|
|
|
// Check the the selected parent exists in the tree
|
|
|
|
// Check that required resources exist in the DAG
|
|
|
|
// Check that created resources don't exist in the DAG
|
|
|
|
// Add resources created by the event to the DAG
|
|
|
|
// Add child to parent
|
|
|
|
func (manager * EventManager) AddEvent(parent Event, child Event, info EventInfo) error {
|
|
|
|
if child == nil {
|
|
|
|
return errors.New("Cannot add nil Event to EventManager")
|
|
|
|
} else if len(child.Children()) != 0 {
|
|
|
|
return errors.New("Adding events recursively not implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, resource := range child.RequiredResources() {
|
|
|
|
_, exists := manager.dag_nodes[resource.ID()]
|
|
|
|
if exists == false {
|
|
|
|
error_str := fmt.Sprintf("Required resource %s not in DAG, cannot add event %s", resource.ID(), child.ID())
|
|
|
|
return errors.New(error_str)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-29 23:54:52 -06:00
|
|
|
resource := child.DoneResource()
|
|
|
|
_, exists := manager.dag_nodes[resource.ID()]
|
|
|
|
if exists == true {
|
|
|
|
error_str := fmt.Sprintf("Created resource %s already exists in DAG, cannot add event %s", resource.ID(), child.ID())
|
|
|
|
return errors.New(error_str)
|
2023-05-29 19:17:52 -06:00
|
|
|
}
|
2023-05-29 23:54:52 -06:00
|
|
|
manager.AddResource(resource)
|
2023-05-29 19:17:52 -06:00
|
|
|
|
|
|
|
if manager.root_event == nil && parent != nil {
|
|
|
|
error_str := fmt.Sprintf("EventManager has no root, so can't add event to parent")
|
|
|
|
return errors.New(error_str)
|
|
|
|
} else if manager.root_event != nil && parent == nil {
|
|
|
|
// TODO
|
|
|
|
return errors.New("Replacing root event not implemented")
|
|
|
|
} else if manager.root_event == nil && parent == nil {
|
|
|
|
manager.root_event = child
|
|
|
|
return nil;
|
|
|
|
} else {
|
2023-06-02 17:31:29 -06:00
|
|
|
if FindChild(manager.root_event, parent.ID()) == nil {
|
2023-05-29 19:17:52 -06:00
|
|
|
error_str := fmt.Sprintf("Event %s is not present in the event tree, cannot add %s as child", parent.ID(), child.ID())
|
|
|
|
return errors.New(error_str)
|
|
|
|
}
|
|
|
|
|
2023-06-02 17:31:29 -06:00
|
|
|
if FindChild(manager.root_event, child.ID()) != nil {
|
2023-05-29 19:17:52 -06:00
|
|
|
error_str := fmt.Sprintf("Event %s already exists in the event tree, can not add again", child.ID())
|
|
|
|
return errors.New(error_str)
|
|
|
|
}
|
2023-06-02 17:31:29 -06:00
|
|
|
return AddChild(parent, child, info)
|
2023-05-29 19:17:52 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|