Exemple #1
0
func (txn *Txn) populate(actionIndices capn.UInt16List, actions msgs.Action_List) {
	localActions := make([]localAction, actionIndices.Len())
	txn.localActions = localActions
	var action *localAction

	actionIndicesIdx := 0
	actionIndex := -1
	if actionIndicesIdx < actionIndices.Len() {
		actionIndex = int(actionIndices.At(actionIndicesIdx))
		action = &localActions[actionIndicesIdx]
	}

	for idx, l := 0, actions.Len(); idx < l; idx++ {
		actionCap := actions.At(idx)

		if idx == actionIndex {
			action.Txn = txn
			action.vUUId = common.MakeVarUUId(actionCap.VarId())
		}

		switch actionCap.Which() {
		case msgs.ACTION_READ:
			if idx == actionIndex {
				readCap := actionCap.Read()
				readVsn := common.MakeTxnId(readCap.Version())
				action.readVsn = readVsn
			}

		case msgs.ACTION_WRITE:
			if idx == actionIndex {
				action.writeTxnActions = &actions
				action.writeAction = &actionCap
				txn.writes = append(txn.writes, action.vUUId)
			} else {
				txn.writes = append(txn.writes, common.MakeVarUUId(actionCap.VarId()))
			}

		case msgs.ACTION_READWRITE:
			if idx == actionIndex {
				readWriteCap := actionCap.Readwrite()
				readVsn := common.MakeTxnId(readWriteCap.Version())
				action.readVsn = readVsn
				action.writeTxnActions = &actions
				action.writeAction = &actionCap
				txn.writes = append(txn.writes, action.vUUId)
			} else {
				txn.writes = append(txn.writes, common.MakeVarUUId(actionCap.VarId()))
			}

		case msgs.ACTION_CREATE:
			if idx == actionIndex {
				createCap := actionCap.Create()
				positions := common.Positions(createCap.Positions())
				action.writeTxnActions = &actions
				action.writeAction = &actionCap
				action.createPositions = &positions
				txn.writes = append(txn.writes, action.vUUId)
			} else {
				txn.writes = append(txn.writes, common.MakeVarUUId(actionCap.VarId()))
			}

		case msgs.ACTION_ROLL:
			if idx == actionIndex {
				rollCap := actionCap.Roll()
				readVsn := common.MakeTxnId(rollCap.Version())
				action.readVsn = readVsn
				action.writeTxnActions = &actions
				action.writeAction = &actionCap
				action.roll = true
				txn.writes = append(txn.writes, action.vUUId)
			} else {
				txn.writes = append(txn.writes, common.MakeVarUUId(actionCap.VarId()))
			}

		default:
			panic(fmt.Sprintf("Unexpected action type: %v", actionCap.Which()))
		}

		if idx == actionIndex {
			actionIndicesIdx++
			if actionIndicesIdx < actionIndices.Len() {
				actionIndex = int(actionIndices.At(actionIndicesIdx))
				action = &localActions[actionIndicesIdx]
			}
		}
	}
	if actionIndicesIdx != actionIndices.Len() {
		panic(fmt.Sprintf("Expected to find %v local actions, but only found %v", actionIndices.Len(), actionIndicesIdx))
	}
}
func (sts *SimpleTxnSubmitter) translateActions(outgoingSeg *capn.Segment, picker *ch.CombinationPicker, actions *msgs.Action_List, clientActions *msgs.ClientAction_List) (map[common.RMId]*[]int, error) {

	referencesInNeedOfPositions := []*msgs.VarIdPos{}
	rmIdToActionIndices := make(map[common.RMId]*[]int)
	createdPositions := make(map[common.VarUUId]*common.Positions)

	for idx, l := 0, clientActions.Len(); idx < l; idx++ {
		clientAction := clientActions.At(idx)
		action := actions.At(idx)
		action.SetVarId(clientAction.VarId())

		var err error
		var hashCodes []common.RMId

		switch clientAction.Which() {
		case msgs.CLIENTACTION_READ:
			sts.translateRead(&action, &clientAction)

		case msgs.CLIENTACTION_WRITE:
			sts.translateWrite(outgoingSeg, &referencesInNeedOfPositions, &action, &clientAction)

		case msgs.CLIENTACTION_READWRITE:
			sts.translateReadWrite(outgoingSeg, &referencesInNeedOfPositions, &action, &clientAction)

		case msgs.CLIENTACTION_CREATE:
			var positions *common.Positions
			positions, hashCodes, err = sts.translateCreate(outgoingSeg, &referencesInNeedOfPositions, &action, &clientAction)
			if err != nil {
				return nil, err
			}
			vUUId := common.MakeVarUUId(clientAction.VarId())
			createdPositions[*vUUId] = positions

		case msgs.CLIENTACTION_ROLL:
			sts.translateRoll(outgoingSeg, &referencesInNeedOfPositions, &action, &clientAction)

		default:
			panic(fmt.Sprintf("Unexpected action type: %v", clientAction.Which()))
		}

		if hashCodes == nil {
			hashCodes, err = sts.hashCache.GetHashCodes(common.MakeVarUUId(action.VarId()))
			if err != nil {
				return nil, err
			}

			if clientAction.Which() == msgs.CLIENTACTION_ROLL && hashCodes[0] != sts.rmId {
				return nil, AbortRollError
			}
		}
		hashCodes = hashCodes[:sts.topology.TwoFInc]
		picker.AddPermutation(hashCodes)
		for _, rmId := range hashCodes {
			if listPtr, found := rmIdToActionIndices[rmId]; found {
				*listPtr = append(*listPtr, idx)
			} else {
				// Use of l for capacity guarantees an upper bound: there
				// are only l actions in total, so each RM can't possibly
				// be involved in > l actions. May waste a tiny amount of
				// memory, but minimises mallocs and copying.
				list := make([]int, 1, l)
				list[0] = idx
				rmIdToActionIndices[rmId] = &list
			}
		}
	}

	// Some of the references may be to vars that are being
	// created. Consequently, we must process all of the actions first
	// to make sure all the positions actually exist before adding the
	// positions into the references.
	for _, vUUIdPos := range referencesInNeedOfPositions {
		vUUId := common.MakeVarUUId(vUUIdPos.Id())
		positions, found := createdPositions[*vUUId]
		if !found {
			positions = sts.hashCache.GetPositions(vUUId)
		}
		if positions == nil {
			return nil, fmt.Errorf("Txn contains reference to unknown var %v", vUUId)
		}
		vUUIdPos.SetPositions((capn.UInt8List)(*positions))
	}
	return rmIdToActionIndices, nil
}