func (sts *SimpleTxnSubmitter) translateWrite(outgoingSeg *capn.Segment, referencesInNeedOfPositions *[]*msgs.VarIdPos, action *msgs.Action, clientAction *msgs.ClientAction) { action.SetWrite() clientWrite := clientAction.Write() write := action.Write() write.SetValue(clientWrite.Value()) clientReferences := clientWrite.References() references := msgs.NewVarIdPosList(outgoingSeg, clientReferences.Len()) write.SetReferences(references) copyReferences(&clientReferences, &references, referencesInNeedOfPositions) }
func (sts *SimpleTxnSubmitter) translateCreate(outgoingSeg *capn.Segment, referencesInNeedOfPositions *[]*msgs.VarIdPos, action *msgs.Action, clientAction *msgs.ClientAction) (*common.Positions, []common.RMId, error) { action.SetCreate() clientCreate := clientAction.Create() create := action.Create() create.SetValue(clientCreate.Value()) vUUId := common.MakeVarUUId(clientAction.VarId()) positions, hashCodes, err := sts.hashCache.CreatePositions(vUUId, int(sts.topology.MaxRMCount)) if err != nil { return nil, nil, err } create.SetPositions((capn.UInt8List)(*positions)) clientReferences := clientCreate.References() references := msgs.NewVarIdPosList(outgoingSeg, clientReferences.Len()) create.SetReferences(references) copyReferences(&clientReferences, &references, referencesInNeedOfPositions) return positions, hashCodes, nil }
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.LessThan(txnId)) { 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) } } } }
func (fo *frameOpen) createRollClientTxn() (*msgs.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 := msgs.NewClientTxn(seg) ctxn.SetRetry(false) actions := msgs.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 GetTopologyFromLocalDatabase(cm *ConnectionManager, varDispatcher *eng.VarDispatcher, lc *client.LocalConnection) (*server.Topology, error) { if paxos.IsDatabaseClean(varDispatcher) { return nil, nil } for { seg := capn.NewBuffer(nil) txn := msgs.NewTxn(seg) txn.SetSubmitter(uint32(cm.RMId)) txn.SetSubmitterBootCount(cm.BootCount) actions := msgs.NewActionList(seg, 1) txn.SetActions(actions) action := actions.At(0) action.SetVarId(server.TopologyVarUUId[:]) action.SetRead() action.Read().SetVersion(common.VersionZero[:]) allocs := msgs.NewAllocationList(seg, 1) txn.SetAllocations(allocs) alloc := allocs.At(0) alloc.SetRmId(uint32(cm.RMId)) alloc.SetActive(cm.BootCount) indices := seg.NewUInt16List(1) alloc.SetActionIndices(indices) indices.Set(0, 0) txn.SetFInc(1) txn.SetTopologyVersion(0) result, err := lc.RunTransaction(&txn, true, cm.RMId) if err != nil { return nil, err } if result == nil { return nil, nil // shutting down } if result.Which() == msgs.OUTCOME_COMMIT { return nil, fmt.Errorf("Internal error: read of topology version 0 failed to abort") } abort := result.Abort() if abort.Which() == msgs.OUTCOMEABORT_RESUBMIT { continue } abortUpdates := abort.Rerun() if abortUpdates.Len() != 1 { return nil, fmt.Errorf("Internal error: read of topology version 0 gave multiple updates") } update := abortUpdates.At(0) dbversion := common.MakeTxnId(update.TxnId()) updateActions := update.Actions() if updateActions.Len() != 1 && updateActions.Len() != 2 { return nil, fmt.Errorf("Internal error: read of topology version 0 gave multiple actions: %v", updateActions.Len()) } var updateAction *msgs.Action for idx, l := 0, updateActions.Len(); idx < l; idx++ { action := updateActions.At(idx) if bytes.Equal(action.VarId(), server.TopologyVarUUId[:]) { updateAction = &action break } } if updateAction == nil { return nil, fmt.Errorf("Internal error: unable to find action for topology from read of topology version 0") } if updateAction.Which() != msgs.ACTION_WRITE { return nil, fmt.Errorf("Internal error: read of topology version 0 gave non-write action") } write := updateAction.Write() var rootPtr *msgs.VarIdPos if refs := write.References(); refs.Len() == 1 { root := refs.At(0) rootPtr = &root } return server.TopologyDeserialize(dbversion, rootPtr, write.Value()) } }
func AddSelfToTopology(cm *ConnectionManager, conns map[common.RMId]paxos.Connection, topology *server.Topology, fInc int, active, passive []common.RMId, lc *client.LocalConnection) (*server.Topology, bool, error) { seg := capn.NewBuffer(nil) txn := msgs.NewTxn(seg) txn.SetSubmitter(uint32(cm.RMId)) txn.SetSubmitterBootCount(cm.BootCount) actions := msgs.NewActionList(seg, 1) txn.SetActions(actions) topologyAction := actions.At(0) topologyAction.SetVarId(server.TopologyVarUUId[:]) topologyAction.SetReadwrite() rw := topologyAction.Readwrite() rw.SetVersion(topology.DBVersion[:]) rw.SetValue(topology.Serialize()) if topology.RootVarUUId == nil { rw.SetReferences(msgs.NewVarIdPosList(seg, 0)) } else { refs := msgs.NewVarIdPosList(seg, 1) rw.SetReferences(refs) varIdPos := refs.At(0) varIdPos.SetId(topology.RootVarUUId[:]) varIdPos.SetPositions((capn.UInt8List)(*topology.RootPositions)) } allocs := msgs.NewAllocationList(seg, len(topology.AllRMs)) txn.SetAllocations(allocs) idx := 0 for listIdx, rmIds := range [][]common.RMId{active, passive} { for _, rmId := range rmIds { alloc := allocs.At(idx) idx++ alloc.SetRmId(uint32(rmId)) if listIdx == 0 { alloc.SetActive(conns[rmId].BootCount()) } else { alloc.SetActive(0) } indices := seg.NewUInt16List(1) alloc.SetActionIndices(indices) indices.Set(0, 0) } } txn.SetFInc(uint8(fInc)) txn.SetTopologyVersion(topology.Version) result, err := lc.RunTransaction(&txn, true, active...) if err != nil || result == nil { return nil, false, err } txnId := common.MakeTxnId(result.Txn().Id()) if result.Which() == msgs.OUTCOME_COMMIT { topology.DBVersion = txnId server.Log("Topology Txn Committed ok with txnId", topology.DBVersion) return topology, false, nil } abort := result.Abort() server.Log("Topology Txn Aborted", txnId) if abort.Which() == msgs.OUTCOMEABORT_RESUBMIT { return nil, true, nil } abortUpdates := abort.Rerun() if abortUpdates.Len() != 1 { return nil, false, fmt.Errorf("Internal error: readwrite of topology gave %v updates (1 expected)", abortUpdates.Len()) } update := abortUpdates.At(0) dbversion := common.MakeTxnId(update.TxnId()) updateActions := update.Actions() if updateActions.Len() != 1 && updateActions.Len() != 2 { return nil, false, fmt.Errorf("Internal error: readwrite of topology gave multiple actions: %v", updateActions.Len()) } var updateAction *msgs.Action for idx, l := 0, updateActions.Len(); idx < l; idx++ { action := updateActions.At(idx) if bytes.Equal(action.VarId(), server.TopologyVarUUId[:]) { updateAction = &action break } } if updateAction == nil { return nil, false, fmt.Errorf("Internal error: unable to find action for topology from readwrite") } if updateAction.Which() != msgs.ACTION_WRITE { return nil, false, fmt.Errorf("Internal error: readwrite of topology gave non-write action") } write := updateAction.Write() var rootVarPos *msgs.VarIdPos if refs := write.References(); refs.Len() == 1 { root := refs.At(0) rootVarPos = &root } else if refs.Len() > 1 { return nil, false, fmt.Errorf("Internal error: readwrite of topology had wrong references: %v", refs.Len()) } topology, err = server.TopologyDeserialize(dbversion, rootVarPos, write.Value()) if err != nil { return nil, false, err } found := false for _, rmId := range topology.AllRMs { if found = rmId == cm.RMId; found { server.Log("Topology Txn Aborted, but found self in topology.") return topology, false, nil } } return topology, true, nil }
func (sts *SimpleTxnSubmitter) translateRead(action *msgs.Action, clientAction *msgs.ClientAction) { action.SetRead() clientRead := clientAction.Read() read := action.Read() read.SetVersion(clientRead.Version()) }