func (cr *connectionRun) handleMsgFromClient(msg *cmsgs.ClientMessage) 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 cmsgs.CLIENTMESSAGE_HEARTBEAT: // do nothing case cmsgs.CLIENTMESSAGE_CLIENTTXNSUBMISSION: ctxn := msg.ClientTxnSubmission() origTxnId := common.MakeTxnId(ctxn.Id()) cr.submitter.SubmitClientTransaction(&ctxn, func(clientOutcome *cmsgs.ClientTxnOutcome, err error) { switch { case err != nil: cr.clientTxnError(&ctxn, err, origTxnId) case clientOutcome == nil: // shutdown return default: seg := capn.NewBuffer(nil) msg := cmsgs.NewRootClientMessage(seg) msg.SetClientTxnOutcome(*clientOutcome) cr.sendMessage(server.SegToBytes(msg.Segment)) } }) default: return cr.maybeRestartConnection(fmt.Errorf("Unexpected message type received from client: %v", which)) } return nil }
func (cr *connectionRun) clientTxnError(ctxn *cmsgs.ClientTxn, err error, origTxnId *common.TxnId) error { seg := capn.NewBuffer(nil) msg := cmsgs.NewRootClientMessage(seg) outcome := cmsgs.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 (cr *connectionRun) start() (bool, error) { log.Printf("Connection established to %v (%v)\n", cr.remoteHost, cr.remoteRMId) cr.restart = true seg := capn.NewBuffer(nil) if cr.isClient { message := cmsgs.NewRootClientMessage(seg) message.SetHeartbeat() } else { message := msgs.NewRootMessage(seg) message.SetHeartbeat() } cr.beatBytes = server.SegToBytes(seg) if cr.isServer { cr.connectionManager.ServerEstablished(cr.Connection, cr.remoteHost, cr.remoteRMId, cr.remoteBootCount, cr.combinedTieBreak, cr.remoteRootId) } if cr.isClient { servers := cr.connectionManager.ClientEstablished(cr.ConnectionNumber, cr.Connection) cr.submitter = client.NewClientTxnSubmitter(cr.connectionManager.RMId, cr.connectionManager.BootCount, cr.connectionManager) cr.submitter.TopologyChanged(cr.topology) cr.submitter.ServerConnectionsChanged(servers) } cr.mustSendBeat = true cr.missingBeats = 0 cr.beater = newConnectionBeater(cr.Connection) go cr.beater.beat() cr.reader = newConnectionReader(cr.Connection) if cr.isClient { go cr.reader.readClient() } else { go cr.reader.readServer() } return false, nil }