diff --git a/benchmark/benchmark.go b/benchmark/benchmark.go index 37423c71..9c49227d 100644 --- a/benchmark/benchmark.go +++ b/benchmark/benchmark.go @@ -37,7 +37,7 @@ type ( serverFunc func(context.Context, *TimedMsg) ) -func runQCBenchmark(opts Options, cfg *Configuration, quorum int, f qcFunc) (*Result, error) { +func runQCBenchmark(opts Options, cfg *BenchmarkConfiguration, quorum int, f qcFunc) (*Result, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() msg := Echo_builder{Payload: make([]byte, opts.Payload)}.Build() @@ -103,7 +103,7 @@ func runQCBenchmark(opts Options, cfg *Configuration, quorum int, f qcFunc) (*Re return result, nil } -func runAsyncQCBenchmark(opts Options, cfg *Configuration, quorum int) (*Result, error) { +func runAsyncQCBenchmark(opts Options, cfg *BenchmarkConfiguration, quorum int) (*Result, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() msg := Echo_builder{Payload: make([]byte, opts.Payload)}.Build() @@ -187,7 +187,7 @@ func runAsyncQCBenchmark(opts Options, cfg *Configuration, quorum int) (*Result, return result, nil } -func runServerBenchmark(opts Options, cfg *Configuration, f serverFunc) (*Result, error) { +func runServerBenchmark(opts Options, cfg *BenchmarkConfiguration, f serverFunc) (*Result, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() payload := make([]byte, opts.Payload) @@ -241,7 +241,7 @@ func runServerBenchmark(opts Options, cfg *Configuration, f serverFunc) (*Result } // GetBenchmarks returns a list of Benchmarks that can be performed on the configuration -func GetBenchmarks(cfg *Configuration, quorum int) []Bench { +func GetBenchmarks(cfg *BenchmarkConfiguration, quorum int) []Bench { m := []Bench{ { Name: "QuorumCall", @@ -270,7 +270,7 @@ func GetBenchmarks(cfg *Configuration, quorum int) []Bench { } // RunBenchmarks runs all the benchmarks that match the given regex with the given options -func RunBenchmarks(benchRegex *regexp.Regexp, options Options, cfg *Configuration, quorum int) ([]*Result, error) { +func RunBenchmarks(benchRegex *regexp.Regexp, options Options, cfg *BenchmarkConfiguration, quorum int) ([]*Result, error) { benchmarks := GetBenchmarks(cfg, quorum) var results []*Result for _, b := range benchmarks { diff --git a/benchmark/benchmark_gorums.pb.go b/benchmark/benchmark_gorums.pb.go index 4060d82b..990e552d 100644 --- a/benchmark/benchmark_gorums.pb.go +++ b/benchmark/benchmark_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: benchmark/benchmark.proto @@ -20,21 +20,49 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// BenchmarkClient is the client interface for the Benchmark service. +type BenchmarkClient interface { + StartServerBenchmark(ctx context.Context, in *StartRequest) gorums.Responses[*StartResponse] + StopServerBenchmark(ctx context.Context, in *StopRequest) gorums.Responses[*Result] + StartBenchmark(ctx context.Context, in *StartRequest) gorums.Responses[*StartResponse] + StopBenchmark(ctx context.Context, in *StopRequest) gorums.Responses[*MemoryStat] + QuorumCall(ctx context.Context, in *Echo) gorums.Responses[*Echo] + AsyncQuorumCall(ctx context.Context, in *Echo) gorums.Responses[*Echo] + SlowServer(ctx context.Context, in *Echo) gorums.Responses[*Echo] + Multicast(ctx context.Context, in *TimedMsg, opts ...gorums.CallOption) +} + +// enforce interface compliance +var _ BenchmarkClient = (*BenchmarkConfiguration)(nil) + +// BenchmarkNodeClient is the single node client interface for the Benchmark service. +type BenchmarkNodeClient interface { +} + +// enforce interface compliance +var _ BenchmarkNodeClient = (*BenchmarkNode)(nil) + +// A BenchmarkConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type BenchmarkConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewBenchmarkConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewBenchmarkConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *BenchmarkConfiguration, err error) { + c = &BenchmarkConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -42,24 +70,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubBenchmarkConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *BenchmarkConfiguration) SubBenchmarkConfiguration(cfg gorums.NodeListOption) (subCfg *BenchmarkConfiguration, err error) { + subCfg = &BenchmarkConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -67,18 +84,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// BenchmarkConfigurationFromRaw returns a new BenchmarkConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func BenchmarkConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*BenchmarkConfiguration, error) { + newCfg := &BenchmarkConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *BenchmarkConfiguration) Nodes() []*BenchmarkNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*BenchmarkNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &BenchmarkNode{n} } return nodes } @@ -86,60 +113,34 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *BenchmarkConfiguration) AllNodes() []*BenchmarkNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*BenchmarkNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &BenchmarkNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c BenchmarkConfiguration) And(d *BenchmarkConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c BenchmarkConfiguration) Except(rm *BenchmarkConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { - *gorums.RawNode -} - -// BenchmarkClient is the client interface for the Benchmark service. -type BenchmarkClient interface { - StartServerBenchmark(ctx context.Context, in *StartRequest) gorums.Responses[*StartResponse] - StopServerBenchmark(ctx context.Context, in *StopRequest) gorums.Responses[*Result] - StartBenchmark(ctx context.Context, in *StartRequest) gorums.Responses[*StartResponse] - StopBenchmark(ctx context.Context, in *StopRequest) gorums.Responses[*MemoryStat] - QuorumCall(ctx context.Context, in *Echo) gorums.Responses[*Echo] - AsyncQuorumCall(ctx context.Context, in *Echo) gorums.Responses[*Echo] - SlowServer(ctx context.Context, in *Echo) gorums.Responses[*Echo] - Multicast(ctx context.Context, in *TimedMsg, opts ...gorums.CallOption) -} - -// enforce interface compliance -var _ BenchmarkClient = (*Configuration)(nil) - // Reference imports to suppress errors if they are not otherwise used. var _ emptypb.Empty // Multicast is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) Multicast(ctx context.Context, in *TimedMsg, opts ...gorums.CallOption) { +func (c *BenchmarkConfiguration) Multicast(ctx context.Context, in *TimedMsg, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "benchmark.Benchmark.Multicast", @@ -148,10 +149,15 @@ func (c *Configuration) Multicast(ctx context.Context, in *TimedMsg, opts ...gor c.RawConfiguration.Multicast(ctx, cd, opts...) } +// BenchmarkNode holds the node specific methods for the Benchmark service. +type BenchmarkNode struct { + *gorums.RawNode +} + // StartServerBenchmark is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) StartServerBenchmark(ctx context.Context, in *StartRequest) gorums.Responses[*StartResponse] { +func (c *BenchmarkConfiguration) StartServerBenchmark(ctx context.Context, in *StartRequest) gorums.Responses[*StartResponse] { cd := gorums.QuorumCallData{ Message: in, Method: "benchmark.Benchmark.StartServerBenchmark", @@ -164,7 +170,7 @@ func (c *Configuration) StartServerBenchmark(ctx context.Context, in *StartReque // StopServerBenchmark is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) StopServerBenchmark(ctx context.Context, in *StopRequest) gorums.Responses[*Result] { +func (c *BenchmarkConfiguration) StopServerBenchmark(ctx context.Context, in *StopRequest) gorums.Responses[*Result] { cd := gorums.QuorumCallData{ Message: in, Method: "benchmark.Benchmark.StopServerBenchmark", @@ -177,7 +183,7 @@ func (c *Configuration) StopServerBenchmark(ctx context.Context, in *StopRequest // StartBenchmark is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) StartBenchmark(ctx context.Context, in *StartRequest) gorums.Responses[*StartResponse] { +func (c *BenchmarkConfiguration) StartBenchmark(ctx context.Context, in *StartRequest) gorums.Responses[*StartResponse] { cd := gorums.QuorumCallData{ Message: in, Method: "benchmark.Benchmark.StartBenchmark", @@ -190,7 +196,7 @@ func (c *Configuration) StartBenchmark(ctx context.Context, in *StartRequest) go // StopBenchmark is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) StopBenchmark(ctx context.Context, in *StopRequest) gorums.Responses[*MemoryStat] { +func (c *BenchmarkConfiguration) StopBenchmark(ctx context.Context, in *StopRequest) gorums.Responses[*MemoryStat] { cd := gorums.QuorumCallData{ Message: in, Method: "benchmark.Benchmark.StopBenchmark", @@ -201,7 +207,7 @@ func (c *Configuration) StopBenchmark(ctx context.Context, in *StopRequest) goru } // benchmarks -func (c *Configuration) QuorumCall(ctx context.Context, in *Echo) gorums.Responses[*Echo] { +func (c *BenchmarkConfiguration) QuorumCall(ctx context.Context, in *Echo) gorums.Responses[*Echo] { cd := gorums.QuorumCallData{ Message: in, Method: "benchmark.Benchmark.QuorumCall", @@ -214,7 +220,7 @@ func (c *Configuration) QuorumCall(ctx context.Context, in *Echo) gorums.Respons // AsyncQuorumCall is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) AsyncQuorumCall(ctx context.Context, in *Echo) gorums.Responses[*Echo] { +func (c *BenchmarkConfiguration) AsyncQuorumCall(ctx context.Context, in *Echo) gorums.Responses[*Echo] { cd := gorums.QuorumCallData{ Message: in, Method: "benchmark.Benchmark.AsyncQuorumCall", @@ -227,7 +233,7 @@ func (c *Configuration) AsyncQuorumCall(ctx context.Context, in *Echo) gorums.Re // SlowServer is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) SlowServer(ctx context.Context, in *Echo) gorums.Responses[*Echo] { +func (c *BenchmarkConfiguration) SlowServer(ctx context.Context, in *Echo) gorums.Responses[*Echo] { cd := gorums.QuorumCallData{ Message: in, Method: "benchmark.Benchmark.SlowServer", @@ -237,7 +243,7 @@ func (c *Configuration) SlowServer(ctx context.Context, in *Echo) gorums.Respons return gorums.QuorumCall[*Echo](ctx, c.RawConfiguration, cd) } -// Benchmark is the server-side API for the Benchmark Service +// BenchmarkServer is the server-side API for the Benchmark Service type BenchmarkServer interface { StartServerBenchmark(ctx gorums.ServerCtx, request *StartRequest) (response *StartResponse, err error) StopServerBenchmark(ctx gorums.ServerCtx, request *StopRequest) (response *Result, err error) @@ -249,6 +255,9 @@ type BenchmarkServer interface { Multicast(ctx gorums.ServerCtx, request *TimedMsg) } +// RegisterBenchmarkServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterBenchmarkServer(srv *gorums.Server, impl BenchmarkServer) { srv.RegisterHandler("benchmark.Benchmark.StartServerBenchmark", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*StartRequest) diff --git a/channel.go b/channel.go index 528861a1..45154bc3 100644 --- a/channel.go +++ b/channel.go @@ -99,6 +99,7 @@ func (c *channel) newNodeStream(conn *grpc.ClientConn) error { c.gorumsStream, err = c.gorumsClient.NodeStream(c.streamCtx) c.streamMut.Unlock() if err != nil { + fmt.Println("oops " + err.Error()) return err } c.streamBroken.clear() diff --git a/cmd/benchmark/main.go b/cmd/benchmark/main.go index bbb204ac..7056d77b 100644 --- a/cmd/benchmark/main.go +++ b/cmd/benchmark/main.go @@ -196,7 +196,7 @@ func main() { gorums.WithSendBufferSize(*sendBuffer), } - cfg, err := benchmark.NewConfiguration(gorums.WithNodeList(remotes[:options.NumNodes]), mgrOpts...) + cfg, err := benchmark.NewBenchmarkConfiguration(gorums.WithNodeList(remotes[:options.NumNodes]), mgrOpts...) checkf("Failed to create configuration: %v", err) defer cfg.Close() diff --git a/cmd/protoc-gen-gorums/dev/config.go b/cmd/protoc-gen-gorums/dev/config.go deleted file mode 100644 index 80d52269..00000000 --- a/cmd/protoc-gen-gorums/dev/config.go +++ /dev/null @@ -1,91 +0,0 @@ -package dev - -import ( - "github.com/relab/gorums" -) - -// A Configuration represents a static set of nodes on which quorum remote -// procedure calls may be invoked. -type Configuration struct { - gorums.RawConfiguration -} - -// NewConfiguration returns a configuration based on the provided list of nodes (required) -// and an optional quorum specification. The QuorumSpec is necessary for call types that -// must process replies. For configurations only used for unicast or multicast call types, -// a QuorumSpec is not needed. -// Nodes can be supplied using WithNodeMap or WithNodeList. -// Using any other type of NodeListOption will not work. -// The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} - c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) - if err != nil { - return nil, err - } - return c, nil -} - -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, -// Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. -// A new configuration can also be created from an existing configuration, -// using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} - subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) - if err != nil { - return nil, err - } - return subCfg, nil -} - -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() -} - -// Nodes returns a slice of the configuration nodes. Sorted by node id. -// -// NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} - } - return nodes -} - -// AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. -// -// NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { - rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) - for i, n := range rawNodes { - nodes[i] = &Node{n} - } - return nodes -} - -// And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { - return c.RawConfiguration.And(d.RawConfiguration) -} - -// Except returns a NodeListOption that can be used to create a new configuration -// from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { - return c.RawConfiguration.Except(rm.RawConfiguration) -} diff --git a/cmd/protoc-gen-gorums/dev/node.go b/cmd/protoc-gen-gorums/dev/node.go deleted file mode 100644 index e5acc464..00000000 --- a/cmd/protoc-gen-gorums/dev/node.go +++ /dev/null @@ -1,9 +0,0 @@ -package dev - -import "github.com/relab/gorums" - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { - *gorums.RawNode -} diff --git a/cmd/protoc-gen-gorums/dev/zorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums.pb.go index 52c8d257..f1e470a2 100644 --- a/cmd/protoc-gen-gorums/dev/zorums.pb.go +++ b/cmd/protoc-gen-gorums/dev/zorums.pb.go @@ -225,6 +225,18 @@ const file_zorums_proto_rawDesc = "" + "\n" + "Multicast4\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x04\x98\xb5\x18\x01\x12,\n" + "\aUnicast\x12\f.dev.Request\x1a\r.dev.Response\"\x04\x90\xb5\x18\x01\x126\n" + + "\bUnicast2\x12\f.dev.Request\x1a\x16.google.protobuf.Empty\"\x04\x90\xb5\x18\x012\xc1\x03\n" + + "\x11ZorumsNoQCService\x12)\n" + + "\bGRPCCall\x12\f.dev.Request\x1a\r.dev.Response\"\x00\x12.\n" + + "\tMulticast\x12\f.dev.Request\x1a\r.dev.Response\"\x04\x98\xb5\x18\x01\x12<\n" + + "\x13MulticastPerNodeArg\x12\f.dev.Request\x1a\r.dev.Response\"\b\x98\xb5\x18\x01\xa0\xb6\x18\x01\x12/\n" + + "\n" + + "Multicast2\x12\f.dev.Request\x1a\r.dev.Response\"\x04\x98\xb5\x18\x01\x128\n" + + "\n" + + "Multicast3\x12\f.dev.Request\x1a\x16.google.protobuf.Empty\"\x04\x98\xb5\x18\x01\x12B\n" + + "\n" + + "Multicast4\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x04\x98\xb5\x18\x01\x12,\n" + + "\aUnicast\x12\f.dev.Request\x1a\r.dev.Response\"\x04\x90\xb5\x18\x01\x126\n" + "\bUnicast2\x12\f.dev.Request\x1a\x16.google.protobuf.Empty\"\x04\x90\xb5\x18\x01B Z\x19cmd/protoc-gen-gorums/dev\x92\x03\x02\b\x02b\beditionsp\xe8\a" var file_zorums_proto_msgTypes = make([]protoimpl.MessageInfo, 3) @@ -251,24 +263,40 @@ var file_zorums_proto_depIdxs = []int32{ 3, // 13: dev.ZorumsService.Multicast4:input_type -> google.protobuf.Empty 0, // 14: dev.ZorumsService.Unicast:input_type -> dev.Request 0, // 15: dev.ZorumsService.Unicast2:input_type -> dev.Request - 1, // 16: dev.ZorumsService.GRPCCall:output_type -> dev.Response - 1, // 17: dev.ZorumsService.QuorumCall:output_type -> dev.Response - 1, // 18: dev.ZorumsService.QuorumCallPerNodeArg:output_type -> dev.Response - 1, // 19: dev.ZorumsService.QuorumCallEmpty:output_type -> dev.Response - 3, // 20: dev.ZorumsService.QuorumCallEmpty2:output_type -> google.protobuf.Empty - 1, // 21: dev.ZorumsService.QuorumCallStream:output_type -> dev.Response - 1, // 22: dev.ZorumsService.QuorumCallStreamPerNodeArg:output_type -> dev.Response - 1, // 23: dev.ZorumsService.QuorumCallStreamEmpty:output_type -> dev.Response - 3, // 24: dev.ZorumsService.QuorumCallStreamEmpty2:output_type -> google.protobuf.Empty - 1, // 25: dev.ZorumsService.Multicast:output_type -> dev.Response - 1, // 26: dev.ZorumsService.MulticastPerNodeArg:output_type -> dev.Response - 1, // 27: dev.ZorumsService.Multicast2:output_type -> dev.Response - 3, // 28: dev.ZorumsService.Multicast3:output_type -> google.protobuf.Empty - 3, // 29: dev.ZorumsService.Multicast4:output_type -> google.protobuf.Empty - 1, // 30: dev.ZorumsService.Unicast:output_type -> dev.Response - 3, // 31: dev.ZorumsService.Unicast2:output_type -> google.protobuf.Empty - 16, // [16:32] is the sub-list for method output_type - 0, // [0:16] is the sub-list for method input_type + 0, // 16: dev.ZorumsNoQCService.GRPCCall:input_type -> dev.Request + 0, // 17: dev.ZorumsNoQCService.Multicast:input_type -> dev.Request + 0, // 18: dev.ZorumsNoQCService.MulticastPerNodeArg:input_type -> dev.Request + 0, // 19: dev.ZorumsNoQCService.Multicast2:input_type -> dev.Request + 0, // 20: dev.ZorumsNoQCService.Multicast3:input_type -> dev.Request + 3, // 21: dev.ZorumsNoQCService.Multicast4:input_type -> google.protobuf.Empty + 0, // 22: dev.ZorumsNoQCService.Unicast:input_type -> dev.Request + 0, // 23: dev.ZorumsNoQCService.Unicast2:input_type -> dev.Request + 1, // 24: dev.ZorumsService.GRPCCall:output_type -> dev.Response + 1, // 25: dev.ZorumsService.QuorumCall:output_type -> dev.Response + 1, // 26: dev.ZorumsService.QuorumCallPerNodeArg:output_type -> dev.Response + 1, // 27: dev.ZorumsService.QuorumCallEmpty:output_type -> dev.Response + 3, // 28: dev.ZorumsService.QuorumCallEmpty2:output_type -> google.protobuf.Empty + 1, // 29: dev.ZorumsService.QuorumCallStream:output_type -> dev.Response + 1, // 30: dev.ZorumsService.QuorumCallStreamPerNodeArg:output_type -> dev.Response + 1, // 31: dev.ZorumsService.QuorumCallStreamEmpty:output_type -> dev.Response + 3, // 32: dev.ZorumsService.QuorumCallStreamEmpty2:output_type -> google.protobuf.Empty + 1, // 33: dev.ZorumsService.Multicast:output_type -> dev.Response + 1, // 34: dev.ZorumsService.MulticastPerNodeArg:output_type -> dev.Response + 1, // 35: dev.ZorumsService.Multicast2:output_type -> dev.Response + 3, // 36: dev.ZorumsService.Multicast3:output_type -> google.protobuf.Empty + 3, // 37: dev.ZorumsService.Multicast4:output_type -> google.protobuf.Empty + 1, // 38: dev.ZorumsService.Unicast:output_type -> dev.Response + 3, // 39: dev.ZorumsService.Unicast2:output_type -> google.protobuf.Empty + 1, // 40: dev.ZorumsNoQCService.GRPCCall:output_type -> dev.Response + 1, // 41: dev.ZorumsNoQCService.Multicast:output_type -> dev.Response + 1, // 42: dev.ZorumsNoQCService.MulticastPerNodeArg:output_type -> dev.Response + 1, // 43: dev.ZorumsNoQCService.Multicast2:output_type -> dev.Response + 3, // 44: dev.ZorumsNoQCService.Multicast3:output_type -> google.protobuf.Empty + 3, // 45: dev.ZorumsNoQCService.Multicast4:output_type -> google.protobuf.Empty + 1, // 46: dev.ZorumsNoQCService.Unicast:output_type -> dev.Response + 3, // 47: dev.ZorumsNoQCService.Unicast2:output_type -> google.protobuf.Empty + 24, // [24:48] is the sub-list for method output_type + 0, // [0:24] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name @@ -287,7 +315,7 @@ func file_zorums_proto_init() { NumEnums: 0, NumMessages: 3, NumExtensions: 0, - NumServices: 1, + NumServices: 2, }, GoTypes: file_zorums_proto_goTypes, DependencyIndexes: file_zorums_proto_depIdxs, diff --git a/cmd/protoc-gen-gorums/dev/zorums.proto b/cmd/protoc-gen-gorums/dev/zorums.proto index 59ffdca4..1d7043b4 100644 --- a/cmd/protoc-gen-gorums/dev/zorums.proto +++ b/cmd/protoc-gen-gorums/dev/zorums.proto @@ -117,3 +117,50 @@ service ZorumsService { option (gorums.unicast) = true; } } + +service ZorumsNoQCService { + // GRPCCall plain gRPC call; testing that Gorums can ignore these, but that + // they are added to the _grpc.pb.go generated file. + rpc GRPCCall(Request) returns (Response) {} + + // ------------------------------------------------------------------ + // Multicast variants + // The multicast call type does not support the 'custom_return_type' + // option since multicast is one-way and so it doesn't make sense to + // operate on response types. + // ------------------------------------------------------------------ + + // Multicast plain. Response type is not needed here. + rpc Multicast(Request) returns (Response) { + option (gorums.multicast) = true; + } + // MulticastPerNodeArg with per_node_arg option. + rpc MulticastPerNodeArg(Request) returns (Response) { + option (gorums.multicast) = true; + option (gorums.per_node_arg) = true; + } + // Multicast2 is testing whether multiple streams work. + rpc Multicast2(Request) returns (Response) { + option (gorums.multicast) = true; + } + // Multicast3 is testing imported message type. + rpc Multicast3(Request) returns (google.protobuf.Empty) { + option (gorums.multicast) = true; + } + // Multicast4 is testing imported message type. + rpc Multicast4(google.protobuf.Empty) returns (google.protobuf.Empty) { + option (gorums.multicast) = true; + } + + // --------------------------------------------------------------- + // Unicast + // --------------------------------------------------------------- + + rpc Unicast(Request) returns (Response) { + option (gorums.unicast) = true; + } + + rpc Unicast2(Request) returns (google.protobuf.Empty) { + option (gorums.unicast) = true; + } +} diff --git a/cmd/protoc-gen-gorums/dev/zorums_client_gorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums_client_gorums.pb.go index ae11117a..efad15ff 100644 --- a/cmd/protoc-gen-gorums/dev/zorums_client_gorums.pb.go +++ b/cmd/protoc-gen-gorums/dev/zorums_client_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: zorums.proto @@ -37,7 +37,7 @@ type ZorumsServiceClient interface { } // enforce interface compliance -var _ ZorumsServiceClient = (*Configuration)(nil) +var _ ZorumsServiceClient = (*ZorumsServiceConfiguration)(nil) // ZorumsServiceNodeClient is the single node client interface for the ZorumsService service. type ZorumsServiceNodeClient interface { @@ -47,4 +47,26 @@ type ZorumsServiceNodeClient interface { } // enforce interface compliance -var _ ZorumsServiceNodeClient = (*Node)(nil) +var _ ZorumsServiceNodeClient = (*ZorumsServiceNode)(nil) + +// ZorumsNoQCServiceClient is the client interface for the ZorumsNoQCService service. +type ZorumsNoQCServiceClient interface { + Multicast(ctx context.Context, in *Request, opts ...gorums.CallOption) + MulticastPerNodeArg(ctx context.Context, in *Request, f func(*Request, uint32) *Request, opts ...gorums.CallOption) + Multicast2(ctx context.Context, in *Request, opts ...gorums.CallOption) + Multicast3(ctx context.Context, in *Request, opts ...gorums.CallOption) + Multicast4(ctx context.Context, in *emptypb.Empty, opts ...gorums.CallOption) +} + +// enforce interface compliance +var _ ZorumsNoQCServiceClient = (*ZorumsNoQCServiceConfiguration)(nil) + +// ZorumsNoQCServiceNodeClient is the single node client interface for the ZorumsNoQCService service. +type ZorumsNoQCServiceNodeClient interface { + GRPCCall(ctx context.Context, in *Request) (resp *Response, err error) + Unicast(ctx context.Context, in *Request, opts ...gorums.CallOption) + Unicast2(ctx context.Context, in *Request, opts ...gorums.CallOption) +} + +// enforce interface compliance +var _ ZorumsNoQCServiceNodeClient = (*ZorumsNoQCServiceNode)(nil) diff --git a/cmd/protoc-gen-gorums/dev/zorums_configuration_gorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums_configuration_gorums.pb.go new file mode 100644 index 00000000..55724e0d --- /dev/null +++ b/cmd/protoc-gen-gorums/dev/zorums_configuration_gorums.pb.go @@ -0,0 +1,188 @@ +// Code generated by protoc-gen-gorums. DO NOT EDIT. +// versions: +// protoc-gen-gorums v0.9.0-devel+a35cbf26 +// protoc v6.30.2 +// source: zorums.proto + +package dev + +import ( + gorums "github.com/relab/gorums" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = gorums.EnforceVersion(9 - gorums.MinVersion) + // Verify that the gorums runtime is sufficiently up-to-date. + _ = gorums.EnforceVersion(gorums.MaxVersion - 9) +) + +// A ZorumsServiceConfiguration represents a static set of nodes on which quorum remote +// procedure calls may be invoked. +type ZorumsServiceConfiguration struct { + gorums.RawConfiguration +} + +// NewZorumsServiceConfiguration returns a configuration based on the provided list of nodes (required) +// and an optional quorum specification. The QuorumSpec is necessary for call types that +// must process replies. For configurations only used for unicast or multicast call types, +// a QuorumSpec is not needed. +// Nodes can be supplied using WithNodeMap or WithNodeList. +// Using any other type of NodeListOption will not work. +// The ManagerOption list controls how the nodes in the configuration are created. +func NewZorumsServiceConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *ZorumsServiceConfiguration, err error) { + c = &ZorumsServiceConfiguration{} + c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) + if err != nil { + return nil, err + } + return c, nil +} + +// SubZorumsServiceConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, +// Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. +// A new configuration can also be created from an existing configuration, +// using the And, WithNewNodes, Except, and WithoutNodes methods. +func (c *ZorumsServiceConfiguration) SubZorumsServiceConfiguration(cfg gorums.NodeListOption) (subCfg *ZorumsServiceConfiguration, err error) { + subCfg = &ZorumsServiceConfiguration{} + subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) + if err != nil { + return nil, err + } + return subCfg, nil +} + +// ZorumsServiceConfigurationFromRaw returns a new ZorumsServiceConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func ZorumsServiceConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*ZorumsServiceConfiguration, error) { + newCfg := &ZorumsServiceConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil +} + +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. +// +// NOTE: mutating the returned slice is not supported. +func (c *ZorumsServiceConfiguration) Nodes() []*ZorumsServiceNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*ZorumsServiceNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &ZorumsServiceNode{n} + } + return nodes +} + +// AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. +// +// NOTE: mutating the returned slice is not supported. +func (c *ZorumsServiceConfiguration) AllNodes() []*ZorumsServiceNode { + rawNodes := c.RawConfiguration.AllNodes() + nodes := make([]*ZorumsServiceNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &ZorumsServiceNode{n} + } + return nodes +} + +// And returns a NodeListOption that can be used to create a new configuration combining c and d. +func (c ZorumsServiceConfiguration) And(d *ZorumsServiceConfiguration) gorums.NodeListOption { + return c.RawConfiguration.And(d.RawConfiguration) +} + +// Except returns a NodeListOption that can be used to create a new configuration +// from c without the nodes in rm. +func (c ZorumsServiceConfiguration) Except(rm *ZorumsServiceConfiguration) gorums.NodeListOption { + return c.RawConfiguration.Except(rm.RawConfiguration) +} + +// A ZorumsNoQCServiceConfiguration represents a static set of nodes on which quorum remote +// procedure calls may be invoked. +type ZorumsNoQCServiceConfiguration struct { + gorums.RawConfiguration +} + +// NewZorumsNoQCServiceConfiguration returns a configuration based on the provided list of nodes (required) +// and an optional quorum specification. The QuorumSpec is necessary for call types that +// must process replies. For configurations only used for unicast or multicast call types, +// a QuorumSpec is not needed. +// Nodes can be supplied using WithNodeMap or WithNodeList. +// Using any other type of NodeListOption will not work. +// The ManagerOption list controls how the nodes in the configuration are created. +func NewZorumsNoQCServiceConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *ZorumsNoQCServiceConfiguration, err error) { + c = &ZorumsNoQCServiceConfiguration{} + c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) + if err != nil { + return nil, err + } + return c, nil +} + +// SubZorumsNoQCServiceConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, +// Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. +// A new configuration can also be created from an existing configuration, +// using the And, WithNewNodes, Except, and WithoutNodes methods. +func (c *ZorumsNoQCServiceConfiguration) SubZorumsNoQCServiceConfiguration(cfg gorums.NodeListOption) (subCfg *ZorumsNoQCServiceConfiguration, err error) { + subCfg = &ZorumsNoQCServiceConfiguration{} + subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) + if err != nil { + return nil, err + } + return subCfg, nil +} + +// ZorumsNoQCServiceConfigurationFromRaw returns a new ZorumsNoQCServiceConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func ZorumsNoQCServiceConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*ZorumsNoQCServiceConfiguration, error) { + newCfg := &ZorumsNoQCServiceConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil +} + +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. +// +// NOTE: mutating the returned slice is not supported. +func (c *ZorumsNoQCServiceConfiguration) Nodes() []*ZorumsNoQCServiceNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*ZorumsNoQCServiceNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &ZorumsNoQCServiceNode{n} + } + return nodes +} + +// AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. +// +// NOTE: mutating the returned slice is not supported. +func (c *ZorumsNoQCServiceConfiguration) AllNodes() []*ZorumsNoQCServiceNode { + rawNodes := c.RawConfiguration.AllNodes() + nodes := make([]*ZorumsNoQCServiceNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &ZorumsNoQCServiceNode{n} + } + return nodes +} + +// And returns a NodeListOption that can be used to create a new configuration combining c and d. +func (c ZorumsNoQCServiceConfiguration) And(d *ZorumsNoQCServiceConfiguration) gorums.NodeListOption { + return c.RawConfiguration.And(d.RawConfiguration) +} + +// Except returns a NodeListOption that can be used to create a new configuration +// from c without the nodes in rm. +func (c ZorumsNoQCServiceConfiguration) Except(rm *ZorumsNoQCServiceConfiguration) gorums.NodeListOption { + return c.RawConfiguration.Except(rm.RawConfiguration) +} diff --git a/cmd/protoc-gen-gorums/dev/zorums_multicast_gorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums_multicast_gorums.pb.go index cba8e726..26993040 100644 --- a/cmd/protoc-gen-gorums/dev/zorums_multicast_gorums.pb.go +++ b/cmd/protoc-gen-gorums/dev/zorums_multicast_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: zorums.proto @@ -21,7 +21,8 @@ const ( ) // Multicast plain. Response type is not needed here. -func (c *Configuration) Multicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { +func (c *ZorumsServiceConfiguration) Multicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.Multicast", @@ -31,7 +32,8 @@ func (c *Configuration) Multicast(ctx context.Context, in *Request, opts ...goru } // MulticastPerNodeArg with per_node_arg option. -func (c *Configuration) MulticastPerNodeArg(ctx context.Context, in *Request, f func(*Request, uint32) *Request, opts ...gorums.CallOption) { +func (c *ZorumsServiceConfiguration) MulticastPerNodeArg(ctx context.Context, in *Request, f func(*Request, uint32) *Request, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.MulticastPerNodeArg", @@ -45,7 +47,8 @@ func (c *Configuration) MulticastPerNodeArg(ctx context.Context, in *Request, f } // Multicast2 is testing whether multiple streams work. -func (c *Configuration) Multicast2(ctx context.Context, in *Request, opts ...gorums.CallOption) { +func (c *ZorumsServiceConfiguration) Multicast2(ctx context.Context, in *Request, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.Multicast2", @@ -58,7 +61,8 @@ func (c *Configuration) Multicast2(ctx context.Context, in *Request, opts ...gor var _ emptypb.Empty // Multicast3 is testing imported message type. -func (c *Configuration) Multicast3(ctx context.Context, in *Request, opts ...gorums.CallOption) { +func (c *ZorumsServiceConfiguration) Multicast3(ctx context.Context, in *Request, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.Multicast3", @@ -71,7 +75,8 @@ func (c *Configuration) Multicast3(ctx context.Context, in *Request, opts ...gor var _ emptypb.Empty // Multicast4 is testing imported message type. -func (c *Configuration) Multicast4(ctx context.Context, in *emptypb.Empty, opts ...gorums.CallOption) { +func (c *ZorumsServiceConfiguration) Multicast4(ctx context.Context, in *emptypb.Empty, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.Multicast4", @@ -79,3 +84,68 @@ func (c *Configuration) Multicast4(ctx context.Context, in *emptypb.Empty, opts c.RawConfiguration.Multicast(ctx, cd, opts...) } + +// Multicast plain. Response type is not needed here. +func (c *ZorumsNoQCServiceConfiguration) Multicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { + + cd := gorums.QuorumCallData{ + Message: in, + Method: "dev.ZorumsNoQCService.Multicast", + } + + c.RawConfiguration.Multicast(ctx, cd, opts...) +} + +// MulticastPerNodeArg with per_node_arg option. +func (c *ZorumsNoQCServiceConfiguration) MulticastPerNodeArg(ctx context.Context, in *Request, f func(*Request, uint32) *Request, opts ...gorums.CallOption) { + + cd := gorums.QuorumCallData{ + Message: in, + Method: "dev.ZorumsNoQCService.MulticastPerNodeArg", + } + + cd.PerNodeArgFn = func(req proto.Message, nid uint32) proto.Message { + return f(req.(*Request), nid) + } + + c.RawConfiguration.Multicast(ctx, cd, opts...) +} + +// Multicast2 is testing whether multiple streams work. +func (c *ZorumsNoQCServiceConfiguration) Multicast2(ctx context.Context, in *Request, opts ...gorums.CallOption) { + + cd := gorums.QuorumCallData{ + Message: in, + Method: "dev.ZorumsNoQCService.Multicast2", + } + + c.RawConfiguration.Multicast(ctx, cd, opts...) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ emptypb.Empty + +// Multicast3 is testing imported message type. +func (c *ZorumsNoQCServiceConfiguration) Multicast3(ctx context.Context, in *Request, opts ...gorums.CallOption) { + + cd := gorums.QuorumCallData{ + Message: in, + Method: "dev.ZorumsNoQCService.Multicast3", + } + + c.RawConfiguration.Multicast(ctx, cd, opts...) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ emptypb.Empty + +// Multicast4 is testing imported message type. +func (c *ZorumsNoQCServiceConfiguration) Multicast4(ctx context.Context, in *emptypb.Empty, opts ...gorums.CallOption) { + + cd := gorums.QuorumCallData{ + Message: in, + Method: "dev.ZorumsNoQCService.Multicast4", + } + + c.RawConfiguration.Multicast(ctx, cd, opts...) +} diff --git a/cmd/protoc-gen-gorums/dev/zorums_node_gorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums_node_gorums.pb.go new file mode 100644 index 00000000..3e8fc74c --- /dev/null +++ b/cmd/protoc-gen-gorums/dev/zorums_node_gorums.pb.go @@ -0,0 +1,28 @@ +// Code generated by protoc-gen-gorums. DO NOT EDIT. +// versions: +// protoc-gen-gorums v0.9.0-devel+a35cbf26 +// protoc v6.30.2 +// source: zorums.proto + +package dev + +import ( + gorums "github.com/relab/gorums" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = gorums.EnforceVersion(9 - gorums.MinVersion) + // Verify that the gorums runtime is sufficiently up-to-date. + _ = gorums.EnforceVersion(gorums.MaxVersion - 9) +) + +// ZorumsServiceNode holds the node specific methods for the ZorumsService service. +type ZorumsServiceNode struct { + *gorums.RawNode +} + +// ZorumsNoQCServiceNode holds the node specific methods for the ZorumsNoQCService service. +type ZorumsNoQCServiceNode struct { + *gorums.RawNode +} diff --git a/cmd/protoc-gen-gorums/dev/zorums_quorumcall_gorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums_quorumcall_gorums.pb.go index 89cf4e31..984ec5d5 100644 --- a/cmd/protoc-gen-gorums/dev/zorums_quorumcall_gorums.pb.go +++ b/cmd/protoc-gen-gorums/dev/zorums_quorumcall_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: zorums.proto @@ -21,7 +21,7 @@ const ( ) // QuorumCall plain. -func (c *Configuration) QuorumCall(ctx context.Context, in *Request) gorums.Responses[*Response] { +func (c *ZorumsServiceConfiguration) QuorumCall(ctx context.Context, in *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.QuorumCall", @@ -32,7 +32,7 @@ func (c *Configuration) QuorumCall(ctx context.Context, in *Request) gorums.Resp } // QuorumCall with per_node_arg option. -func (c *Configuration) QuorumCallPerNodeArg(ctx context.Context, in *Request, f func(*Request, uint32) *Request) gorums.Responses[*Response] { +func (c *ZorumsServiceConfiguration) QuorumCallPerNodeArg(ctx context.Context, in *Request, f func(*Request, uint32) *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.QuorumCallPerNodeArg", @@ -46,7 +46,7 @@ func (c *Configuration) QuorumCallPerNodeArg(ctx context.Context, in *Request, f } // QuorumCallEmpty for testing imported message type. -func (c *Configuration) QuorumCallEmpty(ctx context.Context, in *emptypb.Empty) gorums.Responses[*Response] { +func (c *ZorumsServiceConfiguration) QuorumCallEmpty(ctx context.Context, in *emptypb.Empty) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.QuorumCallEmpty", @@ -57,7 +57,7 @@ func (c *Configuration) QuorumCallEmpty(ctx context.Context, in *emptypb.Empty) } // QuorumCallEmpty2 for testing imported message type. -func (c *Configuration) QuorumCallEmpty2(ctx context.Context, in *Request) gorums.Responses[*emptypb.Empty] { +func (c *ZorumsServiceConfiguration) QuorumCallEmpty2(ctx context.Context, in *Request) gorums.Responses[*emptypb.Empty] { cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.QuorumCallEmpty2", @@ -68,7 +68,7 @@ func (c *Configuration) QuorumCallEmpty2(ctx context.Context, in *Request) gorum } // QuorumCall plain. -func (c *Configuration) QuorumCallStream(ctx context.Context, in *Request) gorums.Responses[*Response] { +func (c *ZorumsServiceConfiguration) QuorumCallStream(ctx context.Context, in *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.QuorumCallStream", @@ -79,7 +79,7 @@ func (c *Configuration) QuorumCallStream(ctx context.Context, in *Request) gorum } // QuorumCall with per_node_arg option. -func (c *Configuration) QuorumCallStreamPerNodeArg(ctx context.Context, in *Request, f func(*Request, uint32) *Request) gorums.Responses[*Response] { +func (c *ZorumsServiceConfiguration) QuorumCallStreamPerNodeArg(ctx context.Context, in *Request, f func(*Request, uint32) *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.QuorumCallStreamPerNodeArg", @@ -93,7 +93,7 @@ func (c *Configuration) QuorumCallStreamPerNodeArg(ctx context.Context, in *Requ } // QuorumCallEmpty for testing imported message type. -func (c *Configuration) QuorumCallStreamEmpty(ctx context.Context, in *emptypb.Empty) gorums.Responses[*Response] { +func (c *ZorumsServiceConfiguration) QuorumCallStreamEmpty(ctx context.Context, in *emptypb.Empty) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.QuorumCallStreamEmpty", @@ -104,7 +104,7 @@ func (c *Configuration) QuorumCallStreamEmpty(ctx context.Context, in *emptypb.E } // QuorumCallEmpty2 for testing imported message type. -func (c *Configuration) QuorumCallStreamEmpty2(ctx context.Context, in *Request) gorums.Responses[*emptypb.Empty] { +func (c *ZorumsServiceConfiguration) QuorumCallStreamEmpty2(ctx context.Context, in *Request) gorums.Responses[*emptypb.Empty] { cd := gorums.QuorumCallData{ Message: in, Method: "dev.ZorumsService.QuorumCallStreamEmpty2", diff --git a/cmd/protoc-gen-gorums/dev/zorums_rpc_gorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums_rpc_gorums.pb.go index 5458b547..e0b7de93 100644 --- a/cmd/protoc-gen-gorums/dev/zorums_rpc_gorums.pb.go +++ b/cmd/protoc-gen-gorums/dev/zorums_rpc_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: zorums.proto @@ -20,7 +20,7 @@ const ( // GRPCCall plain gRPC call; testing that Gorums can ignore these, but that // they are added to the _grpc.pb.go generated file. -func (n *Node) GRPCCall(ctx context.Context, in *Request) (resp *Response, err error) { +func (n *ZorumsServiceNode) GRPCCall(ctx context.Context, in *Request) (resp *Response, err error) { cd := gorums.CallData{ Message: in, Method: "dev.ZorumsService.GRPCCall", @@ -32,3 +32,18 @@ func (n *Node) GRPCCall(ctx context.Context, in *Request) (resp *Response, err e } return res.(*Response), err } + +// GRPCCall plain gRPC call; testing that Gorums can ignore these, but that +// they are added to the _grpc.pb.go generated file. +func (n *ZorumsNoQCServiceNode) GRPCCall(ctx context.Context, in *Request) (resp *Response, err error) { + cd := gorums.CallData{ + Message: in, + Method: "dev.ZorumsNoQCService.GRPCCall", + } + + res, err := n.RawNode.RPCCall(ctx, cd) + if err != nil { + return nil, err + } + return res.(*Response), err +} diff --git a/cmd/protoc-gen-gorums/dev/zorums_server_gorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums_server_gorums.pb.go index 4465ae0f..234d3e6f 100644 --- a/cmd/protoc-gen-gorums/dev/zorums_server_gorums.pb.go +++ b/cmd/protoc-gen-gorums/dev/zorums_server_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: zorums.proto @@ -20,7 +20,7 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// ZorumsService is the server-side API for the ZorumsService Service +// ZorumsServiceServer is the server-side API for the ZorumsService Service type ZorumsServiceServer interface { GRPCCall(ctx gorums.ServerCtx, request *Request) (response *Response, err error) QuorumCall(ctx gorums.ServerCtx, request *Request) (response *Response, err error) @@ -40,6 +40,9 @@ type ZorumsServiceServer interface { Unicast2(ctx gorums.ServerCtx, request *Request) } +// RegisterZorumsServiceServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterZorumsServiceServer(srv *gorums.Server, impl ZorumsServiceServer) { srv.RegisterHandler("dev.ZorumsService.GRPCCall", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*Request) @@ -155,3 +158,62 @@ func RegisterZorumsServiceServer(srv *gorums.Server, impl ZorumsServiceServer) { impl.Unicast2(ctx, req) }) } + +// ZorumsNoQCServiceServer is the server-side API for the ZorumsNoQCService Service +type ZorumsNoQCServiceServer interface { + GRPCCall(ctx gorums.ServerCtx, request *Request) (response *Response, err error) + Multicast(ctx gorums.ServerCtx, request *Request) + MulticastPerNodeArg(ctx gorums.ServerCtx, request *Request) + Multicast2(ctx gorums.ServerCtx, request *Request) + Multicast3(ctx gorums.ServerCtx, request *Request) + Multicast4(ctx gorums.ServerCtx, request *emptypb.Empty) + Unicast(ctx gorums.ServerCtx, request *Request) + Unicast2(ctx gorums.ServerCtx, request *Request) +} + +// RegisterZorumsNoQCServiceServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client +func RegisterZorumsNoQCServiceServer(srv *gorums.Server, impl ZorumsNoQCServiceServer) { + srv.RegisterHandler("dev.ZorumsNoQCService.GRPCCall", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { + req := in.Message.(*Request) + defer ctx.Release() + resp, err := impl.GRPCCall(ctx, req) + gorums.SendMessage(ctx, finished, gorums.WrapMessage(in.Metadata, resp, err)) + }) + srv.RegisterHandler("dev.ZorumsNoQCService.Multicast", func(ctx gorums.ServerCtx, in *gorums.Message, _ chan<- *gorums.Message) { + req := in.Message.(*Request) + defer ctx.Release() + impl.Multicast(ctx, req) + }) + srv.RegisterHandler("dev.ZorumsNoQCService.MulticastPerNodeArg", func(ctx gorums.ServerCtx, in *gorums.Message, _ chan<- *gorums.Message) { + req := in.Message.(*Request) + defer ctx.Release() + impl.MulticastPerNodeArg(ctx, req) + }) + srv.RegisterHandler("dev.ZorumsNoQCService.Multicast2", func(ctx gorums.ServerCtx, in *gorums.Message, _ chan<- *gorums.Message) { + req := in.Message.(*Request) + defer ctx.Release() + impl.Multicast2(ctx, req) + }) + srv.RegisterHandler("dev.ZorumsNoQCService.Multicast3", func(ctx gorums.ServerCtx, in *gorums.Message, _ chan<- *gorums.Message) { + req := in.Message.(*Request) + defer ctx.Release() + impl.Multicast3(ctx, req) + }) + srv.RegisterHandler("dev.ZorumsNoQCService.Multicast4", func(ctx gorums.ServerCtx, in *gorums.Message, _ chan<- *gorums.Message) { + req := in.Message.(*emptypb.Empty) + defer ctx.Release() + impl.Multicast4(ctx, req) + }) + srv.RegisterHandler("dev.ZorumsNoQCService.Unicast", func(ctx gorums.ServerCtx, in *gorums.Message, _ chan<- *gorums.Message) { + req := in.Message.(*Request) + defer ctx.Release() + impl.Unicast(ctx, req) + }) + srv.RegisterHandler("dev.ZorumsNoQCService.Unicast2", func(ctx gorums.ServerCtx, in *gorums.Message, _ chan<- *gorums.Message) { + req := in.Message.(*Request) + defer ctx.Release() + impl.Unicast2(ctx, req) + }) +} diff --git a/cmd/protoc-gen-gorums/dev/zorums_unicast_gorums.pb.go b/cmd/protoc-gen-gorums/dev/zorums_unicast_gorums.pb.go index e7d0b38f..e88ad623 100644 --- a/cmd/protoc-gen-gorums/dev/zorums_unicast_gorums.pb.go +++ b/cmd/protoc-gen-gorums/dev/zorums_unicast_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: zorums.proto @@ -19,10 +19,8 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// Unicast is a quorum call invoked on each node in configuration c, - -// with the same argument in, and returns the responses as an iterator. -func (n *Node) Unicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { +// Unicast is a one-way call; no replies are processed. +func (n *ZorumsServiceNode) Unicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { cd := gorums.CallData{ Message: in, Method: "dev.ZorumsService.Unicast", @@ -34,10 +32,8 @@ func (n *Node) Unicast(ctx context.Context, in *Request, opts ...gorums.CallOpti // Reference imports to suppress errors if they are not otherwise used. var _ emptypb.Empty -// Unicast2 is a quorum call invoked on each node in configuration c, - -// with the same argument in, and returns the responses as an iterator. -func (n *Node) Unicast2(ctx context.Context, in *Request, opts ...gorums.CallOption) { +// Unicast2 is a one-way call; no replies are processed. +func (n *ZorumsServiceNode) Unicast2(ctx context.Context, in *Request, opts ...gorums.CallOption) { cd := gorums.CallData{ Message: in, Method: "dev.ZorumsService.Unicast2", @@ -45,3 +41,26 @@ func (n *Node) Unicast2(ctx context.Context, in *Request, opts ...gorums.CallOpt n.RawNode.Unicast(ctx, cd, opts...) } + +// Unicast is a one-way call; no replies are processed. +func (n *ZorumsNoQCServiceNode) Unicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { + cd := gorums.CallData{ + Message: in, + Method: "dev.ZorumsNoQCService.Unicast", + } + + n.RawNode.Unicast(ctx, cd, opts...) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ emptypb.Empty + +// Unicast2 is a one-way call; no replies are processed. +func (n *ZorumsNoQCServiceNode) Unicast2(ctx context.Context, in *Request, opts ...gorums.CallOption) { + cd := gorums.CallData{ + Message: in, + Method: "dev.ZorumsNoQCService.Unicast2", + } + + n.RawNode.Unicast(ctx, cd, opts...) +} diff --git a/cmd/protoc-gen-gorums/gengorums/gorums.go b/cmd/protoc-gen-gorums/gengorums/gorums.go index 69ae2d9c..33e89780 100644 --- a/cmd/protoc-gen-gorums/gengorums/gorums.go +++ b/cmd/protoc-gen-gorums/gengorums/gorums.go @@ -77,12 +77,6 @@ func gorumsGuard(file *protogen.File) bool { // there is nothing for this plugin to do return false } - if len(file.Services) > 1 { - // To build multiple services, make separate proto files and - // run the plugin separately for each proto file. - // These cannot share the same Go package. - log.Fatalln("Gorums does not support multiple services in the same proto file.") - } // fail generator if a Gorums reserved identifier is used as a message name. for _, msg := range file.Messages { msgName := fmt.Sprintf("%v", msg.Desc.Name()) @@ -95,6 +89,31 @@ func gorumsGuard(file *protogen.File) bool { return true } +var reservedNames map[string]struct{} + +func initReservedNames() { + reservedNames = make(map[string]struct{}) +} + +func checkNameCollision(file *protogen.File) { + for _, msg := range file.Messages { + msgName := fmt.Sprintf("%v", msg.Desc.Name()) + + _, ok := reservedNames[msgName] + if ok { + log.Fatalf("%v.proto: contains message %s, which is a reserved Gorums service type.\n", file.GeneratedFilenamePrefix, msgName) + } + } +} + +func reserveName(name string) { + _, ok := reservedNames[name] + if ok { + log.Fatalf("reserveName: Redefinition of method %s.\n", name) + } + reservedNames[name] = struct{}{} +} + // GenerateFileContent generates the Gorums service definitions, excluding the package statement. func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile) { // sort the gorums types so that output remains stable across rebuilds @@ -103,9 +122,14 @@ func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen. sortedTypes = append(sortedTypes, gorumsType) } sort.Strings(sortedTypes) + + initReservedNames() + for _, gorumsType := range sortedTypes { genGorumsType(g, file.Services, gorumsType) } + + checkNameCollision(file) } // servicesData hold the services to generate and a reference to the file in which @@ -209,8 +233,10 @@ func callTypeName(ext *protoimpl.ExtensionInfo) string { // The entries in this map is used to generate dev/zorums_{type}.pb.go // files for the different keys. var gorumsCallTypesInfo = map[string]*callTypeInfo{ - "server": {template: server}, - "client": {template: client}, + "node": {template: node}, + "configuration": {template: configuration}, + "server": {template: server}, + "client": {template: client}, callTypeName(gorums.E_Rpc): { extInfo: gorums.E_Rpc, diff --git a/cmd/protoc-gen-gorums/gengorums/gorums_dev.go b/cmd/protoc-gen-gorums/gengorums/gorums_dev.go index d6e10f61..8951885b 100644 --- a/cmd/protoc-gen-gorums/gengorums/gorums_dev.go +++ b/cmd/protoc-gen-gorums/gengorums/gorums_dev.go @@ -10,9 +10,14 @@ func GenerateDevFiles(gen *protogen.Plugin, file *protogen.File) { if !gorumsGuard(file) { return } + + initReservedNames() + for gorumsType := range gorumsCallTypesInfo { generateDevFile(gen, file, gorumsType) } + + checkNameCollision(file) } func generateDevFile(gen *protogen.Plugin, file *protogen.File, gorumsType string) { diff --git a/cmd/protoc-gen-gorums/gengorums/gorums_func_map.go b/cmd/protoc-gen-gorums/gengorums/gorums_func_map.go index bd51879b..49e878a7 100644 --- a/cmd/protoc-gen-gorums/gengorums/gorums_func_map.go +++ b/cmd/protoc-gen-gorums/gengorums/gorums_func_map.go @@ -58,6 +58,14 @@ var funcMap = template.FuncMap{ } return g.QualifiedGoIdent(pkg.Ident(ident)) }, + "reserveName": func(name string) string { + reserveName(name) + return "" + }, + "reserveMethod": func(structName, methodName string) string { + reserveName(structName + "." + methodName) + return "" + }, "hasPerNodeArg": func(method *protogen.Method) bool { return hasMethodOption(method, gorums.E_PerNodeArg) }, diff --git a/cmd/protoc-gen-gorums/gengorums/gorums_test.go b/cmd/protoc-gen-gorums/gengorums/gorums_test.go index 1f7a27d8..8f30d541 100644 --- a/cmd/protoc-gen-gorums/gengorums/gorums_test.go +++ b/cmd/protoc-gen-gorums/gengorums/gorums_test.go @@ -4,7 +4,7 @@ import ( "testing" ) -//TODO(meling) Test various generator functions that are non-trivial +// TODO(meling) Test various generator functions that are non-trivial // methods to tests: // qspecMethods // qspecServices diff --git a/cmd/protoc-gen-gorums/gengorums/template_client.go b/cmd/protoc-gen-gorums/gengorums/template_client.go index 0a10e746..666befbf 100644 --- a/cmd/protoc-gen-gorums/gengorums/template_client.go +++ b/cmd/protoc-gen-gorums/gengorums/template_client.go @@ -6,17 +6,26 @@ import ( // gorums need to be imported in the zorums file var clientVariables = ` -{{$context := use "context.Context" .GenFile}} -{{$_ := use "gorums.EnforceVersion" .GenFile}} -{{$callOpt := use "gorums.CallOption" .GenFile}} +{{- $context := use "context.Context" .GenFile}} +{{- $_ := use "gorums.EnforceVersion" .GenFile}} +{{- $callOpt := use "gorums.CallOption" .GenFile}} +` + +var clientServicesBegin = ` + {{- $genFile := .GenFile}} + {{- range configurationsServices .Services}} + {{- $service := .GoName}} +` + +var clientServicesEnd = ` + {{- end}} ` var clientConfigurationInterface = ` -{{- $genFile := .GenFile}} -{{- range configurationsServices .Services}} - {{- $service := .GoName}} {{- $interfaceName := printf "%sClient" $service}} + {{- $configurationName := printf "%sConfiguration" $service}} // {{$interfaceName}} is the client interface for the {{$service}} service. + {{- reserveName $interfaceName}} type {{$interfaceName}} interface { {{- range configurationMethods .Methods}} {{- $method := .GoName}} @@ -30,16 +39,14 @@ var clientConfigurationInterface = ` {{- end}} } // enforce interface compliance - var _ {{$interfaceName}} = (*Configuration)(nil) -{{- end}} + var _ {{$interfaceName}} = (*{{$configurationName}})(nil) ` var clientNodeInterface = ` -{{- $genFile := .GenFile}} -{{- range nodeServices .Services}} - {{- $service := .GoName}} {{- $interfaceName := printf "%sNodeClient" $service}} + {{- $nodeName := printf "%sNode" $service}} // {{$interfaceName}} is the single node client interface for the {{$service}} service. + {{- reserveName $interfaceName}} type {{$interfaceName}} interface { {{- range nodeMethods .Methods}} {{- $method := .GoName}} @@ -52,11 +59,13 @@ var clientNodeInterface = ` {{- end}} } // enforce interface compliance - var _ {{$interfaceName}} = (*Node)(nil) -{{- end}} + var _ {{$interfaceName}} = (*{{$nodeName}})(nil) ` -var client = clientVariables + clientConfigurationInterface + clientNodeInterface +var client = clientVariables + + clientServicesBegin + + clientConfigurationInterface + clientNodeInterface + + clientServicesEnd // configurationsServices returns all services containing at least one multi node method. func configurationsServices(services []*protogen.Service) (s []*protogen.Service) { diff --git a/cmd/protoc-gen-gorums/gengorums/template_configuration.go b/cmd/protoc-gen-gorums/gengorums/template_configuration.go new file mode 100644 index 00000000..c0f7b062 --- /dev/null +++ b/cmd/protoc-gen-gorums/gengorums/template_configuration.go @@ -0,0 +1,129 @@ +package gengorums + +var configurationVars = ` +{{- $rawConfiguration := use "gorums.RawConfiguration" .GenFile}} +{{- $nodeListOptions := use "gorums.NodeListOption" .GenFile}} +` + +var configurationServicesBegin = ` +{{- $genFile := .GenFile}} +{{- range .Services}} + {{- $service := .GoName}} + {{- $configurationName := printf "%sConfiguration" $service}} + {{- $nodeName := printf "%sNode" $service}} +` + +var configurationServicesEnd = ` +{{- end}} +` + +var configurationStruct = ` +// A {{$configurationName}} represents a static set of nodes on which quorum remote +// procedure calls may be invoked. +{{- reserveName $configurationName}} +type {{$configurationName}} struct { + {{$rawConfiguration}} +} +` + +var newConfiguration = ` +{{- $funcName := printf "New%s" $configurationName}} +// {{$funcName}} returns a configuration based on the provided list of nodes (required) +// and an optional quorum specification. The QuorumSpec is necessary for call types that +// must process replies. For configurations only used for unicast or multicast call types, +// a QuorumSpec is not needed. +// Nodes can be supplied using WithNodeMap or WithNodeList. +// Using any other type of NodeListOption will not work. +// The ManagerOption list controls how the nodes in the configuration are created. +{{- reserveName $funcName}} +func {{$funcName}}(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *{{$configurationName}}, err error) { + c = &{{$configurationName}}{} + c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) + if err != nil { + return nil, err + } + return c, nil +} +` + +var subConfiguration = ` +{{- $methodName := printf "Sub%s" $configurationName}} +// {{$methodName}} allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, +// Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. +// A new configuration can also be created from an existing configuration, +// using the And, WithNewNodes, Except, and WithoutNodes methods. +{{- reserveMethod $configurationName $methodName}} +func (c *{{$configurationName}}) {{$methodName}}(cfg gorums.NodeListOption) (subCfg *{{$configurationName}}, err error) { + subCfg = &{{$configurationName}}{} + subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) + if err != nil { + return nil, err + } + return subCfg, nil +} +` + +var configurationFromRaw = ` +{{- $funcName := printf "%sFromRaw" $configurationName}} +// {{$funcName}} returns a new {{$configurationName}} from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +{{- reserveName $funcName}} +func {{$funcName}}(rawCfg {{$rawConfiguration}}) (*{{$configurationName}}, error) { + newCfg := &{{$configurationName}}{ + RawConfiguration: rawCfg, + } + return newCfg, nil +} +` + +var configurationMethodsTemplate = ` +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. +// +// NOTE: mutating the returned slice is not supported. +{{- reserveMethod $configurationName "Nodes"}} +func (c *{{$configurationName}}) Nodes() []*{{$nodeName}} { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*{{$nodeName}}, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &{{$nodeName}}{n} + } + return nodes +} + +// AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. +// +// NOTE: mutating the returned slice is not supported. +{{- reserveMethod $configurationName "AllNodes"}} +func (c *{{$configurationName}}) AllNodes() []*{{$nodeName}} { + rawNodes := c.RawConfiguration.AllNodes() + nodes := make([]*{{$nodeName}}, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &{{$nodeName}}{n} + } + return nodes +} + +// And returns a NodeListOption that can be used to create a new configuration combining c and d. +{{- reserveMethod $configurationName "And"}} +func (c {{$configurationName}}) And(d *{{$configurationName}}) {{$nodeListOptions}} { + return c.RawConfiguration.And(d.RawConfiguration) +} + +// Except returns a NodeListOption that can be used to create a new configuration +// from c without the nodes in rm. +{{- reserveMethod $configurationName "Except"}} +func (c {{$configurationName}}) Except(rm *{{$configurationName}}) {{$nodeListOptions}} { + return c.RawConfiguration.Except(rm.RawConfiguration) +} +` + +var configuration = configurationVars + + configurationServicesBegin + + configurationStruct + newConfiguration + subConfiguration + configurationFromRaw + configurationMethodsTemplate + + configurationServicesEnd diff --git a/cmd/protoc-gen-gorums/gengorums/template_multicast.go b/cmd/protoc-gen-gorums/gengorums/template_multicast.go index f433ea6a..c468ee28 100644 --- a/cmd/protoc-gen-gorums/gengorums/template_multicast.go +++ b/cmd/protoc-gen-gorums/gengorums/template_multicast.go @@ -8,37 +8,41 @@ var _ {{$out}} ` var mcVar = ` -{{$callData := use "gorums.QuorumCallData" .GenFile}} -{{$genFile := .GenFile}} -{{$unexportMethod := unexport .Method.GoName}} -{{$context := use "context.Context" .GenFile}} -{{$callOpt := use "gorums.CallOption" .GenFile}} + {{- $callData := use "gorums.QuorumCallData" .GenFile}} + {{- $genFile := .GenFile}} + {{- $unexportMethod := unexport .Method.GoName}} + {{- $context := use "context.Context" .GenFile}} + {{- $callOpt := use "gorums.CallOption" .GenFile}} ` -var multicastSignature = `func (c *Configuration) {{$method}}(` + +var multicastReserve = `{{reserveMethod $configurationName $method}}` + +var multicastSignature = `func (c *{{$configurationName}}) {{$method}}(` + `ctx {{$context}}, in *{{$in}}` + `{{perNodeFnType .GenFile .Method ", f"}},` + `opts ...{{$callOpt}}) { ` -var multicastBody = ` cd := {{$callData}}{ +var multicastBody = ` + cd := {{$callData}}{ Message: in, Method: "{{$fullName}}", } -{{- if hasPerNodeArg .Method}} -{{$protoMessage := use "proto.Message" .GenFile}} - cd.PerNodeArgFn = func(req {{$protoMessage}}, nid uint32) {{$protoMessage}} { - return f(req.(*{{$in}}), nid) - } -{{- end}} + {{- if hasPerNodeArg .Method}} + {{$protoMessage := use "proto.Message" .GenFile}} + cd.PerNodeArgFn = func(req {{$protoMessage}}, nid uint32) {{$protoMessage}} { + return f(req.(*{{$in}}), nid) + } + {{- end}} - c.RawConfiguration.Multicast(ctx, cd, opts...) -} + c.RawConfiguration.Multicast(ctx, cd, opts...) + } ` var multicastCall = commonVariables + mcVar + multicastRefImports + quorumCallComment + + multicastReserve + multicastSignature + multicastBody diff --git a/cmd/protoc-gen-gorums/gengorums/template_node.go b/cmd/protoc-gen-gorums/gengorums/template_node.go new file mode 100644 index 00000000..fadaeee2 --- /dev/null +++ b/cmd/protoc-gen-gorums/gengorums/template_node.go @@ -0,0 +1,22 @@ +package gengorums + +// gorums need to be imported in the zorums file +var nodeVariables = ` +{{- $_ := use "gorums.EnforceVersion" .GenFile}} +{{- $callOpt := use "gorums.CallOption" .GenFile}} +` + +var nodeStructs = ` +{{- $genFile := .GenFile}} +{{- range .Services}} + {{- $service := .GoName}} + {{- $nodeName := printf "%sNode" $service}} + // {{$nodeName}} holds the node specific methods for the {{$service}} service. + {{- reserveName $nodeName}} + type {{$nodeName}} struct { + *gorums.RawNode + } +{{- end}} +` + +var node = nodeVariables + nodeStructs diff --git a/cmd/protoc-gen-gorums/gengorums/template_quorumcall.go b/cmd/protoc-gen-gorums/gengorums/template_quorumcall.go index e0509d82..b72b937c 100644 --- a/cmd/protoc-gen-gorums/gengorums/template_quorumcall.go +++ b/cmd/protoc-gen-gorums/gengorums/template_quorumcall.go @@ -2,12 +2,15 @@ package gengorums // Common variables used in several template functions. var commonVariables = ` -{{$fullName := .Method.Desc.FullName}} -{{$method := .Method.GoName}} -{{$in := in .GenFile .Method}} -{{$out := out .GenFile .Method}} -{{$intOut := internalOut $out}} -{{$unexportOutput := unexport .Method.Output.GoIdent.GoName}} +{{- $fullName := .Method.Desc.FullName}} +{{- $method := .Method.GoName}} +{{- $in := in .GenFile .Method}} +{{- $out := out .GenFile .Method}} +{{- $intOut := internalOut $out}} +{{- $unexportOutput := unexport .Method.Output.GoIdent.GoName}} +{{- $service := .Method.Parent.GoName}} +{{- $nodeName := printf "%sNode" $service}} +{{- $configurationName := printf "%sConfiguration" $service}} ` // Common variables used in several template functions. @@ -36,17 +39,19 @@ var quorumCallComment = ` {{end -}} ` -var quorumCallSignature = `func (c *Configuration) {{$method}}(` + +var quorumCallReserve = `{{reserveMethod $configurationName $method}}` + +var quorumCallSignature = `func (c *{{$configurationName}}) {{$method}}(` + `ctx {{$context}}, in *{{$in}}` + `{{perNodeFnType .GenFile .Method ", f"}})` + `{{$iterator}}[*{{$out}}] { ` var qcVar = ` -{{$callData := use "gorums.QuorumCallData" .GenFile}} -{{$genFile := .GenFile}} -{{$unexportMethod := unexport .Method.GoName}} -{{$context := use "context.Context" .GenFile}} +{{- $callData := use "gorums.QuorumCallData" .GenFile}} +{{- $genFile := .GenFile}} +{{- $unexportMethod := unexport .Method.GoName}} +{{- $context := use "context.Context" .GenFile}} ` var quorumCallBody = ` cd := {{$callData}}{ @@ -69,5 +74,6 @@ var quorumCall = commonVariables + quorumCallVariables + qcVar + quorumCallComment + + quorumCallReserve + quorumCallSignature + quorumCallBody diff --git a/cmd/protoc-gen-gorums/gengorums/template_rpc.go b/cmd/protoc-gen-gorums/gengorums/template_rpc.go index 83783a92..5f829679 100644 --- a/cmd/protoc-gen-gorums/gengorums/template_rpc.go +++ b/cmd/protoc-gen-gorums/gengorums/template_rpc.go @@ -1,27 +1,29 @@ package gengorums -var rpcSignature = `func (n *Node) {{$method}}(` + - `ctx {{$context}}, in *{{$in}}` + - `{{perNodeFnType .GenFile .Method ", f"}}) (resp *{{$out}}, err error) { +var rpcVar = ` + {{- $callData := use "gorums.CallData" .GenFile}} + {{- $genFile := .GenFile}} + {{- $unexportMethod := unexport .Method.GoName}} + {{- $context := use "context.Context" .GenFile}} ` -var rpcVar = ` -{{$callData := use "gorums.CallData" .GenFile}} -{{$genFile := .GenFile}} -{{$unexportMethod := unexport .Method.GoName}} -{{$context := use "context.Context" .GenFile}} +var rpcReserve = `{{reserveMethod $nodeName $method}}` + +var rpcSignature = `func (n *{{$nodeName}}) {{$method}}(` + + `ctx {{$context}}, in *{{$in}}` + + `{{perNodeFnType .GenFile .Method ", f"}}) (resp *{{$out}}, err error) { ` var rpcBody = ` cd := {{$callData}}{ Message: in, Method: "{{$fullName}}", } -{{- if hasPerNodeArg .Method}} - {{$protoMessage := use "proto.Message" $genFile}} - cd.PerNodeArgFn = func(req {{$protoMessage}}, nid uint32) {{$protoMessage}} { - return f(req.(*{{$in}}), nid) - } -{{- end}} + {{- if hasPerNodeArg .Method}} + {{$protoMessage := use "proto.Message" $genFile}} + cd.PerNodeArgFn = func(req {{$protoMessage}}, nid uint32) {{$protoMessage}} { + return f(req.(*{{$in}}), nid) + } + {{- end}} res, err := n.RawNode.RPCCall(ctx, cd) if err != nil { @@ -34,5 +36,6 @@ var rpcBody = ` cd := {{$callData}}{ var rpcCall = commonVariables + rpcVar + quorumCallComment + + rpcReserve + rpcSignature + rpcBody diff --git a/cmd/protoc-gen-gorums/gengorums/template_server.go b/cmd/protoc-gen-gorums/gengorums/template_server.go index c513aab9..716c2cb8 100644 --- a/cmd/protoc-gen-gorums/gengorums/template_server.go +++ b/cmd/protoc-gen-gorums/gengorums/template_server.go @@ -1,15 +1,27 @@ package gengorums var serverVariables = ` -{{$context := use "gorums.ServerCtx" .GenFile}} +{{- $context := use "gorums.ServerCtx" .GenFile}} +{{- $gorumsMessage := use "gorums.Message" .GenFile}} +{{- $wrapMessage := use "gorums.WrapMessage" .GenFile}} +{{- $sendMessage := use "gorums.SendMessage" .GenFile}} +` + +var serverServicesBegin = ` +{{- $genFile := .GenFile}} +{{- range .Services}} + {{- $service := .GoName}} + {{- $serverName := printf "%sServer" $service}} +` + +var serverServicesEnd = ` +{{- end}} ` var serverInterface = ` -{{$genFile := .GenFile}} -{{range .Services -}} -{{$service := .GoName}} -// {{$service}} is the server-side API for the {{$service}} Service -type {{$service}}Server interface { +// {{$serverName}} is the server-side API for the {{$service}} Service +{{- reserveName $serverName}} +type {{$serverName}} interface { {{- range .Methods}} {{- if isOneway .}} {{.GoName}}(ctx {{$context}}, request *{{in $genFile .}}) @@ -20,17 +32,15 @@ type {{$service}}Server interface { {{- end}} {{- end}} } -{{- end}} ` var registerInterface = ` -{{$genFile := .GenFile}} -{{$gorumsMessage := use "gorums.Message" .GenFile}} -{{$wrapMessage := use "gorums.WrapMessage" $genFile}} -{{$sendMessage := use "gorums.SendMessage" $genFile}} -{{range .Services -}} -{{$service := .GoName}} -func Register{{$service}}Server(srv *{{use "gorums.Server" $genFile}}, impl {{$service}}Server) { +{{- $funcName := printf "Register%s" $serverName}} +// {{$funcName}} adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client +{{- reserveName $funcName}} +func {{$funcName}}(srv *{{use "gorums.Server" $genFile}}, impl {{$serverName}}) { {{- range .Methods}} srv.RegisterHandler("{{.Desc.FullName}}", func(ctx {{$context}}, in *{{$gorumsMessage}}, {{if isOneway .}} _ {{- else}} finished {{- end}} chan<- *{{$gorumsMessage}}) { req := in.Message.(*{{in $genFile .}}) @@ -53,7 +63,9 @@ func Register{{$service}}Server(srv *{{use "gorums.Server" $genFile}}, impl {{$s }) {{- end}} } -{{- end}} ` -var server = serverVariables + serverInterface + registerInterface +var server = serverVariables + + serverServicesBegin + + serverInterface + registerInterface + + serverServicesEnd diff --git a/cmd/protoc-gen-gorums/gengorums/template_static.go b/cmd/protoc-gen-gorums/gengorums/template_static.go index 13366416..f60996f9 100644 --- a/cmd/protoc-gen-gorums/gengorums/template_static.go +++ b/cmd/protoc-gen-gorums/gengorums/template_static.go @@ -9,104 +9,12 @@ var pkgIdentMap = map[string]string{"github.com/relab/gorums": "ContentSubtype", // reservedIdents holds the set of Gorums reserved identifiers. // These identifiers cannot be used to define message types in a proto file. -var reservedIdents = []string{"Configuration", "Node"} +var reservedIdents = []string(nil) -var staticCode = `// A Configuration represents a static set of nodes on which quorum remote -// procedure calls may be invoked. -type Configuration struct { - gorums.RawConfiguration -} - -// NewConfiguration returns a configuration based on the provided list of nodes (required) -// and an optional quorum specification. The QuorumSpec is necessary for call types that -// must process replies. For configurations only used for unicast or multicast call types, -// a QuorumSpec is not needed. -// Nodes can be supplied using WithNodeMap or WithNodeList. -// Using any other type of NodeListOption will not work. -// The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} - c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) - if err != nil { - return nil, err - } - return c, nil -} - -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, -// Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. -// A new configuration can also be created from an existing configuration, -// using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} - subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) - if err != nil { - return nil, err - } - return subCfg, nil -} - -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() -} - -// Nodes returns a slice of the configuration nodes. Sorted by node id. -// -// NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} - } - return nodes -} - -// AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. -// -// NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { - rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) - for i, n := range rawNodes { - nodes[i] = &Node{n} - } - return nodes -} - -// And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { - return c.RawConfiguration.And(d.RawConfiguration) -} - -// Except returns a NodeListOption that can be used to create a new configuration -// from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { - return c.RawConfiguration.Except(rm.RawConfiguration) -} - -func init() { +var staticCode = `func init() { if encoding.GetCodec(gorums.ContentSubtype) == nil { encoding.RegisterCodec(gorums.NewCodec()) } } -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { - *gorums.RawNode -} - ` diff --git a/cmd/protoc-gen-gorums/gengorums/template_unicast.go b/cmd/protoc-gen-gorums/gengorums/template_unicast.go index 89b2bb89..044a2272 100644 --- a/cmd/protoc-gen-gorums/gengorums/template_unicast.go +++ b/cmd/protoc-gen-gorums/gengorums/template_unicast.go @@ -1,8 +1,20 @@ package gengorums -var unicastVar = rpcVar + `{{$callOpt := use "gorums.CallOption" .GenFile}}` +var unicastVar = rpcVar + ` + {{$callOpt := use "gorums.CallOption" .GenFile}} + {{$nodeName := printf "%sNode" .Method.Parent.GoName}} +` + +var unicastCallComment = ` +{{$comments := .Method.Comments.Leading}} +{{if ne $comments ""}} +{{$comments -}} +{{else}} +// {{$method}} is a one-way call; no replies are processed. +{{end -}} +` -var unicastSignature = `func (n *Node) {{$method}}(` + +var unicastSignature = `func (n *{{$nodeName}}) {{$method}}(` + `ctx {{$context}}, in *{{$in}}, opts ...{{$callOpt}}) { ` @@ -18,6 +30,6 @@ var unicastBody = ` cd := {{$callData}}{ var unicastCall = commonVariables + unicastVar + multicastRefImports + - quorumCallComment + + unicastCallComment + unicastSignature + unicastBody diff --git a/config_test.go b/config_test.go index 279ce4a7..13edf0fc 100644 --- a/config_test.go +++ b/config_test.go @@ -208,7 +208,7 @@ func TestConfigConcurrentAccess(t *testing.T) { }) defer teardown() - cfg, err := dummy.NewConfiguration(gorums.WithNodeList(addrs), gorumsTestMgrOpts()...) + cfg, err := dummy.NewDummyConfiguration(gorums.WithNodeList(addrs), gorumsTestMgrOpts()...) if err != nil { t.Fatal(err) } @@ -239,24 +239,24 @@ func TestConfigRelease(t *testing.T) { }) defer teardown() - c1, err := dummy.NewConfiguration(gorums.WithNodeList(addrs[:3]), gorumsTestMgrOpts()...) + c1, err := dummy.NewDummyConfiguration(gorums.WithNodeList(addrs[:3]), gorumsTestMgrOpts()...) if err != nil { t.Fatal(err) } - c2, err := c1.SubConfiguration(gorums.WithNodeList(addrs[2:8])) + c2, err := c1.SubDummyConfiguration(gorums.WithNodeList(addrs[2:8])) if err != nil { t.Fatal(err) } - c3, err := c1.SubConfiguration(gorums.WithNodeList(addrs[5:])) + c3, err := c1.SubDummyConfiguration(gorums.WithNodeList(addrs[5:])) if err != nil { t.Fatal(err) } allNodes := c2.AllNodeIDs() - c1c2, err := c2.SubConfiguration(c1.And(c2)) + c1c2, err := c2.SubDummyConfiguration(c1.And(c2)) if err != nil { t.Fatal(err) } diff --git a/doc/user-guide.md b/doc/user-guide.md index 426acac2..c203fba4 100644 --- a/doc/user-guide.md +++ b/doc/user-guide.md @@ -300,8 +300,8 @@ service QCStorage { The generated methods have the following client-side interface: ```go -func (c *Configuration) Read(ctx context.Context, in *ReadRequest) gorums.Responses[*State] -func (c *Configuration) Write(ctx context.Context, in *State) gorums.Responses[*WriteResponse] +func (c *QCStorageConfiguration) Read(ctx context.Context, in *ReadRequest) gorums.Responses[*State] +func (c *QCStorageConfiguration) Write(ctx context.Context, in *State) gorums.Responses[*WriteResponse] ``` ## The quorum call responses @@ -372,16 +372,13 @@ func ExampleStorageClient() { "127.0.0.1:8082", } - mgr := NewManager( + // Create a configuration including all nodes + allNodesConfig, err := examplepb.NewQCStorageConfiguration( + gorums.WithNodeList(addrs), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), ), ) - // Create a configuration including all nodes - allNodesConfig, err := mgr.NewConfiguration( - &QSpec{2}, - gorums.WithNodeList(addrs), - ) if err != nil { log.Fatalln("error creating read config:", err) } @@ -411,7 +408,7 @@ func ExampleConfigClient() { "127.0.0.1:8082", } // Make configuration c1 from addrs, giving |c1| = |addrs| = 3 - c1, _ := mgr.NewConfiguration( + c1, _ := examplepb.NewExampleConfiguration( gorums.WithNodeList(addrs), ) @@ -419,28 +416,28 @@ func ExampleConfigClient() { "127.0.0.1:9080", "127.0.0.1:9081", } - // Make configuration c2 from newAddrs, giving |c2| = |newAddrs| = 2 - c2, _ := mgr.NewConfiguration( + // Make subconfiguration c2 from newAddrs, giving |c2| = |newAddrs| = 2 + c2, _ := c1.SubExampleConfiguration( gorums.WithNodeList(newAddrs), ) - // Make new configuration c3 from c1 and newAddrs, giving |c3| = |c1| + |newAddrs| = 3+2=5 - c3, _ := mgr.NewConfiguration( + // Make new subconfiguration c3 from c1 and newAddrs, giving |c3| = |c1| + |newAddrs| = 3+2=5 + c3, _ := c1.SubExampleConfiguration( c1.WithNewNodes(gorums.WithNodeList(newAddrs)), ) - // Make new configuration c4 from c1 and c2, giving |c4| = |c1| + |c2| = 3+2=5 - c4, _ := mgr.NewConfiguration( + // Make new subconfiguration c4 from c1 and c2, giving |c4| = |c1| + |c2| = 3+2=5 + c4, _ := c1.SubExampleConfiguration( c1.And(c2), ) - // Make new configuration c5 from c1 except the first node from c1, giving |c5| = |c1| - 1 = 3-1 = 2 - c5, _ := mgr.NewConfiguration( + // Make new subconfiguration c5 from c1 except the first node from c1, giving |c5| = |c1| - 1 = 3-1 = 2 + c5, _ := c1.SubExampleConfiguration( c1.WithoutNodes(c1.NodeIDs()[0]), ) - // Make new configuration c6 from c3 except c1, giving |c6| = |c3| - |c1| = 5-3 = 2 - c6, _ := mgr.NewConfiguration( + // Make new subconfiguration c6 from c3 except c1, giving |c6| = |c3| - |c1| = 5-3 = 2 + c6, _ := c1.SubExampleConfiguration( c3.Except(c1), ) } diff --git a/examples/storage/client.go b/examples/storage/client.go index 688d4041..04e67bc0 100644 --- a/examples/storage/client.go +++ b/examples/storage/client.go @@ -17,7 +17,7 @@ func runClient(addresses []string) error { } // create configuration containing all nodes - cfg, err := proto.NewConfiguration( + cfg, err := proto.NewStorageConfiguration( gorums.WithNodeList(addresses), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), // disable TLS diff --git a/examples/storage/proto/storage_gorums.pb.go b/examples/storage/proto/storage_gorums.pb.go index 91619606..388e8e0e 100644 --- a/examples/storage/proto/storage_gorums.pb.go +++ b/examples/storage/proto/storage_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+abcec912 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: storage/proto/storage.proto @@ -20,21 +20,46 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// StorageClient is the client interface for the Storage service. +type StorageClient interface { + ReadQC(ctx context.Context, in *ReadRequest) gorums.Responses[*ReadResponse] + WriteQC(ctx context.Context, in *WriteRequest) gorums.Responses[*WriteResponse] + WriteMulticast(ctx context.Context, in *WriteRequest, opts ...gorums.CallOption) +} + +// enforce interface compliance +var _ StorageClient = (*StorageConfiguration)(nil) + +// StorageNodeClient is the single node client interface for the Storage service. +type StorageNodeClient interface { + ReadRPC(ctx context.Context, in *ReadRequest) (resp *ReadResponse, err error) + WriteRPC(ctx context.Context, in *WriteRequest) (resp *WriteResponse, err error) +} + +// enforce interface compliance +var _ StorageNodeClient = (*StorageNode)(nil) + +// A StorageConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type StorageConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewStorageConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewStorageConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *StorageConfiguration, err error) { + c = &StorageConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -42,24 +67,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubStorageConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *StorageConfiguration) SubStorageConfiguration(cfg gorums.NodeListOption) (subCfg *StorageConfiguration, err error) { + subCfg = &StorageConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -67,18 +81,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// StorageConfigurationFromRaw returns a new StorageConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func StorageConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*StorageConfiguration, error) { + newCfg := &StorageConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *StorageConfiguration) Nodes() []*StorageNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*StorageNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &StorageNode{n} } return nodes } @@ -86,64 +110,34 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *StorageConfiguration) AllNodes() []*StorageNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*StorageNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &StorageNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c StorageConfiguration) And(d *StorageConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c StorageConfiguration) Except(rm *StorageConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { - *gorums.RawNode -} - -// StorageClient is the client interface for the Storage service. -type StorageClient interface { - ReadQC(ctx context.Context, in *ReadRequest) gorums.Responses[*ReadResponse] - WriteQC(ctx context.Context, in *WriteRequest) gorums.Responses[*WriteResponse] - WriteMulticast(ctx context.Context, in *WriteRequest, opts ...gorums.CallOption) -} - -// enforce interface compliance -var _ StorageClient = (*Configuration)(nil) - -// StorageNodeClient is the single node client interface for the Storage service. -type StorageNodeClient interface { - ReadRPC(ctx context.Context, in *ReadRequest) (resp *ReadResponse, err error) - WriteRPC(ctx context.Context, in *WriteRequest) (resp *WriteResponse, err error) -} - -// enforce interface compliance -var _ StorageNodeClient = (*Node)(nil) - // Reference imports to suppress errors if they are not otherwise used. var _ emptypb.Empty // WriteMulticast is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) WriteMulticast(ctx context.Context, in *WriteRequest, opts ...gorums.CallOption) { +func (c *StorageConfiguration) WriteMulticast(ctx context.Context, in *WriteRequest, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "storage.Storage.WriteMulticast", @@ -152,9 +146,14 @@ func (c *Configuration) WriteMulticast(ctx context.Context, in *WriteRequest, op c.RawConfiguration.Multicast(ctx, cd, opts...) } +// StorageNode holds the node specific methods for the Storage service. +type StorageNode struct { + *gorums.RawNode +} + // ReadQC executes the Read Quorum Call on a configuration // of Nodes and returns the most recent value. -func (c *Configuration) ReadQC(ctx context.Context, in *ReadRequest) gorums.Responses[*ReadResponse] { +func (c *StorageConfiguration) ReadQC(ctx context.Context, in *ReadRequest) gorums.Responses[*ReadResponse] { cd := gorums.QuorumCallData{ Message: in, Method: "storage.Storage.ReadQC", @@ -166,7 +165,7 @@ func (c *Configuration) ReadQC(ctx context.Context, in *ReadRequest) gorums.Resp // WriteQC executes the Write Quorum Call on a configuration // of Nodes and returns true if a majority of Nodes were updated. -func (c *Configuration) WriteQC(ctx context.Context, in *WriteRequest) gorums.Responses[*WriteResponse] { +func (c *StorageConfiguration) WriteQC(ctx context.Context, in *WriteRequest) gorums.Responses[*WriteResponse] { cd := gorums.QuorumCallData{ Message: in, Method: "storage.Storage.WriteQC", @@ -177,7 +176,7 @@ func (c *Configuration) WriteQC(ctx context.Context, in *WriteRequest) gorums.Re } // ReadRPC executes the Read RPC on a single Node -func (n *Node) ReadRPC(ctx context.Context, in *ReadRequest) (resp *ReadResponse, err error) { +func (n *StorageNode) ReadRPC(ctx context.Context, in *ReadRequest) (resp *ReadResponse, err error) { cd := gorums.CallData{ Message: in, Method: "storage.Storage.ReadRPC", @@ -191,7 +190,7 @@ func (n *Node) ReadRPC(ctx context.Context, in *ReadRequest) (resp *ReadResponse } // WriteRPC executes the Write RPC on a single Node -func (n *Node) WriteRPC(ctx context.Context, in *WriteRequest) (resp *WriteResponse, err error) { +func (n *StorageNode) WriteRPC(ctx context.Context, in *WriteRequest) (resp *WriteResponse, err error) { cd := gorums.CallData{ Message: in, Method: "storage.Storage.WriteRPC", @@ -204,7 +203,7 @@ func (n *Node) WriteRPC(ctx context.Context, in *WriteRequest) (resp *WriteRespo return res.(*WriteResponse), err } -// Storage is the server-side API for the Storage Service +// StorageServer is the server-side API for the Storage Service type StorageServer interface { ReadRPC(ctx gorums.ServerCtx, request *ReadRequest) (response *ReadResponse, err error) WriteRPC(ctx gorums.ServerCtx, request *WriteRequest) (response *WriteResponse, err error) @@ -213,6 +212,9 @@ type StorageServer interface { WriteMulticast(ctx gorums.ServerCtx, request *WriteRequest) } +// RegisterStorageServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterStorageServer(srv *gorums.Server, impl StorageServer) { srv.RegisterHandler("storage.Storage.ReadRPC", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*ReadRequest) diff --git a/examples/storage/repl.go b/examples/storage/repl.go index 8ec34234..2305200f 100644 --- a/examples/storage/repl.go +++ b/examples/storage/repl.go @@ -52,11 +52,11 @@ The command performs the write quorum call on node 0 and 2 ` type repl struct { - cfg *pb.Configuration + cfg *pb.StorageConfiguration term *term.Terminal } -func newRepl(cfg *pb.Configuration) *repl { +func newRepl(cfg *pb.StorageConfiguration) *repl { return &repl{ cfg: cfg, term: term.NewTerminal(struct { @@ -88,7 +88,7 @@ func (r repl) ReadLine() (string, error) { // Repl runs an interactive Read-eval-print loop, that allows users to run commands that perform // RPCs and quorum calls using the manager and configuration. -func Repl(cfg *pb.Configuration) error { +func Repl(cfg *pb.StorageConfiguration) error { r := newRepl(cfg) fmt.Println(help) @@ -208,7 +208,7 @@ func (r repl) qcCfg(args []string) { } } -func (repl) readRPC(args []string, node *pb.Node) { +func (repl) readRPC(args []string, node *pb.StorageNode) { if len(args) < 1 { fmt.Println("Read requires a key to read.") return @@ -227,7 +227,7 @@ func (repl) readRPC(args []string, node *pb.Node) { fmt.Printf("%s = %s\n", args[0], resp.GetValue()) } -func (repl) writeRPC(args []string, node *pb.Node) { +func (repl) writeRPC(args []string, node *pb.StorageNode) { if len(args) < 2 { fmt.Println("Write requires a key and a value to write.") return @@ -246,7 +246,7 @@ func (repl) writeRPC(args []string, node *pb.Node) { fmt.Println("Write OK") } -func (repl) readQC(args []string, cfg *pb.Configuration) { +func (repl) readQC(args []string, cfg *pb.StorageConfiguration) { if len(args) < 1 { fmt.Println("Read requires a key to read.") return @@ -268,7 +268,7 @@ func (repl) readQC(args []string, cfg *pb.Configuration) { fmt.Printf("%s = %s\n", args[0], resp.GetValue()) } -func (repl) writeQC(args []string, cfg *pb.Configuration) { +func (repl) writeQC(args []string, cfg *pb.StorageConfiguration) { if len(args) < 2 { fmt.Println("Write requires a key and a value to write.") return @@ -288,7 +288,7 @@ func (repl) writeQC(args []string, cfg *pb.Configuration) { fmt.Println("Write OK") } -func (r repl) parseConfiguration(cfgStr string) (cfg *pb.Configuration) { +func (r repl) parseConfiguration(cfgStr string) (cfg *pb.StorageConfiguration) { // configuration using range syntax if i := strings.Index(cfgStr, ":"); i > -1 { var start, stop int @@ -320,7 +320,7 @@ func (r repl) parseConfiguration(cfgStr string) (cfg *pb.Configuration) { for _, node := range r.cfg.AllNodes()[start:stop] { nodes = append(nodes, node.Address()) } - cfg, err = r.cfg.SubConfiguration(gorums.WithNodeList(nodes)) + cfg, err = r.cfg.SubStorageConfiguration(gorums.WithNodeList(nodes)) if err != nil { fmt.Printf("Failed to create configuration: %v\n", err) return nil @@ -343,7 +343,7 @@ func (r repl) parseConfiguration(cfgStr string) (cfg *pb.Configuration) { } selectedNodes = append(selectedNodes, nodes[i].Address()) } - cfg, err := r.cfg.SubConfiguration(gorums.WithNodeList(selectedNodes)) + cfg, err := r.cfg.SubStorageConfiguration(gorums.WithNodeList(selectedNodes)) if err != nil { fmt.Printf("Failed to create configuration: %v\n", err) return nil diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 00000000..b528810f --- /dev/null +++ b/go.work.sum @@ -0,0 +1,40 @@ +cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= +cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 h1:boJj011Hh+874zpIySeApCX4GeOjPl9qhRF3QuIZq+Q= +github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= +github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= +github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= +github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= +github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//snGVIM3Tx6QRzlQBao= +go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= +golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk= +golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24= +google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/testprotos/failing/reservednames/reserved.proto b/internal/testprotos/failing/reservednames/reserved.proto index 13399cf5..78ffb41d 100644 --- a/internal/testprotos/failing/reservednames/reserved.proto +++ b/internal/testprotos/failing/reservednames/reserved.proto @@ -11,15 +11,28 @@ option features.field_presence = IMPLICIT; import "gorums.proto"; service Reserved { - rpc ConfTest(Configuration) returns (Manager) {} - rpc QuorumCall(Configuration) returns (Manager) { + rpc ConfTest(ReservedConfiguration) returns (ReservedNode) {} + rpc QuorumCall(ReservedServer) returns (ReservedClient) { option (gorums.quorumcall) = true; } } -message Configuration { +message ReservedNode { + string Node = 1; +} + +message ReservedServer { + string Srv = 1; +} + +message ReservedConfiguration { string Conf = 1; } -message Manager { - string Mgr = 1; + +message ReservedClient { + string Client = 1; +} + +message ReservedNodeClient { + string NClient = 1; } diff --git a/rpc_test.go b/rpc_test.go index 824c693e..e02e75b1 100644 --- a/rpc_test.go +++ b/rpc_test.go @@ -18,7 +18,7 @@ func TestRPCCallSuccess(t *testing.T) { }) defer teardown() - cfg, err := dummy.NewConfiguration(gorums.WithNodeList(addrs), gorumsTestMgrOpts()...) + cfg, err := dummy.NewDummyConfiguration(gorums.WithNodeList(addrs), gorumsTestMgrOpts()...) if err != nil { t.Fatal(err) } @@ -43,7 +43,7 @@ func TestRPCCallDownedNode(t *testing.T) { return initServer() }) - cfg, err := dummy.NewConfiguration(gorums.WithNodeList(addrs), gorumsTestMgrOpts()...) + cfg, err := dummy.NewDummyConfiguration(gorums.WithNodeList(addrs), gorumsTestMgrOpts()...) if err != nil { t.Fatal(err) } @@ -71,7 +71,7 @@ func TestRPCCallTimedOut(t *testing.T) { }) defer teardown() - cfg, err := dummy.NewConfiguration(gorums.WithNodeList(addrs), gorumsTestMgrOpts()...) + cfg, err := dummy.NewDummyConfiguration(gorums.WithNodeList(addrs), gorumsTestMgrOpts()...) if err != nil { t.Fatal(err) } diff --git a/tests/config/config_gorums.pb.go b/tests/config/config_gorums.pb.go index 7e491a4f..b46b587e 100644 --- a/tests/config/config_gorums.pb.go +++ b/tests/config/config_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: config/config.proto @@ -19,21 +19,42 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// ConfigTestClient is the client interface for the ConfigTest service. +type ConfigTestClient interface { + Config(ctx context.Context, in *Request) gorums.Responses[*Response] +} + +// enforce interface compliance +var _ ConfigTestClient = (*ConfigTestConfiguration)(nil) + +// ConfigTestNodeClient is the single node client interface for the ConfigTest service. +type ConfigTestNodeClient interface { +} + +// enforce interface compliance +var _ ConfigTestNodeClient = (*ConfigTestNode)(nil) + +// A ConfigTestConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type ConfigTestConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewConfigTestConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewConfigTestConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *ConfigTestConfiguration, err error) { + c = &ConfigTestConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -41,24 +62,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubConfigTestConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *ConfigTestConfiguration) SubConfigTestConfiguration(cfg gorums.NodeListOption) (subCfg *ConfigTestConfiguration, err error) { + subCfg = &ConfigTestConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -66,18 +76,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// ConfigTestConfigurationFromRaw returns a new ConfigTestConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func ConfigTestConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*ConfigTestConfiguration, error) { + newCfg := &ConfigTestConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *ConfigTestConfiguration) Nodes() []*ConfigTestNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*ConfigTestNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &ConfigTestNode{n} } return nodes } @@ -85,50 +105,35 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *ConfigTestConfiguration) AllNodes() []*ConfigTestNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*ConfigTestNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &ConfigTestNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c ConfigTestConfiguration) And(d *ConfigTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c ConfigTestConfiguration) Except(rm *ConfigTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { +// ConfigTestNode holds the node specific methods for the ConfigTest service. +type ConfigTestNode struct { *gorums.RawNode } -// ConfigTestClient is the client interface for the ConfigTest service. -type ConfigTestClient interface { - Config(ctx context.Context, in *Request) gorums.Responses[*Response] -} - -// enforce interface compliance -var _ ConfigTestClient = (*Configuration)(nil) - // Config is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) Config(ctx context.Context, in *Request) gorums.Responses[*Response] { +func (c *ConfigTestConfiguration) Config(ctx context.Context, in *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "config.ConfigTest.Config", @@ -138,11 +143,14 @@ func (c *Configuration) Config(ctx context.Context, in *Request) gorums.Response return gorums.QuorumCall[*Response](ctx, c.RawConfiguration, cd) } -// ConfigTest is the server-side API for the ConfigTest Service +// ConfigTestServer is the server-side API for the ConfigTest Service type ConfigTestServer interface { Config(ctx gorums.ServerCtx, request *Request) (response *Response, err error) } +// RegisterConfigTestServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterConfigTestServer(srv *gorums.Server, impl ConfigTestServer) { srv.RegisterHandler("config.ConfigTest.Config", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*Request) diff --git a/tests/config/config_test.go b/tests/config/config_test.go index 98f7c008..de3c0492 100644 --- a/tests/config/config_test.go +++ b/tests/config/config_test.go @@ -24,7 +24,7 @@ func (srv cfgSrv) Config(_ gorums.ServerCtx, req *Request) (resp *Response, err // setup returns a new configuration of cfgSize and a corresponding teardown function. // Calling setup multiple times will return a different configuration with different // sets of nodes. -func setup(t *testing.T, cfgSize int, mainCfg *Configuration, opts ...gorums.ManagerOption) (cfg *Configuration, teardown func()) { +func setup(t *testing.T, cfgSize int, mainCfg *ConfigTestConfiguration, opts ...gorums.ManagerOption) (cfg *ConfigTestConfiguration, teardown func()) { t.Helper() srvs := make([]*cfgSrv, cfgSize) for i := range srvs { @@ -41,9 +41,9 @@ func setup(t *testing.T, cfgSize int, mainCfg *Configuration, opts ...gorums.Man var err error if mainCfg != nil { - cfg, err = mainCfg.SubConfiguration(gorums.WithNodeList(addrs)) + cfg, err = mainCfg.SubConfigTestConfiguration(gorums.WithNodeList(addrs)) } else { - cfg, err = NewConfiguration(gorums.WithNodeList(addrs), opts...) + cfg, err = NewConfigTestConfiguration(gorums.WithNodeList(addrs), opts...) mainCfg = cfg } if err != nil { @@ -56,7 +56,7 @@ func setup(t *testing.T, cfgSize int, mainCfg *Configuration, opts ...gorums.Man return cfg, teardown } -func configQF(cfg *Configuration, req *Request) (*Response, error) { +func configQF(cfg *ConfigTestConfiguration, req *Request) (*Response, error) { quorum := cfg.Size()/2 + 1 replyCount := int(0) replies := cfg.Config(context.Background(), req) @@ -73,7 +73,7 @@ func configQF(cfg *Configuration, req *Request) (*Response, error) { // TestConfig creates and combines multiple configurations and invokes the Config RPC // method on the different configurations created below. func TestConfig(t *testing.T) { - callRPC := func(cfg *Configuration) { + callRPC := func(cfg *ConfigTestConfiguration) { for i := range 5 { reply, err := configQF(cfg, Request_builder{Num: uint64(i)}.Build()) if err != nil { @@ -97,7 +97,7 @@ func TestConfig(t *testing.T) { callRPC(c2) newNodeList := c1.And(c2) - c3, err := c1.SubConfiguration(newNodeList) + c3, err := c1.SubConfigTestConfiguration(newNodeList) if err != nil { t.Fatal(err) } @@ -105,7 +105,7 @@ func TestConfig(t *testing.T) { callRPC(c3) rmNodeList := c3.Except(c1) - c4, err := c1.SubConfiguration(rmNodeList) + c4, err := c1.SubConfigTestConfiguration(rmNodeList) if err != nil { t.Fatal(err) } diff --git a/tests/correctable/correctable_gorums.pb.go b/tests/correctable/correctable_gorums.pb.go index 06484517..1717b046 100644 --- a/tests/correctable/correctable_gorums.pb.go +++ b/tests/correctable/correctable_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: correctable/correctable.proto @@ -21,21 +21,43 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// CorrectableTestClient is the client interface for the CorrectableTest service. +type CorrectableTestClient interface { + Correctable(ctx context.Context, in *CorrectableRequest) gorums.Responses[*CorrectableResponse] + CorrectableStream(ctx context.Context, in *CorrectableRequest) gorums.Responses[*CorrectableResponse] +} + +// enforce interface compliance +var _ CorrectableTestClient = (*CorrectableTestConfiguration)(nil) + +// CorrectableTestNodeClient is the single node client interface for the CorrectableTest service. +type CorrectableTestNodeClient interface { +} + +// enforce interface compliance +var _ CorrectableTestNodeClient = (*CorrectableTestNode)(nil) + +// A CorrectableTestConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type CorrectableTestConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewCorrectableTestConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewCorrectableTestConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *CorrectableTestConfiguration, err error) { + c = &CorrectableTestConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -43,24 +65,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubCorrectableTestConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *CorrectableTestConfiguration) SubCorrectableTestConfiguration(cfg gorums.NodeListOption) (subCfg *CorrectableTestConfiguration, err error) { + subCfg = &CorrectableTestConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -68,18 +79,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// CorrectableTestConfigurationFromRaw returns a new CorrectableTestConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func CorrectableTestConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*CorrectableTestConfiguration, error) { + newCfg := &CorrectableTestConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *CorrectableTestConfiguration) Nodes() []*CorrectableTestNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*CorrectableTestNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &CorrectableTestNode{n} } return nodes } @@ -87,51 +108,35 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *CorrectableTestConfiguration) AllNodes() []*CorrectableTestNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*CorrectableTestNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &CorrectableTestNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c CorrectableTestConfiguration) And(d *CorrectableTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c CorrectableTestConfiguration) Except(rm *CorrectableTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { +// CorrectableTestNode holds the node specific methods for the CorrectableTest service. +type CorrectableTestNode struct { *gorums.RawNode } -// CorrectableTestClient is the client interface for the CorrectableTest service. -type CorrectableTestClient interface { - Correctable(ctx context.Context, in *CorrectableRequest) gorums.Responses[*CorrectableResponse] - CorrectableStream(ctx context.Context, in *CorrectableRequest) gorums.Responses[*CorrectableResponse] -} - -// enforce interface compliance -var _ CorrectableTestClient = (*Configuration)(nil) - // Correctable is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) Correctable(ctx context.Context, in *CorrectableRequest) gorums.Responses[*CorrectableResponse] { +func (c *CorrectableTestConfiguration) Correctable(ctx context.Context, in *CorrectableRequest) gorums.Responses[*CorrectableResponse] { cd := gorums.QuorumCallData{ Message: in, Method: "correctable.CorrectableTest.Correctable", @@ -146,7 +151,7 @@ func (c *Configuration) Correctable(ctx context.Context, in *CorrectableRequest) // with the same argument in, and returns the responses as an iterator. // This is a streaming quorum call, so each can respond with any amount of responses. -func (c *Configuration) CorrectableStream(ctx context.Context, in *CorrectableRequest) gorums.Responses[*CorrectableResponse] { +func (c *CorrectableTestConfiguration) CorrectableStream(ctx context.Context, in *CorrectableRequest) gorums.Responses[*CorrectableResponse] { cd := gorums.QuorumCallData{ Message: in, Method: "correctable.CorrectableTest.CorrectableStream", @@ -156,12 +161,15 @@ func (c *Configuration) CorrectableStream(ctx context.Context, in *CorrectableRe return gorums.QuorumCall[*CorrectableResponse](ctx, c.RawConfiguration, cd) } -// CorrectableTest is the server-side API for the CorrectableTest Service +// CorrectableTestServer is the server-side API for the CorrectableTest Service type CorrectableTestServer interface { Correctable(ctx gorums.ServerCtx, request *CorrectableRequest) (response *CorrectableResponse, err error) CorrectableStream(ctx gorums.ServerCtx, request *CorrectableRequest, send func(response *CorrectableResponse) error) error } +// RegisterCorrectableTestServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterCorrectableTestServer(srv *gorums.Server, impl CorrectableTestServer) { srv.RegisterHandler("correctable.CorrectableTest.Correctable", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*CorrectableRequest) diff --git a/tests/correctable/correctable_test.go b/tests/correctable/correctable_test.go index 276ca983..fc69ea38 100644 --- a/tests/correctable/correctable_test.go +++ b/tests/correctable/correctable_test.go @@ -14,7 +14,7 @@ import ( // n is the number of replicas, and div is a divider. // the target level is n, and the level is calculated by the quorum function // by dividing the sum of levels from the servers with the divider. -func run(t *testing.T, n, div int, corr func(context.Context, *Configuration, int, int) *gorums.Correctable[int]) { +func run(t *testing.T, n, div int, corr func(context.Context, *CorrectableTestConfiguration, int, int) *gorums.Correctable[int]) { addrs, teardown := gorums.TestSetup(t, n, func(_ int) gorums.ServerIface { gorumsSrv := gorums.NewServer() RegisterCorrectableTestServer(gorumsSrv, &testSrv{n}) @@ -22,7 +22,7 @@ func run(t *testing.T, n, div int, corr func(context.Context, *Configuration, in }) defer teardown() - cfg, err := NewConfiguration( + cfg, err := NewCorrectableTestConfiguration( gorums.WithNodeList(addrs), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), @@ -76,7 +76,7 @@ func (q qspec) corrQF(responses gorums.Responses[*CorrectableResponse], levelSet } func TestCorrectable(t *testing.T) { - run(t, 4, 1, func(ctx context.Context, c *Configuration, n, div int) *gorums.Correctable[int] { + run(t, 4, 1, func(ctx context.Context, c *CorrectableTestConfiguration, n, div int) *gorums.Correctable[int] { corr := c.Correctable(ctx, &CorrectableRequest{}) qspec := qspec{div, n} return gorums.NewCorrectable(corr, qspec.corrQF) @@ -84,7 +84,7 @@ func TestCorrectable(t *testing.T) { } func TestCorrectableStream(t *testing.T) { - run(t, 4, 4, func(ctx context.Context, c *Configuration, n, div int) *gorums.Correctable[int] { + run(t, 4, 4, func(ctx context.Context, c *CorrectableTestConfiguration, n, div int) *gorums.Correctable[int] { corr := c.CorrectableStream(ctx, &CorrectableRequest{}) qspec := qspec{div, n} return gorums.NewCorrectable(corr, qspec.corrQF) diff --git a/tests/dummy/dummy_gorums.pb.go b/tests/dummy/dummy_gorums.pb.go index 31e9da48..bf5896d9 100644 --- a/tests/dummy/dummy_gorums.pb.go +++ b/tests/dummy/dummy_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: dummy/dummy.proto @@ -19,21 +19,27 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// A DummyConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type DummyConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewDummyConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewDummyConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *DummyConfiguration, err error) { + c = &DummyConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -41,24 +47,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubDummyConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *DummyConfiguration) SubDummyConfiguration(cfg gorums.NodeListOption) (subCfg *DummyConfiguration, err error) { + subCfg = &DummyConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -66,18 +61,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// DummyConfigurationFromRaw returns a new DummyConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func DummyConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*DummyConfiguration, error) { + newCfg := &DummyConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *DummyConfiguration) Nodes() []*DummyNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*DummyNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &DummyNode{n} } return nodes } @@ -85,50 +90,35 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *DummyConfiguration) AllNodes() []*DummyNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*DummyNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &DummyNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c DummyConfiguration) And(d *DummyConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c DummyConfiguration) Except(rm *DummyConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { +// DummyNode holds the node specific methods for the Dummy service. +type DummyNode struct { *gorums.RawNode } -// DummyNodeClient is the single node client interface for the Dummy service. -type DummyNodeClient interface { - Test(ctx context.Context, in *Empty) (resp *Empty, err error) -} - -// enforce interface compliance -var _ DummyNodeClient = (*Node)(nil) - // Test is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (n *Node) Test(ctx context.Context, in *Empty) (resp *Empty, err error) { +func (n *DummyNode) Test(ctx context.Context, in *Empty) (resp *Empty, err error) { cd := gorums.CallData{ Message: in, Method: "dummy.Dummy.Test", @@ -141,11 +131,14 @@ func (n *Node) Test(ctx context.Context, in *Empty) (resp *Empty, err error) { return res.(*Empty), err } -// Dummy is the server-side API for the Dummy Service +// DummyServer is the server-side API for the Dummy Service type DummyServer interface { Test(ctx gorums.ServerCtx, request *Empty) (response *Empty, err error) } +// RegisterDummyServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterDummyServer(srv *gorums.Server, impl DummyServer) { srv.RegisterHandler("dummy.Dummy.Test", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*Empty) diff --git a/tests/metadata/metadata_gorums.pb.go b/tests/metadata/metadata_gorums.pb.go index e24761b6..67637f5e 100644 --- a/tests/metadata/metadata_gorums.pb.go +++ b/tests/metadata/metadata_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: metadata/metadata.proto @@ -20,21 +20,27 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// A MetadataTestConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type MetadataTestConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewMetadataTestConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewMetadataTestConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *MetadataTestConfiguration, err error) { + c = &MetadataTestConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -42,24 +48,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubMetadataTestConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *MetadataTestConfiguration) SubMetadataTestConfiguration(cfg gorums.NodeListOption) (subCfg *MetadataTestConfiguration, err error) { + subCfg = &MetadataTestConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -67,18 +62,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// MetadataTestConfigurationFromRaw returns a new MetadataTestConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func MetadataTestConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*MetadataTestConfiguration, error) { + newCfg := &MetadataTestConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *MetadataTestConfiguration) Nodes() []*MetadataTestNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*MetadataTestNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &MetadataTestNode{n} } return nodes } @@ -86,49 +91,33 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *MetadataTestConfiguration) AllNodes() []*MetadataTestNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*MetadataTestNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &MetadataTestNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c MetadataTestConfiguration) And(d *MetadataTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c MetadataTestConfiguration) Except(rm *MetadataTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { +// MetadataTestNode holds the node specific methods for the MetadataTest service. +type MetadataTestNode struct { *gorums.RawNode } -// MetadataTestNodeClient is the single node client interface for the MetadataTest service. -type MetadataTestNodeClient interface { - IDFromMD(ctx context.Context, in *emptypb.Empty) (resp *NodeID, err error) - WhatIP(ctx context.Context, in *emptypb.Empty) (resp *IPAddr, err error) -} - -// enforce interface compliance -var _ MetadataTestNodeClient = (*Node)(nil) - // IDFromMD returns the 'id' field from the metadata. -func (n *Node) IDFromMD(ctx context.Context, in *emptypb.Empty) (resp *NodeID, err error) { +func (n *MetadataTestNode) IDFromMD(ctx context.Context, in *emptypb.Empty) (resp *NodeID, err error) { cd := gorums.CallData{ Message: in, Method: "metadata.MetadataTest.IDFromMD", @@ -142,7 +131,7 @@ func (n *Node) IDFromMD(ctx context.Context, in *emptypb.Empty) (resp *NodeID, e } // WhatIP returns the address of the client that calls it. -func (n *Node) WhatIP(ctx context.Context, in *emptypb.Empty) (resp *IPAddr, err error) { +func (n *MetadataTestNode) WhatIP(ctx context.Context, in *emptypb.Empty) (resp *IPAddr, err error) { cd := gorums.CallData{ Message: in, Method: "metadata.MetadataTest.WhatIP", @@ -155,12 +144,15 @@ func (n *Node) WhatIP(ctx context.Context, in *emptypb.Empty) (resp *IPAddr, err return res.(*IPAddr), err } -// MetadataTest is the server-side API for the MetadataTest Service +// MetadataTestServer is the server-side API for the MetadataTest Service type MetadataTestServer interface { IDFromMD(ctx gorums.ServerCtx, request *emptypb.Empty) (response *NodeID, err error) WhatIP(ctx gorums.ServerCtx, request *emptypb.Empty) (response *IPAddr, err error) } +// RegisterMetadataTestServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterMetadataTestServer(srv *gorums.Server, impl MetadataTestServer) { srv.RegisterHandler("metadata.MetadataTest.IDFromMD", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*emptypb.Empty) diff --git a/tests/metadata/metadata_test.go b/tests/metadata/metadata_test.go index 2a762418..4aa2fd78 100644 --- a/tests/metadata/metadata_test.go +++ b/tests/metadata/metadata_test.go @@ -58,7 +58,7 @@ func TestMetadata(t *testing.T) { "id": fmt.Sprint(want), }) - cfg, err := NewConfiguration( + cfg, err := NewMetadataTestConfiguration( gorums.WithNodeList(addrs), gorums.WithMetadata(md), gorums.WithGrpcDialOptions( @@ -86,7 +86,7 @@ func TestPerMessageMetadata(t *testing.T) { addrs, teardown := gorums.TestSetup(t, 1, func(_ int) gorums.ServerIface { return initServer() }) defer teardown() - cfg, err := NewConfiguration(gorums.WithNodeList(addrs), + cfg, err := NewMetadataTestConfiguration(gorums.WithNodeList(addrs), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), ), @@ -121,7 +121,7 @@ func TestPerNodeMetadata(t *testing.T) { }) } - cfg, err := NewConfiguration( + cfg, err := NewMetadataTestConfiguration( gorums.WithNodeList(addrs), gorums.WithPerNodeMetadata(perNodeMD), gorums.WithGrpcDialOptions( @@ -148,7 +148,7 @@ func TestCanGetPeerInfo(t *testing.T) { addrs, teardown := gorums.TestSetup(t, 1, func(_ int) gorums.ServerIface { return initServer() }) defer teardown() - cfg, err := NewConfiguration( + cfg, err := NewMetadataTestConfiguration( gorums.WithNodeList(addrs), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), diff --git a/tests/mock/mock.pb.go b/tests/mock/mock.pb.go index 5808077e..e81e4119 100644 --- a/tests/mock/mock.pb.go +++ b/tests/mock/mock.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v3.12.4 -// source: mock.proto +// protoc-gen-go v1.36.6 +// protoc v6.30.2 +// source: tests/mock/mock.proto package mock @@ -10,7 +10,7 @@ import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" - sync "sync" + unsafe "unsafe" ) const ( @@ -21,20 +21,17 @@ const ( ) type Request struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val string `protobuf:"bytes,1,opt,name=val,proto3" json:"val,omitempty"` + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Val string `protobuf:"bytes,1,opt,name=val"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Request) Reset() { *x = Request{} - if protoimpl.UnsafeEnabled { - mi := &file_mock_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tests_mock_mock_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Request) String() string { @@ -44,8 +41,8 @@ func (x *Request) String() string { func (*Request) ProtoMessage() {} func (x *Request) ProtoReflect() protoreflect.Message { - mi := &file_mock_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_tests_mock_mock_proto_msgTypes[0] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -55,33 +52,43 @@ func (x *Request) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Request.ProtoReflect.Descriptor instead. -func (*Request) Descriptor() ([]byte, []int) { - return file_mock_proto_rawDescGZIP(), []int{0} -} - func (x *Request) GetVal() string { if x != nil { - return x.Val + return x.xxx_hidden_Val } return "" } -type Response struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields +func (x *Request) SetVal(v string) { + x.xxx_hidden_Val = v +} + +type Request_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Val string +} - Val string `protobuf:"bytes,1,opt,name=val,proto3" json:"val,omitempty"` +func (b0 Request_builder) Build() *Request { + m0 := &Request{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Val = b.Val + return m0 +} + +type Response struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Val string `protobuf:"bytes,1,opt,name=val"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Response) Reset() { *x = Response{} - if protoimpl.UnsafeEnabled { - mi := &file_mock_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tests_mock_mock_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Response) String() string { @@ -91,8 +98,8 @@ func (x *Response) String() string { func (*Response) ProtoMessage() {} func (x *Response) ProtoReflect() protoreflect.Message { - mi := &file_mock_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_tests_mock_mock_proto_msgTypes[1] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -102,49 +109,47 @@ func (x *Response) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Response.ProtoReflect.Descriptor instead. -func (*Response) Descriptor() ([]byte, []int) { - return file_mock_proto_rawDescGZIP(), []int{1} -} - func (x *Response) GetVal() string { if x != nil { - return x.Val + return x.xxx_hidden_Val } return "" } -var File_mock_proto protoreflect.FileDescriptor - -var file_mock_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x6d, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x6d, 0x6f, - 0x63, 0x6b, 0x22, 0x1b, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, - 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, - 0x1c, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x76, - 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x42, 0x24, 0x5a, - 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x6c, 0x61, - 0x62, 0x2f, 0x67, 0x6f, 0x72, 0x75, 0x6d, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x6d, - 0x6f, 0x63, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +func (x *Response) SetVal(v string) { + x.xxx_hidden_Val = v } -var ( - file_mock_proto_rawDescOnce sync.Once - file_mock_proto_rawDescData = file_mock_proto_rawDesc -) +type Response_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. -func file_mock_proto_rawDescGZIP() []byte { - file_mock_proto_rawDescOnce.Do(func() { - file_mock_proto_rawDescData = protoimpl.X.CompressGZIP(file_mock_proto_rawDescData) - }) - return file_mock_proto_rawDescData + Val string } -var file_mock_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_mock_proto_goTypes = []interface{}{ +func (b0 Response_builder) Build() *Response { + m0 := &Response{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Val = b.Val + return m0 +} + +var File_tests_mock_mock_proto protoreflect.FileDescriptor + +const file_tests_mock_mock_proto_rawDesc = "" + + "\n" + + "\x15tests/mock/mock.proto\x12\x04mock\"\x1b\n" + + "\aRequest\x12\x10\n" + + "\x03val\x18\x01 \x01(\tR\x03val\"\x1c\n" + + "\bResponse\x12\x10\n" + + "\x03val\x18\x01 \x01(\tR\x03valB)Z\"github.com/relab/gorums/tests/mock\x92\x03\x02\b\x02b\beditionsp\xe8\a" + +var file_tests_mock_mock_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_tests_mock_mock_proto_goTypes = []any{ (*Request)(nil), // 0: mock.Request (*Response)(nil), // 1: mock.Response } -var file_mock_proto_depIdxs = []int32{ +var file_tests_mock_mock_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -152,53 +157,26 @@ var file_mock_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for field type_name } -func init() { file_mock_proto_init() } -func file_mock_proto_init() { - if File_mock_proto != nil { +func init() { file_tests_mock_mock_proto_init() } +func file_tests_mock_mock_proto_init() { + if File_tests_mock_mock_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_mock_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Request); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_mock_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Response); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_mock_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_tests_mock_mock_proto_rawDesc), len(file_tests_mock_mock_proto_rawDesc)), NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_mock_proto_goTypes, - DependencyIndexes: file_mock_proto_depIdxs, - MessageInfos: file_mock_proto_msgTypes, + GoTypes: file_tests_mock_mock_proto_goTypes, + DependencyIndexes: file_tests_mock_mock_proto_depIdxs, + MessageInfos: file_tests_mock_mock_proto_msgTypes, }.Build() - File_mock_proto = out.File - file_mock_proto_rawDesc = nil - file_mock_proto_goTypes = nil - file_mock_proto_depIdxs = nil + File_tests_mock_mock_proto = out.File + file_tests_mock_mock_proto_goTypes = nil + file_tests_mock_mock_proto_depIdxs = nil } diff --git a/tests/oneway/oneway_gorums.pb.go b/tests/oneway/oneway_gorums.pb.go index d253b125..cabe13c5 100644 --- a/tests/oneway/oneway_gorums.pb.go +++ b/tests/oneway/oneway_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: oneway/oneway.proto @@ -20,21 +20,44 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// OnewayTestClient is the client interface for the OnewayTest service. +type OnewayTestClient interface { + Multicast(ctx context.Context, in *Request, opts ...gorums.CallOption) + MulticastPerNode(ctx context.Context, in *Request, f func(*Request, uint32) *Request, opts ...gorums.CallOption) +} + +// enforce interface compliance +var _ OnewayTestClient = (*OnewayTestConfiguration)(nil) + +// OnewayTestNodeClient is the single node client interface for the OnewayTest service. +type OnewayTestNodeClient interface { + Unicast(ctx context.Context, in *Request, opts ...gorums.CallOption) +} + +// enforce interface compliance +var _ OnewayTestNodeClient = (*OnewayTestNode)(nil) + +// A OnewayTestConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type OnewayTestConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewOnewayTestConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewOnewayTestConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *OnewayTestConfiguration, err error) { + c = &OnewayTestConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -42,24 +65,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubOnewayTestConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *OnewayTestConfiguration) SubOnewayTestConfiguration(cfg gorums.NodeListOption) (subCfg *OnewayTestConfiguration, err error) { + subCfg = &OnewayTestConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -67,18 +79,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// OnewayTestConfigurationFromRaw returns a new OnewayTestConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func OnewayTestConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*OnewayTestConfiguration, error) { + newCfg := &OnewayTestConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *OnewayTestConfiguration) Nodes() []*OnewayTestNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*OnewayTestNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &OnewayTestNode{n} } return nodes } @@ -86,59 +108,31 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *OnewayTestConfiguration) AllNodes() []*OnewayTestNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*OnewayTestNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &OnewayTestNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c OnewayTestConfiguration) And(d *OnewayTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c OnewayTestConfiguration) Except(rm *OnewayTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { - *gorums.RawNode -} - -// OnewayTestClient is the client interface for the OnewayTest service. -type OnewayTestClient interface { - Multicast(ctx context.Context, in *Request, opts ...gorums.CallOption) - MulticastPerNode(ctx context.Context, in *Request, f func(*Request, uint32) *Request, opts ...gorums.CallOption) -} - -// enforce interface compliance -var _ OnewayTestClient = (*Configuration)(nil) - -// OnewayTestNodeClient is the single node client interface for the OnewayTest service. -type OnewayTestNodeClient interface { - Unicast(ctx context.Context, in *Request, opts ...gorums.CallOption) -} - -// enforce interface compliance -var _ OnewayTestNodeClient = (*Node)(nil) - // Multicast is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) Multicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { +func (c *OnewayTestConfiguration) Multicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "oneway.OnewayTest.Multicast", @@ -154,7 +148,8 @@ func (c *Configuration) Multicast(ctx context.Context, in *Request, opts ...goru // The per node function f receives a copy of the Request request argument and // returns a Request manipulated to be passed to the given nodeID. // The function f must be thread-safe. -func (c *Configuration) MulticastPerNode(ctx context.Context, in *Request, f func(*Request, uint32) *Request, opts ...gorums.CallOption) { +func (c *OnewayTestConfiguration) MulticastPerNode(ctx context.Context, in *Request, f func(*Request, uint32) *Request, opts ...gorums.CallOption) { + cd := gorums.QuorumCallData{ Message: in, Method: "oneway.OnewayTest.MulticastPerNode", @@ -167,13 +162,21 @@ func (c *Configuration) MulticastPerNode(ctx context.Context, in *Request, f fun c.RawConfiguration.Multicast(ctx, cd, opts...) } -// OnewayTest is the server-side API for the OnewayTest Service +// OnewayTestNode holds the node specific methods for the OnewayTest service. +type OnewayTestNode struct { + *gorums.RawNode +} + +// OnewayTestServer is the server-side API for the OnewayTest Service type OnewayTestServer interface { Unicast(ctx gorums.ServerCtx, request *Request) Multicast(ctx gorums.ServerCtx, request *Request) MulticastPerNode(ctx gorums.ServerCtx, request *Request) } +// RegisterOnewayTestServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterOnewayTestServer(srv *gorums.Server, impl OnewayTestServer) { srv.RegisterHandler("oneway.OnewayTest.Unicast", func(ctx gorums.ServerCtx, in *gorums.Message, _ chan<- *gorums.Message) { req := in.Message.(*Request) @@ -192,10 +195,8 @@ func RegisterOnewayTestServer(srv *gorums.Server, impl OnewayTestServer) { }) } -// Unicast is a quorum call invoked on each node in configuration c, - -// with the same argument in, and returns the responses as an iterator. -func (n *Node) Unicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { +// Unicast is a one-way call; no replies are processed. +func (n *OnewayTestNode) Unicast(ctx context.Context, in *Request, opts ...gorums.CallOption) { cd := gorums.CallData{ Message: in, Method: "oneway.OnewayTest.Unicast", diff --git a/tests/oneway/oneway_test.go b/tests/oneway/oneway_test.go index f88ff03f..bba2e98b 100644 --- a/tests/oneway/oneway_test.go +++ b/tests/oneway/oneway_test.go @@ -42,7 +42,7 @@ func (s *onewaySrv) MulticastPerNode(_ gorums.ServerCtx, r *oneway.Request) { s.wg.Done() } -func setup(t testing.TB, cfgSize int) (cfg *oneway.Configuration, srvs []*onewaySrv, teardown func()) { +func setup(t testing.TB, cfgSize int) (cfg *oneway.OnewayTestConfiguration, srvs []*onewaySrv, teardown func()) { t.Helper() srvs = make([]*onewaySrv, cfgSize) for i := range cfgSize { @@ -59,7 +59,7 @@ func setup(t testing.TB, cfgSize int) (cfg *oneway.Configuration, srvs []*oneway nodeMap[addr] = uint32(i) } - cfg, err := oneway.NewConfiguration( + cfg, err := oneway.NewOnewayTestConfiguration( gorums.WithNodeMap(nodeMap), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), @@ -94,7 +94,7 @@ func TestOnewayCalls(t *testing.T) { {name: "MulticastNoSendWaiting", calls: numCalls, servers: 9, sendWait: false}, } - f := func(c *oneway.Configuration) func(context.Context, *oneway.Request, ...gorums.CallOption) { + f := func(c *oneway.OnewayTestConfiguration) func(context.Context, *oneway.Request, ...gorums.CallOption) { if c.Size() == 1 { return c.Nodes()[0].Unicast } diff --git a/tests/ordering/order_gorums.pb.go b/tests/ordering/order_gorums.pb.go index 094283bb..26fe6385 100644 --- a/tests/ordering/order_gorums.pb.go +++ b/tests/ordering/order_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: ordering/order.proto @@ -19,21 +19,44 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// GorumsTestClient is the client interface for the GorumsTest service. +type GorumsTestClient interface { + QC(ctx context.Context, in *Request) gorums.Responses[*Response] + QCAsync(ctx context.Context, in *Request) gorums.Responses[*Response] +} + +// enforce interface compliance +var _ GorumsTestClient = (*GorumsTestConfiguration)(nil) + +// GorumsTestNodeClient is the single node client interface for the GorumsTest service. +type GorumsTestNodeClient interface { + UnaryRPC(ctx context.Context, in *Request) (resp *Response, err error) +} + +// enforce interface compliance +var _ GorumsTestNodeClient = (*GorumsTestNode)(nil) + +// A GorumsTestConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type GorumsTestConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewGorumsTestConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewGorumsTestConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *GorumsTestConfiguration, err error) { + c = &GorumsTestConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -41,24 +64,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubGorumsTestConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *GorumsTestConfiguration) SubGorumsTestConfiguration(cfg gorums.NodeListOption) (subCfg *GorumsTestConfiguration, err error) { + subCfg = &GorumsTestConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -66,18 +78,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// GorumsTestConfigurationFromRaw returns a new GorumsTestConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func GorumsTestConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*GorumsTestConfiguration, error) { + newCfg := &GorumsTestConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *GorumsTestConfiguration) Nodes() []*GorumsTestNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*GorumsTestNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &GorumsTestNode{n} } return nodes } @@ -85,59 +107,35 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *GorumsTestConfiguration) AllNodes() []*GorumsTestNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*GorumsTestNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &GorumsTestNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c GorumsTestConfiguration) And(d *GorumsTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c GorumsTestConfiguration) Except(rm *GorumsTestConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { +// GorumsTestNode holds the node specific methods for the GorumsTest service. +type GorumsTestNode struct { *gorums.RawNode } -// GorumsTestClient is the client interface for the GorumsTest service. -type GorumsTestClient interface { - QC(ctx context.Context, in *Request) gorums.Responses[*Response] - QCAsync(ctx context.Context, in *Request) gorums.Responses[*Response] -} - -// enforce interface compliance -var _ GorumsTestClient = (*Configuration)(nil) - -// GorumsTestNodeClient is the single node client interface for the GorumsTest service. -type GorumsTestNodeClient interface { - UnaryRPC(ctx context.Context, in *Request) (resp *Response, err error) -} - -// enforce interface compliance -var _ GorumsTestNodeClient = (*Node)(nil) - // QC is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) QC(ctx context.Context, in *Request) gorums.Responses[*Response] { +func (c *GorumsTestConfiguration) QC(ctx context.Context, in *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "ordering.GorumsTest.QC", @@ -150,7 +148,7 @@ func (c *Configuration) QC(ctx context.Context, in *Request) gorums.Responses[*R // QCAsync is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) QCAsync(ctx context.Context, in *Request) gorums.Responses[*Response] { +func (c *GorumsTestConfiguration) QCAsync(ctx context.Context, in *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "ordering.GorumsTest.QCAsync", @@ -163,7 +161,7 @@ func (c *Configuration) QCAsync(ctx context.Context, in *Request) gorums.Respons // UnaryRPC is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (n *Node) UnaryRPC(ctx context.Context, in *Request) (resp *Response, err error) { +func (n *GorumsTestNode) UnaryRPC(ctx context.Context, in *Request) (resp *Response, err error) { cd := gorums.CallData{ Message: in, Method: "ordering.GorumsTest.UnaryRPC", @@ -176,13 +174,16 @@ func (n *Node) UnaryRPC(ctx context.Context, in *Request) (resp *Response, err e return res.(*Response), err } -// GorumsTest is the server-side API for the GorumsTest Service +// GorumsTestServer is the server-side API for the GorumsTest Service type GorumsTestServer interface { QC(ctx gorums.ServerCtx, request *Request) (response *Response, err error) QCAsync(ctx gorums.ServerCtx, request *Request) (response *Response, err error) UnaryRPC(ctx gorums.ServerCtx, request *Request) (response *Response, err error) } +// RegisterGorumsTestServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterGorumsTestServer(srv *gorums.Server, impl GorumsTestServer) { srv.RegisterHandler("ordering.GorumsTest.QC", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*Request) diff --git a/tests/ordering/order_test.go b/tests/ordering/order_test.go index a38bf9b1..683a731f 100644 --- a/tests/ordering/order_test.go +++ b/tests/ordering/order_test.go @@ -78,14 +78,14 @@ func orderQF(ctx context.Context, responses gorums.Responses[*Response], quorum return nil, errors.New("orderQF: quorum not found") } -func setup(t *testing.T, cfgSize int) (cfg *Configuration, teardown func()) { +func setup(t *testing.T, cfgSize int) (cfg *GorumsTestConfiguration, teardown func()) { t.Helper() addrs, closeServers := gorums.TestSetup(t, cfgSize, func(_ int) gorums.ServerIface { srv := gorums.NewServer() RegisterGorumsTestServer(srv, &testSrv{}) return srv }) - cfg, err := NewConfiguration( + cfg, err := NewGorumsTestConfiguration( gorums.WithNodeList(addrs), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), @@ -207,7 +207,7 @@ func TestMixedOrdering(t *testing.T) { var wg sync.WaitGroup wg.Add(len(nodes)) for _, node := range nodes { - go func(node *Node) { + go func(node *GorumsTestNode) { defer wg.Done() resp, err := node.UnaryRPC(context.Background(), Request_builder{Num: uint64(i)}.Build()) if err != nil { diff --git a/tests/qf/qf_gorums.pb.go b/tests/qf/qf_gorums.pb.go index 07e12504..ab96fde5 100644 --- a/tests/qf/qf_gorums.pb.go +++ b/tests/qf/qf_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: qf/qf.proto @@ -19,21 +19,43 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// QuorumFunctionClient is the client interface for the QuorumFunction service. +type QuorumFunctionClient interface { + UseReq(ctx context.Context, in *Request) gorums.Responses[*Response] + IgnoreReq(ctx context.Context, in *Request) gorums.Responses[*Response] +} + +// enforce interface compliance +var _ QuorumFunctionClient = (*QuorumFunctionConfiguration)(nil) + +// QuorumFunctionNodeClient is the single node client interface for the QuorumFunction service. +type QuorumFunctionNodeClient interface { +} + +// enforce interface compliance +var _ QuorumFunctionNodeClient = (*QuorumFunctionNode)(nil) + +// A QuorumFunctionConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type QuorumFunctionConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewQuorumFunctionConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewQuorumFunctionConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *QuorumFunctionConfiguration, err error) { + c = &QuorumFunctionConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -41,24 +63,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubQuorumFunctionConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *QuorumFunctionConfiguration) SubQuorumFunctionConfiguration(cfg gorums.NodeListOption) (subCfg *QuorumFunctionConfiguration, err error) { + subCfg = &QuorumFunctionConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -66,18 +77,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// QuorumFunctionConfigurationFromRaw returns a new QuorumFunctionConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func QuorumFunctionConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*QuorumFunctionConfiguration, error) { + newCfg := &QuorumFunctionConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *QuorumFunctionConfiguration) Nodes() []*QuorumFunctionNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*QuorumFunctionNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &QuorumFunctionNode{n} } return nodes } @@ -85,51 +106,35 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *QuorumFunctionConfiguration) AllNodes() []*QuorumFunctionNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*QuorumFunctionNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &QuorumFunctionNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c QuorumFunctionConfiguration) And(d *QuorumFunctionConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c QuorumFunctionConfiguration) Except(rm *QuorumFunctionConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { +// QuorumFunctionNode holds the node specific methods for the QuorumFunction service. +type QuorumFunctionNode struct { *gorums.RawNode } -// QuorumFunctionClient is the client interface for the QuorumFunction service. -type QuorumFunctionClient interface { - UseReq(ctx context.Context, in *Request) gorums.Responses[*Response] - IgnoreReq(ctx context.Context, in *Request) gorums.Responses[*Response] -} - -// enforce interface compliance -var _ QuorumFunctionClient = (*Configuration)(nil) - // UseReq is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) UseReq(ctx context.Context, in *Request) gorums.Responses[*Response] { +func (c *QuorumFunctionConfiguration) UseReq(ctx context.Context, in *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "qf.QuorumFunction.UseReq", @@ -142,7 +147,7 @@ func (c *Configuration) UseReq(ctx context.Context, in *Request) gorums.Response // IgnoreReq is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (c *Configuration) IgnoreReq(ctx context.Context, in *Request) gorums.Responses[*Response] { +func (c *QuorumFunctionConfiguration) IgnoreReq(ctx context.Context, in *Request) gorums.Responses[*Response] { cd := gorums.QuorumCallData{ Message: in, Method: "qf.QuorumFunction.IgnoreReq", @@ -152,12 +157,15 @@ func (c *Configuration) IgnoreReq(ctx context.Context, in *Request) gorums.Respo return gorums.QuorumCall[*Response](ctx, c.RawConfiguration, cd) } -// QuorumFunction is the server-side API for the QuorumFunction Service +// QuorumFunctionServer is the server-side API for the QuorumFunction Service type QuorumFunctionServer interface { UseReq(ctx gorums.ServerCtx, request *Request) (response *Response, err error) IgnoreReq(ctx gorums.ServerCtx, request *Request) (response *Response, err error) } +// RegisterQuorumFunctionServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterQuorumFunctionServer(srv *gorums.Server, impl QuorumFunctionServer) { srv.RegisterHandler("qf.QuorumFunction.UseReq", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*Request) diff --git a/tests/qf/qf_test.go b/tests/qf/qf_test.go index cb5c9340..fd594ff6 100644 --- a/tests/qf/qf_test.go +++ b/tests/qf/qf_test.go @@ -268,8 +268,8 @@ func BenchmarkFullStackQF(b *testing.B) { RegisterQuorumFunctionServer(srv, &testSrv{}) return srv }) - c, err := NewConfiguration( - gorums.WithNodeList(addrs), // dummy node list; won't actually be used in test + c, err := NewQuorumFunctionConfiguration( + gorums.WithNodeList(addrs), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), ), diff --git a/tests/tls/tls_gorums.pb.go b/tests/tls/tls_gorums.pb.go index 4becf6ca..00e349e6 100644 --- a/tests/tls/tls_gorums.pb.go +++ b/tests/tls/tls_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: tls/tls.proto @@ -19,21 +19,27 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// A TLSConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type TLSConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewTLSConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewTLSConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *TLSConfiguration, err error) { + c = &TLSConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -41,24 +47,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubTLSConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *TLSConfiguration) SubTLSConfiguration(cfg gorums.NodeListOption) (subCfg *TLSConfiguration, err error) { + subCfg = &TLSConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -66,18 +61,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// TLSConfigurationFromRaw returns a new TLSConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func TLSConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*TLSConfiguration, error) { + newCfg := &TLSConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *TLSConfiguration) Nodes() []*TLSNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*TLSNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &TLSNode{n} } return nodes } @@ -85,50 +90,35 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *TLSConfiguration) AllNodes() []*TLSNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*TLSNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &TLSNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c TLSConfiguration) And(d *TLSConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c TLSConfiguration) Except(rm *TLSConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { +// TLSNode holds the node specific methods for the TLS service. +type TLSNode struct { *gorums.RawNode } -// TLSNodeClient is the single node client interface for the TLS service. -type TLSNodeClient interface { - TestTLS(ctx context.Context, in *Request) (resp *Response, err error) -} - -// enforce interface compliance -var _ TLSNodeClient = (*Node)(nil) - // TestTLS is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (n *Node) TestTLS(ctx context.Context, in *Request) (resp *Response, err error) { +func (n *TLSNode) TestTLS(ctx context.Context, in *Request) (resp *Response, err error) { cd := gorums.CallData{ Message: in, Method: "tls.TLS.TestTLS", @@ -141,11 +131,14 @@ func (n *Node) TestTLS(ctx context.Context, in *Request) (resp *Response, err er return res.(*Response), err } -// TLS is the server-side API for the TLS Service +// TLSServer is the server-side API for the TLS Service type TLSServer interface { TestTLS(ctx gorums.ServerCtx, request *Request) (response *Response, err error) } +// RegisterTLSServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterTLSServer(srv *gorums.Server, impl TLSServer) { srv.RegisterHandler("tls.TLS.TestTLS", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*Request) diff --git a/tests/tls/tls_test.go b/tests/tls/tls_test.go index b877da01..bd58ec3d 100644 --- a/tests/tls/tls_test.go +++ b/tests/tls/tls_test.go @@ -45,7 +45,7 @@ func TestTLS(t *testing.T) { }) defer teardown() - cfg, err := NewConfiguration( + cfg, err := NewTLSConfiguration( gorums.WithNodeList(addrs), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(cp, "")), diff --git a/tests/unresponsive/unreponsive_test.go b/tests/unresponsive/unreponsive_test.go index 2bd3db54..ec8a552d 100644 --- a/tests/unresponsive/unreponsive_test.go +++ b/tests/unresponsive/unreponsive_test.go @@ -28,7 +28,7 @@ func TestUnresponsive(t *testing.T) { }) defer teardown() - cfg, err := NewConfiguration( + cfg, err := NewUnresponsiveConfiguration( gorums.WithNodeList(addrs), gorums.WithGrpcDialOptions( grpc.WithTransportCredentials(insecure.NewCredentials()), diff --git a/tests/unresponsive/unresponsive_gorums.pb.go b/tests/unresponsive/unresponsive_gorums.pb.go index c4fca0b4..4d129c8d 100644 --- a/tests/unresponsive/unresponsive_gorums.pb.go +++ b/tests/unresponsive/unresponsive_gorums.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-gorums. DO NOT EDIT. // versions: -// protoc-gen-gorums v0.9.0-devel+967e3a70 +// protoc-gen-gorums v0.9.0-devel+a35cbf26 // protoc v6.30.2 // source: unresponsive/unresponsive.proto @@ -19,21 +19,27 @@ const ( _ = gorums.EnforceVersion(gorums.MaxVersion - 9) ) -// A Configuration represents a static set of nodes on which quorum remote +func init() { + if encoding.GetCodec(gorums.ContentSubtype) == nil { + encoding.RegisterCodec(gorums.NewCodec()) + } +} + +// A UnresponsiveConfiguration represents a static set of nodes on which quorum remote // procedure calls may be invoked. -type Configuration struct { +type UnresponsiveConfiguration struct { gorums.RawConfiguration } -// NewConfiguration returns a configuration based on the provided list of nodes (required) +// NewUnresponsiveConfiguration returns a configuration based on the provided list of nodes (required) // and an optional quorum specification. The QuorumSpec is necessary for call types that // must process replies. For configurations only used for unicast or multicast call types, // a QuorumSpec is not needed. // Nodes can be supplied using WithNodeMap or WithNodeList. // Using any other type of NodeListOption will not work. // The ManagerOption list controls how the nodes in the configuration are created. -func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *Configuration, err error) { - c = &Configuration{} +func NewUnresponsiveConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) (c *UnresponsiveConfiguration, err error) { + c = &UnresponsiveConfiguration{} c.RawConfiguration, err = gorums.NewRawConfiguration(cfg, opts...) if err != nil { return nil, err @@ -41,24 +47,13 @@ func NewConfiguration(cfg gorums.NodeListOption, opts ...gorums.ManagerOption) ( return c, nil } -// ConfigurationFromRaw returns a new configuration from the given raw configuration. -// -// cfg1, err := pb.NewConfiguration(nodeList, opts...) -// cfg2 := ConfigurationFromRaw(cfg1.RawConfig) -func ConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*Configuration, error) { - newCfg := &Configuration{ - RawConfiguration: rawCfg, - } - return newCfg, nil -} - -// SubConfiguration allows for making a new Configuration from the ManagerOption list and -// node list of another configuration, +// SubUnresponsiveConfiguration allows for making a new Configuration from the +// ManagerOption list and node list of another set of configurations, // Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. // A new configuration can also be created from an existing configuration, // using the And, WithNewNodes, Except, and WithoutNodes methods. -func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Configuration, err error) { - subCfg = &Configuration{} +func (c *UnresponsiveConfiguration) SubUnresponsiveConfiguration(cfg gorums.NodeListOption) (subCfg *UnresponsiveConfiguration, err error) { + subCfg = &UnresponsiveConfiguration{} subCfg.RawConfiguration, err = c.SubRawConfiguration(cfg) if err != nil { return nil, err @@ -66,18 +61,28 @@ func (c *Configuration) SubConfiguration(cfg gorums.NodeListOption) (subCfg *Con return subCfg, nil } -// Close closes the nodes which aren't used by other subconfigurations -func (c *Configuration) Close() error { - return c.RawConfiguration.Close() +// UnresponsiveConfigurationFromRaw returns a new UnresponsiveConfiguration from the given raw configuration. +// +// This function may for example be used to "clone" a configuration: +// +// cfg1, err := mgr.NewConfiguration(qspec1, opts...) +// cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2) +func UnresponsiveConfigurationFromRaw(rawCfg gorums.RawConfiguration) (*UnresponsiveConfiguration, error) { + newCfg := &UnresponsiveConfiguration{ + RawConfiguration: rawCfg, + } + return newCfg, nil } -// Nodes returns a slice of the configuration nodes. Sorted by node id. +// Nodes returns a slice of each available node. IDs are returned in the same +// order as they were provided in the creation of the Manager. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) Nodes() []*Node { - nodes := make([]*Node, c.Size()) - for i, n := range c.RawConfiguration.RawNodes { - nodes[i] = &Node{n} +func (c *UnresponsiveConfiguration) Nodes() []*UnresponsiveNode { + rawNodes := c.RawConfiguration.Nodes() + nodes := make([]*UnresponsiveNode, len(rawNodes)) + for i, n := range rawNodes { + nodes[i] = &UnresponsiveNode{n} } return nodes } @@ -85,50 +90,35 @@ func (c *Configuration) Nodes() []*Node { // AllNodes returns a slice of each available node of all subconfigurations. Sorted by node id. // // NOTE: mutating the returned slice is not supported. -func (c *Configuration) AllNodes() []*Node { +func (c *UnresponsiveConfiguration) AllNodes() []*UnresponsiveNode { rawNodes := c.RawConfiguration.AllNodes() - nodes := make([]*Node, len(rawNodes)) + nodes := make([]*UnresponsiveNode, len(rawNodes)) for i, n := range rawNodes { - nodes[i] = &Node{n} + nodes[i] = &UnresponsiveNode{n} } return nodes } // And returns a NodeListOption that can be used to create a new configuration combining c and d. -func (c *Configuration) And(d *Configuration) gorums.NodeListOption { +func (c UnresponsiveConfiguration) And(d *UnresponsiveConfiguration) gorums.NodeListOption { return c.RawConfiguration.And(d.RawConfiguration) } // Except returns a NodeListOption that can be used to create a new configuration // from c without the nodes in rm. -func (c *Configuration) Except(rm *Configuration) gorums.NodeListOption { +func (c UnresponsiveConfiguration) Except(rm *UnresponsiveConfiguration) gorums.NodeListOption { return c.RawConfiguration.Except(rm.RawConfiguration) } -func init() { - if encoding.GetCodec(gorums.ContentSubtype) == nil { - encoding.RegisterCodec(gorums.NewCodec()) - } -} - -// Node encapsulates the state of a node on which a remote procedure call -// can be performed. -type Node struct { +// UnresponsiveNode holds the node specific methods for the Unresponsive service. +type UnresponsiveNode struct { *gorums.RawNode } -// UnresponsiveNodeClient is the single node client interface for the Unresponsive service. -type UnresponsiveNodeClient interface { - TestUnresponsive(ctx context.Context, in *Empty) (resp *Empty, err error) -} - -// enforce interface compliance -var _ UnresponsiveNodeClient = (*Node)(nil) - // TestUnresponsive is a quorum call invoked on each node in configuration c, // with the same argument in, and returns the responses as an iterator. -func (n *Node) TestUnresponsive(ctx context.Context, in *Empty) (resp *Empty, err error) { +func (n *UnresponsiveNode) TestUnresponsive(ctx context.Context, in *Empty) (resp *Empty, err error) { cd := gorums.CallData{ Message: in, Method: "unresponsive.Unresponsive.TestUnresponsive", @@ -141,11 +131,14 @@ func (n *Node) TestUnresponsive(ctx context.Context, in *Empty) (resp *Empty, er return res.(*Empty), err } -// Unresponsive is the server-side API for the Unresponsive Service +// UnresponsiveServer is the server-side API for the Unresponsive Service type UnresponsiveServer interface { TestUnresponsive(ctx gorums.ServerCtx, request *Empty) (response *Empty, err error) } +// RegisterUnresponsiveServer adds rpc handler functions to a server, +// the handlers decide how the server responds when it receives +// a request from a client func RegisterUnresponsiveServer(srv *gorums.Server, impl UnresponsiveServer) { srv.RegisterHandler("unresponsive.Unresponsive.TestUnresponsive", func(ctx gorums.ServerCtx, in *gorums.Message, finished chan<- *gorums.Message) { req := in.Message.(*Empty)