-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FAB-6832] Add peer resource config bundlesource
This CR mimics the channel config bundle, and adds a peer resource config bundle source which provides access to an underlying set of channel config bundle and peer resource config bundle. The underlying data structures are updateable via an atomic pointer assignment, and stable views of the current configuration (totaling both the channel configuration and the peer resource configuration) may be obtained. Change-Id: I84646c526b256aa140d23f4d7982c91dd67b0aa3 Signed-off-by: Jason Yellick <[email protected]>
- Loading branch information
Jason Yellick
committed
Nov 2, 2017
1 parent
ecabe49
commit 1874d35
Showing
7 changed files
with
260 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package resourcesconfig | ||
|
||
import ( | ||
"sync/atomic" | ||
|
||
"github.com/hyperledger/fabric/common/channelconfig" | ||
configtxapi "github.com/hyperledger/fabric/common/configtx/api" | ||
"github.com/hyperledger/fabric/common/policies" | ||
) | ||
|
||
// BundleSource stores a reference to the current peer resource configuration bundle | ||
// It also provides a method to update this bundle. The assorted methods of BundleSource | ||
// largely pass through to the underlying bundle, but do so through an atomic pointer | ||
// so that cross go-routine reads are not vulnerable to out-of-order execution memory | ||
// type bugs. | ||
type BundleSource struct { | ||
bundle atomic.Value | ||
callbacks []func(*Bundle) | ||
} | ||
|
||
// NewBundleSource creates a new BundleSource with an initial Bundle value | ||
// The callbacks will be invoked whenever the Update method is called for the | ||
// BundleSource. Note, these callbacks are called immediately before this function | ||
// returns. | ||
func NewBundleSource(bundle *Bundle, callbacks ...func(*Bundle)) *BundleSource { | ||
bs := &BundleSource{ | ||
callbacks: callbacks, | ||
} | ||
bs.Update(bundle) | ||
return bs | ||
} | ||
|
||
// Update sets a new bundle as the bundle source and calls any registered callbacks | ||
func (bs *BundleSource) Update(newBundle *Bundle) { | ||
bs.bundle.Store(newBundle) | ||
for _, callback := range bs.callbacks { | ||
callback(newBundle) | ||
} | ||
} | ||
|
||
// StableBundle returns a pointer to a stable Bundle. | ||
// It is stable because calls to its assorted methods will always return the same | ||
// result, as the underlying data structures are immutable. For instance, calling | ||
// BundleSource.PolicyManager() and BundleSource.APIPolicyMapper() to get first the | ||
// the policy manager and then references into that policy manager could result in a | ||
// bug because an update might replace the underlying Bundle in between. Therefore, | ||
// for operations which require consistency between the Bundle calls, the caller | ||
// should first retrieve a StableBundle, then operate on it. | ||
func (bs *BundleSource) StableBundle() *Bundle { | ||
return bs.bundle.Load().(*Bundle) | ||
} | ||
|
||
// ConfigtxManager returns a reference to a configtx.Manager which can process updates to this config. | ||
func (bs *BundleSource) ConfigtxManager() configtxapi.Manager { | ||
return bs.StableBundle().ConfigtxManager() | ||
} | ||
|
||
// PolicyManager returns a policy manager which can resolve names both in the /Channel and /Resources namespaces. | ||
func (bs *BundleSource) PolicyManager() policies.Manager { | ||
return bs.StableBundle().PolicyManager() | ||
} | ||
|
||
// APIPolicyMapper returns a way to map API names to policies governing their invocation. | ||
func (bs *BundleSource) APIPolicyMapper() PolicyMapper { | ||
return bs.StableBundle().APIPolicyMapper() | ||
} | ||
|
||
// ChaincodeRegistery returns a way to query for chaincodes defined in this channel. | ||
func (bs *BundleSource) ChaincodeRegistry() ChaincodeRegistry { | ||
return bs.StableBundle().ChaincodeRegistry() | ||
} | ||
|
||
// ChannelConfig returns the channel config which this resources config depends on. | ||
// Note, consumers of the resourcesconfig should almost never refer to the PolicyManager | ||
// within the channel config, and should instead refer to the PolicyManager exposed by | ||
// this Bundle. | ||
func (bs *BundleSource) ChannelConfig() channelconfig.Resources { | ||
return bs.StableBundle().ChannelConfig() | ||
} | ||
|
||
// ValidateNew passes through to the current bundle | ||
func (bs *BundleSource) ValidateNew(resources Resources) error { | ||
return bs.StableBundle().ValidateNew(resources) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package resourcesconfig | ||
|
||
import ( | ||
"testing" | ||
|
||
mockchannelconfig "github.com/hyperledger/fabric/common/mocks/config" | ||
cb "github.com/hyperledger/fabric/protos/common" | ||
"github.com/hyperledger/fabric/protos/utils" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestBundleSource(t *testing.T) { | ||
env, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, "foo", nil, &cb.ConfigEnvelope{ | ||
Config: &cb.Config{ | ||
ChannelGroup: sampleResourceGroup, | ||
}, | ||
}, 0, 0) | ||
assert.NoError(t, err) | ||
|
||
b, err := NewBundleFromEnvelope(env, &mockchannelconfig.Resources{}) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, b) | ||
|
||
calledBack := false | ||
var calledBackWith *Bundle | ||
|
||
bs := NewBundleSource(b, func(ib *Bundle) { | ||
calledBack = true | ||
calledBackWith = ib | ||
}) | ||
|
||
assert.True(t, calledBack) | ||
assert.Equal(t, b, calledBackWith) | ||
|
||
assert.Equal(t, b.ConfigtxManager(), bs.ConfigtxManager()) | ||
assert.Equal(t, b.PolicyManager(), bs.PolicyManager()) | ||
assert.Equal(t, b.APIPolicyMapper(), bs.APIPolicyMapper()) | ||
assert.Equal(t, b.ChannelConfig(), bs.ChannelConfig()) | ||
assert.Equal(t, b.ChaincodeRegistry(), bs.ChaincodeRegistry()) | ||
assert.Equal(t, b.ValidateNew(nil), bs.ValidateNew(nil)) | ||
|
||
calledBack = false | ||
nb := &Bundle{} | ||
bs.Update(nb) | ||
assert.True(t, calledBack) | ||
assert.Equal(t, nb, calledBackWith) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.