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...) var removeSenderCh chan server.EmptyStruct if delay == 0 { sts.connPub.AddServerConnectionSubscriber(txnSender) } else { removeSenderCh = make(chan server.EmptyStruct) go func() { // fmt.Printf("%v ", delay) time.Sleep(delay) sts.connPub.AddServerConnectionSubscriber(txnSender) <-removeSenderCh sts.connPub.RemoveServerConnectionSubscriber(txnSender) }() } acceptors := paxos.GetAcceptorsFromTxn(txnCap) shutdownFun := func(shutdown bool) { delete(sts.outcomeConsumers, *txnId) // fmt.Printf("sts%v ", len(sts.outcomeConsumers)) if delay == 0 { sts.connPub.RemoveServerConnectionSubscriber(txnSender) } else { close(removeSenderCh) } // OSS is safe here - see above. paxos.NewOneShotSender(paxos.MakeTxnSubmissionCompleteMsg(txnId), sts.connPub, acceptors...) if shutdown { if txnCap.Retry() { // If this msg doesn't make it then proposers should // observe our death and tidy up anyway. If it's just this // connection shutting down then there should be no // problem with these msgs getting to the propposers. paxos.NewOneShotSender(paxos.MakeTxnSubmissionAbortMsg(txnId), sts.connPub, activeRMs...) } continuation(txnId, nil, 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, nil) } } sts.outcomeConsumers[*txnId] = consumer // fmt.Printf("sts%v ", len(sts.outcomeConsumers)) }
func (sts *SimpleTxnSubmitter) SubmissionOutcomeReceived(sender common.RMId, txnId *common.TxnId, outcome *msgs.Outcome) { if consumer, found := sts.outcomeConsumers[*txnId]; found { consumer(sender, txnId, outcome) } else { paxos.NewOneShotSender(paxos.MakeTxnSubmissionCompleteMsg(txnId), sts.connectionManager, sender) } }
func (sts *SimpleTxnSubmitter) SubmissionOutcomeReceived(sender common.RMId, txnId *common.TxnId, outcome *msgs.Outcome) { if consumer, found := sts.outcomeConsumers[*txnId]; found { consumer(sender, txnId, outcome) } else { // OSS is safe here - it's the default action on receipt of an unknown txnid paxos.NewOneShotSender(paxos.MakeTxnSubmissionCompleteMsg(txnId), sts.connPub, 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 (cm *ConnectionManager) DispatchMessage(sender common.RMId, msgType msgs.Message_Which, msg *msgs.Message) { d := cm.Dispatchers switch msgType { case msgs.MESSAGE_TXNSUBMISSION: txn := msg.TxnSubmission() d.ProposerDispatcher.TxnReceived(sender, &txn) case msgs.MESSAGE_SUBMISSIONOUTCOME: outcome := msg.SubmissionOutcome() txnId := common.MakeTxnId(outcome.Txn().Id()) connNumber := binary.BigEndian.Uint32(txnId[8:12]) bootNumber := binary.BigEndian.Uint32(txnId[12:16]) if conn := cm.GetClient(bootNumber, connNumber); conn == nil { // OSS is safe here - it's the default action on receipt of outcome for unknown client. paxos.NewOneShotSender(paxos.MakeTxnSubmissionCompleteMsg(txnId), cm, sender) } else { conn.SubmissionOutcomeReceived(sender, txnId, &outcome) return } case msgs.MESSAGE_SUBMISSIONCOMPLETE: tsc := msg.SubmissionComplete() d.AcceptorDispatcher.TxnSubmissionCompleteReceived(sender, &tsc) case msgs.MESSAGE_SUBMISSIONABORT: tsa := msg.SubmissionAbort() d.ProposerDispatcher.TxnSubmissionAbortReceived(sender, &tsa) case msgs.MESSAGE_ONEATXNVOTES: oneATxnVotes := msg.OneATxnVotes() d.AcceptorDispatcher.OneATxnVotesReceived(sender, &oneATxnVotes) case msgs.MESSAGE_ONEBTXNVOTES: oneBTxnVotes := msg.OneBTxnVotes() d.ProposerDispatcher.OneBTxnVotesReceived(sender, &oneBTxnVotes) case msgs.MESSAGE_TWOATXNVOTES: twoATxnVotes := msg.TwoATxnVotes() d.AcceptorDispatcher.TwoATxnVotesReceived(sender, &twoATxnVotes) case msgs.MESSAGE_TWOBTXNVOTES: twoBTxnVotes := msg.TwoBTxnVotes() d.ProposerDispatcher.TwoBTxnVotesReceived(sender, &twoBTxnVotes) case msgs.MESSAGE_TXNLOCALLYCOMPLETE: tlc := msg.TxnLocallyComplete() d.AcceptorDispatcher.TxnLocallyCompleteReceived(sender, &tlc) case msgs.MESSAGE_TXNGLOBALLYCOMPLETE: tgc := msg.TxnGloballyComplete() d.ProposerDispatcher.TxnGloballyCompleteReceived(sender, &tgc) case msgs.MESSAGE_TOPOLOGYCHANGEREQUEST: // do nothing - we've just sent it to ourselves. case msgs.MESSAGE_MIGRATION: migration := msg.Migration() cm.Transmogrifier.MigrationReceived(sender, &migration) case msgs.MESSAGE_MIGRATIONCOMPLETE: migrationComplete := msg.MigrationComplete() cm.Transmogrifier.MigrationCompleteReceived(sender, &migrationComplete) default: panic(fmt.Sprintf("Unexpected message received from %v (%v)", sender, msgType)) } }