// Connect to a STOMP broker, publish some messages and disconnect. func main() { st := time.Now() // Standard example connect sequence n, conn, e := sngecomm.CommonConnect(exampid, tag, ll) if e != nil { ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v", exampid, tag, sngecomm.Lcs, e.Error()) // Handle this ...... } // *NOTE* application specific functionaltiy starts here! sh := stompngo.Headers{"destination", sngecomm.Dest()} ll.Printf("%stag:%s connsess:%s destination dest:%s\n", exampid, tag, conn.Session(), sngecomm.Dest()) if senv.Persistent() { sh = sh.Add("persistent", "true") } ms := exampid + "message: " for i := 1; i <= senv.Nmsgs(); i++ { mse := ms + fmt.Sprintf("%d", i) ll.Printf("%stag:%s connsess:%s main_sending mse:~%s~\n", exampid, tag, conn.Session(), mse) e := conn.Send(sh, mse) if e != nil { ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v", exampid, tag, conn.Session(), e.Error()) // Handle this ...... } ll.Printf("%stag:%s connsess:%s main_send_complete mse:~%s~\n", exampid, tag, conn.Session(), mse) time.Sleep(100 * time.Millisecond) } // *NOTE* application specific functionaltiy ends here! // Standard example disconnect sequence e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll) if e != nil { ll.Fatalf("%stag:%s connsess:%s main_on_disconnect error:%v", exampid, tag, conn.Session(), e.Error()) // Handle this ...... } ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n", exampid, tag, conn.Session(), time.Now().Sub(st)) }
func ShowRunParms(exampid string) { llu.Printf("%sHOST:%v\n", exampid, os.Getenv("STOMP_HOST")) llu.Printf("%sPORT:%v\n", exampid, os.Getenv("STOMP_PORT")) llu.Printf("%sPROTOCOL:%v\n", exampid, senv.Protocol()) llu.Printf("%sVHOST:%v\n", exampid, senv.Vhost()) llu.Printf("%sNQS:%v\n", exampid, Nqs()) llu.Printf("%sNMSGS:%v\n", exampid, senv.Nmsgs()) llu.Printf("%sSUBCHANCAP:%v\n", exampid, senv.SubChanCap()) llu.Printf("%sRECVFACT:%v\n", exampid, RecvFactor()) llu.Printf("%sSENDFACT:%v\n", exampid, SendFactor()) llu.Printf("%sRECVWAIT:%t\n", exampid, RecvWait()) llu.Printf("%sSENDWAIT:%t\n", exampid, SendWait()) llu.Printf("%sACKMODE:%v\n", exampid, AckMode()) }
/* runSender sends all messages to a specified queue. */ func runSender(conn *stompngo.Connection, qns string) { ltag := tag + "-runsender" d := sngecomm.Dest() + "." + qns id := stompngo.Uuid() // A unique sender id ll.Printf("%stag:%s connsess:%s start id:%s dest:%s\n", exampid, ltag, conn.Session(), id, d) wh := stompngo.Headers{"destination", d, "senderId", id, "qnum", qns} // basic send Headers if senv.Persistent() { wh = wh.Add("persistent", "true") } tmr := time.NewTimer(100 * time.Hour) nmsgs := senv.Nmsgs() for mc := 1; mc <= nmsgs; mc++ { sh := append(wh, "msgnum", fmt.Sprintf("%d", mc)) // Generate a message to send ............... ll.Printf("%stag:%s connsess:%s send id:%s qns:%s mc:%d\n", exampid, ltag, conn.Session(), id, qns, mc) e := conn.Send(sh, string(sngecomm.Partial())) if e != nil { ll.Fatalf("%stag:%s connsess:%s send_error qns:%v error:%v", exampid, ltag, conn.Session(), qns, e.Error()) // Handle this ...... } if mc == nmsgs { break } if sw { dt := time.Duration(sngecomm.ValueBetween(min, max, sf)) ll.Printf("%stag:%s connsess:%s send_stagger dt:%v qns:%s mc:%d\n", exampid, ltag, conn.Session(), dt, qns, mc) tmr.Reset(dt) _ = <-tmr.C runtime.Gosched() } } ll.Printf("%stag:%s connsess:%s end id:%s dest:%s\n", exampid, ltag, conn.Session(), id, d) // wgs.Done() }
/* Start all sender go routines. */ func startSenders(nqs int) { ltag := tag + "-startsenders" ll.Printf("%stag:%s connsess:%s queue_count nqs:%v\n", exampid, ltag, conn.Session(), nqs) mc := senv.Nmsgs() // message count ll.Printf("%stag:%s connsess:%s message_count mc:%v\n", exampid, ltag, conn.Session(), mc) for i := 1; i <= nqs; i++ { // all queues wgs.Add(1) go sender(i, mc) } wgs.Wait() ll.Printf("%stag:%s connsess:%s ends nqs:%v mc:%v\n", exampid, ltag, conn.Session(), nqs, mc) wga.Done() }
func startReceivers(qn int) { ltag := tag + "-startreceivers" ll.Printf("%stag:%s connsess:%s starts qn:%d\n", exampid, ltag, sngecomm.Lcs, qn) // Standard example connect sequence n, conn, e := sngecomm.CommonConnect(exampid, ltag, ll) if e != nil { ll.Fatalf("%stag:%s connsess:%s on_connect error:%v", exampid, ltag, sngecomm.Lcs, e.Error()) // Handle this ...... } nmsgs := senv.Nmsgs() // get message count ll.Printf("%stag:%s connsess:%s message_count nmsgs:%d qn:%d\n", exampid, ltag, conn.Session(), nmsgs, qn) for i := 1; i <= qn; i++ { // all queues wgr.Add(1) go receiver(conn, i, nmsgs) } ll.Printf("%stag:%s connsess:%s starts_done\n", exampid, ltag, conn.Session()) wgr.Wait() // Standard example disconnect sequence e = sngecomm.CommonDisconnect(n, conn, exampid, ltag, ll) if e != nil { ll.Fatalf("%stag:%s connsess:%s on_disconnect error:%v", exampid, ltag, conn.Session(), e.Error()) // Handle this ...... } sngecomm.ShowStats(exampid, ltag, conn) wga.Done() }
/* runReceive receives all messages from a specified queue. */ func runReceive(conn *stompngo.Connection, q int, w *sync.WaitGroup) { ltag := tag + "-runreceive" qns := fmt.Sprintf("%d", q) // queue number id := stompngo.Uuid() // A unique subscription ID d := sngecomm.Dest() + "." + qns ll.Printf("%stag:%s connsess:%s starts id:%s qns:%s d:%s\n", exampid, ltag, conn.Session(), id, qns, d) // Subscribe (use common helper) sc := sngecomm.HandleSubscribe(conn, d, id, sngecomm.AckMode()) ll.Printf("%stag:%s connsess:%s subscribe_done id:%s qns:%s d:%s\n", exampid, ltag, conn.Session(), id, qns, d) // tmr := time.NewTimer(100 * time.Hour) pbc := sngecomm.Pbc() // Print byte count nmsgs := senv.Nmsgs() // Receive loop var md stompngo.MessageData for mc := 1; mc <= nmsgs; mc++ { ll.Printf("%stag:%s connsess:%s chanchek id:%s qns:%s lensc:%d capsc:%d\n", exampid, ltag, conn.Session(), id, qns, len(sc), cap(sc)) select { case md = <-sc: case md = <-conn.MessageData: // Frames RECEIPT or ERROR not expected here ll.Fatalf("%stag:%s connsess:%s send_error qns:%v md:%v", exampid, ltag, conn.Session(), qns, md) // Handle this ...... } if md.Error != nil { ll.Fatalf("%stag:%s connsess:%s receive_error qns:%v error:%v\n", exampid, ltag, conn.Session(), qns, md.Error) } // Process the inbound message ................. ll.Printf("%stag:%s connsess:%s inbound id:%s qns:%s mc:%d\n", exampid, ltag, conn.Session(), id, qns, mc) // Sanity check the message Command, and the queue and message numbers mns := fmt.Sprintf("%d", mc) // string message number if md.Message.Command != stompngo.MESSAGE { ll.Fatalf("%stag:%s connsess:%s bad_frame qns:%s mc:%d md:%v\n", exampid, ltag, conn.Session(), qns, mc, md) } if !md.Message.Headers.ContainsKV("qnum", qns) || !md.Message.Headers.ContainsKV("msgnum", mns) { ll.Fatalf("%stag:%s connsess:%s dirty_message qns:%v msgnum:%v md:%v", exampid, tag, conn.Session(), qns, mns, md) // Handle this ...... } sl := len(md.Message.Body) if pbc > 0 { sl = pbc if len(md.Message.Body) < sl { sl = len(md.Message.Body) } } ll.Printf("%stag:%s connsess:%s runReceive_recv_message id:%s body:%s qns:%s msgnum:%s\n", exampid, ltag, conn.Session(), id, string(md.Message.Body[0:sl]), qns, md.Message.Headers.Value("msgnum")) // Handle ACKs if needed if sngecomm.AckMode() != "auto" { ah := stompngo.Headers{} sngecomm.HandleAck(conn, ah, id) } if mc == nmsgs { break } if rw { dt := time.Duration(sngecomm.ValueBetween(min, max, rf)) ll.Printf("%stag:%s connsess:%s recv_stagger dt:%v qns:%s mc:%d\n", exampid, ltag, conn.Session(), dt, qns, mc) tmr.Reset(dt) _ = <-tmr.C runtime.Gosched() } } // Unsubscribe sngecomm.HandleUnsubscribe(conn, d, id) ll.Printf("%stag:%s connsess:%s runRecieve_ends id:%s qns:%s\n", exampid, ltag, conn.Session(), id, qns) w.Done() }
// Connect to a STOMP broker, receive some messages, ACK them, and disconnect. func main() { st := time.Now() // Standard example connect sequence n, conn, e := sngecomm.CommonConnect(exampid, tag, ll) if e != nil { ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v", exampid, tag, sngecomm.Lcs, e.Error()) // Handle this ...... } pbc := sngecomm.Pbc() // Print byte count // *NOTE* your application functionaltiy goes here! // With Stomp, you must SUBSCRIBE to a destination in order to receive. // Subscribe returns a channel of MessageData struct. // Here we use a common utility routine to handle the differing subscribe // requirements of each protocol level. d := senv.Dest() id := stompngo.Uuid() sc := sngecomm.HandleSubscribe(conn, d, id, "client") ll.Printf("%stag:%s connsess:%s main_subscribe_complete\n", exampid, tag, conn.Session()) // Read data from the returned channel var md stompngo.MessageData for i := 1; i <= senv.Nmsgs(); i++ { select { case md = <-sc: case md = <-conn.MessageData: // Frames RECEIPT or ERROR not expected here ll.Fatalf("%stag:%s connsess:%s main_channel_frame error:%v", exampid, tag, conn.Session(), e.Error()) // Handle this ...... } ll.Printf("%stag:%s connsess:%s main_channel_read_complete\n", exampid, tag, conn.Session()) // MessageData has two components: // a) a Message struct // b) an Error value. Check the error value as usual if md.Error != nil { ll.Fatalf("%stag:%s connsess:%s main_channel_read error:%v", exampid, tag, conn.Session(), e.Error()) // Handle this ...... } // ll.Printf("%stag:%s connsess:%s frame_type:%v\n", exampid, tag, conn.Session(), md.Message.Command) if md.Message.Command != stompngo.MESSAGE { ll.Fatalf("%stag:%s connsess:%s bad_frame frame:%v", exampid, tag, conn.Session(), md.Message.Command) // Handle this ...... } wh := md.Message.Headers for j := 0; j < len(wh)-1; j += 2 { ll.Printf("%stag:%s connsess:%s header:%s:%s\n", exampid, tag, conn.Session(), wh[j], wh[j+1]) } if pbc > 0 { maxlen := pbc if len(md.Message.Body) < maxlen { maxlen = len(md.Message.Body) } ss := string(md.Message.Body[0:maxlen]) ll.Printf("%stag:%s connsess:%s message_payload body:%s\n", exampid, tag, conn.Session(), ss) } // ACK the message just received. // Agiain we use a utility routine to handle the different requirements // of the protocol versions. sngecomm.HandleAck(conn, md.Message.Headers, id) ll.Printf("%stag:%s connsess:%s ack_complete\n", exampid, tag, conn.Session()) } // It is polite to unsubscribe, although unnecessary if a disconnect follows. // Again we use a utility routine to handle the different protocol level // requirements. sngecomm.HandleUnsubscribe(conn, d, id) ll.Printf("%stag:%s connsess:%s stomp_unsubscribe_complete\n", exampid, tag, conn.Session()) // Standard example disconnect sequence e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll) if e != nil { ll.Fatalf("%stag:%s connsess:%s disconnect error:%v", exampid, tag, conn.Session(), e.Error()) // Handle this ...... } ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n", exampid, tag, conn.Session(), time.Now().Sub(st)) }
// Connect to a STOMP broker, subscribe and receive some messages and disconnect. func main() { st := time.Now() // Standard example connect sequence n, conn, e := sngecomm.CommonConnect(exampid, tag, ll) if e != nil { ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v", exampid, tag, sngecomm.Lcs, e.Error()) // Handle this ...... } session = conn.Session() conn.SetLogger(ll) // stompngo logging pbc := sngecomm.Pbc() // Print byte count d := senv.Dest() // Destination id := stompngo.Uuid() // A unique name/id nmsgs := senv.Nmsgs() // int number of messages to get mns := fmt.Sprintf("%d", nmsgs) // string number of messages to get am := sngecomm.AckMode() // ACK mode to use on SUBSCRIBE nfa := true // Need "final" ACK (possiby reset below) wh := stompngo.Headers{ // Starting SUBSCRIBE headers stompngo.StompPlusDrainAfter, mns} // Need a string here // Sanity check ACK mode if conn.Protocol() == stompngo.SPL_10 && am == stompngo.AckModeClientIndividual { ll.Fatalf("%stag:%s connsess:%s invalid_ack_mode am:%v proto:%v\n", exampid, tag, session, am, conn.Protocol()) // } // Do not do final ACK if running ACKs are issued if am == stompngo.AckModeClientIndividual || am == stompngo.AckModeAuto { nfa = false } // Show run parameters ll.Printf("%stag:%s connsess:%s run_parms\n\tpbc:%v\n\td:%v\n\tid:%v\n\tnmsgs:%v\n\tam:%v\n\tnfa:%v\n\twh:%v\n", exampid, tag, session, pbc, d, id, nmsgs, am, nfa, wh) // Run SUBSCRIBE sc := doSubscribe(conn, d, id, am, wh) ll.Printf("%stag:%s connsess:%s stomp_subscribe_complete\n", exampid, tag, session) var md stompngo.MessageData // Message data from basic read var lmd stompngo.MessageData // Possible save (copy) of received data mc := 1 // Initial message number // Loop for the requested number of messages GetLoop: for { ll.Printf("%stag:%s connsess:%s start_of_read_loop mc:%v nmsgs:%v\n", exampid, tag, session, mc, nmsgs) mcs := fmt.Sprintf("%d", mc) // string number message count // Get something from the stompngo read routine select { case md = <-sc: case md = <-conn.MessageData: // if md.Message.Command == stompngo.RECEIPT { ll.Printf("%stag:%s connsess:%s have_receipt md:%v\n", exampid, tag, session, md) continue GetLoop } ll.Fatalf("%stag:%s connsess:%s ERROR_frame hdrs:%v body:%v\n", exampid, tag, session, md.Message.Headers, string(md.Message.Body)) // Handle this ...... } // Save message data for possible use in the final ACK if mc == nmsgs && nfa { lmd = md // Save last message } // Basic loop logging ll.Printf("%stag:%s connsess:%s channel_read_complete mns:%s mc:%d\n", exampid, tag, session, mns, mc) ll.Printf("%stag:%s connsess:%s message_number:%v\n", exampid, tag, session, mc) // Check if reader returned any error if md.Error != nil { ll.Fatalf("%stag:%s connsess:%s error_read error:%v", exampid, tag, session, md.Error) // Handle this ...... } // Show frame type ll.Printf("%stag:%s connsess:%s frame_type cmd:%s\n", exampid, tag, session, md.Message.Command) // Pure sanity check: this should *never* happen based on logic // above. if md.Message.Command != stompngo.MESSAGE { ll.Fatalf("%stag:%s connsess:%s error_frame_type md:%v", exampid, tag, session, md) // Handle this ...... } // Show Message Headers wh := md.Message.Headers for j := 0; j < len(wh)-1; j += 2 { ll.Printf("%stag:%s connsess:%s Header:%s:%s\n", exampid, tag, session, wh[j], wh[j+1]) } // Show (part of) Message Body if pbc > 0 { maxlen := pbc if len(md.Message.Body) < maxlen { maxlen = len(md.Message.Body) } ss := string(md.Message.Body[0:maxlen]) ll.Printf("%stag:%s connsess:%s payload body:%s\n", exampid, tag, session, ss) } // Sanity check this message payload wm := wlp + mcs // The left part plus the (string) meassage number] bm := string(md.Message.Body) if bm != wm { ll.Fatalf("%stag:%s connsess:%s error_message_payload\n\tGot %s\n\tWant%s\n", exampid, tag, session, bm, wm) // Handle this ...... } else { ll.Printf("%stag:%s connsess:%s matched_body_string\n%s\n%s\n", exampid, tag, session, bm, wm) // Handle this ......) } // Run individual ACK if required if am == stompngo.AckModeClientIndividual { wh := md.Message.Headers // Copy Headers if ar { // ACK receipt wanted wh = wh.Add(stompngo.HK_RECEIPT, "rwanted-"+mcs) } sngecomm.HandleAck(conn, wh, id) ll.Printf("%stag:%s connsess:%s individual_ack_complete mc:%v headers:%v\n", exampid, tag, session, mc, md.Message.Headers) } // Check for end of loop condition if mc == nmsgs { break } // Increment loop/message counter mc++ } // Issue the final ACK if needed if nfa { wh := lmd.Message.Headers // Copy Headers if ar { // ACK receipt wanted wh = wh.Add(stompngo.HK_RECEIPT, "rwanted-fin") } sngecomm.HandleAck(conn, wh, id) ll.Printf("%stag:%s connsess:%s final_ack_complete\n", exampid, tag, session) if ar { getReceipt(conn) } } // Unsubscribe (may be skipped if requested) if unsub { sngecomm.HandleUnsubscribe(conn, d, id) ll.Printf("%stag:%s connsess:%s stomp_unsubscribe_complete\n", exampid, tag, session) } else { ll.Printf("%stag:%s connsess:%s skipping_unsubscribe\n", exampid, tag, session) } // Standard example disconnect sequence (may be skipped if requested) // a) Closes the *stompngo.Connection // b) Closes the net.Conn if dodisc { e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll) if e != nil { ll.Fatalf("%stag:%s connsess:%s main_on_disconnect error:%v", exampid, tag, session, e.Error()) // Handle this ...... } ll.Printf("%stag:%s connsess:%s disconnect_receipt:%v\n", exampid, tag, session, conn.DisconnectReceipt) } else { ll.Printf("%stag:%s connsess:%s skipping_disconnect\n", exampid, tag, session) } // End of work logging, show elapsed time ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n", exampid, tag, session, time.Now().Sub(st)) }
func main() { st := time.Now() sngecomm.ShowRunParms(exampid) ll.Printf("%stag:%s connsess:%s main_starts\n", exampid, tag, sngecomm.Lcs) ll.Printf("%stag:%s connsess:%s main_profiling pprof:%v\n", exampid, tag, sngecomm.Lcs, sngecomm.Pprof()) ll.Printf("%stag:%s connsess:%s main_current_GOMAXPROCS gmp:%v\n", exampid, tag, sngecomm.Lcs, runtime.GOMAXPROCS(-1)) if sngecomm.SetMAXPROCS() { nc := runtime.NumCPU() ll.Printf("%stag:%s connsess:%s main_current_num_cpus cncpu:%v\n", exampid, tag, sngecomm.Lcs, nc) gmp := runtime.GOMAXPROCS(nc) ll.Printf("%stag:%s connsess:%s main_previous_num_cpus pncpu:%v\n", exampid, tag, sngecomm.Lcs, gmp) ll.Printf("%stag:%s connsess:%s main_current_GOMAXPROCS gmp:%v\n", exampid, tag, sngecomm.Lcs, runtime.GOMAXPROCS(-1)) } // sw = sngecomm.SendWait() rw = sngecomm.RecvWait() sf = sngecomm.SendFactor() rf = sngecomm.RecvFactor() ll.Printf("%stag:%s connsess:%s main_wait_sleep_factors sw:%v rw:%v sf:%v rf:%v\n", exampid, tag, sngecomm.Lcs, sw, rw, sf, rf) // numq := sngecomm.Nqs() nmsgs = senv.Nmsgs() // message count // ll.Printf("%stag:%s connsess:%s main_starting_receivers\n", exampid, tag, sngecomm.Lcs) for q := 1; q <= numq; q++ { wgr.Add(1) go runReceiver(q) } ll.Printf("%stag:%s connsess:%s main_started_receivers\n", exampid, tag, sngecomm.Lcs) // ll.Printf("%stag:%s connsess:%s main_starting_senders\n", exampid, tag, sngecomm.Lcs) for q := 1; q <= numq; q++ { wgs.Add(1) go runSender(q) } ll.Printf("%stag:%s connsess:%s main_started_senders\n", exampid, tag, sngecomm.Lcs) // wgs.Wait() ll.Printf("%stag:%s connsess:%s main_senders_complete\n", exampid, tag, sngecomm.Lcs) wgr.Wait() ll.Printf("%stag:%s connsess:%s main_receivers_complete\n", exampid, tag, sngecomm.Lcs) // // The end ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n", exampid, tag, sngecomm.Lcs, time.Now().Sub(st)) }
// We 'stagger' between each message send and message receive for a random // amount of time. // Vary these for experimental purposes. YMMV. max int64 = 1e9 // Max stagger time (nanoseconds) min int64 = max / 10 // Min stagger time (nanoseconds) // Wait flags sw = true rw = true // Sleep multipliers sf float64 = 1.0 rf float64 = 1.0 // Number of messages nmsgs = senv.Nmsgs() ll = log.New(os.Stdout, "EMSMR ", log.Ldate|log.Lmicroseconds|log.Lshortfile) tag = "manyconn" ) func sendMessages(conn *stompngo.Connection, qnum int, nc net.Conn) { ltag := tag + "-sendmessages" qns := fmt.Sprintf("%d", qnum) // queue number d := sngecomm.Dest() + "." + qns ll.Printf("%stag:%s connsess:%s start d:%s qnum:%d\n", exampid, ltag, conn.Session(), d, qnum) wh := stompngo.Headers{"destination", d,