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 }