diff --git a/hal/cluster.go b/hal/cluster.go index b5a5c37..0edbe05 100644 --- a/hal/cluster.go +++ b/hal/cluster.go @@ -19,18 +19,54 @@ func (c *Cluster) Run(ctx context.Context) error { type ModuleMapping map[MultiThreadedIOPort]MultiThreadedIOPort -func (mapping ModuleMapping) BuildCluster() *Cluster { - modules := make(map[*Module]struct{}) - for host, client := range mapping { - modules[host.Module] = struct{}{} - modules[client.Module] = struct{}{} - host.Module.IO[host.IOPort] = NewMultiThreadedIO(&client) +func (config *ClusterConfig) BuildCluster(modules map[string]*Module) (*Cluster, error) { + // We assume all modules in the connection config exist + for _, c := range config.Connections { + + // For a connection like a -> b we need two channels: + // One which is the IN channel on a and the OUT channel on b + // One which is the OUT channel on a and the IN channel on b + // That means we need to create two IOs, one for each node and two channels + // The two channels then need to be passed around + // hmmmmmmm... + + outConn := &MultiThreadedIOPort{ + Module: modules[c.DestNode], + IOPort: c.DestPort, + } + conn := NewMultiThreadedIO(outConn) + modules[c.SourceNode].IO[c.SourcePort] = conn } + + // for host, client := range mapping { + // modules[host.Module] = struct{}{} + // modules[client.Module] = struct{}{} + // host.Module.IO[host.IOPort] = NewMultiThreadedIO(&client) + // } + cluster := &Cluster{modules: make([]*Module, len(modules), len(modules))} var index int64 - for module := range modules { + for _, module := range modules { cluster.modules[index] = module index++ } - return cluster + return cluster, nil +} + +type ClusterConnection struct { + SourcePort int64 `yaml:"source_port"` + SourceNode string `yaml:"source_node"` + DestPort int64 `yaml:"dest_port"` + DestNode string `yaml:"dest_node"` +} + +type ClusterNode struct { + Name string `yaml:"name"` + // Path to the hal program + Program string `yaml:"program"` +} + +type ClusterConfig struct { + Nodes []*ClusterNode `yaml:"nodes"` + Connections []*ClusterConnection `yaml:"connections"` } diff --git a/hal/cluster_test.go b/hal/cluster_test.go index aca165f..5b3b59f 100644 --- a/hal/cluster_test.go +++ b/hal/cluster_test.go @@ -1,41 +1,125 @@ package hal import ( - "context" "github.com/stretchr/testify/assert" "testing" ) -func TestCluster_Run(t *testing.T) { - var mapping ModuleMapping +// func TestCluster_Run(t *testing.T) { +// var mapping ModuleMapping +// +// firstModule := &Module{ +// programStorage: map[int64]*ProgrammedInstruction{ +// 1: { +// Instruction: InstructionStart, +// }, +// }, +// register: []float64{0}, +// IO: map[int64]IO{}, +// } +// secondModule := &Module{ +// programStorage: map[int64]*ProgrammedInstruction{ +// 1: { +// Instruction: InstructionStop, +// }, +// }, +// register: []float64{0}, +// IO: map[int64]IO{}, +// } +// +// mapping = map[MultiThreadedIOPort]MultiThreadedIOPort{ +// { +// Module: firstModule, +// IOPort: 0, +// }: { +// Module: secondModule, +// IOPort: 0, +// }, +// } +// assert.NoError(t, mapping.BuildCluster().Run(context.Background())) +// } - firstModule := &Module{ - programStorage: map[int64]*ProgrammedInstruction{ - 1: { - Instruction: InstructionStart, +func TestModuleMapping_BuildCluster(t *testing.T) { + config := &ClusterConfig{ + Nodes: []*ClusterNode{ + { + Name: "node1", + }, + { + Name: "node2", + }, + { + Name: "node3", }, }, - register: []float64{0}, - IO: map[int64]IO{}, - } - secondModule := &Module{ - programStorage: map[int64]*ProgrammedInstruction{ - 1: { - Instruction: InstructionStop, + Connections: []*ClusterConnection{ + { + SourceNode: "node1", + SourcePort: 1, + DestNode: "node2", + DestPort: 1, + }, + { + SourceNode: "node1", + SourcePort: 2, + DestNode: "node2", + DestPort: 2, + }, + { + SourceNode: "node2", + SourcePort: 3, + DestNode: "node3", + DestPort: 2, + }, + { + SourceNode: "node1", + SourcePort: 3, + DestNode: "node3", + DestPort: 3, }, }, - register: []float64{0}, - IO: map[int64]IO{}, } - mapping = map[MultiThreadedIOPort]MultiThreadedIOPort{ - { - Module: firstModule, - IOPort: 0, - }: { - Module: secondModule, - IOPort: 0, + modules := make(map[string]*Module) + modules = map[string]*Module{ + "node1": { + programStorage: map[int64]*ProgrammedInstruction{ + 1: {Instruction: InstructionStart}, + 2: {Instruction: InstructionStop}, + }, + register: []float64{0}, + IO: map[int64]IO{}, + }, + "node2": { + programStorage: map[int64]*ProgrammedInstruction{ + 1: {Instruction: InstructionStart}, + 2: {Instruction: InstructionStop}, + }, + register: []float64{0}, + IO: map[int64]IO{}, + }, + "node3": { + programStorage: map[int64]*ProgrammedInstruction{ + 1: {Instruction: InstructionStart}, + 2: {Instruction: InstructionStop}, + }, + register: []float64{0}, + IO: map[int64]IO{}, }, } - assert.NoError(t, mapping.BuildCluster().Run(context.Background())) + + cluster, err := config.BuildCluster(modules) + assert.NoError(t, err) + // First connection config + assert.NotNil(t, cluster.modules[0].IO[1]) + assert.NotNil(t, cluster.modules[1].IO[1]) + // Second + assert.NotNil(t, cluster.modules[0].IO[2]) + assert.NotNil(t, cluster.modules[1].IO[2]) + // Third + assert.NotNil(t, cluster.modules[1].IO[3]) + assert.NotNil(t, cluster.modules[2].IO[2]) + // Fourth + assert.NotNil(t, cluster.modules[0].IO[3]) + assert.NotNil(t, cluster.modules[2].IO[3]) }