Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ledger: POC of simpler lookupLatest #3747

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 7 additions & 35 deletions ledger/acctupdates.go
Original file line number Diff line number Diff line change
Expand Up @@ -872,19 +872,13 @@ func (au *accountUpdates) newBlockImpl(blk bookkeeping.Block, delta ledgercore.S
// even while it does return the AccountData which represent the "rewarded" account data.
func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.AccountData, rnd basics.Round, withoutRewards basics.MicroAlgos, err error) {
au.accountsMu.RLock()
needUnlock := true
defer func() {
if needUnlock {
au.accountsMu.RUnlock()
}
}()
defer au.accountsMu.RUnlock()
var offset uint64
var rewardsProto config.ConsensusParams
var rewardsLevel uint64
var persistedData persistedAccountData
var persistedResources []persistedResourcesData
var resourceDbRound basics.Round
withRewards := true

foundAccount := false
var ad ledgercore.AccountData
Expand Down Expand Up @@ -944,9 +938,7 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
return false
}

for {
currentDbRound := au.cachedDBRound
currentDeltaLen := len(au.deltas)
rnd = au.latest()
offset, err = au.roundOffset(rnd)
if err != nil {
Expand All @@ -963,18 +955,14 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
rewardsProto = config.Consensus[au.versions[offset]]
rewardsLevel = au.roundTotals[offset].RewardsLevel

// we're testing the withRewards here and setting the defer function only once, and only if withRewards is true.
// we want to make this defer only after setting the above rewardsProto/rewardsLevel.
if withRewards {
defer func() {
if err == nil {
ledgercore.AssignAccountData(&data, ad)
withoutRewards = data.MicroAlgos // record balance before updating rewards
data = data.WithUpdatedRewards(rewardsProto, rewardsLevel)
}
}()
withRewards = false
}

// check if we've had this address modified in the past rounds. ( i.e. if it's in the deltas )
macct, indeltas := au.accounts[addr]
Expand All @@ -984,9 +972,6 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
ad = macct.data
foundAccount = true
} else if macct, has := au.baseAccounts.read(addr); has && macct.round == currentDbRound {
// we don't technically need this, since it's already in the baseAccounts, however, writing this over
// would ensure that we promote this field.
au.baseAccounts.writePending(macct)
ad = macct.accountData.GetLedgerCoreAccountData()
foundAccount = true
}
Expand All @@ -1009,18 +994,13 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
// check the baseResources -
if prds := au.baseResources.readAll(addr); len(prds) > 0 {
for _, prd := range prds {
// we don't technically need this, since it's already in the baseResources, however, writing this over
// would ensure that we promote this field.
au.baseResources.writePending(prd, addr)
if prd.addrid != 0 {
if err := addResource(prd.aidx, rnd, prd.AccountResource()); err != nil {
return basics.AccountData{}, basics.Round(0), basics.MicroAlgos{}, err
}
}
}
}
au.accountsMu.RUnlock()
needUnlock = false

if checkDone() {
return
Expand All @@ -1039,7 +1019,6 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
if persistedData.round == currentDbRound {
if persistedData.rowid != 0 {
// if we read actual data return it
au.baseAccounts.writePending(persistedData)
ad = persistedData.accountData.GetLedgerCoreAccountData()
} else {
ad = ledgercore.AccountData{}
Expand All @@ -1056,7 +1035,8 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
return basics.AccountData{}, basics.Round(0), basics.MicroAlgos{}, &StaleDatabaseRoundError{databaseRound: persistedData.round, memoryRound: currentDbRound}
}
if persistedData.round > currentDbRound {
goto tryAgain
// this can't happen: persistedData.round shouldn't be able to run ahead of currentDbRound
return basics.AccountData{}, basics.Round(0), basics.MicroAlgos{}, &RoundOffsetError{round: persistedData.round, dbRound: currentDbRound}
}
}

Expand All @@ -1067,27 +1047,19 @@ func (au *accountUpdates) lookupLatest(addr basics.Address) (data basics.Account
}
if resourceDbRound == currentDbRound {
for _, pd := range persistedResources {
au.baseResources.writePending(pd, addr)
if err := addResource(pd.aidx, currentDbRound, pd.AccountResource()); err != nil {
return basics.AccountData{}, basics.Round(0), basics.MicroAlgos{}, err
}
}
// We've found all the resources we could find for this address.
return
}

if resourceDbRound < currentDbRound {
} else if resourceDbRound < currentDbRound {
au.log.Errorf("accountUpdates.lookupLatest: resource database round %d is behind in-memory round %d", resourceDbRound, currentDbRound)
return basics.AccountData{}, basics.Round(0), basics.MicroAlgos{}, &StaleDatabaseRoundError{databaseRound: resourceDbRound, memoryRound: currentDbRound}
}

tryAgain:
au.accountsMu.RLock()
needUnlock = true
for currentDbRound >= au.cachedDBRound && currentDeltaLen == len(au.deltas) {
au.accountsReadCond.Wait()
}
}
// else if resourceDbRound > currentDbRound
// this can't happen: resourceDbRound shouldn't be able to run ahead of currentDbRound
return basics.AccountData{}, basics.Round(0), basics.MicroAlgos{}, &RoundOffsetError{round: persistedData.round, dbRound: currentDbRound}
}

// lookupWithRewards returns the online account data for a given address at a given round.
Expand Down