Exemple #1
0
func (vb *varBallot) CalculateResult(br badReads, clock *eng.VectorClock) {
	vb.result = eng.NewBallot(vb.vUUId, eng.Commit, eng.NewVectorClock())
	for _, rmBal := range vb.rmToBallot {
		vb.combineVote(rmBal, br)
	}
	if !vb.result.Aborted() {
		clock.MergeInMax(vb.result.Clock)
	}
}
Exemple #2
0
func (br badReads) AddToSeg(seg *capn.Segment) msgs.Update_List {
	txnIdToBadReadActions := make(map[common.TxnId]*[]*badReadAction, len(br))
	for _, bra := range br {
		if bras, found := txnIdToBadReadActions[*bra.txnId]; found {
			*bras = append(*bras, bra)
		} else {
			list := []*badReadAction{bra}
			txnIdToBadReadActions[*bra.txnId] = &list
		}
	}

	updates := msgs.NewUpdateList(seg, len(txnIdToBadReadActions))
	idx := 0
	for txnId, badReadActions := range txnIdToBadReadActions {
		update := updates.At(idx)
		idx++
		update.SetTxnId(txnId[:])
		actionList := msgs.NewActionList(seg, len(*badReadActions))
		update.SetActions(actionList)
		clock := eng.NewVectorClock()
		for idy, bra := range *badReadActions {
			action := bra.action
			switch action.Which() {
			case msgs.ACTION_READ:
				newAction := actionList.At(idy)
				newAction.SetVarId(action.VarId())
				newAction.SetMissing()
			case msgs.ACTION_WRITE:
				actionList.Set(idy, *action)
			case msgs.ACTION_READWRITE:
				readWrite := action.Readwrite()
				newAction := actionList.At(idy)
				newAction.SetVarId(action.VarId())
				newAction.SetWrite()
				newWrite := newAction.Write()
				newWrite.SetValue(readWrite.Value())
				newWrite.SetReferences(readWrite.References())
			case msgs.ACTION_CREATE:
				create := action.Create()
				newAction := actionList.At(idy)
				newAction.SetVarId(action.VarId())
				newAction.SetWrite()
				newWrite := newAction.Write()
				newWrite.SetValue(create.Value())
				newWrite.SetReferences(create.References())
			case msgs.ACTION_ROLL:
				roll := action.Roll()
				newAction := actionList.At(idy)
				newAction.SetVarId(action.VarId())
				newAction.SetWrite()
				newWrite := newAction.Write()
				newWrite.SetValue(roll.Value())
				newWrite.SetReferences(roll.References())
			default:
				panic(fmt.Sprintf("Unexpected action type (%v) for badread of %v at %v",
					action.Which(), action.VarId(), txnId))
			}
			clock.SetVarIdMax(*bra.vUUId, bra.clockElem)
		}
		update.SetClock(clock.AddToSeg(seg))
	}

	return updates
}
Exemple #3
0
func (ba *BallotAccumulator) determineOutcome() *outcomeEqualId {
	// Even in the case of retries, we must wait until we have at least
	// F+1 results for one var, otherwise we run the risk of
	// timetravel: a slow learner could issue a badread based on not
	// being caught up. By waiting for at least F+1 ballots for a var
	// (they don't have to be the same ballot!), we avoid this as there
	// must be at least one voter who isn't in the past.
	if !(ba.dirty && (ba.incompleteVars == 0 || ba.Txn.Retry())) {
		return nil
	}
	ba.dirty = false

	combinedClock := eng.NewVectorClock()
	aborted, deadlock := false, false

	vUUIds := common.VarUUIds(make([]*common.VarUUId, 0, len(ba.vUUIdToBallots)))
	br := NewBadReads()
	server.Log(ba.txnId, "Calculating result")
	for _, vBallot := range ba.vUUIdToBallots {
		if len(vBallot.rmToBallot) < vBallot.voters {
			continue
		}
		vUUIds = append(vUUIds, vBallot.vUUId)
		if vBallot.result == nil {
			vBallot.CalculateResult(br, combinedClock)
		}
		aborted = aborted || vBallot.result.Aborted()
		deadlock = deadlock || vBallot.result.Vote == eng.AbortDeadlock
	}

	vUUIds.Sort()

	seg := capn.NewBuffer(nil)
	outcome := msgs.NewOutcome(seg)
	outcomeIdList := msgs.NewOutcomeIdList(seg, len(vUUIds))
	outcome.SetId(outcomeIdList)
	for idx, vUUId := range vUUIds {
		outcomeId := outcomeIdList.At(idx)
		outcomeId.SetVarId(vUUId[:])
		vBallot := ba.vUUIdToBallots[*vUUId]
		instanceIdList := msgs.NewAcceptedInstanceIdList(seg, len(vBallot.rmToBallot))
		outcomeId.SetAcceptedInstances(instanceIdList)
		for idy, rmBal := range vBallot.rmToBallot {
			instanceId := instanceIdList.At(idy)
			instanceId.SetRmId(uint32(rmBal.instanceRMId))
			instanceId.SetVote(rmBal.ballot.Vote.ToVoteEnum())
		}
	}

	if aborted {
		deflatedTxn := deflateTxn(ba.Txn, seg)
		outcome.SetTxn(*deflatedTxn)
		outcome.SetAbort()
		abort := outcome.Abort()
		if deadlock {
			abort.SetResubmit()
		} else {
			abort.SetRerun(br.AddToSeg(seg))
		}

	} else {
		outcome.SetTxn(*ba.Txn)
		outcome.SetCommit(combinedClock.AddToSeg(seg))
	}

	ba.outcome = (*outcomeEqualId)(&outcome)
	return ba.outcome
}