Commit d611b109 authored by Kostas Christidis's avatar Kostas Christidis
Browse files

[FAB-2579] Fix inconsistencies in ledger package

https://jira.hyperledger.org/browse/FAB-2579



This changeset:

1. Removes the stuttering that was prevalent in filenames and package
names throughout the package
2. Updates function definitions where appropriate
3. Makes the layout of "ram" and "json" implementation consistent with
the "file" one by moving the relevant functions to `factory.go`
4. Switches all panic calls to their logger-equivalents. (We will be
doing this for all packages inside `orderer`.)
5. Per Binh's request: creates paths via the `filepath.Join` call

Change-Id: I918519cf66b3287864560d1fa2e6734b6953d657
Signed-off-by: default avatarKostas Christidis <kostas@christidis.io>
parent fd47bea6
......@@ -23,7 +23,7 @@ import (
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/orderer/common/filter"
"github.com/hyperledger/fabric/orderer/common/sigfilter"
ordererledger "github.com/hyperledger/fabric/orderer/ledger"
"github.com/hyperledger/fabric/orderer/ledger"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
"github.com/op/go-logging"
......@@ -50,7 +50,7 @@ type Support interface {
PolicyManager() policies.Manager
// Reader returns the chain Reader for the chain
Reader() ordererledger.Reader
Reader() ledger.Reader
// SharedConfig returns the shared config manager for this chain
SharedConfig() configvaluesapi.Orderer
......
......@@ -26,7 +26,7 @@ import (
mockconfigvaluesorderer "github.com/hyperledger/fabric/common/mocks/configvalues/channel/orderer"
mockpolicies "github.com/hyperledger/fabric/common/mocks/policies"
"github.com/hyperledger/fabric/common/policies"
ordererledger "github.com/hyperledger/fabric/orderer/ledger"
"github.com/hyperledger/fabric/orderer/ledger"
ramledger "github.com/hyperledger/fabric/orderer/ledger/ram"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
......@@ -81,7 +81,7 @@ func (mm *mockSupportManager) GetChain(chainID string) (Support, bool) {
}
type mockSupport struct {
ledger ordererledger.ReadWriter
ledger ledger.ReadWriter
sharedConfig *mockconfigvaluesorderer.SharedConfig
policyManager *mockpolicies.Manager
}
......@@ -90,11 +90,11 @@ func (mcs *mockSupport) PolicyManager() policies.Manager {
return mcs.policyManager
}
func (mcs *mockSupport) Reader() ordererledger.Reader {
func (mcs *mockSupport) Reader() ledger.Reader {
return mcs.ledger
}
func NewRAMLedger() ordererledger.ReadWriter {
func NewRAMLedger() ledger.ReadWriter {
rlf := ramledger.New(ledgerSize + 1)
rl, _ := rlf.GetOrCreate(provisional.TestChainID)
rl.Append(genesisBlock)
......@@ -118,11 +118,11 @@ func newMockMultichainManager() *mockSupportManager {
return mm
}
var seekOldest = &ab.SeekPosition{Type: &ab.SeekPosition_Oldest{&ab.SeekOldest{}}}
var seekNewest = &ab.SeekPosition{Type: &ab.SeekPosition_Newest{&ab.SeekNewest{}}}
var seekOldest = &ab.SeekPosition{Type: &ab.SeekPosition_Oldest{Oldest: &ab.SeekOldest{}}}
var seekNewest = &ab.SeekPosition{Type: &ab.SeekPosition_Newest{Newest: &ab.SeekNewest{}}}
func seekSpecified(number uint64) *ab.SeekPosition {
return &ab.SeekPosition{Type: &ab.SeekPosition_Specified{&ab.SeekSpecified{Number: number}}}
return &ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: number}}}
}
func makeSeek(chainID string, seekInfo *ab.SeekInfo) *cb.Envelope {
......@@ -142,8 +142,8 @@ func makeSeek(chainID string, seekInfo *ab.SeekInfo) *cb.Envelope {
func TestOldestSeek(t *testing.T) {
mm := newMockMultichainManager()
for i := 1; i < ledgerSize; i++ {
ledger := mm.chains[systemChainID].ledger
ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
l := mm.chains[systemChainID].ledger
l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
}
m := newMockD()
......@@ -181,8 +181,8 @@ func TestOldestSeek(t *testing.T) {
func TestNewestSeek(t *testing.T) {
mm := newMockMultichainManager()
for i := 1; i < ledgerSize; i++ {
ledger := mm.chains[systemChainID].ledger
ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
l := mm.chains[systemChainID].ledger
l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
}
m := newMockD()
......@@ -213,8 +213,8 @@ func TestNewestSeek(t *testing.T) {
func TestSpecificSeek(t *testing.T) {
mm := newMockMultichainManager()
for i := 1; i < ledgerSize; i++ {
ledger := mm.chains[systemChainID].ledger
ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
l := mm.chains[systemChainID].ledger
l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
}
m := newMockD()
......@@ -251,8 +251,8 @@ func TestSpecificSeek(t *testing.T) {
func TestUnauthorizedSeek(t *testing.T) {
mm := newMockMultichainManager()
for i := 1; i < ledgerSize; i++ {
ledger := mm.chains[systemChainID].ledger
ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
l := mm.chains[systemChainID].ledger
l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
}
mm.chains[systemChainID].policyManager.Policy.Err = fmt.Errorf("Fail to evaluate policy")
......@@ -277,8 +277,8 @@ func TestUnauthorizedSeek(t *testing.T) {
func TestBadSeek(t *testing.T) {
mm := newMockMultichainManager()
for i := 1; i < ledgerSize; i++ {
ledger := mm.chains[systemChainID].ledger
ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
l := mm.chains[systemChainID].ledger
l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
}
m := newMockD()
......@@ -302,8 +302,8 @@ func TestBadSeek(t *testing.T) {
func TestFailFastSeek(t *testing.T) {
mm := newMockMultichainManager()
for i := 1; i < ledgerSize; i++ {
ledger := mm.chains[systemChainID].ledger
ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
l := mm.chains[systemChainID].ledger
l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
}
m := newMockD()
......@@ -336,8 +336,8 @@ func TestFailFastSeek(t *testing.T) {
func TestBlockingSeek(t *testing.T) {
mm := newMockMultichainManager()
for i := 1; i < ledgerSize; i++ {
ledger := mm.chains[systemChainID].ledger
ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
l := mm.chains[systemChainID].ledger
l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", i))}}))
}
m := newMockD()
......@@ -363,8 +363,8 @@ func TestBlockingSeek(t *testing.T) {
case <-time.After(50 * time.Millisecond):
}
ledger := mm.chains[systemChainID].ledger
ledger.Append(ordererledger.CreateNextBlock(ledger, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", ledgerSize+1))}}))
l := mm.chains[systemChainID].ledger
l.Append(ledger.CreateNextBlock(l, []*cb.Envelope{&cb.Envelope{Payload: []byte(fmt.Sprintf("%d", ledgerSize+1))}}))
select {
case deliverReply := <-m.sendChan:
......
......@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package ordererledger_test
package ledger_test
import (
"bytes"
......
......@@ -21,58 +21,58 @@ import (
"github.com/hyperledger/fabric/common/ledger/blkstorage"
"github.com/hyperledger/fabric/common/ledger/blkstorage/fsblkstorage"
ordererledger "github.com/hyperledger/fabric/orderer/ledger"
"github.com/hyperledger/fabric/orderer/ledger"
)
type fileLedgerFactory struct {
blkstorageProvider blkstorage.BlockStoreProvider
ledgers map[string]ordererledger.ReadWriter
ledgers map[string]ledger.ReadWriter
mutex sync.Mutex
}
// GetOrCreate gets an existing ledger (if it exists) or creates it if it does not
func (lf *fileLedgerFactory) GetOrCreate(chainID string) (ordererledger.ReadWriter, error) {
lf.mutex.Lock()
defer lf.mutex.Unlock()
func (flf *fileLedgerFactory) GetOrCreate(chainID string) (ledger.ReadWriter, error) {
flf.mutex.Lock()
defer flf.mutex.Unlock()
key := chainID
// check cache
ledger, ok := lf.ledgers[key]
ledger, ok := flf.ledgers[key]
if ok {
return ledger, nil
}
// open fresh
blockStore, err := lf.blkstorageProvider.OpenBlockStore(key)
blockStore, err := flf.blkstorageProvider.OpenBlockStore(key)
if err != nil {
return nil, err
}
ledger = &fileLedger{blockStore: blockStore, signal: make(chan struct{})}
lf.ledgers[key] = ledger
flf.ledgers[key] = ledger
return ledger, nil
}
// ChainIDs returns the chain IDs the Factory is aware of
func (lf *fileLedgerFactory) ChainIDs() []string {
chainIDs, err := lf.blkstorageProvider.List()
// ChainIDs returns the chain IDs the factory is aware of
func (flf *fileLedgerFactory) ChainIDs() []string {
chainIDs, err := flf.blkstorageProvider.List()
if err != nil {
panic(err)
logger.Panic(err)
}
return chainIDs
}
// Close closes the file ledgers served by this factory
func (lf *fileLedgerFactory) Close() {
lf.blkstorageProvider.Close()
// Close releases all resources acquired by the factory
func (flf *fileLedgerFactory) Close() {
flf.blkstorageProvider.Close()
}
// New creates a new ledger factory
func New(directory string) ordererledger.Factory {
func New(directory string) ledger.Factory {
return &fileLedgerFactory{
blkstorageProvider: fsblkstorage.NewProvider(
fsblkstorage.NewConf(directory, -1),
&blkstorage.IndexConfig{
AttrsToIndex: []blkstorage.IndexableAttr{blkstorage.IndexableAttrBlockNum}},
),
ledgers: make(map[string]ordererledger.ReadWriter),
ledgers: make(map[string]ledger.ReadWriter),
}
}
......@@ -18,13 +18,13 @@ package fileledger
import (
"github.com/hyperledger/fabric/common/ledger/blkstorage"
ordererledger "github.com/hyperledger/fabric/orderer/ledger"
ledger "github.com/hyperledger/fabric/orderer/ledger"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
"github.com/op/go-logging"
)
var logger = logging.MustGetLogger("ordererledger/fileledger")
var logger = logging.MustGetLogger("orderer/fileledger")
var closedChan chan struct{}
func init() {
......@@ -69,33 +69,33 @@ func (i *fileLedgerIterator) ReadyChan() <-chan struct{} {
// Iterator returns an Iterator, as specified by a cb.SeekInfo message, and its
// starting block number
func (fl *fileLedger) Iterator(startPosition *ab.SeekPosition) (ordererledger.Iterator, uint64) {
func (fl *fileLedger) Iterator(startPosition *ab.SeekPosition) (ledger.Iterator, uint64) {
switch start := startPosition.Type.(type) {
case *ab.SeekPosition_Oldest:
return &fileLedgerIterator{ledger: fl, blockNumber: 0}, 0
case *ab.SeekPosition_Newest:
info, err := fl.blockStore.GetBlockchainInfo()
if err != nil {
panic(err)
logger.Panic(err)
}
newestBlockNumber := info.Height - 1
return &fileLedgerIterator{ledger: fl, blockNumber: newestBlockNumber}, newestBlockNumber
case *ab.SeekPosition_Specified:
height := fl.Height()
if start.Specified.Number > height {
return &ordererledger.NotFoundErrorIterator{}, 0
return &ledger.NotFoundErrorIterator{}, 0
}
return &fileLedgerIterator{ledger: fl, blockNumber: start.Specified.Number}, start.Specified.Number
}
// This line should be unreachable, but the compiler requires it
return &ordererledger.NotFoundErrorIterator{}, 0
return &ledger.NotFoundErrorIterator{}, 0
}
// Height returns the number of blocks on the ledger
func (fl *fileLedger) Height() uint64 {
info, err := fl.blockStore.GetBlockchainInfo()
if err != nil {
panic(err)
logger.Panic(err)
}
return info.Height
}
......
......@@ -23,7 +23,7 @@ import (
"testing"
"github.com/hyperledger/fabric/common/configtx/tool/provisional"
ordererledger "github.com/hyperledger/fabric/orderer/ledger"
"github.com/hyperledger/fabric/orderer/ledger"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
......@@ -39,7 +39,7 @@ func init() {
type testEnv struct {
t *testing.T
location string
flf ordererledger.Factory
flf ledger.Factory
}
func initialize(t *testing.T) (*testEnv, *fileLedger) {
......@@ -75,7 +75,7 @@ func TestInitialization(t *testing.T) {
if fl.Height() != 1 {
t.Fatalf("Block height should be 1")
}
block := ordererledger.GetBlock(fl, 0)
block := ledger.GetBlock(fl, 0)
if block == nil {
t.Fatalf("Error retrieving genesis block")
}
......@@ -92,7 +92,7 @@ func TestReinitialization(t *testing.T) {
defer tev.tearDown()
// create a block to add to the ledger
b1 := ordererledger.CreateNextBlock(leger1, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}})
b1 := ledger.CreateNextBlock(leger1, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}})
// add the block to the ledger
leger1.Append(b1)
......@@ -122,7 +122,7 @@ func TestReinitialization(t *testing.T) {
if fl.Height() != 2 {
t.Fatalf("Block height should be 2. Got %v", fl.Height())
}
block := ordererledger.GetBlock(fl, 1)
block := ledger.GetBlock(fl, 1)
if block == nil {
t.Fatalf("Error retrieving block 1")
}
......@@ -159,11 +159,11 @@ func TestAddition(t *testing.T) {
defer tev.tearDown()
info, _ := fl.blockStore.GetBlockchainInfo()
prevHash := info.CurrentBlockHash
fl.Append(ordererledger.CreateNextBlock(fl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
fl.Append(ledger.CreateNextBlock(fl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
if fl.Height() != 2 {
t.Fatalf("Block height should be 2")
}
block := ordererledger.GetBlock(fl, 1)
block := ledger.GetBlock(fl, 1)
if block == nil {
t.Fatalf("Error retrieving genesis block")
}
......@@ -175,7 +175,7 @@ func TestAddition(t *testing.T) {
func TestRetrieval(t *testing.T) {
tev, fl := initialize(t)
defer tev.tearDown()
fl.Append(ordererledger.CreateNextBlock(fl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
fl.Append(ledger.CreateNextBlock(fl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
it, num := fl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Oldest{}})
if num != 0 {
t.Fatalf("Expected genesis block iterator, but got %d", num)
......@@ -221,7 +221,7 @@ func TestBlockedRetrieval(t *testing.T) {
t.Fatalf("Should not be ready for block read")
default:
}
fl.Append(ordererledger.CreateNextBlock(fl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
fl.Append(ledger.CreateNextBlock(fl, []*cb.Envelope{&cb.Envelope{Payload: []byte("My Data")}}))
select {
case <-signal:
default:
......
......@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package ordererledger_test
package ledger_test
import (
"io/ioutil"
......
/*
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 jsonledger
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sync"
"github.com/golang/protobuf/jsonpb"
"github.com/hyperledger/fabric/orderer/ledger"
)
type jsonLedgerFactory struct {
directory string
ledgers map[string]ledger.ReadWriter
mutex sync.Mutex
}
// GetOrCreate gets an existing ledger (if it exists) or creates it if it does not
func (jlf *jsonLedgerFactory) GetOrCreate(chainID string) (ledger.ReadWriter, error) {
jlf.mutex.Lock()
defer jlf.mutex.Unlock()
key := chainID
l, ok := jlf.ledgers[key]
if ok {
return l, nil
}
directory := filepath.Join(jlf.directory, fmt.Sprintf(chainDirectoryFormatString, chainID))
logger.Debugf("Initializing chain at: %s", directory)
if err := os.MkdirAll(directory, 0700); err != nil {
return nil, err
}
ch := newChain(directory)
jlf.ledgers[key] = ch
return ch, nil
}
// newChain creates a new chain backed by a JSON ledger
func newChain(directory string) ledger.ReadWriter {
jl := &jsonLedger{
directory: directory,
signal: make(chan struct{}),
marshaler: &jsonpb.Marshaler{Indent: " "},
}
jl.initializeBlockHeight()
logger.Debugf("Initialized to block height %d with hash %x", jl.height-1, jl.lastHash)
return jl
}
// initializeBlockHeight verifies that all blocks exist between 0 and the block
// height, and populates the lastHash
func (jl *jsonLedger) initializeBlockHeight() {
infos, err := ioutil.ReadDir(jl.directory)
if err != nil {
logger.Panic(err)
}
nextNumber := uint64(0)
for _, info := range infos {
if info.IsDir() {
continue
}
var number uint64
_, err := fmt.Sscanf(info.Name(), blockFileFormatString, &number)
if err != nil {
continue
}
if number != nextNumber {
logger.Panicf("Missing block %d in the chain", nextNumber)
}
nextNumber++
}
jl.height = nextNumber
if jl.height == 0 {
return
}
block, found := jl.readBlock(jl.height - 1)
if !found {
logger.Panicf("Block %d was in directory listing but error reading", jl.height-1)
}
if block == nil {
logger.Panicf("Error reading block %d", jl.height-1)
}
jl.lastHash = block.Header.Hash()
}
// ChainIDs returns the chain IDs the factory is aware of
func (jlf *jsonLedgerFactory) ChainIDs() []string {
jlf.mutex.Lock()
defer jlf.mutex.Unlock()
ids := make([]string, len(jlf.ledgers))
i := 0
for key := range jlf.ledgers {
ids[i] = key
i++
}
return ids
}
// Close is a no-op for the JSON ledger
func (jlf *jsonLedgerFactory) Close() {
return // nothing to do
}
// New creates a new ledger factory
func New(directory string) ledger.Factory {
logger.Debugf("Initializing ledger at: %s", directory)
if err := os.MkdirAll(directory, 0700); err != nil {
logger.Fatalf("Could not create directory %s: %s", directory, err)
}
jlf := &jsonLedgerFactory{
directory: directory,
ledgers: make(map[string]ledger.ReadWriter),
}
infos, err := ioutil.ReadDir(jlf.directory)
if err != nil {
logger.Panicf("Error reading from directory %s while initializing ledger: %s", jlf.directory, err)
}
for _, info := range infos {
if !info.IsDir() {
continue
}
var chainID string
_, err := fmt.Sscanf(info.Name(), chainDirectoryFormatString, &chainID)
if err != nil {
continue
}
jl, err := jlf.GetOrCreate(chainID)
if err != nil {
logger.Warningf("Failed to initialize chain from %s: %s", chainID, err)
continue
}
jlf.ledgers[chainID] = jl
}
return jlf
}
......@@ -19,11 +19,10 @@ package jsonledger
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"sync"
"path/filepath"
ordererledger "github.com/hyperledger/fabric/orderer/ledger"
ledger "github.com/hyperledger/fabric/orderer/ledger"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
"github.com/op/go-logging"
......@@ -31,7 +30,7 @@ import (
"github.com/golang/protobuf/jsonpb"
)
var logger = logging.MustGetLogger("ordererledger/jsonledger")
var logger = logging.MustGetLogger("orderer/jsonledger")
var closedChan chan struct{}
func init() {
......@@ -58,161 +57,6 @@ type jsonLedger struct {
marshaler *jsonpb.Marshaler
}
type jsonLedgerFactory struct {
directory string
ledgers map[string]ordererledger.ReadWriter
mutex sync.Mutex
}
// New creates a new jsonledger Factory and the ordering system chain specified by the systemGenesis block (if it does not already exist)
func New(directory string) ordererledger.Factory {
logger.Debugf("Initializing jsonLedger at '%s'", directory)
if err := os.MkdirAll(directory, 0700); err != nil {
logger.Fatalf("Could not create directory %s: %s", directory, err)
}
jlf := &jsonLedgerFactory{
directory: directory,
ledgers: make(map[string]ordererledger.ReadWriter),
}
infos, err := ioutil.ReadDir(jlf.directory)
if err != nil {
logger.Panicf("Error reading from directory %s while initializing jsonledger: %s", jlf.directory, err)
}
for _, info := range infos {
if !info.IsDir() {
continue
}
var chainID string
_, err := fmt.Sscanf(info.Name(), chainDirectoryFormatString, &chainID)
if err != nil {
continue
}
jl, err