Skip to content

Commit 910e496

Browse files
committed
Sync block index with block storage
This commit adds the functionality of checkpointing block index progress and sync-ing (updating) the index during start of the block storage system Change-Id: Ib1a325add455bce47e510ccfc7af052db51117e6 Signed-off-by: manish <[email protected]>
1 parent a069514 commit 910e496

File tree

5 files changed

+296
-50
lines changed

5 files changed

+296
-50
lines changed

core/ledgernext/blkstorage/fsblkstorage/block_stream.go

+41-18
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ var ErrUnexpectedEndOfBlockfile = errors.New("unexpected end of blockfile")
3434
// blockfileStream reads blocks sequentially from a single file.
3535
// It starts from the given offset and can traverse till the end of the file
3636
type blockfileStream struct {
37+
fileNum int
3738
file *os.File
3839
reader *bufio.Reader
3940
currentOffset int64
@@ -49,10 +50,19 @@ type blockStream struct {
4950
currentFileStream *blockfileStream
5051
}
5152

53+
// blockPlacementInfo captures the information related
54+
// to block's placement in the file.
55+
type blockPlacementInfo struct {
56+
fileNum int
57+
blockStartOffset int64
58+
blockBytesOffset int64
59+
}
60+
5261
///////////////////////////////////
5362
// blockfileStream functions
5463
////////////////////////////////////
55-
func newBlockfileStream(filePath string, startOffset int64) (*blockfileStream, error) {
64+
func newBlockfileStream(rootDir string, fileNum int, startOffset int64) (*blockfileStream, error) {
65+
filePath := deriveBlockfilePath(rootDir, fileNum)
5666
logger.Debugf("newBlockfileStream(): filePath=[%s], startOffset=[%d]", filePath, startOffset)
5767
var file *os.File
5868
var err error
@@ -68,41 +78,50 @@ func newBlockfileStream(filePath string, startOffset int64) (*blockfileStream, e
6878
panic(fmt.Sprintf("Could not seek file [%s] to given startOffset [%d]. New position = [%d]",
6979
filePath, startOffset, newPosition))
7080
}
71-
s := &blockfileStream{file, bufio.NewReader(file), startOffset}
81+
s := &blockfileStream{fileNum, file, bufio.NewReader(file), startOffset}
7282
return s, nil
7383
}
7484

7585
func (s *blockfileStream) nextBlockBytes() ([]byte, error) {
86+
blockBytes, _, err := s.nextBlockBytesAndPlacementInfo()
87+
return blockBytes, err
88+
}
89+
90+
func (s *blockfileStream) nextBlockBytesAndPlacementInfo() ([]byte, *blockPlacementInfo, error) {
7691
var lenBytes []byte
7792
var err error
7893
if lenBytes, err = s.reader.Peek(8); err != nil {
7994
// reader.Peek raises io.EOF error if enough bytes not available
8095
if err == io.EOF {
8196
if len(lenBytes) > 0 {
82-
return nil, ErrUnexpectedEndOfBlockfile
97+
return nil, nil, ErrUnexpectedEndOfBlockfile
8398
}
84-
return nil, nil
99+
return nil, nil, nil
85100
}
86-
return nil, err
101+
return nil, nil, err
87102
}
88103
len, n := proto.DecodeVarint(lenBytes)
89104
if n == 0 {
90105
panic(fmt.Errorf("Error in decoding varint bytes"))
91106
}
92107
if _, err = s.reader.Discard(n); err != nil {
93-
return nil, err
108+
return nil, nil, err
94109
}
95110
blockBytes := make([]byte, len)
96111
if _, err = io.ReadAtLeast(s.reader, blockBytes, int(len)); err != nil {
97112
// io.ReadAtLeast raises io.ErrUnexpectedEOF error if it is able to
98113
// read a fewer (non-zero) bytes and io.EOF is encountered
99114
if err == io.ErrUnexpectedEOF {
100-
return nil, ErrUnexpectedEndOfBlockfile
115+
return nil, nil, ErrUnexpectedEndOfBlockfile
101116
}
102-
return nil, err
117+
return nil, nil, err
103118
}
119+
blockPlacementInfo := &blockPlacementInfo{
120+
fileNum: s.fileNum,
121+
blockStartOffset: s.currentOffset,
122+
blockBytesOffset: s.currentOffset + int64(n)}
104123
s.currentOffset += int64(n) + int64(len)
105-
return blockBytes, nil
124+
return blockBytes, blockPlacementInfo, nil
106125
}
107126

108127
func (s *blockfileStream) close() error {
@@ -113,8 +132,7 @@ func (s *blockfileStream) close() error {
113132
// blockStream functions
114133
////////////////////////////////////
115134
func newBlockStream(rootDir string, startFileNum int, startOffset int64, endFileNum int) (*blockStream, error) {
116-
startFile := deriveBlockfilePath(rootDir, startFileNum)
117-
startFileStream, err := newBlockfileStream(startFile, startOffset)
135+
startFileStream, err := newBlockfileStream(rootDir, startFileNum, startOffset)
118136
if err != nil {
119137
return nil, err
120138
}
@@ -127,30 +145,35 @@ func (s *blockStream) moveToNextBlockfileStream() error {
127145
return err
128146
}
129147
s.currentFileNum++
130-
nextFile := deriveBlockfilePath(s.rootDir, s.currentFileNum)
131-
if s.currentFileStream, err = newBlockfileStream(nextFile, 0); err != nil {
148+
if s.currentFileStream, err = newBlockfileStream(s.rootDir, s.currentFileNum, 0); err != nil {
132149
return err
133150
}
134151
return nil
135152
}
136153

137154
func (s *blockStream) nextBlockBytes() ([]byte, error) {
155+
blockBytes, _, err := s.nextBlockBytesAndPlacementInfo()
156+
return blockBytes, err
157+
}
158+
159+
func (s *blockStream) nextBlockBytesAndPlacementInfo() ([]byte, *blockPlacementInfo, error) {
138160
var blockBytes []byte
161+
var blockPlacementInfo *blockPlacementInfo
139162
var err error
140-
if blockBytes, err = s.currentFileStream.nextBlockBytes(); err != nil {
163+
if blockBytes, blockPlacementInfo, err = s.currentFileStream.nextBlockBytesAndPlacementInfo(); err != nil {
141164
logger.Debugf("current file [%d]", s.currentFileNum)
142165
logger.Debugf("blockbytes [%d]. Err:%s", len(blockBytes), err)
143-
return nil, err
166+
return nil, nil, err
144167
}
145168
logger.Debugf("blockbytes [%d] read from file [%d]", len(blockBytes), s.currentFileNum)
146169
if blockBytes == nil && s.currentFileNum < s.endFileNum {
147170
logger.Debugf("current file [%d] exhausted. Moving to next file", s.currentFileNum)
148171
if err = s.moveToNextBlockfileStream(); err != nil {
149-
return nil, err
172+
return nil, nil, err
150173
}
151-
return s.nextBlockBytes()
174+
return s.nextBlockBytesAndPlacementInfo()
152175
}
153-
return blockBytes, nil
176+
return blockBytes, blockPlacementInfo, nil
154177
}
155178

156179
func (s *blockStream) close() error {

core/ledgernext/blkstorage/fsblkstorage/block_stream_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func testBlockfileStream(t *testing.T, numBlocks int) {
3939
w.addBlocks(blocks)
4040
w.close()
4141

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

@@ -80,7 +80,7 @@ func testBlockFileStreamUnexpectedEOF(t *testing.T, numBlocks int, partialBlockB
8080
w.addBlocks(blocks)
8181
blockfileMgr.currentFileWriter.append(partialBlockBytes, true)
8282
w.close()
83-
s, err := newBlockfileStream(deriveBlockfilePath(blockfileMgr.rootDir, 0), 0)
83+
s, err := newBlockfileStream(blockfileMgr.rootDir, 0, 0)
8484
defer s.close()
8585
testutil.AssertNoError(t, err, "Error in constructing blockfile stream")
8686

core/ledgernext/blkstorage/fsblkstorage/blockfile_mgr.go

+72-9
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type blockfileMgr struct {
4444
conf *Conf
4545
db *db.DB
4646
defaultCF *gorocksdb.ColumnFamilyHandle
47-
index *blockIndex
47+
index index
4848
cpInfo *checkpointInfo
4949
currentFileWriter *blockfileWriter
5050
bcInfo atomic.Value
@@ -79,9 +79,11 @@ func newBlockfileMgr(conf *Conf) *blockfileMgr {
7979
panic(fmt.Sprintf("Could not truncate current file to known size in db: %s", err))
8080
}
8181

82-
mgr.index = newBlockIndex(db)
82+
mgr.index = newBlockIndex(db, db.GetCFHandle(blockIndexCF))
8383
mgr.cpInfo = cpInfo
8484
mgr.currentFileWriter = currentFileWriter
85+
mgr.syncIndex()
86+
8587
// init BlockchainInfo
8688
bcInfo := &protos.BlockchainInfo{
8789
Height: 0,
@@ -130,7 +132,8 @@ func updateCPInfo(conf *Conf, cpInfo *checkpointInfo) {
130132
// check point info is in sync with the file on disk
131133
return
132134
}
133-
endOffsetLastBlock, numBlocks, err := scanForLastCompleteBlock(filePath, int64(cpInfo.latestFileChunksize))
135+
endOffsetLastBlock, numBlocks, err := scanForLastCompleteBlock(
136+
rootDir, cpInfo.latestFileChunkSuffixNum, int64(cpInfo.latestFileChunksize))
134137
if err != nil {
135138
panic(fmt.Sprintf("Could not open current file for detecting last block in the file: %s", err))
136139
}
@@ -217,11 +220,73 @@ func (mgr *blockfileMgr) addBlock(block *protos.Block2) error {
217220
}
218221
blockFLP := &fileLocPointer{fileSuffixNum: mgr.cpInfo.latestFileChunkSuffixNum}
219222
blockFLP.offset = currentOffset
220-
mgr.index.indexBlock(mgr.cpInfo.lastBlockNumber, blockHash, blockFLP, blockBytesLen, len(blockBytesEncodedLen), txOffsets)
223+
// shift the txoffset because we prepend length of bytes before block bytes
224+
for i := 0; i < len(txOffsets); i++ {
225+
txOffsets[i] += len(blockBytesEncodedLen)
226+
}
227+
mgr.index.indexBlock(&blockIdxInfo{
228+
blockNum: mgr.cpInfo.lastBlockNumber, blockHash: blockHash,
229+
flp: blockFLP, txOffsets: txOffsets})
221230
mgr.updateBlockchainInfo(blockHash, block)
222231
return nil
223232
}
224233

234+
func (mgr *blockfileMgr) syncIndex() error {
235+
var lastBlockIndexed uint64
236+
var err error
237+
if lastBlockIndexed, err = mgr.index.getLastBlockIndexed(); err != nil {
238+
return err
239+
}
240+
startFileNum := 0
241+
startOffset := 0
242+
blockNum := uint64(1)
243+
endFileNum := mgr.cpInfo.latestFileChunkSuffixNum
244+
if lastBlockIndexed != 0 {
245+
var flp *fileLocPointer
246+
if flp, err = mgr.index.getBlockLocByBlockNum(lastBlockIndexed); err != nil {
247+
return err
248+
}
249+
startFileNum = flp.fileSuffixNum
250+
startOffset = flp.locPointer.offset
251+
blockNum = lastBlockIndexed
252+
}
253+
254+
var stream *blockStream
255+
if stream, err = newBlockStream(mgr.rootDir, startFileNum, int64(startOffset), endFileNum); err != nil {
256+
return err
257+
}
258+
var blockBytes []byte
259+
var blockPlacementInfo *blockPlacementInfo
260+
261+
for {
262+
if blockBytes, blockPlacementInfo, err = stream.nextBlockBytesAndPlacementInfo(); err != nil {
263+
return err
264+
}
265+
if blockBytes == nil {
266+
break
267+
}
268+
serBlock2 := protos.NewSerBlock2(blockBytes)
269+
var txOffsets []int
270+
if txOffsets, err = serBlock2.GetTxOffsets(); err != nil {
271+
return err
272+
}
273+
for i := 0; i < len(txOffsets); i++ {
274+
txOffsets[i] += int(blockPlacementInfo.blockBytesOffset)
275+
}
276+
blockIdxInfo := &blockIdxInfo{}
277+
blockIdxInfo.blockHash = serBlock2.ComputeHash()
278+
blockIdxInfo.blockNum = blockNum
279+
blockIdxInfo.flp = &fileLocPointer{fileSuffixNum: blockPlacementInfo.fileNum,
280+
locPointer: locPointer{offset: int(blockPlacementInfo.blockStartOffset)}}
281+
blockIdxInfo.txOffsets = txOffsets
282+
if err = mgr.index.indexBlock(blockIdxInfo); err != nil {
283+
return err
284+
}
285+
blockNum++
286+
}
287+
return nil
288+
}
289+
225290
func (mgr *blockfileMgr) getBlockchainInfo() *protos.BlockchainInfo {
226291
return mgr.bcInfo.Load().(*protos.BlockchainInfo)
227292
}
@@ -320,8 +385,7 @@ func (mgr *blockfileMgr) fetchTransaction(lp *fileLocPointer) (*protos.Transacti
320385
}
321386

322387
func (mgr *blockfileMgr) fetchBlockBytes(lp *fileLocPointer) ([]byte, error) {
323-
filePath := deriveBlockfilePath(mgr.rootDir, lp.fileSuffixNum)
324-
stream, err := newBlockfileStream(filePath, int64(lp.offset))
388+
stream, err := newBlockfileStream(mgr.rootDir, lp.fileSuffixNum, int64(lp.offset))
325389
if err != nil {
326390
return nil, err
327391
}
@@ -378,10 +442,9 @@ func (mgr *blockfileMgr) saveCurrentInfo(i *checkpointInfo, flush bool) error {
378442
return nil
379443
}
380444

381-
func scanForLastCompleteBlock(filePath string, startingOffset int64) (int64, int, error) {
382-
logger.Debugf("scanForLastCompleteBlock(): filePath=[%s], startingOffset=[%d]", filePath, startingOffset)
445+
func scanForLastCompleteBlock(rootDir string, fileNum int, startingOffset int64) (int64, int, error) {
383446
numBlocks := 0
384-
blockStream, err := newBlockfileStream(filePath, startingOffset)
447+
blockStream, err := newBlockfileStream(rootDir, fileNum, startingOffset)
385448
if err != nil {
386449
return 0, 0, err
387450
}

0 commit comments

Comments
 (0)