From f93027473a2e6a0c3621c639caabe4e3028795aa Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Wed, 16 Aug 2017 22:34:21 -0400 Subject: [PATCH] [FAB-5817] Remove dead mutable config related code With the channel config values now immutable, large chunks of common code which facilitated their mutation are no longer needed. This CR simply removes that code. Change-Id: I99d1af9961461ff0a2f0777f83c1b45430dac83f Signed-off-by: Jason Yellick --- common/channelconfig/util.go | 51 ---------- common/config/api.go | 23 ----- common/config/proposer.go | 152 ---------------------------- common/config/proposer_test.go | 180 --------------------------------- 4 files changed, 406 deletions(-) delete mode 100644 common/channelconfig/util.go delete mode 100644 common/config/api.go delete mode 100644 common/config/proposer.go delete mode 100644 common/config/proposer_test.go diff --git a/common/channelconfig/util.go b/common/channelconfig/util.go deleted file mode 100644 index 4438bce28bd..00000000000 --- a/common/channelconfig/util.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package channelconfig - -import ( - "github.com/hyperledger/fabric/common/config" - cb "github.com/hyperledger/fabric/protos/common" - - "github.com/pkg/errors" -) - -// InitializeConfigValues takes a config group and uses it to initialize a config Root -// XXX This goes away by the end of the CR series so no test logic -func InitializeConfigValues(vp config.ValueProposer, group *cb.ConfigGroup) error { - subGroups := make([]string, len(group.Groups)) - i := 0 - for subGroup := range group.Groups { - subGroups[i] = subGroup - i++ - } - - valueDeserializer, subValueHandlers, err := vp.BeginValueProposals("", subGroups) - if err != nil { - return err - } - - for key, value := range group.Values { - _, err := valueDeserializer.Deserialize(key, value.Value) - if err != nil { - return errors.Wrapf(err, "failed to deserialize key %s", key) - } - } - - for i := range subGroups { - if err := InitializeConfigValues(subValueHandlers[i], group.Groups[subGroups[i]]); err != nil { - return errors.Wrapf(err, "failed initializing values for subgroup %s", subGroups[i]) - } - } - - err = vp.PreCommit("") - if err != nil { - return errors.Wrapf(err, "precommit failed for group") - } - - vp.CommitProposals("") - return nil -} diff --git a/common/config/api.go b/common/config/api.go deleted file mode 100644 index 2822b130662..00000000000 --- a/common/config/api.go +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package config - -type ValueProposer interface { - // BeginValueProposals called when a config proposal is begun - BeginValueProposals(tx interface{}, groups []string) (ValueDeserializer, []ValueProposer, error) - - // RollbackProposals called when a config proposal is abandoned - RollbackProposals(tx interface{}) - - // PreCommit is invoked before committing the config to catch - // any errors which cannot be caught on a per proposal basis - // TODO, rename other methods to remove Value/Proposal references - PreCommit(tx interface{}) error - - // CommitProposals called when a config proposal is committed - CommitProposals(tx interface{}) -} diff --git a/common/config/proposer.go b/common/config/proposer.go deleted file mode 100644 index 46e971337d5..00000000000 --- a/common/config/proposer.go +++ /dev/null @@ -1,152 +0,0 @@ -/* -Copyright IBM Corp. 2017 All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package config - -import ( - "fmt" - "sync" - - "github.com/golang/protobuf/proto" - "github.com/hyperledger/fabric/common/flogging" -) - -var logger = flogging.MustGetLogger("common/config") - -// ValueDeserializer provides a mechanism to retrieve proto messages to deserialize config values into -type ValueDeserializer interface { - // Deserialize takes a Value key as a string, and a marshaled Value value as bytes - // and returns the deserialized version of that value. Note, this function operates - // with side effects intended. Using a ValueDeserializer to deserialize a message will - // generally set the value in the Values interface that the ValueDeserializer derived from - // Therefore, the proto.Message may be safely discarded, but may be retained for - // inspection and or debugging purposes. - Deserialize(key string, value []byte) (proto.Message, error) -} - -// Values defines a mechanism to supply messages to unmarshal from config -// and a mechanism to validate the results -type Values interface { - ValueDeserializer - - // Validate should ensure that the values set into the proto messages are correct - // and that the new group values are allowed. It also includes a tx ID in case cross - // Handler invocations (ie to the MSP Config Manager) must be made - Validate(interface{}, map[string]ValueProposer) error - - // Commit should call back into the Value handler to update the config - Commit() -} - -// Handler -type Handler interface { - Allocate() Values - NewGroup(name string) (ValueProposer, error) -} - -type config struct { - allocated Values - groups map[string]ValueProposer -} - -type Proposer struct { - vh Handler - pending map[interface{}]*config - current *config - pendingLock sync.RWMutex -} - -func NewProposer(vh Handler) *Proposer { - return &Proposer{ - vh: vh, - current: &config{}, - pending: make(map[interface{}]*config), - } -} - -// BeginValueProposals called when a config proposal is begun -func (p *Proposer) BeginValueProposals(tx interface{}, groups []string) (ValueDeserializer, []ValueProposer, error) { - p.pendingLock.Lock() - defer p.pendingLock.Unlock() - if _, ok := p.pending[tx]; ok { - logger.Panicf("Duplicated BeginValueProposals without Rollback or Commit") - } - - result := make([]ValueProposer, len(groups)) - - pending := &config{ - allocated: p.vh.Allocate(), - groups: make(map[string]ValueProposer), - } - - for i, groupName := range groups { - var group ValueProposer - var ok bool - - if p.current == nil { - ok = false - } else { - group, ok = p.current.groups[groupName] - } - - if !ok { - var err error - group, err = p.vh.NewGroup(groupName) - if err != nil { - pending = nil - return nil, nil, fmt.Errorf("Error creating group %s: %s", groupName, err) - } - } - - pending.groups[groupName] = group - result[i] = group - } - - p.pending[tx] = pending - - return pending.allocated, result, nil -} - -// Validate ensures that the new config values is a valid change -func (p *Proposer) PreCommit(tx interface{}) error { - p.pendingLock.RLock() - pending, ok := p.pending[tx] - p.pendingLock.RUnlock() - if !ok { - logger.Panicf("Serious Programming Error: attempted to pre-commit tx which had not been begun") - } - return pending.allocated.Validate(tx, pending.groups) -} - -// RollbackProposals called when a config proposal is abandoned -func (p *Proposer) RollbackProposals(tx interface{}) { - p.pendingLock.Lock() - defer p.pendingLock.Unlock() - delete(p.pending, tx) -} - -// CommitProposals called when a config proposal is committed -func (p *Proposer) CommitProposals(tx interface{}) { - p.pendingLock.Lock() - defer p.pendingLock.Unlock() - pending, ok := p.pending[tx] - if !ok { - logger.Panicf("Serious Programming Error: attempted to commit tx which had not been begun") - } - p.current = pending - p.current.allocated.Commit() - delete(p.pending, tx) -} diff --git a/common/config/proposer_test.go b/common/config/proposer_test.go deleted file mode 100644 index 273a7bb9c3f..00000000000 --- a/common/config/proposer_test.go +++ /dev/null @@ -1,180 +0,0 @@ -/* -Copyright IBM Corp. 2017 All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package config - -import ( - "fmt" - "testing" - - cb "github.com/hyperledger/fabric/protos/common" - "github.com/hyperledger/fabric/protos/utils" - - "github.com/golang/protobuf/proto" - logging "github.com/op/go-logging" - "github.com/stretchr/testify/assert" -) - -func init() { - logging.SetLevel(logging.DEBUG, "") -} - -type mockValues struct { - ProtoMsgMap map[string]proto.Message - ValidateReturn error -} - -func (v *mockValues) Deserialize(key string, value []byte) (proto.Message, error) { - msg, ok := v.ProtoMsgMap[key] - if !ok { - return nil, fmt.Errorf("Missing message key: %s", key) - } - err := proto.Unmarshal(value, msg) - if err != nil { - return nil, err - } - - return msg, nil -} - -func (v *mockValues) Validate(interface{}, map[string]ValueProposer) error { - return v.ValidateReturn -} - -func (v *mockValues) Commit() {} - -func newMockValues() *mockValues { - return &mockValues{ - ProtoMsgMap: make(map[string]proto.Message), - } -} - -type mockHandler struct { - AllocateReturn *mockValues - NewGroupMap map[string]ValueProposer - NewGroupError error -} - -func (h *mockHandler) Allocate() Values { - return h.AllocateReturn -} - -func (h *mockHandler) NewGroup(name string) (ValueProposer, error) { - group, ok := h.NewGroupMap[name] - if !ok { - return nil, fmt.Errorf("Missing group implies error") - } - return group, nil -} - -func newMockHandler() *mockHandler { - return &mockHandler{ - AllocateReturn: newMockValues(), - NewGroupMap: make(map[string]ValueProposer), - } -} - -func TestDoubleSameBegin(t *testing.T) { - p := NewProposer(&mockHandler{AllocateReturn: &mockValues{}}) - p.BeginValueProposals(p, nil) - assert.Panics(t, func() { p.BeginValueProposals(p, nil) }, "Two begins back to back should have caused a panic") -} - -func TestDoubleDifferentBegin(t *testing.T) { - p := NewProposer(&mockHandler{AllocateReturn: &mockValues{}}) - p.BeginValueProposals(t, nil) - p.BeginValueProposals(p, nil) - // This function would panic on error -} - -func TestCommitWithoutBegin(t *testing.T) { - p := NewProposer(&mockHandler{AllocateReturn: &mockValues{}}) - assert.Panics(t, func() { p.CommitProposals(t) }, "Commit without begin should have caused a panic") -} - -func TestRollback(t *testing.T) { - p := NewProposer(&mockHandler{AllocateReturn: &mockValues{}}) - p.pending[t] = &config{} - p.RollbackProposals(t) - assert.Nil(t, p.pending[t], "Should have cleared pending config on rollback") -} - -func TestGoodKeys(t *testing.T) { - mh := newMockHandler() - mh.AllocateReturn.ProtoMsgMap["Envelope"] = &cb.Envelope{} - mh.AllocateReturn.ProtoMsgMap["Payload"] = &cb.Payload{} - - p := NewProposer(mh) - vd, _, err := p.BeginValueProposals(t, nil) - assert.NoError(t, err) - - env := &cb.Envelope{Payload: []byte("SOME DATA")} - pay := &cb.Payload{Data: []byte("SOME OTHER DATA")} - - msg, err := vd.Deserialize("Envelope", utils.MarshalOrPanic(env)) - assert.NoError(t, err) - assert.Equal(t, msg, env) - - msg, err = vd.Deserialize("Payload", utils.MarshalOrPanic(pay)) - assert.NoError(t, err) - assert.Equal(t, msg, pay) -} - -func TestBadMarshaling(t *testing.T) { - mh := newMockHandler() - mh.AllocateReturn.ProtoMsgMap["Envelope"] = &cb.Envelope{} - - p := NewProposer(mh) - vd, _, err := p.BeginValueProposals(t, nil) - assert.NoError(t, err) - - _, err = vd.Deserialize("Envelope", []byte("GARBAGE")) - assert.Error(t, err, "Should have errored unmarshaling") -} - -func TestBadMissingMessage(t *testing.T) { - mh := newMockHandler() - mh.AllocateReturn.ProtoMsgMap["Payload"] = &cb.Payload{} - - p := NewProposer(mh) - vd, _, err := p.BeginValueProposals(t, nil) - assert.NoError(t, err) - - _, err = vd.Deserialize("Envelope", utils.MarshalOrPanic(&cb.Envelope{})) - assert.Error(t, err, "Should have errored on unexpected message") -} - -func TestGroups(t *testing.T) { - mh := newMockHandler() - mh.NewGroupMap["foo"] = nil - mh.NewGroupMap["bar"] = nil - - p := NewProposer(mh) - _, _, err := p.BeginValueProposals(t, []string{"foo", "bar"}) - assert.NoError(t, err, "Both groups were present") - p.CommitProposals(t) - - mh.NewGroupMap = make(map[string]ValueProposer) - _, _, err = p.BeginValueProposals(t, []string{"foo", "bar"}) - assert.NoError(t, err, "Should not have tried to recreate the groups") - p.CommitProposals(t) - - _, _, err = p.BeginValueProposals(t, []string{"foo", "other"}) - assert.Error(t, err, "Should not have errored when trying to create 'other'") - - _, _, err = p.BeginValueProposals(t, []string{"foo"}) - assert.NoError(t, err, "Should be able to begin again without rolling back because of error") -}