func newTwoBTxnVotesSender(outcome *msgs.Outcome, txnId *common.TxnId, submitter common.RMId, recipients ...common.RMId) *twoBTxnVotesSender { submitterSeg := capn.NewBuffer(nil) submitterMsg := msgs.NewRootMessage(submitterSeg) submitterMsg.SetSubmissionOutcome(*outcome) if outcome.Which() == msgs.OUTCOME_ABORT { abort := outcome.Abort() abort.SetResubmit() // nuke out the updates as proposers don't need them. } seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) twoB := msgs.NewTwoBTxnVotes(seg) msg.SetTwoBTxnVotes(twoB) twoB.SetOutcome(*outcome) server.Log(txnId, "Sending 2B to", recipients) return &twoBTxnVotesSender{ msg: server.SegToBytes(seg), recipients: recipients, submitterMsg: server.SegToBytes(submitterSeg), submitter: submitter, } }
func (am *AcceptorManager) OneATxnVotesReceived(sender common.RMId, txnId *common.TxnId, oneATxnVotes *msgs.OneATxnVotes) { instanceRMId := common.RMId(oneATxnVotes.RmId()) server.Log(txnId, "1A received from", sender, "; instance:", instanceRMId) instId := instanceId([instanceIdLen]byte{}) instIdSlice := instId[:] copy(instIdSlice, txnId[:]) binary.BigEndian.PutUint32(instIdSlice[common.KeyLen:], uint32(instanceRMId)) replySeg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(replySeg) oneBTxnVotes := msgs.NewOneBTxnVotes(replySeg) msg.SetOneBTxnVotes(oneBTxnVotes) oneBTxnVotes.SetRmId(oneATxnVotes.RmId()) oneBTxnVotes.SetTxnId(oneATxnVotes.TxnId()) proposals := oneATxnVotes.Proposals() promises := msgs.NewTxnVotePromiseList(replySeg, proposals.Len()) oneBTxnVotes.SetPromises(promises) for idx, l := 0, proposals.Len(); idx < l; idx++ { proposal := proposals.At(idx) vUUId := common.MakeVarUUId(proposal.VarId()) copy(instIdSlice[common.KeyLen+4:], vUUId[:]) promise := promises.At(idx) promise.SetVarId(vUUId[:]) am.ensureInstance(txnId, &instId, vUUId).OneATxnVotesReceived(&proposal, &promise) } NewOneShotSender(server.SegToBytes(replySeg), am.ConnectionManager, sender) }
func (cr *connectionRun) start() (bool, error) { log.Printf("Connection established to %v (%v)\n", cr.remoteHost, cr.remoteRMId) seg := capn.NewBuffer(nil) message := msgs.NewRootMessage(seg) message.SetHeartbeat() cr.beatBytes = server.SegToBytes(seg) if cr.isServer { cr.connectionManager.ServerEstablished(cr.Connection) } if cr.isClient { topology, servers := cr.connectionManager.ClientEstablished(cr.ConnectionNumber, cr.Connection) cr.connectionManager.AddSender(cr.Connection) cr.submitter = client.NewClientTxnSubmitter(cr.connectionManager.RMId, cr.connectionManager.BootCount, topology, cr.connectionManager) cr.submitter.TopologyChange(nil, servers) } cr.mustSendBeat = true cr.missingBeats = 0 cr.beater = newConnectionBeater(cr.Connection) go cr.beater.beat() cr.reader = newConnectionReader(cr.Connection) go cr.reader.read() return false, nil }
func (cr *connectionRun) handleMsgFromPeer(msg *msgs.Message) error { if cr.currentState != cr { // probably just draining the queue from the reader after a restart return nil } cr.missingBeats = 0 switch which := msg.Which(); which { case msgs.MESSAGE_HEARTBEAT: // do nothing case msgs.MESSAGE_CLIENTTXNSUBMISSION: ctxn := msg.ClientTxnSubmission() origTxnId := common.MakeTxnId(ctxn.Id()) cr.submitter.SubmitClientTransaction(&ctxn, func(clientOutcome *msgs.ClientTxnOutcome, err error) { switch { case err != nil: cr.clientTxnError(&ctxn, err, origTxnId) case clientOutcome == nil: // shutdown return default: seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) msg.SetClientTxnOutcome(*clientOutcome) cr.sendMessage(server.SegToBytes(msg.Segment)) } }) default: cr.connectionManager.Dispatchers.DispatchMessage(cr.remoteRMId, which, msg) } return nil }
func (cr *connectionRun) submitTxn(txnMsg *connectionMsgTxn) error { if cr.currentState != cr { if !txnMsg.setOutcomeError(nil, nil, fmt.Errorf("Connection in wrong state: %v", cr.currentState)) { return fmt.Errorf("Live txn already closed") } return nil } if cr.liveTxn != nil { if !txnMsg.setOutcomeError(nil, nil, fmt.Errorf("Existing live txn")) { return fmt.Errorf("Live txn already closed") } return nil } binary.BigEndian.PutUint64(cr.namespace[:8], cr.nextTxnId) txnMsg.txn.SetId(cr.namespace) seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) msg.SetClientTxnSubmission(*txnMsg.txn) if err := cr.sendMessage(&msg); err == nil { cr.liveTxn = txnMsg return nil } else { cr.nextTxnId++ return err } }
func (cr *connectionRun) start() (bool, error) { log.Printf("Connection established to %v (%v)\n", cr.serverHost, cr.rmId) seg := capn.NewBuffer(nil) message := msgs.NewRootMessage(seg) message.SetHeartbeat() buf := new(bytes.Buffer) _, err := seg.WriteTo(buf) if err != nil { return false, err } cr.beatBytes = buf.Bytes() cr.mustSendBeat = true cr.missingBeats = 0 cr.beater = newConnectionBeater(cr.Connection) go cr.beater.beat() cr.reader = newConnectionReader(cr.Connection) go cr.reader.read() if cr.awaiting != nil { close(cr.awaiting.resultChan) cr.awaiting = nil } return false, nil }
func (p *proposal) maybeSendOneA() { pendingPromises := p.pending[:0] for _, pi := range p.instances { if pi.currentState == &pi.proposalOneA { pendingPromises = append(pendingPromises, pi) } } if len(pendingPromises) == 0 { return } seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) sender := newProposalSender(p, pendingPromises) oneACap := msgs.NewOneATxnVotes(seg) msg.SetOneATxnVotes(oneACap) oneACap.SetTxnId(p.txnId[:]) oneACap.SetRmId(uint32(p.instanceRMId)) proposals := msgs.NewTxnVoteProposalList(seg, len(pendingPromises)) oneACap.SetProposals(proposals) for idx, pi := range pendingPromises { proposal := proposals.At(idx) pi.addOneAToProposal(&proposal, sender) } sender.msg = server.SegToBytes(seg) server.Log(p.txnId, "Adding sender for 1A") p.proposerManager.ConnectionManager.AddSender(sender) }
func (p *proposal) maybeSendTwoA() { pendingAccepts := p.pending[:0] for _, pi := range p.instances { if pi.currentState == &pi.proposalTwoA { pendingAccepts = append(pendingAccepts, pi) } } if len(pendingAccepts) == 0 { return } seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) sender := newProposalSender(p, pendingAccepts) twoACap := msgs.NewTwoATxnVotes(seg) msg.SetTwoATxnVotes(twoACap) twoACap.SetRmId(uint32(p.instanceRMId)) acceptRequests := msgs.NewTxnVoteAcceptRequestList(seg, len(pendingAccepts)) twoACap.SetAcceptRequests(acceptRequests) deflate := false for idx, pi := range pendingAccepts { acceptRequest := acceptRequests.At(idx) deflate = pi.addTwoAToAcceptRequest(seg, &acceptRequest, sender) || deflate } if deflate { deflated := deflateTxn(p.txn, seg) twoACap.SetTxn(*deflated) } else { twoACap.SetTxn(*p.txn) } sender.msg = server.SegToBytes(seg) server.Log(p.txnId, "Adding sender for 2A") p.proposerManager.ConnectionManager.AddSender(sender) }
func MakeTxnSubmissionAbortMsg(txnId *common.TxnId) []byte { seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) tsa := msgs.NewTxnSubmissionAbort(seg) msg.SetSubmissionAbort(tsa) tsa.SetTxnId(txnId[:]) return server.SegToBytes(seg) }
func MakeTxnSubmissionCompleteMsg(txnId *common.TxnId) []byte { seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) tsc := msgs.NewTxnSubmissionComplete(seg) msg.SetSubmissionComplete(tsc) tsc.SetTxnId(txnId[:]) return server.SegToBytes(seg) }
func MakeTxnLocallyCompleteMsg(txnId *common.TxnId) []byte { seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) tlc := msgs.NewTxnLocallyComplete(seg) msg.SetTxnLocallyComplete(tlc) tlc.SetTxnId(txnId[:]) return server.SegToBytes(seg) }
func (adfd *acceptorDeleteFromDisk) deletionDone() { if adfd.currentState == adfd { adfd.nextState(nil) adfd.acceptorManager.AcceptorFinished(adfd.txnId) seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) tgc := msgs.NewTxnGloballyComplete(seg) msg.SetTxnGloballyComplete(tgc) tgc.SetTxnId(adfd.txnId[:]) server.Log(adfd.txnId, "Sending TGC to", adfd.tgcRecipients) NewOneShotSender(server.SegToBytes(seg), adfd.acceptorManager.ConnectionManager, adfd.tgcRecipients...) } }
func (cr *connectionRun) clientTxnError(ctxn *msgs.ClientTxn, err error, origTxnId *common.TxnId) error { seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) outcome := msgs.NewClientTxnOutcome(seg) msg.SetClientTxnOutcome(outcome) if origTxnId == nil { outcome.SetId(ctxn.Id()) } else { outcome.SetId(origTxnId[:]) } outcome.SetFinalId(ctxn.Id()) outcome.SetError(err.Error()) return cr.sendMessage(server.SegToBytes(seg)) }
func (am *AcceptorManager) TwoATxnVotesReceived(sender common.RMId, txnId *common.TxnId, twoATxnVotes *msgs.TwoATxnVotes) { instanceRMId := common.RMId(twoATxnVotes.RmId()) server.Log(txnId, "2A received from", sender, "; instance:", instanceRMId) instId := instanceId([instanceIdLen]byte{}) instIdSlice := instId[:] copy(instIdSlice, txnId[:]) binary.BigEndian.PutUint32(instIdSlice[common.KeyLen:], uint32(instanceRMId)) txnCap := twoATxnVotes.Txn() a := am.ensureAcceptor(txnId, &txnCap) requests := twoATxnVotes.AcceptRequests() failureInstances := make([]*instance, 0, requests.Len()) failureRequests := make([]*msgs.TxnVoteAcceptRequest, 0, requests.Len()) for idx, l := 0, requests.Len(); idx < l; idx++ { request := requests.At(idx) vUUId := common.MakeVarUUId(request.Ballot().VarId()) copy(instIdSlice[common.KeyLen+4:], vUUId[:]) inst := am.ensureInstance(txnId, &instId, vUUId) accepted, rejected := inst.TwoATxnVotesReceived(&request) if accepted { a.BallotAccepted(instanceRMId, inst, vUUId, &txnCap) } else if rejected { failureInstances = append(failureInstances, inst) failureRequests = append(failureRequests, &request) } } if len(failureInstances) != 0 { replySeg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(replySeg) twoBTxnVotes := msgs.NewTwoBTxnVotes(replySeg) msg.SetTwoBTxnVotes(twoBTxnVotes) twoBTxnVotes.SetFailures() failuresCap := twoBTxnVotes.Failures() failuresCap.SetTxnId(txnId[:]) failuresCap.SetRmId(uint32(instanceRMId)) nacks := msgs.NewTxnVoteTwoBFailureList(replySeg, len(failureInstances)) failuresCap.SetNacks(nacks) for idx, inst := range failureInstances { failure := nacks.At(idx) failure.SetVarId(inst.vUUId[:]) failure.SetRoundNumber(failureRequests[idx].RoundNumber()) failure.SetRoundNumberTooLow(uint32(inst.promiseNum >> 32)) } server.Log(txnId, "Sending 2B failures to", sender, "; instance:", instanceRMId) NewOneShotSender(server.SegToBytes(replySeg), am.ConnectionManager, sender) } }
func (sts *SimpleTxnSubmitter) SubmitTransaction(txnCap *msgs.Txn, activeRMs []common.RMId, continuation TxnCompletionConsumer, delay time.Duration) { seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) msg.SetTxnSubmission(*txnCap) txnId := common.MakeTxnId(txnCap.Id()) server.Log(txnId, "Submitting txn") txnSender := paxos.NewRepeatingSender(server.SegToBytes(seg), activeRMs...) if delay == 0 { sts.connectionManager.AddSender(txnSender) } else { go func() { // fmt.Printf("%v ", delay) time.Sleep(delay) sts.connectionManager.AddSender(txnSender) }() } acceptors := paxos.GetAcceptorsFromTxn(txnCap) shutdownFun := func(shutdown bool) { delete(sts.outcomeConsumers, *txnId) // fmt.Printf("sts%v ", len(sts.outcomeConsumers)) sts.connectionManager.RemoveSenderAsync(txnSender) paxos.NewOneShotSender(paxos.MakeTxnSubmissionCompleteMsg(txnId), sts.connectionManager, acceptors...) if shutdown { if txnCap.Retry() { paxos.NewOneShotSender(paxos.MakeTxnSubmissionAbortMsg(txnId), sts.connectionManager, activeRMs...) } continuation(txnId, nil) } } shutdownFunPtr := &shutdownFun sts.onShutdown[shutdownFunPtr] = server.EmptyStructVal outcomeAccumulator := paxos.NewOutcomeAccumulator(int(txnCap.FInc()), acceptors) consumer := func(sender common.RMId, txnId *common.TxnId, outcome *msgs.Outcome) { if outcome, _ = outcomeAccumulator.BallotOutcomeReceived(sender, outcome); outcome != nil { delete(sts.onShutdown, shutdownFunPtr) shutdownFun(false) continuation(txnId, outcome) } } sts.outcomeConsumers[*txnId] = consumer // fmt.Printf("sts%v ", len(sts.outcomeConsumers)) }
func (am *AcceptorManager) TxnLocallyCompleteReceived(sender common.RMId, txnId *common.TxnId, tlc *msgs.TxnLocallyComplete) { if aInst, found := am.acceptors[*txnId]; found && aInst.acceptor != nil { server.Log(txnId, "TLC received from", sender, "(acceptor found)") aInst.acceptor.TxnLocallyCompleteReceived(sender) } else { // We must have deleted the acceptor state from disk, // immediately prior to sending TGC, and then died. Now we're // back up, the proposers have sent us more TLCs, and we should // just reply with TGCs. server.Log(txnId, "TLC received from", sender, "(acceptor not found)") seg := capn.NewBuffer(nil) msg := msgs.NewRootMessage(seg) tgc := msgs.NewTxnGloballyComplete(seg) msg.SetTxnGloballyComplete(tgc) tgc.SetTxnId(txnId[:]) server.Log(txnId, "Sending single TGC to", sender) NewOneShotSender(server.SegToBytes(seg), am.ConnectionManager, sender) } }