func (sts *SimpleTxnSubmitter) clientToServerTxn(clientTxnCap *msgs.ClientTxn) (*msgs.Txn, []common.RMId, []common.RMId, error) { outgoingSeg := capn.NewBuffer(nil) txnCap := msgs.NewTxn(outgoingSeg) txnCap.SetId(clientTxnCap.Id()) txnCap.SetRetry(clientTxnCap.Retry()) txnCap.SetSubmitter(uint32(sts.rmId)) txnCap.SetSubmitterBootCount(sts.bootCount) txnCap.SetFInc(sts.topology.FInc) txnCap.SetTopologyVersion(sts.topology.Version) clientActions := clientTxnCap.Actions() actions := msgs.NewActionList(outgoingSeg, clientActions.Len()) txnCap.SetActions(actions) picker := ch.NewCombinationPicker(int(sts.topology.FInc), sts.disabledHashCodes) rmIdToActionIndices, err := sts.translateActions(outgoingSeg, picker, &actions, &clientActions) if err != nil { return nil, nil, nil, fmt.Errorf("Error translating actions: %v", err) } // NB: we're guaranteed that activeRMs and passiveRMs are // disjoint. Thus there is no RM that has some active and some // passive actions. activeRMs, passiveRMs, err := picker.Choose() if err != nil { return nil, nil, nil, err } allocations := msgs.NewAllocationList(outgoingSeg, len(activeRMs)+len(passiveRMs)) txnCap.SetAllocations(allocations) sts.setAllocations(0, rmIdToActionIndices, &allocations, outgoingSeg, true, activeRMs) sts.setAllocations(len(activeRMs), rmIdToActionIndices, &allocations, outgoingSeg, false, passiveRMs) return &txnCap, activeRMs, passiveRMs, nil }
func CreateTopologyZero(cm *ConnectionManager, topology *server.Topology, lc *client.LocalConnection) (*common.TxnId, error) { seg := capn.NewBuffer(nil) txn := msgs.NewTxn(seg) txnId := server.VersionOne txn.SetId(txnId[:]) 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.SetCreate() create := action.Create() positions := seg.NewUInt8List(int(topology.MaxRMCount)) create.SetPositions(positions) for idx, l := 0, positions.Len(); idx < l; idx++ { positions.Set(idx, uint8(idx)) } create.SetValue(topology.Serialize()) create.SetReferences(msgs.NewVarIdPosList(seg, 0)) 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(topology.Version) result, err := lc.RunTransaction(&txn, false, cm.RMId) if err != nil { return nil, err } if result == nil { return nil, nil // shutting down } if result.Which() == msgs.OUTCOME_COMMIT { return txnId, nil } else { return nil, fmt.Errorf("Internal error: unable to write initial topology to local data store") } }
func MaybeCreateRoot(topology *server.Topology, conns map[common.RMId]paxos.Connection, cm *ConnectionManager, lc *client.LocalConnection) error { if topology.RootVarUUId != nil { return nil } requiredKnownRMs := int(topology.TwoFInc) if len(topology.AllRMs) < requiredKnownRMs { return nil } activeRMs := make([]common.RMId, 0, int(topology.FInc)) passiveRMs := make([]common.RMId, 0, int(topology.F)) for _, rmId := range topology.AllRMs[:requiredKnownRMs] { if _, found := conns[rmId]; found && len(activeRMs) < cap(activeRMs) { activeRMs = append(activeRMs, rmId) } else { passiveRMs = append(passiveRMs, rmId) } } if len(activeRMs) < cap(activeRMs) { return nil } server.Log("Creating Root. Actives:", activeRMs, "; Passives:", passiveRMs) 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) vUUId := lc.NextVarUUId() action.SetVarId(vUUId[:]) action.SetCreate() create := action.Create() positions := seg.NewUInt8List(int(topology.MaxRMCount)) create.SetPositions(positions) for idx, l := 0, positions.Len(); idx < l; idx++ { positions.Set(idx, uint8(idx)) } create.SetValue([]byte{}) create.SetReferences(msgs.NewVarIdPosList(seg, 0)) allocs := msgs.NewAllocationList(seg, requiredKnownRMs) txn.SetAllocations(allocs) idx := 0 for listIdx, rmIds := range [][]common.RMId{activeRMs, passiveRMs} { 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(topology.FInc) txn.SetTopologyVersion(topology.Version) result, err := lc.RunTransaction(&txn, true, activeRMs...) if err != nil { return err } if result == nil { return nil } if result.Which() == msgs.OUTCOME_COMMIT { server.Log("Root created in", vUUId) topology.RootVarUUId = vUUId topology.RootPositions = (*common.Positions)(&positions) return nil } abort := result.Abort() if abort.Which() == msgs.OUTCOMEABORT_RESUBMIT { continue } return fmt.Errorf("Internal error: creation of root gave rerun outcome") } }
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 }