func (fo *frameOpen) createRollClientTxn() (*cmsgs.ClientTxn, map[common.VarUUId]*common.Positions) { var origWrite *msgs.Action vUUIdBytes := fo.v.UUId[:] for idx, l := 0, fo.frameTxnActions.Len(); idx < l; idx++ { action := fo.frameTxnActions.At(idx) if bytes.Equal(action.VarId(), vUUIdBytes) { origWrite = &action break } } seg := capn.NewBuffer(nil) ctxn := cmsgs.NewClientTxn(seg) ctxn.SetRetry(false) actions := cmsgs.NewClientActionList(seg, 1) ctxn.SetActions(actions) action := actions.At(0) action.SetVarId(fo.v.UUId[:]) action.SetRoll() roll := action.Roll() roll.SetVersion(fo.frameTxnId[:]) var refs msgs.VarIdPos_List switch origWrite.Which() { case msgs.ACTION_WRITE: ow := origWrite.Write() roll.SetValue(ow.Value()) refs = ow.References() case msgs.ACTION_READWRITE: owr := origWrite.Readwrite() roll.SetValue(owr.Value()) refs = owr.References() case msgs.ACTION_CREATE: oc := origWrite.Create() roll.SetValue(oc.Value()) refs = oc.References() case msgs.ACTION_ROLL: owr := origWrite.Roll() roll.SetValue(owr.Value()) refs = owr.References() default: panic(fmt.Sprintf("%v unexpected action type when building roll: %v", fo.frame, origWrite.Which())) } posMap := make(map[common.VarUUId]*common.Positions) posMap[*fo.v.UUId] = fo.v.positions refVarList := seg.NewDataList(refs.Len()) roll.SetReferences(refVarList) for idx, l := 0, refs.Len(); idx < l; idx++ { ref := refs.At(idx) vUUId := common.MakeVarUUId(ref.Id()) pos := common.Positions(ref.Positions()) posMap[*vUUId] = &pos refVarList.Set(idx, vUUId[:]) } return &ctxn, posMap }
func (bra *badReadAction) combine(action *msgs.Action, rmBal *rmBallot, txnId *common.TxnId, clockElem uint64) { newActionType := action.Which() braActionType := bra.action.Which() switch { case braActionType != msgs.ACTION_READ && newActionType != msgs.ACTION_READ: // They're both writes in some way. Just order the txns if clockElem > bra.clockElem || (clockElem == bra.clockElem && bra.txnId.Compare(txnId) == common.LT) { bra.set(action, rmBal, txnId, clockElem) } case braActionType == msgs.ACTION_READ && newActionType == msgs.ACTION_READ: braRead := bra.action.Read() newRead := action.Read() clockElem-- // If they read the same version, we really don't care. if !bytes.Equal(braRead.Version(), newRead.Version()) { // They read different versions, but which version was the latter? if clockElem > bra.clockElem { bra.set(action, rmBal, common.MakeTxnId(newRead.Version()), clockElem) } } case braActionType == msgs.ACTION_READ: if bytes.Equal(bra.txnId[:], txnId[:]) { // The write will obviously be in the past of the // existing read, but it's better to have the write // as we can update the client with the actual // value. bra.set(action, rmBal, txnId, clockElem) } else if clockElem > bra.clockElem { // The write is after than the read bra.set(action, rmBal, txnId, clockElem) } default: // Existing is not a read, but new is a read. newRead := action.Read() clockElem-- // If the read is a read of the existing write, better to keep the write if !bytes.Equal(bra.txnId[:], newRead.Version()) { if clockElem > bra.clockElem { // The read must be of some value which was written after our existing write. bra.set(action, rmBal, common.MakeTxnId(newRead.Version()), clockElem) } } } }