-
Notifications
You must be signed in to change notification settings - Fork 8.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FAB-6552] Block-to-live policy for pvtdata
This CR introduces a BTL policy based on configuration in the core.yaml file Change-Id: Icef38b180d8a1f1c3336a59cca2f63dfbdab3964 Signed-off-by: manish <manish.sethi@gmail.com>
- Loading branch information
1 parent
9015790
commit 3ac6358
Showing
2 changed files
with
128 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package pvtdatapolicy | ||
|
||
import ( | ||
"math" | ||
"sync" | ||
|
||
"github.com/spf13/viper" | ||
) | ||
|
||
var defaultBLT uint64 = math.MaxUint64 | ||
var btlPolicyMap map[string]BTLPolicy | ||
var lock = &sync.Mutex{} | ||
|
||
func init() { | ||
btlPolicyMap = make(map[string]BTLPolicy) | ||
} | ||
|
||
// BTLPolicy BlockToLive policy for the pvt data | ||
type BTLPolicy interface { | ||
// init initializes BTLPolicy for the given channelName | ||
init(channelName string) error | ||
// GetBTL returns BlockToLive for a given namespace and collection | ||
GetBTL(ns string, coll string) uint64 | ||
// GetExpiringBlock returns the block number by which the pvtdata for given namespace,collection, and committingBlock should expire | ||
GetExpiringBlock(namesapce string, collection string, committingBlock uint64) uint64 | ||
} | ||
|
||
// GetBTLPolicy constructs (if not already done) and returns the BTLPolicy for the given channel | ||
func GetBTLPolicy(channelName string) (BTLPolicy, error) { | ||
lock.Lock() | ||
defer lock.Unlock() | ||
m := btlPolicyMap[channelName] | ||
if m == nil { | ||
m = &configBasedBTLPolicy{} | ||
m.init(channelName) | ||
btlPolicyMap[channelName] = m | ||
} | ||
return m, nil | ||
} | ||
|
||
// configBasedBTLPolicy implements interface BTLPolicy. | ||
// This implementation loads the BTL policy from configuration. This implementation is meant as a stop gap arrangement | ||
// until the config transaction framework is in place. This is becasue, the BTL policy should be consistent across peer | ||
// and should not change across different replays of transactions in the chain and hence it should be set via a config | ||
// transaction only. Later, another implementation should be provided that loads the BTL policy from config transactions | ||
type configBasedBTLPolicy struct { | ||
channelName string | ||
cache map[btlkey]uint64 | ||
} | ||
|
||
type btlkey struct { | ||
ns string | ||
coll string | ||
} | ||
|
||
// Init implements corresponding function in interface `BTLPolicyMgr` | ||
func (m *configBasedBTLPolicy) init(channelName string) error { | ||
m.channelName = channelName | ||
m.cache = make(map[btlkey]uint64) | ||
return nil | ||
} | ||
|
||
// GetBTL implements corresponding function in interface `BTLPolicyMgr` | ||
func (m *configBasedBTLPolicy) GetBTL(namesapce string, collection string) uint64 { | ||
var btl uint64 | ||
var ok bool | ||
key := btlkey{namesapce, collection} | ||
btl, ok = m.cache[key] | ||
if !ok { | ||
btlConfigured := viper.GetInt("ledger.pvtdata.btlpolicy." + m.channelName + "." + namesapce + "." + collection) | ||
if btlConfigured > 0 { | ||
btl = uint64(btlConfigured) | ||
} else { | ||
btl = defaultBLT | ||
} | ||
m.cache[key] = btl | ||
} | ||
return btl | ||
} | ||
|
||
func (m *configBasedBTLPolicy) GetExpiringBlock(namesapce string, collection string, committingBlock uint64) uint64 { | ||
btl := m.GetBTL(namesapce, collection) | ||
expiryBlk := committingBlock + btl + uint64(1) | ||
if expiryBlk <= committingBlock { // committingBlk + btl overflows uint64-max | ||
expiryBlk = math.MaxUint64 | ||
} | ||
return expiryBlk | ||
} |
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,34 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package pvtdatapolicy | ||
|
||
import ( | ||
"math" | ||
"testing" | ||
|
||
"github.com/spf13/viper" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestBTLPolicy(t *testing.T) { | ||
viper.Set("ledger.pvtdata.btlpolicy.ch1.ns1.coll1", 1) | ||
viper.Set("ledger.pvtdata.btlpolicy.ch1.ns2.coll2", 2) | ||
viper.Set("ledger.pvtdata.btlpolicy.ch2.ns2.coll2", 3) | ||
viper.Set("ledger.pvtdata.btlpolicy.ch2.ns3.coll4", 4) | ||
|
||
btlCh1, _ := GetBTLPolicy("ch1") | ||
btlCh2, _ := GetBTLPolicy("ch2") | ||
|
||
assert.Equal(t, uint64(1), btlCh1.GetBTL("ns1", "coll1")) | ||
assert.Equal(t, uint64(4), btlCh2.GetBTL("ns3", "coll4")) | ||
assert.Equal(t, defaultBLT, btlCh2.GetBTL("ns1", "coll5")) | ||
|
||
assert.Equal(t, uint64(5), btlCh1.GetExpiringBlock("ns1", "coll1", 3)) | ||
assert.Equal(t, uint64(8), btlCh2.GetExpiringBlock("ns3", "coll4", 3)) | ||
assert.Equal(t, uint64(math.MaxUint64), btlCh2.GetExpiringBlock("ns3", "coll4", math.MaxUint64-uint64(2))) | ||
assert.Equal(t, uint64(math.MaxUint64), btlCh2.GetExpiringBlock("ns1", "coll5", math.MaxUint64-uint64(2))) | ||
} |