Skip to content

Commit d01be60

Browse files
committed
Adding comments
Change-Id: Id4969474c8ed4fcccc9332ea7a33de41cc85b7ec Signed-off-by: Mari Wade <[email protected]>
1 parent 7e7e23c commit d01be60

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

core/ledger/blkstorage/fsblkstorage/blockfile_mgr.go

+95-2
Original file line numberDiff line numberDiff line change
@@ -52,47 +52,109 @@ type blockfileMgr struct {
5252
bcInfo atomic.Value
5353
}
5454

55+
/*
56+
Creates a new manager that will manage the files used for block persistence.
57+
This manager manages the file system FS including
58+
-- the directory where the files are stored
59+
-- the individual files where the blocks are stored
60+
-- the checkpoint which tracks the latest file being persisted to
61+
-- the index which tracks what block and transaction is in what file
62+
When a new blockfile manager is started (i.e. only on start-up), it checks
63+
if this start-up is the first time the system is coming up or is this a restart
64+
of the system.
65+
66+
The blockfile manager stores blocks of data into a file system. That file
67+
storage is done by creating sequentially numbered files of a configured size
68+
i.e blockfile_000000, blockfile_000001, etc..
69+
70+
Each transcation in a block is stored with information about the number of
71+
bytes in that transaction
72+
Adding txLoc [fileSuffixNum=0, offset=3, bytesLength=104] for tx [1:0] to index
73+
Adding txLoc [fileSuffixNum=0, offset=107, bytesLength=104] for tx [1:1] to index
74+
Each block is stored with the total encoded length of that block as well as the
75+
tx location offsets.
76+
77+
Remember that these steps are only done once at start-up of the system.
78+
At start up a new manager:
79+
*) Checks if the directory for storing files exists, if not creates the dir
80+
*) Checks if the key value database exists, if not creates one
81+
(will create a db dir)
82+
*) Determines the checkpoint information (cpinfo) used for storage
83+
-- Loads from db if exist, if not instantiate a new cpinfo
84+
-- If cpinfo was loaded from db, compares to FS
85+
-- If cpinfo and file system are not in sync, syncs cpInfo from FS
86+
*) Starts a new file writer
87+
-- truncates file per cpinfo to remove any excess past last block
88+
*) Determines the index information used to find tx and blocks in
89+
the file blkstorage
90+
-- Instantiates a new blockIdxInfo
91+
-- Loads the index from the db if exists
92+
-- syncIndex comparing the last block indexed to what is in the FS
93+
-- If index and file system are not in sync, syncs index from the FS
94+
*) Updates blockchain info used by the APIs
95+
*/
5596
func newBlockfileMgr(conf *Conf, indexConfig *blkstorage.IndexConfig) *blockfileMgr {
97+
//Determine the root directory for the blockfile storage, if it does not exist create it
5698
rootDir := conf.blockfilesDir
5799
_, err := util.CreateDirIfMissing(rootDir)
58100
if err != nil {
59101
panic(fmt.Sprintf("Error: %s", err))
60102
}
103+
//Determine the kev value db instance, if it does not exist, create the directory and instantiate the database.
61104
db := initDB(conf)
105+
// Instantiate the manager, i.e. blockFileMgr structure
62106
mgr := &blockfileMgr{rootDir: rootDir, conf: conf, db: db}
107+
108+
// cp = checkpointInfo, retrieve from the database the file suffix or number of where blocks were stored.
109+
// It also retrieves the current size of that file and the last block number that was written to that file.
110+
// At init checkpointInfo:latestFileChunkSuffixNum=[0], latestFileChunksize=[0], lastBlockNumber=[0]
63111
cpInfo, err := mgr.loadCurrentInfo()
64112
if err != nil {
65113
panic(fmt.Sprintf("Could not get block file info for current block file from db: %s", err))
66114
}
67-
if cpInfo == nil {
115+
if cpInfo == nil { //if no cpInfo stored in db initiate to zero
68116
cpInfo = &checkpointInfo{latestFileChunkSuffixNum: 0, latestFileChunksize: 0}
69117
err = mgr.saveCurrentInfo(cpInfo, true)
70118
if err != nil {
71119
panic(fmt.Sprintf("Could not save next block file info to db: %s", err))
72120
}
73121
}
122+
//Verify that the checkpoint stored in db is accurate with what is actually stored in block file system
123+
// If not the same, sync the cpInfo and the file system
74124
syncCPInfoFromFS(conf, cpInfo)
125+
//Open a writer to the file identified by the number and truncate it to only contain the latest block
126+
// that was completely saved (file system, index, cpinfo, etc)
75127
currentFileWriter, err := newBlockfileWriter(deriveBlockfilePath(rootDir, cpInfo.latestFileChunkSuffixNum))
76128
if err != nil {
77129
panic(fmt.Sprintf("Could not open writer to current file: %s", err))
78130
}
131+
//Truncate the file to remove excess past last block
79132
err = currentFileWriter.truncateFile(cpInfo.latestFileChunksize)
80133
if err != nil {
81134
panic(fmt.Sprintf("Could not truncate current file to known size in db: %s", err))
82135
}
83136

137+
// Create a new KeyValue store database handler for the blocks index in the keyvalue database
84138
mgr.index = newBlockIndex(indexConfig, db)
139+
140+
// Update the manager with the checkpoint info and the file writer
85141
mgr.cpInfo = cpInfo
86142
mgr.currentFileWriter = currentFileWriter
143+
// Create a checkpoint condition (event) variable, for the goroutine waiting for
144+
// or announcing the occurrence of an event.
87145
mgr.cpInfoCond = sync.NewCond(&sync.Mutex{})
146+
147+
// Verify that the index stored in db is accurate with what is actually stored in block file system
148+
// If not the same, sync the index and the file system
88149
mgr.syncIndex()
89150

90-
// init BlockchainInfo
151+
// init BlockchainInfo for external API's
91152
bcInfo := &pb.BlockchainInfo{
92153
Height: 0,
93154
CurrentBlockHash: nil,
94155
PreviousBlockHash: nil}
95156

157+
//If start up is a restart of an existing storage, update BlockchainInfo for external API's
96158
if cpInfo.lastBlockNumber > 0 {
97159
lastBlock, err := mgr.retrieveSerBlockByNumber(cpInfo.lastBlockNumber)
98160
if err != nil {
@@ -109,6 +171,7 @@ func newBlockfileMgr(conf *Conf, indexConfig *blkstorage.IndexConfig) *blockfile
109171
PreviousBlockHash: previousBlockHash}
110172
}
111173
mgr.bcInfo.Store(bcInfo)
174+
//return the new manager (blockfileMgr)
112175
return mgr
113176
}
114177

@@ -119,24 +182,34 @@ func initDB(conf *Conf) *db.DB {
119182
return dbInst
120183
}
121184

185+
//cp = checkpointInfo, from the database gets the file suffix and the size of
186+
// the file of where the last block was written. Also retrieves contains the
187+
// last block number that was written. At init
188+
//checkpointInfo:latestFileChunkSuffixNum=[0], latestFileChunksize=[0], lastBlockNumber=[0]
122189
func syncCPInfoFromFS(conf *Conf, cpInfo *checkpointInfo) {
123190
logger.Debugf("Starting checkpoint=%s", cpInfo)
191+
//Checks if the file suffix of where the last block was written exists
124192
rootDir := conf.blockfilesDir
125193
filePath := deriveBlockfilePath(rootDir, cpInfo.latestFileChunkSuffixNum)
126194
exists, size, err := util.FileExists(filePath)
127195
if err != nil {
128196
panic(fmt.Sprintf("Error in checking whether file [%s] exists: %s", filePath, err))
129197
}
130198
logger.Debugf("status of file [%s]: exists=[%t], size=[%d]", filePath, exists, size)
199+
//Test is !exists because when file number is first used the file does not exist yet
200+
//checks that the file exists and that the size of the file is what is stored in cpinfo
201+
//status of file [/tmp/tests/ledger/blkstorage/fsblkstorage/blocks/blockfile_000000]: exists=[false], size=[0]
131202
if !exists || int(size) == cpInfo.latestFileChunksize {
132203
// check point info is in sync with the file on disk
133204
return
134205
}
206+
//Scan the file system to verify that the checkpoint info stored in db is correct
135207
endOffsetLastBlock, numBlocks, err := scanForLastCompleteBlock(
136208
rootDir, cpInfo.latestFileChunkSuffixNum, int64(cpInfo.latestFileChunksize))
137209
if err != nil {
138210
panic(fmt.Sprintf("Could not open current file for detecting last block in the file: %s", err))
139211
}
212+
//Updates the checkpoint info for the actual last block number stored and it's end location
140213
cpInfo.lastBlockNumber += uint64(numBlocks)
141214
cpInfo.latestFileChunksize = int(endOffsetLastBlock)
142215
logger.Debugf("Checkpoint after updates by scanning the last file segment:%s", cpInfo)
@@ -183,6 +256,7 @@ func (mgr *blockfileMgr) addBlock(block *pb.Block2) error {
183256
}
184257
blockBytes := serBlock.GetBytes()
185258
blockHash := serBlock.ComputeHash()
259+
//Get the location / offset where each transaction starts in the block and where the block ends
186260
txOffsets, err := serBlock.GetTxOffsets()
187261
currentOffset := mgr.cpInfo.latestFileChunksize
188262
if err != nil {
@@ -192,12 +266,16 @@ func (mgr *blockfileMgr) addBlock(block *pb.Block2) error {
192266
blockBytesEncodedLen := proto.EncodeVarint(uint64(blockBytesLen))
193267
totalBytesToAppend := blockBytesLen + len(blockBytesEncodedLen)
194268

269+
//Determine if we need to start a new file since the size of this block
270+
//exceeds the amount of space left in the current file
195271
if currentOffset+totalBytesToAppend > mgr.conf.maxBlockfileSize {
196272
mgr.moveToNextFile()
197273
currentOffset = 0
198274
}
275+
//append blockBytesEncodedLen to the file
199276
err = mgr.currentFileWriter.append(blockBytesEncodedLen, false)
200277
if err == nil {
278+
//append the actual block bytes to the file
201279
err = mgr.currentFileWriter.append(blockBytes, true)
202280
}
203281
if err != nil {
@@ -208,11 +286,13 @@ func (mgr *blockfileMgr) addBlock(block *pb.Block2) error {
208286
return fmt.Errorf("Error while appending block to file: %s", err)
209287
}
210288

289+
//Update the checkpoint info with the results of adding the new block
211290
currentCPInfo := mgr.cpInfo
212291
newCPInfo := &checkpointInfo{
213292
latestFileChunkSuffixNum: currentCPInfo.latestFileChunkSuffixNum,
214293
latestFileChunksize: currentCPInfo.latestFileChunksize + totalBytesToAppend,
215294
lastBlockNumber: currentCPInfo.lastBlockNumber + 1}
295+
//save the checkpoint information in the database
216296
if err = mgr.saveCurrentInfo(newCPInfo, false); err != nil {
217297
truncateErr := mgr.currentFileWriter.truncateFile(currentCPInfo.latestFileChunksize)
218298
if truncateErr != nil {
@@ -221,16 +301,19 @@ func (mgr *blockfileMgr) addBlock(block *pb.Block2) error {
221301
return fmt.Errorf("Error while saving current file info to db: %s", err)
222302
}
223303

304+
//Index block file location pointer updated with file suffex and offset for the new block
224305
blockFLP := &fileLocPointer{fileSuffixNum: newCPInfo.latestFileChunkSuffixNum}
225306
blockFLP.offset = currentOffset
226307
// shift the txoffset because we prepend length of bytes before block bytes
227308
for i := 0; i < len(txOffsets); i++ {
228309
txOffsets[i] += len(blockBytesEncodedLen)
229310
}
311+
//save the index in the database
230312
mgr.index.indexBlock(&blockIdxInfo{
231313
blockNum: newCPInfo.lastBlockNumber, blockHash: blockHash,
232314
flp: blockFLP, txOffsets: txOffsets})
233315

316+
//update the checkpoint info (for storage) and the blockchain info (for APIs) in the manager
234317
mgr.updateCheckpoint(newCPInfo)
235318
mgr.updateBlockchainInfo(blockHash, block)
236319
return nil
@@ -239,13 +322,17 @@ func (mgr *blockfileMgr) addBlock(block *pb.Block2) error {
239322
func (mgr *blockfileMgr) syncIndex() error {
240323
var lastBlockIndexed uint64
241324
var err error
325+
//from the database, get the last block that was indexed
242326
if lastBlockIndexed, err = mgr.index.getLastBlockIndexed(); err != nil {
243327
return err
244328
}
329+
//initialize index to file number:zero, offset:zero and block:1
245330
startFileNum := 0
246331
startOffset := 0
247332
blockNum := uint64(1)
333+
//get the last file that blocks were added to using the checkpoint info
248334
endFileNum := mgr.cpInfo.latestFileChunkSuffixNum
335+
//if the index stored in the db has value, update the index information with those values
249336
if lastBlockIndexed != 0 {
250337
var flp *fileLocPointer
251338
if flp, err = mgr.index.getBlockLocByBlockNum(lastBlockIndexed); err != nil {
@@ -256,13 +343,16 @@ func (mgr *blockfileMgr) syncIndex() error {
256343
blockNum = lastBlockIndexed
257344
}
258345

346+
//open a blockstream to the file location that was stored in the index
259347
var stream *blockStream
260348
if stream, err = newBlockStream(mgr.rootDir, startFileNum, int64(startOffset), endFileNum); err != nil {
261349
return err
262350
}
263351
var blockBytes []byte
264352
var blockPlacementInfo *blockPlacementInfo
265353

354+
//Should be at the last block, but go ahead and loop looking for next blockBytes
355+
//If there is another block, add it to the index
266356
for {
267357
if blockBytes, blockPlacementInfo, err = stream.nextBlockBytesAndPlacementInfo(); err != nil {
268358
return err
@@ -278,6 +368,7 @@ func (mgr *blockfileMgr) syncIndex() error {
278368
for i := 0; i < len(txOffsets); i++ {
279369
txOffsets[i] += int(blockPlacementInfo.blockBytesOffset)
280370
}
371+
//Update the blockIndexInfo with what was actually stored in file system
281372
blockIdxInfo := &blockIdxInfo{}
282373
blockIdxInfo.blockHash = serBlock2.ComputeHash()
283374
blockIdxInfo.blockNum = blockNum
@@ -414,6 +505,7 @@ func (mgr *blockfileMgr) fetchRawBytes(lp *fileLocPointer) ([]byte, error) {
414505
return b, nil
415506
}
416507

508+
//Get the current checkpoint information that is stored in the database
417509
func (mgr *blockfileMgr) loadCurrentInfo() (*checkpointInfo, error) {
418510
var b []byte
419511
var err error
@@ -442,6 +534,7 @@ func (mgr *blockfileMgr) saveCurrentInfo(i *checkpointInfo, sync bool) error {
442534
// scanForLastCompleteBlock scan a given block file and detects the last offset in the file
443535
// after which there may lie a block partially written (towards the end of the file in a crash scenario).
444536
func scanForLastCompleteBlock(rootDir string, fileNum int, startingOffset int64) (int64, int, error) {
537+
//scan the passed file number suffix starting from the passed offset to find the last completed block
445538
numBlocks := 0
446539
blockStream, errOpen := newBlockfileStream(rootDir, fileNum, startingOffset)
447540
if errOpen != nil {

0 commit comments

Comments
 (0)