idstore里面存的主要是ledgerid与genesisblock的关系,另外也用来判断ledger是否在构建中。实现本身很简单,这里主要还是从使用方的角度来剖析下吧。不然理解不到精髓。
createLedgerID
func (s *idStore) createLedgerID(ledgerID string, gb *common.Block) error {
key := s.encodeLedgerKey(ledgerID)
var val []byte
var err error
if val, err = s.db.Get(key); err != nil {
return err
}
if val != nil {
return ErrLedgerIDExists
}
if val, err = proto.Marshal(gb); err != nil {
return err
}
batch := &leveldb.Batch{}
batch.Put(key, val)
batch.Delete(underConstructionLedgerKey)
return s.db.WriteBatch(batch, true)
}
- 很简单,这里的gb就是genesisblock。那什么情况下会调用呢?
创建账本的时候
func (provider *Provider) Create(genesisBlock *common.Block) (ledger.PeerLedger, error) {
ledgerID, err := utils.GetChainIDFromBlock(genesisBlock)
if err != nil {
return nil, err
}
exists, err := provider.idStore.ledgerIDExists(ledgerID)
...
if err = provider.idStore.setUnderConstructionFlag(ledgerID); err != nil {
return nil, err
}
lgr, err := provider.openInternal(ledgerID)
...
panicOnErr(provider.idStore.createLedgerID(ledgerID, genesisBlock), "Error while marking ledger as created")
return lgr, nil
}
- 可以看到,首先拿到gb里面的chainid也就是账本id。
- 去idstore里面看看这个id是否已经存在
- 如果不存在,紧接着去idstore里面保存一个标志位,provider.idStore.setUnderConstructionFlag这里表示这个账本正在创建中。
- provider.openInternal不用太关注,进去看眼就是拿到各个store的句柄,组成统一的kvledger视图对外提供账本相关的服务。
- 接下来就是创建账本了。如没有意外的话最后会去除UnderConstructionFlag这个标志,表示至此账本创建成功。
恢复账本的时候
func (provider *Provider) recoverUnderConstructionLedger() {
ledgerID, err := provider.idStore.getUnderConstructionFlag()
panicOnErr(err, "Error while checking whether the under construction flag is set")
if ledgerID == "" {
logger.Debugf("No under construction ledger found. Quitting recovery")
return
}
ledger, err := provider.openInternal(ledgerID)
bcInfo, err := ledger.GetBlockchainInfo()
ledger.Close()
switch bcInfo.Height {
case 0:
panicOnErr(provider.runCleanup(ledgerID), "Error while running cleanup for ledger id [%s]", ledgerID)
panicOnErr(provider.idStore.unsetUnderConstructionFlag(), "Error while unsetting under construction flag")
case 1:
genesisBlock, err := ledger.GetBlockByNumber(0)
panicOnErr(err, "Error while retrieving genesis block from blockchain for ledger [%s]", ledgerID)
panicOnErr(provider.idStore.createLedgerID(ledgerID, genesisBlock), "Error while adding ledgerID [%s] to created list", ledgerID)
default:
panic(errors.Errorf(
"data inconsistency: under construction flag is set for ledger [%s] while the height of the blockchain is [%d]",
ledgerID, bcInfo.Height))
}
return
}
这里的意义在于,前面创建的时候如果意外宕机,有可能账本新建不成功。这里如果高度为0,说明genesisblock还没有commit,去除unsetUnderConstructionFlag标记。因为你压根就没有开始。
如果高度为1,说明genesisblock已经提交,可以拿到去idstore了。
网友评论