idstore里面存的主要是ledgerid與genesisblock的關(guān)系,另外也用來(lái)判斷l(xiāng)edger是否在構(gòu)建中。實(shí)現(xiàn)本身很簡(jiǎn)單,這里主要還是從使用方的角度來(lái)剖析下吧。不然理解不到精髓。
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)
}
- 很簡(jiǎn)單,這里的gb就是genesisblock。那什么情況下會(huì)調(diào)用呢?
創(chuàng)建賬本的時(shí)候
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里面看看這個(gè)id是否已經(jīng)存在
- 如果不存在,緊接著去idstore里面保存一個(gè)標(biāo)志位,provider.idStore.setUnderConstructionFlag這里表示這個(gè)賬本正在創(chuàng)建中。
- provider.openInternal不用太關(guān)注,進(jìn)去看眼就是拿到各個(gè)store的句柄,組成統(tǒng)一的kvledger視圖對(duì)外提供賬本相關(guān)的服務(wù)。
- 接下來(lái)就是創(chuàng)建賬本了。如沒(méi)有意外的話最后會(huì)去除UnderConstructionFlag這個(gè)標(biāo)志,表示至此賬本創(chuàng)建成功。
恢復(fù)賬本的時(shí)候
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
}
這里的意義在于,前面創(chuàng)建的時(shí)候如果意外宕機(jī),有可能賬本新建不成功。這里如果高度為0,說(shuō)明genesisblock還沒(méi)有commit,去除unsetUnderConstructionFlag標(biāo)記。因?yàn)槟銐焊蜎](méi)有開(kāi)始。
如果高度為1,說(shuō)明genesisblock已經(jīng)提交,可以拿到去idstore了。