Skip to content

Commit 8cdd0f4

Browse files
committed
SingleLevelDB for block index
https://jira.hyperledger.org/browse/FAB-1664 This changeset: - Renames package ledger/util/db to ledger/util/leveldbhelper - Implements a leveldb provider (that enables using same leveldb instance as a multiple logical dbs) in util package for being able to reuse across statedb, index, and later for historydb - Implements a provider as a single point of invocation for managing multiple block storage - Uses a single leveldb instance for block storage index - Makes the structures other than providers as private to their respective packages Change-Id: I5f0b3b9aa8ef3ac1ccdce4f3c6fa6d842b5318c1 Signed-off-by: manish <[email protected]>
1 parent 1642e88 commit 8cdd0f4

32 files changed

+842
-425
lines changed

core/ledger/blkstorage/blockstorage.go

+9
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ var (
4848
ErrAttrNotIndexed = errors.New("Attribute not indexed")
4949
)
5050

51+
// BlockStoreProvider provides an handle to a BlockStore
52+
type BlockStoreProvider interface {
53+
CreateBlockStore(ledgerid string) (BlockStore, error)
54+
OpenBlockStore(ledgerid string) (BlockStore, error)
55+
Exists(ledgerid string) (bool, error)
56+
List() ([]string, error)
57+
Close()
58+
}
59+
5160
// BlockStore - an interface for persisting and retrieving blocks
5261
// An implementation of this interface is expected to take an argument
5362
// of type `IndexConfig` which configures the block store on what items should be indexed

core/ledger/blkstorage/fsblkstorage/block_stream_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ func TestBlockfileStream(t *testing.T) {
3030
}
3131

3232
func testBlockfileStream(t *testing.T, numBlocks int) {
33-
env := newTestEnv(t)
33+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
3434
defer env.Cleanup()
35-
w := newTestBlockfileWrapper(t, env)
36-
blockfileMgr := w.blockfileMgr
35+
ledgerid := "testledger"
36+
w := newTestBlockfileWrapper(env, ledgerid)
3737
blocks := testutil.ConstructTestBlocks(t, numBlocks)
3838
w.addBlocks(blocks)
3939
w.close()
4040

41-
s, err := newBlockfileStream(blockfileMgr.rootDir, 0, 0)
41+
s, err := newBlockfileStream(w.blockfileMgr.rootDir, 0, 0)
4242
defer s.close()
4343
testutil.AssertNoError(t, err, "Error in constructing blockfile stream")
4444

@@ -71,9 +71,9 @@ func TestBlockFileStreamUnexpectedEOF(t *testing.T) {
7171
}
7272

7373
func testBlockFileStreamUnexpectedEOF(t *testing.T, numBlocks int, partialBlockBytes []byte) {
74-
env := newTestEnv(t)
74+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
7575
defer env.Cleanup()
76-
w := newTestBlockfileWrapper(t, env)
76+
w := newTestBlockfileWrapper(env, "testLedger")
7777
blockfileMgr := w.blockfileMgr
7878
blocks := testutil.ConstructTestBlocks(t, numBlocks)
7979
w.addBlocks(blocks)
@@ -100,9 +100,9 @@ func TestBlockStream(t *testing.T) {
100100
}
101101

102102
func testBlockStream(t *testing.T, numFiles int) {
103-
env := newTestEnv(t)
103+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
104104
defer env.Cleanup()
105-
w := newTestBlockfileWrapper(t, env)
105+
w := newTestBlockfileWrapper(env, "testLedger")
106106
defer w.close()
107107
blockfileMgr := w.blockfileMgr
108108

core/ledger/blkstorage/fsblkstorage/blockfile_mgr.go

+14-20
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
"github.com/golang/protobuf/proto"
2626
"github.com/hyperledger/fabric/core/ledger/blkstorage"
2727
"github.com/hyperledger/fabric/core/ledger/util"
28-
"github.com/hyperledger/fabric/core/ledger/util/db"
28+
"github.com/hyperledger/fabric/core/ledger/util/leveldbhelper"
2929
"github.com/hyperledger/fabric/protos/common"
3030
pb "github.com/hyperledger/fabric/protos/peer"
3131
putil "github.com/hyperledger/fabric/protos/utils"
@@ -43,10 +43,15 @@ var (
4343
blkMgrInfoKey = []byte("blkMgrInfo")
4444
)
4545

46+
type conf struct {
47+
blockfilesDir string
48+
maxBlockfileSize int
49+
}
50+
4651
type blockfileMgr struct {
4752
rootDir string
4853
conf *Conf
49-
db *db.DB
54+
db *leveldbhelper.DBHandle
5055
index index
5156
cpInfo *checkpointInfo
5257
cpInfoCond *sync.Cond
@@ -95,17 +100,15 @@ At start up a new manager:
95100
-- If index and file system are not in sync, syncs index from the FS
96101
*) Updates blockchain info used by the APIs
97102
*/
98-
func newBlockfileMgr(conf *Conf, indexConfig *blkstorage.IndexConfig) *blockfileMgr {
103+
func newBlockfileMgr(id string, conf *Conf, indexConfig *blkstorage.IndexConfig, indexStore *leveldbhelper.DBHandle) *blockfileMgr {
99104
//Determine the root directory for the blockfile storage, if it does not exist create it
100-
rootDir := conf.blockfilesDir
105+
rootDir := conf.getLedgerBlockDir(id)
101106
_, err := util.CreateDirIfMissing(rootDir)
102107
if err != nil {
103108
panic(fmt.Sprintf("Error: %s", err))
104109
}
105-
//Determine the kev value db instance, if it does not exist, create the directory and instantiate the database.
106-
db := initDB(conf)
107110
// Instantiate the manager, i.e. blockFileMgr structure
108-
mgr := &blockfileMgr{rootDir: rootDir, conf: conf, db: db}
111+
mgr := &blockfileMgr{rootDir: rootDir, conf: conf, db: indexStore}
109112

110113
// cp = checkpointInfo, retrieve from the database the file suffix or number of where blocks were stored.
111114
// It also retrieves the current size of that file and the last block number that was written to that file.
@@ -123,7 +126,7 @@ func newBlockfileMgr(conf *Conf, indexConfig *blkstorage.IndexConfig) *blockfile
123126
}
124127
//Verify that the checkpoint stored in db is accurate with what is actually stored in block file system
125128
// If not the same, sync the cpInfo and the file system
126-
syncCPInfoFromFS(conf, cpInfo)
129+
syncCPInfoFromFS(rootDir, cpInfo)
127130
//Open a writer to the file identified by the number and truncate it to only contain the latest block
128131
// that was completely saved (file system, index, cpinfo, etc)
129132
currentFileWriter, err := newBlockfileWriter(deriveBlockfilePath(rootDir, cpInfo.latestFileChunkSuffixNum))
@@ -137,7 +140,7 @@ func newBlockfileMgr(conf *Conf, indexConfig *blkstorage.IndexConfig) *blockfile
137140
}
138141

139142
// Create a new KeyValue store database handler for the blocks index in the keyvalue database
140-
mgr.index = newBlockIndex(indexConfig, db)
143+
mgr.index = newBlockIndex(indexConfig, indexStore)
141144

142145
// Update the manager with the checkpoint info and the file writer
143146
mgr.cpInfo = cpInfo
@@ -174,21 +177,13 @@ func newBlockfileMgr(conf *Conf, indexConfig *blkstorage.IndexConfig) *blockfile
174177
return mgr
175178
}
176179

177-
func initDB(conf *Conf) *db.DB {
178-
dbInst := db.CreateDB(&db.Conf{
179-
DBPath: conf.dbPath})
180-
dbInst.Open()
181-
return dbInst
182-
}
183-
184180
//cp = checkpointInfo, from the database gets the file suffix and the size of
185181
// the file of where the last block was written. Also retrieves contains the
186182
// last block number that was written. At init
187183
//checkpointInfo:latestFileChunkSuffixNum=[0], latestFileChunksize=[0], lastBlockNumber=[0]
188-
func syncCPInfoFromFS(conf *Conf, cpInfo *checkpointInfo) {
184+
func syncCPInfoFromFS(rootDir string, cpInfo *checkpointInfo) {
189185
logger.Debugf("Starting checkpoint=%s", cpInfo)
190186
//Checks if the file suffix of where the last block was written exists
191-
rootDir := conf.blockfilesDir
192187
filePath := deriveBlockfilePath(rootDir, cpInfo.latestFileChunkSuffixNum)
193188
exists, size, err := util.FileExists(filePath)
194189
if err != nil {
@@ -224,7 +219,6 @@ func (mgr *blockfileMgr) open() error {
224219

225220
func (mgr *blockfileMgr) close() {
226221
mgr.currentFileWriter.close()
227-
mgr.db.Close()
228222
}
229223

230224
func (mgr *blockfileMgr) moveToNextFile() {
@@ -443,7 +437,7 @@ func (mgr *blockfileMgr) retrieveBlockHeaderByNumber(blockNum uint64) (*common.B
443437
return info.blockHeader, nil
444438
}
445439

446-
func (mgr *blockfileMgr) retrieveBlocks(startNum uint64) (*BlocksItr, error) {
440+
func (mgr *blockfileMgr) retrieveBlocks(startNum uint64) (*blocksItr, error) {
447441
return newBlockItr(mgr, startNum), nil
448442
}
449443

core/ledger/blkstorage/fsblkstorage/blockfile_mgr_test.go

+23-23
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ import (
2828
)
2929

3030
func TestBlockfileMgrBlockReadWrite(t *testing.T) {
31-
env := newTestEnv(t)
31+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
3232
defer env.Cleanup()
33-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
33+
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
3434
defer blkfileMgrWrapper.close()
3535
blocks := testutil.ConstructTestBlocks(t, 10)
3636
blkfileMgrWrapper.addBlocks(blocks)
@@ -47,9 +47,10 @@ func TestBlockfileMgrCrashDuringWriting(t *testing.T) {
4747

4848
func testBlockfileMgrCrashDuringWriting(t *testing.T, numBlocksBeforeCheckpoint int,
4949
numBlocksAfterCheckpoint int, numLastBlockBytes int, numPartialBytesToWrite int) {
50-
env := newTestEnv(t)
50+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
5151
defer env.Cleanup()
52-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
52+
ledgerid := "testLedger"
53+
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
5354
bg := testutil.NewBlockGenerator(t)
5455
blocksBeforeCP := bg.NextTestBlocks(numBlocksBeforeCheckpoint)
5556
blkfileMgrWrapper.addBlocks(blocksBeforeCP)
@@ -75,7 +76,7 @@ func testBlockfileMgrCrashDuringWriting(t *testing.T, numBlocksBeforeCheckpoint
7576
blkfileMgrWrapper.close()
7677

7778
// simulate a start after a crash
78-
blkfileMgrWrapper = newTestBlockfileWrapper(t, env)
79+
blkfileMgrWrapper = newTestBlockfileWrapper(env, ledgerid)
7980
defer blkfileMgrWrapper.close()
8081
cpInfo3 := blkfileMgrWrapper.blockfileMgr.cpInfo
8182
testutil.AssertEquals(t, cpInfo3, cpInfo2)
@@ -91,9 +92,9 @@ func testBlockfileMgrCrashDuringWriting(t *testing.T, numBlocksBeforeCheckpoint
9192
}
9293

9394
func TestBlockfileMgrBlockIterator(t *testing.T) {
94-
env := newTestEnv(t)
95+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
9596
defer env.Cleanup()
96-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
97+
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
9798
defer blkfileMgrWrapper.close()
9899
blocks := testutil.ConstructTestBlocks(t, 10)
99100
blkfileMgrWrapper.addBlocks(blocks)
@@ -109,7 +110,7 @@ func testBlockfileMgrBlockIterator(t *testing.T, blockfileMgr *blockfileMgr,
109110
for {
110111
block, err := itr.Next()
111112
testutil.AssertNoError(t, err, fmt.Sprintf("Error while getting block number [%d] from iterator", numBlocksItrated))
112-
testutil.AssertEquals(t, block.(*BlockHolder).GetBlock(), expectedBlocks[numBlocksItrated])
113+
testutil.AssertEquals(t, block.(*blockHolder).GetBlock(), expectedBlocks[numBlocksItrated])
113114
numBlocksItrated++
114115
if numBlocksItrated == lastBlockNum-firstBlockNum+1 {
115116
break
@@ -119,9 +120,9 @@ func testBlockfileMgrBlockIterator(t *testing.T, blockfileMgr *blockfileMgr,
119120
}
120121

121122
func TestBlockfileMgrBlockchainInfo(t *testing.T) {
122-
env := newTestEnv(t)
123+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
123124
defer env.Cleanup()
124-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
125+
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
125126
defer blkfileMgrWrapper.close()
126127

127128
bcInfo := blkfileMgrWrapper.blockfileMgr.getBlockchainInfo()
@@ -134,9 +135,9 @@ func TestBlockfileMgrBlockchainInfo(t *testing.T) {
134135
}
135136

136137
func TestBlockfileMgrGetTxById(t *testing.T) {
137-
env := newTestEnv(t)
138+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
138139
defer env.Cleanup()
139-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
140+
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
140141
defer blkfileMgrWrapper.close()
141142
blocks := testutil.ConstructTestBlocks(t, 10)
142143
blkfileMgrWrapper.addBlocks(blocks)
@@ -155,21 +156,21 @@ func TestBlockfileMgrGetTxById(t *testing.T) {
155156
}
156157

157158
func TestBlockfileMgrRestart(t *testing.T) {
158-
env := newTestEnv(t)
159+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
159160
defer env.Cleanup()
160-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
161+
ledgerid := "testLedger"
162+
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
161163
blocks := testutil.ConstructTestBlocks(t, 10)
162164
blkfileMgrWrapper.addBlocks(blocks)
163165
blkfileMgrWrapper.close()
164166

165-
blkfileMgrWrapper = newTestBlockfileWrapper(t, env)
167+
blkfileMgrWrapper = newTestBlockfileWrapper(env, ledgerid)
166168
defer blkfileMgrWrapper.close()
167169
testutil.AssertEquals(t, int(blkfileMgrWrapper.blockfileMgr.cpInfo.lastBlockNumber), 10)
168170
blkfileMgrWrapper.testGetBlockByHash(blocks)
169171
}
170172

171173
func TestBlockfileMgrFileRolling(t *testing.T) {
172-
env := newTestEnv(t)
173174
blocks := testutil.ConstructTestBlocks(t, 100)
174175
size := 0
175176
for _, block := range blocks {
@@ -180,18 +181,17 @@ func TestBlockfileMgrFileRolling(t *testing.T) {
180181
size += blockBytesSize + len(encodedLen)
181182
}
182183

183-
env.conf.maxBlockfileSize = int(0.75 * float64(size))
184-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
184+
maxFileSie := int(0.75 * float64(size))
185+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", maxFileSie))
186+
defer env.Cleanup()
187+
ledgerid := "testLedger"
188+
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
185189
blkfileMgrWrapper.addBlocks(blocks)
186190
testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.cpInfo.latestFileChunkSuffixNum, 1)
187191
blkfileMgrWrapper.testGetBlockByHash(blocks)
188192
blkfileMgrWrapper.close()
189-
env.Cleanup()
190193

191-
env = newTestEnv(t)
192-
defer env.Cleanup()
193-
env.conf.maxBlockfileSize = int(0.40 * float64(size))
194-
blkfileMgrWrapper = newTestBlockfileWrapper(t, env)
194+
blkfileMgrWrapper = newTestBlockfileWrapper(env, ledgerid)
195195
defer blkfileMgrWrapper.close()
196196
blkfileMgrWrapper.addBlocks(blocks)
197197
testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.cpInfo.latestFileChunkSuffixNum, 2)

core/ledger/blkstorage/fsblkstorage/blockfile_scan_test.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ import (
2727
)
2828

2929
func TestBlockFileScanSmallTxOnly(t *testing.T) {
30-
env := newTestEnv(t)
30+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
3131
defer env.Cleanup()
32-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
32+
ledgerid := "testLedger"
33+
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
3334
bg := testutil.NewBlockGenerator(t)
3435
blocks := []*common.Block{}
3536
blocks = append(blocks, bg.NextTestBlock(0, 0))
@@ -38,20 +39,21 @@ func TestBlockFileScanSmallTxOnly(t *testing.T) {
3839
blkfileMgrWrapper.addBlocks(blocks)
3940
blkfileMgrWrapper.close()
4041

41-
filePath := deriveBlockfilePath(env.conf.blockfilesDir, 0)
42+
filePath := deriveBlockfilePath(env.provider.conf.getLedgerBlockDir(ledgerid), 0)
4243
_, fileSize, err := util.FileExists(filePath)
4344
testutil.AssertNoError(t, err, "")
4445

45-
endOffsetLastBlock, numBlocks, err := scanForLastCompleteBlock(env.conf.blockfilesDir, 0, 0)
46+
endOffsetLastBlock, numBlocks, err := scanForLastCompleteBlock(env.provider.conf.getLedgerBlockDir(ledgerid), 0, 0)
4647
testutil.AssertNoError(t, err, "")
4748
testutil.AssertEquals(t, numBlocks, len(blocks))
4849
testutil.AssertEquals(t, endOffsetLastBlock, fileSize)
4950
}
5051

5152
func TestBlockFileScanSmallTxLastTxIncomplete(t *testing.T) {
52-
env := newTestEnv(t)
53+
env := newTestEnv(t, NewConf("/tmp/fabric/ledgertests", 0))
5354
defer env.Cleanup()
54-
blkfileMgrWrapper := newTestBlockfileWrapper(t, env)
55+
ledgerid := "testLedger"
56+
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
5557
bg := testutil.NewBlockGenerator(t)
5658
blocks := []*common.Block{}
5759
blocks = append(blocks, bg.NextTestBlock(0, 0))
@@ -60,7 +62,7 @@ func TestBlockFileScanSmallTxLastTxIncomplete(t *testing.T) {
6062
blkfileMgrWrapper.addBlocks(blocks)
6163
blkfileMgrWrapper.close()
6264

63-
filePath := deriveBlockfilePath(env.conf.blockfilesDir, 0)
65+
filePath := deriveBlockfilePath(env.provider.conf.getLedgerBlockDir(ledgerid), 0)
6466
_, fileSize, err := util.FileExists(filePath)
6567
testutil.AssertNoError(t, err, "")
6668

@@ -70,7 +72,7 @@ func TestBlockFileScanSmallTxLastTxIncomplete(t *testing.T) {
7072
err = file.Truncate(fileSize - 1)
7173
testutil.AssertNoError(t, err, "")
7274

73-
_, numBlocks, err := scanForLastCompleteBlock(env.conf.blockfilesDir, 0, 0)
75+
_, numBlocks, err := scanForLastCompleteBlock(env.provider.conf.getLedgerBlockDir(ledgerid), 0, 0)
7476
testutil.AssertNoError(t, err, "")
7577
testutil.AssertEquals(t, numBlocks, len(blocks)-1)
7678
}

core/ledger/blkstorage/fsblkstorage/blockindex.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ import (
2222
"github.com/golang/protobuf/proto"
2323
"github.com/hyperledger/fabric/core/ledger/blkstorage"
2424
"github.com/hyperledger/fabric/core/ledger/util"
25-
"github.com/hyperledger/fabric/core/ledger/util/db"
26-
"github.com/syndtr/goleveldb/leveldb"
25+
"github.com/hyperledger/fabric/core/ledger/util/leveldbhelper"
2726
)
2827

2928
const (
@@ -54,10 +53,10 @@ type blockIdxInfo struct {
5453

5554
type blockIndex struct {
5655
indexItemsMap map[blkstorage.IndexableAttr]bool
57-
db *db.DB
56+
db *leveldbhelper.DBHandle
5857
}
5958

60-
func newBlockIndex(indexConfig *blkstorage.IndexConfig, db *db.DB) *blockIndex {
59+
func newBlockIndex(indexConfig *blkstorage.IndexConfig, db *leveldbhelper.DBHandle) *blockIndex {
6160
indexItems := indexConfig.AttrsToIndex
6261
logger.Debugf("newBlockIndex() - indexItems:[%s]", indexItems)
6362
indexItemsMap := make(map[blkstorage.IndexableAttr]bool)
@@ -85,7 +84,7 @@ func (index *blockIndex) indexBlock(blockIdxInfo *blockIdxInfo) error {
8584
logger.Debugf("Indexing block [%s]", blockIdxInfo)
8685
flp := blockIdxInfo.flp
8786
txOffsets := blockIdxInfo.txOffsets
88-
batch := &leveldb.Batch{}
87+
batch := leveldbhelper.NewUpdateBatch()
8988
flpBytes, err := flp.marshal()
9089
if err != nil {
9190
return err

0 commit comments

Comments
 (0)