func (vc versionCache) UpdateFromCommit(txnId *common.TxnId, outcome *msgs.Outcome) { clock := eng.VectorClockFromCap(outcome.Commit()) actions := outcome.Txn().Actions() for idx, l := 0, actions.Len(); idx < l; idx++ { action := actions.At(idx) if action.Which() != msgs.ACTION_READ { vUUId := common.MakeVarUUId(action.VarId()) if c, found := vc[*vUUId]; found { c.txnId = txnId c.clockElem = clock.Clock[*vUUId] } else { vc[*vUUId] = &cached{ txnId: txnId, clockElem: clock.Clock[*vUUId], } } } } }
// Callback (from network/paxos) func (tro *txnReceiveOutcome) BallotOutcomeReceived(outcome *msgs.Outcome) { if tro.outcomeClock != nil || tro.aborted { // We've already been here. Be silent if we receive extra outcomes. return } if tro.Retry && tro.currentState == &tro.txnAwaitLocalBallots { tro.nextState() } if tro.currentState != tro { // We've received the outcome too early! Be noisy! panic(fmt.Sprintf("%v error: Ballot outcome received with txn in wrong state: %v\n", tro.Id, tro.currentState)) return } switch outcome.Which() { case msgs.OUTCOME_COMMIT: tro.outcomeClock = VectorClockFromCap(outcome.Commit()) default: tro.aborted = true } tro.nextState() // advance state FIRST! if tro.preAbortedBool { if !tro.aborted { panic(fmt.Sprintf("%v We preAborted the txn, but the txn outcome is to commit!", tro.Id)) } return } for idx := 0; idx < len(tro.localActions); idx++ { action := &tro.localActions[idx] f := func(v *Var, err error) { if err != nil { panic(fmt.Sprintf("%v error (%v, aborted? %v, preAborted? %v, frame == nil? %v): %v", tro.Id, tro, tro.aborted, tro.preAbortedBool, action.frame == nil, err)) } else { v.ReceiveTxnOutcome(action) } } // Should only have to create missing vars if we're a learner (i.e. !voter). tro.vd.ApplyToVar(f, !tro.voter, action.vUUId) } }